diff --git a/point_cloud_transformer/CMakeLists.txt b/point_cloud_transformer/CMakeLists.txt new file mode 100644 index 0000000..1b5e500 --- /dev/null +++ b/point_cloud_transformer/CMakeLists.txt @@ -0,0 +1,46 @@ +cmake_minimum_required(VERSION 2.8.3) +project(point_cloud_transformer) + +## Find catkin macros and libraries +## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz) +## is used, also find other catkin packages +find_package(catkin REQUIRED COMPONENTS + nodelet + pcl_ros + roscpp + rospy + sensor_msgs + tf +) + +catkin_package( + INCLUDE_DIRS include + LIBRARIES PC2TransformerNodelet + CATKIN_DEPENDS pcl_ros roscpp rospy sensor_msgs tf nodelet + DEPENDS system_lib +) + +include_directories( + ${catkin_INCLUDE_DIRS} +) + + +## Create the nodelet tutorial library +add_library(PC2TransformerNodelet src/point_cloud_transform.cpp) #nodelet_PC2_transformer + +target_link_libraries(PC2TransformerNodelet + ${catkin_LIBRARIES} +) + +#if(catkin_EXPORTED_LIBRARIES) +# add_dependencies(PC2TransformerNodelet ) # ${catkin_EXPORTED_LIBRARIES}) +#endif() + +install(TARGETS PC2TransformerNodelet + ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} + LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} + RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}) + +## Mark other files for installation (e.g. launch and bag files, etc.) +install(FILES nodelet_PC2_transformer.xml point_cloud_transformer.launch + DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}) diff --git a/point_cloud_transformer/launch/point_cloud_transformer.launch b/point_cloud_transformer/launch/point_cloud_transformer.launch new file mode 100644 index 0000000..4da9ce3 --- /dev/null +++ b/point_cloud_transformer/launch/point_cloud_transformer.launch @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/point_cloud_transformer/nodelet_PC2_transformer.xml b/point_cloud_transformer/nodelet_PC2_transformer.xml new file mode 100644 index 0000000..46b048a --- /dev/null +++ b/point_cloud_transformer/nodelet_PC2_transformer.xml @@ -0,0 +1,7 @@ + + + + A node for transforming a PointCloud2 + + + diff --git a/point_cloud_transformer/package.xml b/point_cloud_transformer/package.xml new file mode 100644 index 0000000..54ba729 --- /dev/null +++ b/point_cloud_transformer/package.xml @@ -0,0 +1,66 @@ + + + point_cloud_transformer + 0.0.2 + Transform a PointCloude2 from frame A to frame B (using a Nodelet) + + + + + gadringer + + + + + + BSD + + + + + + + + + + + + + + + + + + + + + + + + + + catkin + + nodelet + pcl_ros + roscpp + rospy + sensor_msgs + tf + nodelet + pcl_ros + roscpp + rospy + sensor_msgs + tf + + + + + + + + + + + diff --git a/point_cloud_transformer/src/point_cloud_transform.cpp b/point_cloud_transformer/src/point_cloud_transform.cpp new file mode 100644 index 0000000..03fe51b --- /dev/null +++ b/point_cloud_transformer/src/point_cloud_transform.cpp @@ -0,0 +1,65 @@ +#include + +//This header allows you to publish and subscribe pcl::PointCloud objects as ROS message +#include +#include +#include +#include + +namespace point_cloud_transformer{ + +class PC2TransformerNodelet : public nodelet::Nodelet{ + public: + sensor_msgs::PointCloud2 cloud_transformed, cloud_income; + bool is_cloud_subscribed; + std::string target_frame_name; + + + PC2TransformerNodelet() {}; //:is_cloud_subscribed(false) + ~PC2TransformerNodelet() {} + + void cmdCallback(const sensor_msgs::PointCloud2::ConstPtr &msg){ + cloud_income = *msg; + is_cloud_subscribed = true; + } + private: + + virtual void onInit(){ + + ros::NodeHandle n = this->getPrivateNodeHandle(); + is_cloud_subscribed = false; + ros::Publisher point_cloud_pub = n.advertise("/cloud_transformed", 100); //params: topic, size of the message queue + + // Create a subscriber. + // Name the topic, message queue, callback function with class name, and object containing callback function. + ros::Subscriber point_cloud_sub = n.subscribe("/camera/depth/points", 100, &PC2TransformerNodelet::cmdCallback, this); + tf::TransformListener listener; ///cloud_throttled + + ros::Rate rate(5.0); + while(n.ok()){ + ros::spinOnce(); // for callbacks + if(is_cloud_subscribed){ + try{ + pcl_ros::transformPointCloud ("target_frame",cloud_income,cloud_transformed,listener); + //target_frame_name + point_cloud_pub.publish(cloud_transformed); + // cloud_subscribed = false; + } + catch(tf::TransformException e){ + ROS_INFO("Transform_PointCloud: %s", e.what()); + } + } + + rate.sleep(); + } + } +}; + +#include +//PLUGINLIB_DECLARE_CLASS(point_cloud_transformer, PC2TransformerNodelet, point_cloud_transformer::PC2TransformerNodelet, nodelet::Nodelet) + +PLUGINLIB_EXPORT_CLASS(point_cloud_transformer::PC2TransformerNodelet, + nodelet::Nodelet); +} + + diff --git a/point_cloud_transformer_test/CMakeLists.txt b/point_cloud_transformer_test/CMakeLists.txt new file mode 100644 index 0000000..104aabf --- /dev/null +++ b/point_cloud_transformer_test/CMakeLists.txt @@ -0,0 +1,46 @@ +cmake_minimum_required(VERSION 2.8.3) +project(point_cloud_transformer_test) + +## Find catkin macros and libraries +## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz) +## is used, also find other catkin packages +find_package(catkin REQUIRED COMPONENTS + pcl_ros + roscpp + rospy + sensor_msgs + tf +) + +################################### +## catkin specific configuration ## +################################### +## The catkin_package macro generates cmake config files for your package +## Declare things to be passed to dependent projects +## INCLUDE_DIRS: uncomment this if you package contains header files +## LIBRARIES: libraries you create in this project that dependent projects also need +## CATKIN_DEPENDS: catkin_packages dependent projects also need +## DEPENDS: system dependencies of this project that dependent projects also need + +catkin_package( + INCLUDE_DIRS include + LIBRARIES point_cloud_transformer_test + CATKIN_DEPENDS pcl_ros roscpp rospy sensor_msgs tf + DEPENDS system_lib +) + +########### +## Build ## +########### + +## Specify additional locations of header files +## Your package locations should be listed before other locations +# include_directories(include) + +include_directories( + ${catkin_INCLUDE_DIRS} +) + +add_executable(point_cloud_trans src/point_cloud_trans.cpp) +target_link_libraries(point_cloud_trans ${catkin_LIBRARIES}) +add_dependencies(point_cloud_trans ${catkin_EXPORTED_TARGETS}) #depend on all necessary targets diff --git a/point_cloud_transformer_test/launch/RVIZ_rob.rviz b/point_cloud_transformer_test/launch/RVIZ_rob.rviz new file mode 100644 index 0000000..7895198 --- /dev/null +++ b/point_cloud_transformer_test/launch/RVIZ_rob.rviz @@ -0,0 +1,465 @@ +Panels: + - Class: rviz/Displays + Help Height: 78 + Name: Displays + Property Tree Widget: + Expanded: + - /Global Options1 + - /Status1 + - /RobotModel1/Status1 + - /PointCloud21 + - /PointCloud21/Status1 + - /TF1 + Splitter Ratio: 0.483221 + Tree Height: 633 + - Class: rviz/Selection + Name: Selection + - Class: rviz/Tool Properties + Expanded: + - /2D Pose Estimate1 + - /2D Nav Goal1 + - /Publish Point1 + Name: Tool Properties + Splitter Ratio: 0.588679 + - Class: rviz/Views + Expanded: + - /Current View1 + Name: Views + Splitter Ratio: 0.5 + - Class: rviz/Time + Experimental: false + Name: Time + SyncMode: 0 + SyncSource: PointCloud2 +Visualization Manager: + Class: "" + Displays: + - Alpha: 0.5 + Cell Size: 1 + Class: rviz/Grid + Color: 160; 160; 164 + Enabled: true + Line Style: + Line Width: 0.03 + Value: Lines + Name: Grid + Normal Cell Count: 0 + Offset: + X: 0 + Y: 0 + Z: 0 + Plane: XY + Plane Cell Count: 10 + Reference Frame: + Value: true + - Alpha: 1 + Class: rviz/RobotModel + Collision Enabled: false + Enabled: true + Links: + All Links Enabled: true + Expand Joint Details: false + Expand Link Details: false + Expand Tree: false + Link Tree Style: Links in Alphabetic Order + base_footprint: + Alpha: 1 + Show Axes: false + Show Trail: false + base_link: + Alpha: 1 + Show Axes: false + Show Trail: false + Value: true + camera_depth_frame: + Alpha: 1 + Show Axes: false + Show Trail: false + camera_depth_optical_frame: + Alpha: 1 + Show Axes: false + Show Trail: false + camera_link: + Alpha: 1 + Show Axes: false + Show Trail: false + Value: true + camera_rgb_frame: + Alpha: 1 + Show Axes: false + Show Trail: false + camera_rgb_optical_frame: + Alpha: 1 + Show Axes: false + Show Trail: false + caster_back_link: + Alpha: 1 + Show Axes: false + Show Trail: false + Value: true + caster_front_link: + Alpha: 1 + Show Axes: false + Show Trail: false + Value: true + cliff_sensor_front_link: + Alpha: 1 + Show Axes: false + Show Trail: false + cliff_sensor_left_link: + Alpha: 1 + Show Axes: false + Show Trail: false + cliff_sensor_right_link: + Alpha: 1 + Show Axes: false + Show Trail: false + gyro_link: + Alpha: 1 + Show Axes: false + Show Trail: false + plate_bottom_link: + Alpha: 1 + Show Axes: false + Show Trail: false + Value: true + plate_middle_link: + Alpha: 1 + Show Axes: false + Show Trail: false + Value: true + plate_top_link: + Alpha: 1 + Show Axes: false + Show Trail: false + Value: true + pole_bottom_0_link: + Alpha: 1 + Show Axes: false + Show Trail: false + Value: true + pole_bottom_1_link: + Alpha: 1 + Show Axes: false + Show Trail: false + Value: true + pole_bottom_2_link: + Alpha: 1 + Show Axes: false + Show Trail: false + Value: true + pole_bottom_3_link: + Alpha: 1 + Show Axes: false + Show Trail: false + Value: true + pole_bottom_4_link: + Alpha: 1 + Show Axes: false + Show Trail: false + Value: true + pole_bottom_5_link: + Alpha: 1 + Show Axes: false + Show Trail: false + Value: true + pole_kinect_0_link: + Alpha: 1 + Show Axes: false + Show Trail: false + Value: true + pole_kinect_1_link: + Alpha: 1 + Show Axes: false + Show Trail: false + Value: true + pole_middle_0_link: + Alpha: 1 + Show Axes: false + Show Trail: false + Value: true + pole_middle_1_link: + Alpha: 1 + Show Axes: false + Show Trail: false + Value: true + pole_middle_2_link: + Alpha: 1 + Show Axes: false + Show Trail: false + Value: true + pole_middle_3_link: + Alpha: 1 + Show Axes: false + Show Trail: false + Value: true + pole_top_0_link: + Alpha: 1 + Show Axes: false + Show Trail: false + Value: true + pole_top_1_link: + Alpha: 1 + Show Axes: false + Show Trail: false + Value: true + pole_top_2_link: + Alpha: 1 + Show Axes: false + Show Trail: false + Value: true + pole_top_3_link: + Alpha: 1 + Show Axes: false + Show Trail: false + Value: true + wheel_left_link: + Alpha: 1 + Show Axes: false + Show Trail: false + Value: true + wheel_right_link: + Alpha: 1 + Show Axes: false + Show Trail: false + Value: true + Name: RobotModel + Robot Description: robot_description + TF Prefix: "" + Update Interval: 0 + Value: true + Visual Enabled: true + - Alpha: 1 + Autocompute Intensity Bounds: true + Autocompute Value Bounds: + Max Value: 10 + Min Value: -10 + Value: true + Axis: Z + Channel Name: intensity + Class: rviz/PointCloud2 + Color: 255; 255; 255 + Color Transformer: RGB8 + Decay Time: 0 + Enabled: true + Invert Rainbow: false + Max Color: 255; 255; 255 + Max Intensity: 4096 + Min Color: 0; 0; 0 + Min Intensity: 0 + Name: PointCloud2 + Position Transformer: XYZ + Queue Size: 10 + Selectable: true + Size (Pixels): 3 + Size (m): 0.01 + Style: Flat Squares + Topic: /camera/depth/points + Use Fixed Frame: true + Use rainbow: true + Value: true + - Class: rviz/TF + Enabled: true + Frame Timeout: 15 + Frames: + All Enabled: true + base_footprint: + Value: true + base_link: + Value: true + camera_depth_frame: + Value: true + camera_depth_optical_frame: + Value: true + camera_link: + Value: true + camera_rgb_frame: + Value: true + camera_rgb_optical_frame: + Value: true + caster_back_link: + Value: true + caster_front_link: + Value: true + cliff_sensor_front_link: + Value: true + cliff_sensor_left_link: + Value: true + cliff_sensor_right_link: + Value: true + gyro_link: + Value: true + link1: + Value: true + odom: + Value: true + plate_bottom_link: + Value: true + plate_middle_link: + Value: true + plate_top_link: + Value: true + pole_bottom_0_link: + Value: true + pole_bottom_1_link: + Value: true + pole_bottom_2_link: + Value: true + pole_bottom_3_link: + Value: true + pole_bottom_4_link: + Value: true + pole_bottom_5_link: + Value: true + pole_kinect_0_link: + Value: true + pole_kinect_1_link: + Value: true + pole_middle_0_link: + Value: true + pole_middle_1_link: + Value: true + pole_middle_2_link: + Value: true + pole_middle_3_link: + Value: true + pole_top_0_link: + Value: true + pole_top_1_link: + Value: true + pole_top_2_link: + Value: true + pole_top_3_link: + Value: true + wheel_left_link: + Value: true + wheel_right_link: + Value: true + Marker Scale: 1 + Name: TF + Show Arrows: true + Show Axes: true + Show Names: true + Tree: + odom: + base_footprint: + base_link: + camera_rgb_frame: + camera_depth_frame: + camera_depth_optical_frame: + link1: + {} + camera_link: + {} + camera_rgb_optical_frame: + {} + caster_back_link: + {} + caster_front_link: + {} + cliff_sensor_front_link: + {} + cliff_sensor_left_link: + {} + cliff_sensor_right_link: + {} + gyro_link: + {} + plate_bottom_link: + {} + plate_middle_link: + {} + plate_top_link: + {} + pole_bottom_0_link: + {} + pole_bottom_1_link: + {} + pole_bottom_2_link: + {} + pole_bottom_3_link: + {} + pole_bottom_4_link: + {} + pole_bottom_5_link: + {} + pole_kinect_0_link: + {} + pole_kinect_1_link: + {} + pole_middle_0_link: + {} + pole_middle_1_link: + {} + pole_middle_2_link: + {} + pole_middle_3_link: + {} + pole_top_0_link: + {} + pole_top_1_link: + {} + pole_top_2_link: + {} + pole_top_3_link: + {} + wheel_left_link: + {} + wheel_right_link: + {} + Update Interval: 0 + Value: true + Enabled: true + Global Options: + Background Color: 48; 48; 48 + Fixed Frame: odom + Frame Rate: 30 + Name: root + Tools: + - Class: rviz/Interact + Hide Inactive Objects: true + - Class: rviz/MoveCamera + - Class: rviz/Select + - Class: rviz/FocusCamera + - Class: rviz/Measure + - Class: rviz/SetInitialPose + Topic: /initialpose + - Class: rviz/SetGoal + Topic: /move_base_simple/goal + - Class: rviz/PublishPoint + Single click: true + Topic: /clicked_point + Value: true + Views: + Current: + Class: rviz/Orbit + Distance: 2.39289 + Focal Point: + X: 0 + Y: 0 + Z: 0 + Name: Current View + Near Clip Distance: 0.01 + Pitch: 0.940398 + Target Frame: + Value: Orbit (rviz) + Yaw: 0.520398 + Saved: ~ +Window Geometry: + Displays: + collapsed: false + Height: 914 + Hide Left Dock: false + Hide Right Dock: false + QMainWindow State: 000000ff00000000fd00000004000000000000013c00000308fc0200000008fb0000001200530065006c0065006300740069006f006e00000001e10000009b0000006400fffffffb0000001e0054006f006f006c002000500072006f007000650072007400690065007302000001ed000001df00000185000000a3fb000000120056006900650077007300200054006f006f02000001df000002110000018500000122fb000000200054006f006f006c002000500072006f0070006500720074006900650073003203000002880000011d000002210000017afb000000100044006900730070006c006100790073010000002800000308000000dd00fffffffb0000002000730065006c0065006300740069006f006e00200062007500660066006500720200000138000000aa0000023a00000294fb00000014005700690064006500530074006500720065006f02000000e6000000d2000003ee0000030bfb0000000c004b0069006e0065006300740200000186000001060000030c00000261000000010000010f00000308fc0200000003fb0000001e0054006f006f006c002000500072006f00700065007200740069006500730100000041000000780000000000000000fb0000000a00560069006500770073010000002800000308000000b000fffffffb0000001200530065006c0065006300740069006f006e010000025a000000b200000000000000000000000200000490000000a9fc0100000001fb0000000a00560069006500770073030000004e00000080000002e10000019700000003000005f40000003efc0100000002fb0000000800540069006d00650100000000000005f4000002f600fffffffb0000000800540069006d006501000000000000045000000000000000000000039d0000030800000004000000040000000800000008fc0000000100000002000000010000000a0054006f006f006c00730100000000ffffffff0000000000000000 + Selection: + collapsed: false + Time: + collapsed: false + Tool Properties: + collapsed: false + Views: + collapsed: false + Width: 1524 + X: 318 + Y: 77 diff --git a/point_cloud_transformer_test/launch/point_cloud_transformer_test.launch b/point_cloud_transformer_test/launch/point_cloud_transformer_test.launch new file mode 100644 index 0000000..29ebc40 --- /dev/null +++ b/point_cloud_transformer_test/launch/point_cloud_transformer_test.launch @@ -0,0 +1,12 @@ + + + + + + + + + + + diff --git a/point_cloud_transformer_test/package.xml b/point_cloud_transformer_test/package.xml new file mode 100644 index 0000000..e216e9c --- /dev/null +++ b/point_cloud_transformer_test/package.xml @@ -0,0 +1,66 @@ + + + point_cloud_transformer_test + 0.0.2 + Transform a PointCloude2 from frame A to frame B + + + + + gadringer + + + + + + BSD + + + + + + + + + + + + + + + + + + + + + + + + + + + catkin + + pcl_ros + roscpp + rospy + sensor_msgs + tf + + pcl_ros + roscpp + rospy + sensor_msgs + tf + + + + + + + + + + + diff --git a/point_cloud_transformer_test/src/point_cloud_trans.cpp b/point_cloud_transformer_test/src/point_cloud_trans.cpp new file mode 100644 index 0000000..5a6da86 --- /dev/null +++ b/point_cloud_transformer_test/src/point_cloud_trans.cpp @@ -0,0 +1,55 @@ +#include + +//This header allows you to publish and subscribe pcl::PointCloud objects as ROS message +#include +#include +#include + +sensor_msgs::PointCloud2 cloud_transformed, cloud_income; +bool is_cloud_subscribed; +std::string target_frame_name; + +void cmdCallback(const sensor_msgs::PointCloud2::ConstPtr &msg){ + cloud_income = *msg; + is_cloud_subscribed = true; +} + +int main(int argc, char** argv){ + ros::init(argc, argv, "point_cloud_trans"); + if (argc != 2){ROS_ERROR("need target frame name as argument"); return -1;}; + target_frame_name = argv[1]; + + is_cloud_subscribed = false; + ros::NodeHandle n; + ros::Publisher point_cloud_pub = n.advertise("/cloud_transformed", 100); //params: topic, size of the message queue + + // Create a subscriber. + // Name the topic, message queue, callback function with class name, and object containing callback function. + ros::Subscriber point_cloud_sub = n.subscribe("/camera/depth/points", 100, cmdCallback); + tf::TransformListener tf_listener; + + ros::Rate rate(5.0); + while(n.ok()){ + ros::spinOnce(); // for callbacks + if(is_cloud_subscribed){ + try{ + // wait for the transform of the pointcloud (error message "Lookup would require extrapolation into the past" always comes once!) + tf_listener.waitForTransform(target_frame_name, cloud_income.header.frame_id, cloud_income.header.stamp, ros::Duration(0.5)); + + //bool transformPointCloud (const std::string &target_frame, const sensor_msgs::PointCloud2 &in, sensor_msgs::PointCloud2 &out, const tf::TransformListener &tf_listener) + pcl_ros::transformPointCloud (target_frame_name,cloud_income,cloud_transformed,tf_listener); + point_cloud_pub.publish(cloud_transformed); + + } + catch(tf::TransformException e){ + ROS_INFO("Transform_PointCloud: %s", e.what()); + } + } + rate.sleep(); + } +} + + + + +