在坐标变换的时候常有这样的写法:
tfTutorialsAdding a frame (C++)
transform.setOrigin( tf::Vector3(0.0, 2.0, 0.0) );
transform.setRotation( tf::Quaternion(0, 0, 0, 1) );
br.sendTransform(tf::StampedTransform(transform,ros::Time::now(), "turtle1", "carrot1"));
这三句话分别做了以下工作:
1、设置carrot1在turtle1坐标系下的坐标原点
2、设置carrot1相对于turtle1的旋转角度,这里用四元数表示
3、发送变换信息
上面四元数表示旋转角度的方式不太直观,我们写代码的时候不想将旋转变换换算成四元数的时候可以采用如下方法写这个变换:
turtle_tf_ broadcaster.cpp
static tf::TransformBroadcaster br;
tf::Transform transform;
transform.setOrigin( tf::Vector3(msg->x, msg->y, 0.0) );
tf::Quaternion q;
q.setRPY(0, 0, msg->theta);
transform.setRotation(q);
br.sendTransform(tf::StampedTransform(transform, ros::Time::now(), "world", turtle_name));
这样通过这三句话就可以直接用RPY(分别对应绕XYZ轴旋转角度)来设置旋转变换了
tf::Quaternion q;
q.setRPY(0, 0, msg->theta);
transform.setRotation(q);
这里的msg->x, msg->y,msg->theta是解引用msg并获取该元素名为x(或者y,theta)的成员,相当于(*msg).x,(*msg).y,(*msg).theta
四元数的直观意义:
四元数 (x,y,z,w) 表示绕轴 (x0,y0,z0) 旋转 α 角度,他们之间的关系是: w=cos(α2) , x=x0⋅sin(α2) , y=y0⋅sin(α2) , z=z0⋅sin(α2)
在使用的时候往往将四元数归一化,即要求四元数的模为1:
x2+y2+z2+w2=1
[ERROR] [1397783547.530858724]: "turtle2" passed to lookupTransform argument target_frame does not exist.
根据教程写完turtle_tf_listener.cpp之后,用catkin_make命令编译,再在start_demo.launch文件里面添加这句
"learning_tf" type="turtle_tf_listener"
name="listener" />
接下来运行
$ roslaunch learning_tf start_demo.launch
程序出现两只乌龟,且一切正常,turtle2可以跟随turtle1,但是出现报错
[ERROR] [1397783547.530858724]: "turtle2" passed to lookupTransform argument target_frame does not exist.
可以按照如下代码修改turtle_tf_listener.cpp
tf::StampedTransform transform;
try{
listener.waitForTransform("/turtle2", "/turtle1", ros::Time(0), ros::Duration(3.0));
listener.lookupTransform("/turtle2", "/turtle1",ros::Time(0), transform);
}
就是在原本listener.lookupTransform函数的前面再加一行listener.waitForTransform(“/turtle2”, “/turtle1”, ros::Time(0), ros::Duration(3.0));报错就会消失。我在indigo下面运行到这里就正常了,没有接下来的问题。
注:如果按键只能控制一只乌龟,另外一只还在不停的从一边移动到另外一边,再将turtle_tf_broadcaster.cpp中的 “q.setRPY(msg->theta, 0, 0)” 改为 “q.setRPY(0, 0, msg->theta)”此时则没有错误了,按键能控制一只乌龟移动,另外一只会跟着这只乌龟的轨迹移动