在学习ROS2时,本来满怀欢喜的,不想刚刚开始就受到了打击。真的想摔键盘骂娘,这是什么破玩意儿,这么个半成品也好意思拿出来正式发布,连个像样的文档也没有。在ROS1中要显示机械臂的模型是一件非常简单的事情,但在ROS2中却感觉无从下手,在google中竟然没有一篇文章介绍怎么来操作。本着不放弃的精神,还是好好研究一下其中的原委吧。
在ROS2中提供了一个dummy_robot_bringup的包,里面提供了launch.py和urdf文件。注意ROS2中将launch文件有原来的xml格式文件改成了由python脚本文件完成,这是为了让节点具有状态,从而可以根据不同的条件进行启动和运行。而urdf文件则可以直接于ROS1兼容,所以直接拿过来就可以了。
所以将原来《ROS中URDF格式及使用》中使用的myrobot.xacro拿过来用。oops~~,ROS2中没用xacro程序将xacro格式转换为urdf,只要用ROS1中的先转换了。
将dummy_robot_bringup包中的launch.py文件拷过来,进行修改后的内容如下:
import os
from ament_index_python.packages import get_package_share_directory
from launch import LaunchDescription
from launch_ros.actions import Node
def generate_launch_description():
urdf = os.path.join(get_package_share_directory('myrobot_description'), 'launch', 'myrobot.urdf')
return LaunchDescription([
Node(package='robot_state_publisher', node_executable='robot_state_publisher', output='screen', arguments=[urdf] )
])
其中删除了原来有的"dummy_map_server","dummy_joint_states"和"dummy_laser"节点。毕竟只是为了显示而已。然后,运行如下:
# Terminal 1:
ros2 launch myrobot_description display.py
# Terminal 2:
rviz2
这样就启动了rviz2,rviz2与rviz不同的是,其机器人描述的来源为topic和file两种。topic不知道怎么用,dummy_robot没有用。file则表示从文件读取之,需要手动设置,或者从.rviz配置文件自动载入。这里使用手动的方式指定之,以为就能正确显示了,但是在RobotModel下面,对于link_1和link_2却出现"No transform from [link_1]/[link_2] to [base_link]"的错误,因此显示的模型也是错误的。也不知道是为什么。
怀着疑问,将dummy_robot_bringup包中的single_rrbot.urdf文件拷贝过来,也是同样的问题。然后就在display.py中加入了:
Node(package='dummy_sensors', node_executable='dummy_joint_states', output='screen')
single_rrobot.urdf变得正常显示了,但myrobot.urdf并不能。同时我们还将single_rrbot.urdf进行了最简化,删除了其中所有的、以及部分,并只保留到single_rrbot_link3及之前的连杆和关节。这样也能正常显示并运动(dummy_joint_states会发送运动数据)。
这就说明dummy_joint_states可以上single_rrobot正确配置起来,但对myrobot无效,因为其中的关节名称不一样(将single_rrobot中的关节改掉就不行了)。
那么现在就要研究下到底dummy_joint_states节点程序做了什么。在dummy_joint_states中其实很简单,它创建dummy_joint_states节点,并且每50毫秒在joint_states主题上发布JointState类型的消息来告知rviz2关节的位置。
因此,我们将ROS2源代码中的dummy_sensor包拷贝到我们的工作空间中,将其名称改为myrobot_sensor,并修改其中的dummy_joint_states.cpp,让其发布myrobot的关节的位置消息(只需要将其中的关节名称进行替换即可)。 果然,原本无法正常显示的myrobot也正常显示并运动了起来。
那么,我们是不是可以在dummy_joint_states节点中只发送一个初始关节位置然后退出。试了一下不行,要一直保持关节状态消息的发送(起码保持一段时间)。 转念一想,这不就是ROS1中joint_state_publisher所起的作用么。joint_state_publisher会一直读取某个来源的关节信息,然后将其转发到**/joint_states**主题上。 只是在ROS2中没有实现这个joint_state_publisher罢了。