출처 : http://wiki.ros.org/navigation/Tutorials/RobotSetup/TF
$ cd %TOP_DIR_YOUR_CATKIN_WS%/src
$ catkin_create_pkg robot_setup_tf roscpp tf geometry_msgs
1 #include <ros/ros.h>
2 #include <tf/transform_broadcaster.h>
3
4 int main(int argc, char** argv){
5 ros::init(argc, argv, "robot_tf_publisher");
6 ros::NodeHandle n;
7
8 ros::Rate r(100);
9
10 tf::TransformBroadcaster broadcaster;
11
12 while(n.ok()){
13 broadcaster.sendTransform(
14 tf::StampedTransform(
15 tf::Transform(tf::Quaternion(0, 0, 0, 1), tf::Vector3(0.1, 0.0, 0.2)),
16 ros::Time::now(),"base_link", "base_laser"));
17 r.sleep();
18 }
19 }
#include <tf/transform_broadcaster.h>
tf::TransformBroadcaster broadcaster;
13 broadcaster.sendTransform(
14 tf::StampedTransform(
15 tf::Transform(tf::Quaternion(0, 0, 0, 1), tf::Vector3(0.1, 0.0, 0.2)),
16 ros::Time::now(),"base_link", "base_laser"));
#include <ros/ros.h>
2 #include <geometry_msgs/PointStamped.h>
3 #include <tf/transform_listener.h>
4
5 void transformPoint(const tf::TransformListener& listener){
6 //we'll create a point in the base_laser frame that we'd like to transform to the base_link frame
7 geometry_msgs::PointStamped laser_point;
8 laser_point.header.frame_id = "base_laser";
9
10 //we'll just use the most recent transform available for our simple example
11 laser_point.header.stamp = ros::Time();
12
13 //just an arbitrary point in space
14 laser_point.point.x = 1.0;
15 laser_point.point.y = 0.2;
16 laser_point.point.z = 0.0;
17
18 try{
19 geometry_msgs::PointStamped base_point;
20 listener.transformPoint("base_link", laser_point, base_point);
21
22 ROS_INFO("base_laser: (%.2f, %.2f. %.2f) -----> base_link: (%.2f, %.2f, %.2f) at time %.2f",
23 laser_point.point.x, laser_point.point.y, laser_point.point.z,
24 base_point.point.x, base_point.point.y, base_point.point.z, base_point.header.stamp.toSec());
25 }
26 catch(tf::TransformException& ex){
27 ROS_ERROR("Received an exception trying to transform a point from \"base_laser\" to \"base_link\": %s", ex.what());
28 }
29 }
30
31 int main(int argc, char** argv){
32 ros::init(argc, argv, "robot_tf_listener");
33 ros::NodeHandle n;
34
35 tf::TransformListener listener(ros::Duration(10));
36
37 //we'll transform a point once every second
38 ros::Timer timer = n.createTimer(ros::Duration(1.0), boost::bind(&transformPoint, boost::ref(listener)));
39
40 ros::spin();
41
42 }
#include <tf/transform_listener.h>
void transformPoint(const tf::TransformListener& listener){
6 //we'll create a point in the base_laser frame that we'd like to transform to the base_link frame
7 geometry_msgs::PointStamped laser_point;
8 laser_point.header.frame_id = "base_laser";
9
10 //we'll just use the most recent transform available for our simple example
11 laser_point.header.stamp = ros::Time();
12
13 //just an arbitrary point in space
14 laser_point.point.x = 1.0;
15 laser_point.point.y = 0.2;
16 laser_point.point.z = 0.0;
이 부분에서는 point를 geometry_msgs::PointStamped로 생성하였는데, 여기서 "Stamped"는 timestamp와 frame_id를 메세지에 연계시킬수있게 해주는 헤더를 이 객체가 include하고 있음을 의미한다.
이후 laser_point 메세지의 stamp field를 ros::Time()으로 설정한다. 이를 통해 TransformListener으로 부터 가장 최신의 transform을 얻을 수 있게 된다.
헤더의 frame_id field의 경우 현재 생성중인 point가 "base_laser" frame에 위치하므로 "base_laser"로 설정한다.
마지막으로 point에 값을 입력해 준다.
18 try{
19 geometry_msgs::PointStamped base_point;
20 listener.transformPoint("base_link", laser_point, base_point);
21
22 ROS_INFO("base_laser: (%.2f, %.2f. %.2f) -----> base_link: (%.2f, %.2f, %.2f) at time %.2f",
23 laser_point.point.x, laser_point.point.y, laser_point.point.z,
24 base_point.point.x, base_point.point.y, base_point.point.z, base_point.header.stamp.toSec());
25 }
"base_laser" frame에 point를 설정하였으므로, 이제 그것을 "base_link" frame으로 변환하자.
이를 수행하기 위해 TransformListenr 객체를 이용하여 transformPoint()를 호출하자.
transformPoint()는 세개의 arguments를 가진다.
-> 기존의 point를 변환시킬 목적지 frame(예제의 경우 "base_link")
-> 변환할 point
-> 변환된 point를 보관할 공간
transformPoint()를 호출하면, base_point는 laser_point가 가지고 있던 정보와 동일한 정보를 가지게 된다. 여기서 차이점은 base_point는 "base_laser" frame이 아닌 "base_link" frame에 존재한다는 것이다.
26 catch(tf::TransformException& ex){
27 ROS_ERROR("Received an exception trying to transform a point from \"base_laser\" to \"base_link\": %s", ex.what());
28 }
만약 transform이 정상적으로 수행되지 않으면 TransformListener가 exception을 throw하고, 오류메세지가 출력되도록 한다.
add_executable(tf_broadcaster src/tf_broadcaster.cpp)
add_executable(tf_listener src/tf_listener.cpp)
target_link_libraries(tf_broadcaster ${catkin_LIBRARIES})
target_link_libraries(tf_listener ${catkin_LIBRARIES})
$ cd %TOP_DIR_YOUR_CATKIN_WS%
$ catkin_make
roscore
rosrun robot_setup_tf tf_broadcaster
rosrun robot_setup_tf tf_listener
[ INFO] 1248138528.200823000: base_laser: (1.00, 0.20. 0.00) -----> base_link: (1.10, 0.20, 0.20) at time 1248138528.19
[ INFO] 1248138529.200820000: base_laser: (1.00, 0.20. 0.00) -----> base_link: (1.10, 0.20, 0.20) at time 1248138529.19
[ INFO] 1248138530.200821000: base_laser: (1.00, 0.20. 0.00) -----> base_link: (1.10, 0.20, 0.20) at time 1248138530.19
[ INFO] 1248138531.200835000: base_laser: (1.00, 0.20. 0.00) -----> base_link: (1.10, 0.20, 0.20) at time 1248138531.19
[ INFO] 1248138532.200849000: base_laser: (1.00, 0.20. 0.00) -----> base_link: (1.10, 0.20, 0.20) at time 1248138532.19