CMakelist.txt的find_package中增加urdf依赖。
package.xml中增加urdf依赖:
urdf
urdf
一般的urdf文件test.urdf起来像是这样:
以下逐行解释上面的urdf的语法结构和关键字:
在ROS官方有更详细的joint、link和properties的关键字解释。
(上面带注释的代码可能会在执行时报错,使用无注释的部分即可。)
check_urdf test.urdf
检查urdf文件是否正确。
urdf_to_graphiz test.urdf
生成这个urdf文件的pdf图像。
使用urdf语法解析器检查urdf、xml文件是否可以可以正常载入(可忽略,Parse a urdf file)。
这个launch仅为示例,告诉joint_states、robot_description这两个接口话题如何更改名字使用。
robot_description目前未见到由话题发布urdf的例子,但它有同名的参数接口使用:
joint_states话题的消息为sensor_msgs/JointState.msg,内容:
std_msgs/Header header
uint32 seq
time stamp
string frame_id
string[] name
float64[] position
float64[] velocity
float64[] effort
在消息中name用来指定robot_state_publisher要操作test.urdf载入文件中的joint。
在消息中position用来为name所指定的joint设置运动参数值,其余的为关节中与之对应的速度和力量。
可以在上面launch的节点state_publisher_node中来发布joint_states话题。
state_publisher_node看起来像这样:
#include
#include
#include
int main(int argc, char** argv)
{
ros::init(argc, argv, "state_publisher_node");
ros::NodeHandle n;
ros::Publisher joint_pub = n.advertise("joint_states", 1);
ros::Rate loop_rate(30);
double connect_value = 0;
bool jump = 0;
sensor_msgs::JointState joint_state_msg;
while (ros::ok())
{
joint_state_msg.header.stamp = ros::Time::now();
joint_state_msg.name.resize(1);
joint_state_msg.position.resize(1);
joint_state_msg.name[0] ="connect";
joint_state_msg.position[0] = connect_value;
joint_pub.publish(joint_state_msg);
if (connect_value >= -0.01 && jump == 1)
{
connect_value += 0.01;
if (connect_value >= 1)
jump = 0;
}
if (connect_value <= 1.01 && jump == 0)
{
connect_value -= 0.01;
if (connect_value <= 0)
jump = 1;
}
loop_rate.sleep();
}
return 0;
}
使用launch启动这个节点:
可以看到蓝色的杆延x轴前后移动,但程序中的移动范围不受urdf文件中limit的约束:
接下来,在程序中加入TF变换使整个系统移动起来,依靠joint的连接使所有的link处于同一个相对坐标系:
#include
#include
#include
int main(int argc, char** argv)
{
ros::init(argc, argv, "state_publisher_node");
ros::NodeHandle n;
ros::Publisher joint_pub = n.advertise("joint_states", 1);
tf::TransformBroadcaster broadcaster;
ros::Rate loop_rate(30);
const double degree = M_PI/180;
double connect_value = 0, angle=0;
bool jump = 0;
geometry_msgs::TransformStamped odom_trans;
sensor_msgs::JointState joint_state_msg;
odom_trans.header.frame_id = "odom";
odom_trans.child_frame_id = "base_link";
while (ros::ok())
{
joint_state_msg.header.stamp = ros::Time::now();
joint_state_msg.name.resize(1);
joint_state_msg.position.resize(1);
joint_state_msg.name[0] ="connect";
joint_state_msg.position[0] = connect_value;
odom_trans.header.stamp = ros::Time::now();
odom_trans.transform.translation.x = cos(angle)*2;
odom_trans.transform.translation.y = sin(angle)*2;
odom_trans.transform.translation.z = 0.7;
odom_trans.transform.rotation = tf::createQuaternionMsgFromYaw(angle+M_PI/2);
joint_pub.publish(joint_state_msg);
broadcaster.sendTransform(odom_trans);
if (connect_value >= -0.01 && jump == 1)
{
connect_value += 0.01;
if (connect_value >= 1)
jump = 0;
}
if (connect_value <= 1.01 && jump == 0)
{
connect_value -= 0.01;
if (connect_value <= 0)
jump = 1;
}
angle += degree/4;
loop_rate.sleep();
}
return 0;
}
继续使用上一个launch启动,在rviz中将odom设为Fixed Frame,可以看到两个杆围绕着odom转的很魔性:
如果不使用joint,就需要两个TF变换才是使两个杆相对运动,这里不再浪费篇幅。
joint_state_publisher的GUI会加载所有非fixed类型的joint控制link移动,修改test_urdf.launch为:
启动它后,可使用joint_state_publisher的GUI:
因为只有一个joint所以只有一个可用滑块,滑动它观察rviz中两个杆的相对位置。(urdf中limit参数会用来约束这里滑块上下限值。)
使用以xacro为后缀的文件,而不再是urdf后缀。ROS官方网站对Using Xacro to Clean Up a URDF File和Xacro tutorials已经讲述的很明晰,不再敖述,此处只做归纳。
1、在xacro中,前两行必须是:
2、初始化变量的关键字为property:
在其他位置可以以"${width}"、"${width+2}"的方式调用,也可使用立即数"${5/6}",字符串类型可以"${width}_abc"叠加等。
可以使用YAML文件来初始化变量:
3、宏的关键字为macro:
①name用来指定宏名,供之后调用。
②params用来声明这个宏内的多个变量。
不带“*”的为普通变量。
一颗“*”的变量为一个insert_block,在urdf中相当于一行,例如这种:
两颗“*”的变量也为一个insert_block,但它相当于urdf中的一层,例如这种:
③在宏声明好之后,在下面继续写macro所包含的内容,insert_block的使用形式如下:
这个macro中包含了一个joint和一个link,使用这个macro:
0.1
“suffix”在第一行初始化,“*origin”会在第二行定义出pose,“**content”在3~6行定义出container。(按变量定义的顺序初始化)
使用了这个宏后,相当于写了一个:
0.1
4、预处理关键字为include:
用来载入其他xacro文件,为载入的文件增加名称空间:
使用“${namespace.property}”的方式来调用不同名称空间的参数。
5、向robot_state_publisher的robot_description接口载入xacro文件:
6、那两根魔性的杆test.urdf文件写成xacro文件如下:
将每个link和joint都写成了macro,然后再分别定义,其实较短的urdf不宜写成xacro,反倒复杂了,以上只是做练习不考虑实用。
用launch启动: