4.1 launch启动文件
启动文件(Launch File)是ROS中一种同时启动多个节点的途径,它还可以自动启动ROS Master节点管理器,并且可以实现每个节点的各种配置,为多个节点的操作提供很大便利。
4.1.1 基本元素
一个简单而完整的launch文件,采用XML的形式进行描述,包含一个根元素<launch>
和两个节点元素 <node>
:
<launch>
<node pkg="turtlesim" type="turtlesim_node" name="sim1"/>
<node pkg="turtlesim" type="turtlesim_node" name="sim2"/>
</launch>
<launch>
XML文件必须包含一个根元素,launch文件的根元素采用<launch>
标签定义,文件中的其他内容必须包含在这个标签中。<node>
启动文件的核心:是启动ROS节点。采用<node>
标签定义。pkg
:定义节点所在的功能包名称。type
:定义节点的可执行文件名称name
:定义节点运行的名称,将覆盖节点中init()赋予节点的名称output="screen"
:将节点的标准输出打印到终端屏幕,默认输出为日志文档。respawn="true"
:复位属性,该节点停止时,会自动重启,默认为false。required="true"
:必要节点,当该节点终止时,launch文件中的其他节点也别终止。ns="namespace"
:命名空间,为节点内的相对名称添加命名空间前缀。args="arguments"
:节点需要的输入参数。
在实际应用的launch文件中往往会更加复杂,使用的标签也会更多。除了上面介绍的<launch>
和<node>
外,<arg>
、<param>
、<remap>
都是常用的标签元素。
4.1.2 参数设置
launch文件支持参数设置的功能。关于参数设置的标签元素有两个:<param>
代表parameter、<arg>
代表argument。
<param>
:
-
parameter是ROS系统运行中的参数,存储在参数服务器中。在launch文件中通过
<param>
元素加载parameter;在launch文件执行后,parameter就加载到ROS的参数服务器上。每个活跃的节点都可以通过ros::param::get()
接口来获取parameter的值,用户也可以在终端中通过rosparam
命令获取parameter的值。 -
语法:
<param name="output_frame" value="odom" />
运行launch文件后,output_frame这个parameter的值设置为odom,并且加载到ROS参数服务器上了。
但是,在复杂系统中参数很多,一个一个设置会非常麻烦,ROS也提供了另外一种类似的参数(<rosparam>
)加载方式:<rosparam file="$(find 2dnav_pr2)/config/costmap_common_params.yaml" command="load" ns="local_costmap" />
<rosparam>
可以将一个YAML格式文件中的参数全部加载到ROS参数服务器中,需要设置command属性为“load”,还可以选择设置命名空间“ns”。
<arg>
:
-
argument是另外一个概念,类似于launch文件内部的局部变量,仅限于launch文件使用,便于launch文件的重构,与ROS节点内部的实现没有关系。
-
语法:
<arg name="arg-name" default="arg-value" />
launch文件中需要使用argument时,使用如下方式调用:
<param name="foo" value="$(arg arg-name)" /> <node name="node" pkg="package" type="type" args="$(arg arg-name)" />
4.1.3 重映射机制
ROS的设计目的:提高代码的复用率。
面对别人的功能包接口和自己的系统不兼容的问题,ROS提供了一种重映射机制。
简单说就是取别名:不需要修改别人的功能包接口,只需要将接口名称重映射一下,取一个别名,我们的系统就认识了(接口的数据类型必须相同)。
重映射功能的实现:launch文件中的<remap>
标签。
例如:turtlebot的键盘控制节点发布的速度控制指令的话题可能是/turtlebot/cmd_vel
,但是我们自己的机器人订阅的速度控制话题是/cmd_vel
。这时使用<remap>
就可以轻松解决问题,将/turtlebot/cmd_vel重映射为/cmd_vel,我们的机器人就可以接受到速度控制指令了:
<remap from="/turtlebot/cmd_vel" to="/cmd_vel"/>\
注意:重映射机制在ROS中的使用非常广泛,也非常重要,方法不止一种,可以在终端实现重映射(参考03.ROS基础 3.8.3节)。
4.1.4 嵌套复用
在复杂系统中,launch文件很多,这些launch文件之间也会存在依赖关系。
如果直接复用一个已有launch文件中的内容,可以使用<include>
标签包含其他launch文件:
<include file="$(dirname)/other.launch" />
launch是ROS框架中非常实用、灵活的功能,它类似于一种高级编程语言,可以帮助我们管理启动系统时的方方面面。在使用ROS的过程中,很多情况下我们并不需要编写大量代码,仅需要使用已有的功能包,编辑一下launch文件就可以完成很多机器人功能。
注意:更多高级的标签元素可以访问 roslaunchXML 来学习。
4.2 TF坐标变换
机器人本体和机器人的工作环境中往往存在大量的组件元素,在机器人设计和机器人应用中都会涉及不同组件的位置和姿态,这就需要引入坐标系以及坐标系变换的概念。
坐标变换时机器人系统中常用的基础功能,ROS中的坐标变换系统由TF功能包维护。
4.2.1 TF功能包
TF是一个让用户随时间跟踪多个坐标系的功能包,它使用树形数据结构,根据时间缓冲并维护多个坐标系之间的坐标变换关系,可以帮助开发者在任意时间、在坐标系间完成点、向量等坐标的变换。
TF可以在分布式系统中进行操作,也就是说,一个机器人系统中所有的坐标变换关系,对于所有的节点组件都是可用的,所有订阅TF消息的节点都会缓冲一份所有坐标系的变换关系数据,所有这种结构不需要中心服务器来存储任何数据。
使用TF功能包,总体来说需要以下两个步骤:
- 监听TF变换
接收并缓存系统中发布的所有坐标变换数据,并从中查询所需要的坐标变换关系。 - 广播TF变换
向系统中广播坐标系之间的坐标变换关系。系统中可能会存在多个不同部分的TF变换广播,每个广播都可以直接将坐标变换关系插入TF树中,不需要再进行同步。
4.2.2 TF工具
坐标系统虽然是一个基础理论,但是由于涉及多个空间之间的变换,不容易进行想象,所有TF提供了丰富的终端工具来帮助开发者调试和创建TF变换。
-
tf_monitor
功能:打印TF树中所有坐标系的发布状态,也可以输入参数来查看指定坐标系之间的发布状态。roslaunch learning_tf start_demo.launch rosrun tf tf_monitor #可以查看指定坐标系之间的发布状态 rosrun tf tf_monitor <source_frame> <target_frame>
图4-1 使用tf_monitor查看TF树中所有坐标系的发布状态
-
tf_echo
功能:查看指定坐标系之间的变换关系。rosrun tf tf_echo <source_frame> <target_frame>
-
static_transform_publisher
功能:发布两个坐标系之间的静态坐标变换,这两个坐标系不发生相对位置变化。rosrun tf static_transform_publisher x y z yaw pitch roll frame_id child_frame_id period_in_ms rosrun tf static_transform_publisher x y z qx qy qz qw frame_id child_frame_id period_in_ms
以上两种命令格式,需要设置坐标的偏移参数和旋转参数:偏移参数使用相对于x、y、z三轴的坐标位移;而旋转参数的第一种命令格式使用以弧度为单位的yaw/pitch/roll角度(yaw是围绕z轴旋转的偏航角,pitch是围绕y轴旋转的俯仰角,roll是围绕x轴旋转的翻滚角),第二种命令格式使用四元数表达旋转角度。发布频率以ms为单位。
该命令也可在launch文件中使用:<launch> <node pkg="tf" type="static_transform_publisher" name="link1_broadcaster" args="1 0 0 0 0 0 1 link1_parent link1 100" /> </launch>
-
view_frames
view_frames
是可视化的调试工具,可以生成pdf文件,显示整颗TF树的信息。rosrun tf view_frames #使用如下命令,或者使用PDF阅读器查看生成的PDF文件 evince frames.pdf
图4-2 使用view_frames工具生成TF树的信息
图4-3 可视化的TF树信息
除此之外,rviz中还提供TF可视化显示的插件。
4.2.3 乌龟例程中的TF
安装乌龟仿真器中的turtle_tr功能包:
sudo apt-get install ros-melodic-turtle-tf
安装完成后,可以运行如下命令:
roslaunch turtle_tf turtle_tf_demo.launch
乌龟仿真器打开后会出现两只小乌龟,并且下方的小乌龟会自动向中心位置的小乌龟移动。
打开键盘控制节点,控制中心位置的小乌龟运行:
rosrun turtlesim turtle_teleop_key
另外一只小乌龟总会跟随我们控制的那种乌龟运行。
在这个例程中的TF是如何运用的呢?
首先使用TF工具来查看TF树:
rosrun tf view_frames
图4-4 乌龟跟随例程中的TF树
如上图所示:在当前系统中存在三个坐标系:world、turtle1、turtle2。world是世界坐标系,作为系统的基础坐标系,其他坐标系都是相对该坐标系建立的,所以world是TF树的根节点。相对于world坐标系,又分别针对两只乌龟创建了两个乌龟坐标系,这两个坐标系的原点就是乌龟在世界坐标系下的坐标位置。
现在要让turtle2跟随turtle1运动,等价于turtle2坐标系需要向turtle1坐标系移动,这就需要知道turtle1和turtle2之间的坐标变换。三个坐标系之间的变换关系可以使用如下公式描述:
T
t
u
r
t
l
e
1
_
t
u
r
t
l
e
2
=
T
t
u
r
t
l
e
1
_
w
o
r
l
d
×
T
w
o
r
l
d
_
t
u
r
t
l
e
2
T_{turtle1\_turtle2}=T_{turtle1\_world}\times T_{world\_turtle2 }
Tturtle1_turtle2=Tturtle1_world×Tworld_turtle2
使用tf_echo 工具在TF树中查找乌龟坐标系之间的变换关系:
rosrun tf tf_echo turtle1 turtle2
图4-5 乌龟坐标系之间的变换关系
也可以通过rviz的图形界面更加形象地看到这三者之间的坐标关系:
rosrun rviz rviz -d 'rospack find turtle_tf' //rviz/turtle_rviz.rviz
在打开的rviz界面中,将Global Options选项下的Fixed Frame后面的坐标系改成world,然后通过左下角add按键,在By display type下面找到TF并添加。即可显示两只乌龟和世界坐标系之间的坐标关系。
在得到turtle2与turtle1之间的坐标变换后,就可以计算两只乌龟间的距离和角度,即可控制turtle2向turtle1移动了。
接下来,我们以这个例程为目标,学习如何实现TF的广播和监听功能。
4.2.4 创建TF广播器
首先,我们需要创建一个发布乌龟坐标系与世界坐标系之间TF变换的节点,实现源码/ros_primary/learning_tf/src/turtle_tf_broadcaster.cpp
如下:
#include <ros/ros.h>
#include <tf/transform_broadcaster.h>
#include <turtlesim/Pose.h>
std::string turtle_name;
void poseCallback(const turtlesim::PoseConstPtr& msg)
{
// tf广播器
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));
}
int main(int argc, char** argv)
{
// 初始化节点
ros::init(argc, argv, "my_tf_broadcaster");
if (argc != 2)
{
ROS_ERROR("need turtle name as argument");
return -1;
};
turtle_name = argv[1];
// 订阅乌龟的pose信息
ros::NodeHandle node;
ros::Subscriber sub = node.subscribe(turtle_name+"/pose", 10, &poseCallback);
ros::spin();
return 0;
};
以上代码的关键部分是处理乌龟pose消息的回调函数poseCallback,在广播TF消息之前需要定义tf::TransformBroadcaster
广播器,然后根据乌龟当前的位姿设置tf::Transform
类型的坐标变换,包含setOrigin
设置的平移变换以及setRotation
设置的旋转变换。
然后使用广播器将坐标变换插入TF树并进行发布,这里发布的TF消息类型是tf::StampedTransform,不仅包含tf::Transform类型的坐标变换、时间戳、而且需要指定坐标变换的源坐标系(parent)和目标坐标系(child)。
4.2.5 创建TF监听器
TF消息广播之后,其他节点就可以监听该TF消息了,从而获取需要的坐标变换了。目前我们已经将乌龟相对于world坐标系的TF变换进行了广播,接下来需要监听TF消息,并从中获取turtle2相对于turtle1坐标系的变换,从而控制turtle2移动。实现源码/ros_primary/learning_tf/src/turtle_tf_listener.cpp
的详细内容如下:
#include <ros/ros.h>
#include <tf/transform_listener.h>
#include <geometry_msgs/Twist.h>
#include <turtlesim/Spawn.h>
int main(int argc, char** argv)
{
// 初始化节点
ros::init(argc, argv, "my_tf_listener");
ros::NodeHandle node;
// 通过服务调用,产生第二只乌龟turtle2
ros::service::waitForService("spawn");
ros::ServiceClient add_turtle =
node.serviceClient<turtlesim::Spawn>("spawn");
turtlesim::Spawn srv;
add_turtle.call(srv);
// 定义turtle2的速度控制发布器
ros::Publisher turtle_vel =
node.advertise<geometry_msgs::Twist>("turtle2/cmd_vel", 10);
// tf监听器
tf::TransformListener listener;
ros::Rate rate(10.0);
while (node.ok())
{
tf::StampedTransform transform;
try
{
// 查找turtle2与turtle1的坐标变换
listener.waitForTransform("/turtle2", "/turtle1", ros::Time(0), ros::Duration(3.0));
listener.lookupTransform("/turtle2", "/turtle1", ros::Time(0), transform);
}
catch (tf::TransformException &ex)
{
ROS_ERROR("%s",ex.what());
ros::Duration(1.0).sleep();
continue;
}
// 根据turtle1和turtle2之间的坐标变换,计算turtle2需要运动的线速度和角速度
// 并发布速度控制指令,使turtle2向turtle1移动
geometry_msgs::Twist vel_msg;
vel_msg.angular.z = 4.0 * atan2(transform.getOrigin().y(),
transform.getOrigin().x());
vel_msg.linear.x = 0.5 * sqrt(pow(transform.getOrigin().x(), 2) +
pow(transform.getOrigin().y(), 2));
turtle_vel.publish(vel_msg);
rate.sleep();
}
return 0;
};
该节点首先通过服务调用产生乌龟turtle2,然后声明控制turtle2速度的Publisher。在监听TF消息之前,需要创建一个tf::TransformListener
类型的监听器,创建成功后监听器会自动接受TF树的消息,并且缓存10秒。然后在循环中就可以实时查找TF树中的坐标变化了。这里需要调用的是tf::TransformListener
中的两个接口:
waitForTransform(const std::string &target_frame, const std::string &source_frame, const ros::Time &time, const ros::Duration &timeout)
:给定源坐标系(source_frame)和目的坐标系(target_frame),等待两个坐标系之间指定时间(time)的变换关系,该函数会阻塞程序运行,所以要设置超时时间(timeout);lookupTransform(const std::string & target_frame, const std::string & source_frame, const ros::Time & time, StampedTransform & transform)
:给定源坐标系(source_frame)和目标坐标系(target_frame),得到两个坐标系之间指定时间(time)的坐标变换(transform),ros::Time(0)
表示我们想要的是最新一次的坐标变换。
通过以上两个接口的调用,就可以获得turtle2相对于turtle1的坐标变换了。然后根据坐标系之间的位置关系,计算得到turtle2需要运动的线速度和角速度,并发布速度控制指令使turtle2向turtle1移动。
4.2.6 实现乌龟跟随运动
以上小乌龟跟随例程的所有代码已经完成,下面来编写一个launch文件,使所有节点运行起来,实现源码learning_tf/launch/start_demo_with_listener.launch的详细内容如下:
<launch>
<!--海龟仿真器-->
<node pkg="turtlesim" type="turtlesim_node" name="sim" />
<!--键盘控制-->
<node pkg="turtlesim" type="turtle_teleop_key" name="teleop" output="screen" />
<!--两只海龟的TF广播-->
<node pkg="learning_tf" type="turtle_tf_broadcaster" args="/turtle1" name="turtle1_tf_broadcaster" />
<node pkg="learning_tf" type="turtle_tf_broadcaster" args="/turtle2" name="turtle2_tf_broadcaster" />
<!--监听TF广播,并且控制turtle2移动-->
<node pkg="learning_tf" type="turtle_tf_listener" name="listener" />
</launch>
然后运行该launch文件,就可以看到与之前例程类似的两只乌龟的界面了,在终端中通过键盘控制turtle1移动,turtle2也跟随移动。
通过这个例程的实现,学习了TF广播与监听的实现方法,在实际应用中会产生更多的坐标系,TF树的结构也会更加复杂,但是基本的使用方法依然相同。
4.3 QT工具箱
为了方便可视化调试和显示,ROS提供了一个Qt架构的后台图形工具套件——rqt_common_plugins
,其中包含不少实用工具。
安装Qt工具箱:
sudo apt-get install ros-melodic-rqt
sudo apt-get install ros-melodic-rqt-common-plugins
4.3.1 日志输出工具(rqt_console)
rqt_console工具用来图形化显示和过滤ROS系统运行状态中的所有日志消息,包括info、warn、error等级别的日志。使用如下命令启动该工具:
rqt_console
图4-6 rqt_console工具界面
当系统中有不同级别的日志消息时,rqt_console的界面就会依次显示这些日志的相关内容,包括日志内容、时间戳、级别等。当日志较多时,也可以使用该工具进行过滤显示。
4.3.2 计算图可视化工具(rqt_graph)
rqt_graph工具可以图形化显示当前ROS系统中的计算图。在系统运行时,使用如下命令启动该工具:
rqt_graph
图4-7 rqt_graph 工具界面
4.3.3 数据绘图工具(rqt_plot)
rqt_plot是一个二维数值曲线绘制工具,可以将需要显示的数据在xy坐标系中使用曲线描绘。使用如下命令启动该工具:
rqt_plot
然后在界面上方的Topic输入框中输入需要显示的话题消息,如果不确定话题名称,可以在终端中使用“rostopic lsit
”命令查看。
图4-8 rqt_plot工具
4.3.4 参数动态配置工具(rqt_reconfigure)
rqt_reconfigure工具可以在不重启系统的情况下,动态配置ROS系统中的参数,但是该功能的使用需要在代码中设置参数的相关属性,从而支持动态配置。使用如下命令启动该工具:
rosrun rqt_reconfigure rqt_reconfigure
图4-9 rqt_reconfigure工具界面
启动后的界面将显示当前系统中所有可动态配置的参数。在界面中使用输入框、滑动条或下拉框进行设置即可实现参数的动态配置。关于ROS参数动态配置功能的实现,将在后续进行具体讲解。
4.4 rviz三维可视化平台
机器人系统中存在大量数据,比如图像数据中0~255的RGB值。但是这种数据形态的值往往不利于开发者感受数据所描述的内容,所有常常需要将数据可视化显示,例如机器人模型的可视化、图像数据的可视化、地图数据的可视化等。
ROS针对机器人系统的可视化需求,为用户提供了一款显示多种数据的三维可视化平台——rviz。
rviz是一款三维可视化工具,很好地兼容了各种基于ROS软件框架的机器人平台。在rviz中,可以使用XML对机器人、周围物体等任何实物进行尺寸、质量、位置、材质、关节等属性的描述,并且在界面中呈现出来。同时,rviz还可以通过图形化方式,实时显示机器人传感器的信息、机器人的运动状态、周围环境的变化等。总而言之,rviz可以帮助开发者实现所有可监测信息的图形化显示,开发者也可以在rviz的控制界面下,通过按钮、滑动条、数值等方式控制机器人的行为。
4.4.1 安装并运行rviz
rviz已经集成到桌面完整版的ROS中,如果已经成功安装桌面完整版的ROS,可以直接跳过这一步。否则,使用如下命令安装:
sudo apt-get install ros-melodic-rviz
安装完成后,分别在终端运行如下命令,启动ROS和rviz平台:
roscore
rosrun rviz rviz
启动rviz主界面:
图4-10 rviz的主界面
rviz主界面主要包含以下几个部分:
- 0:3D视图区,用于可视化显示数据,目前没有任何数据,所以显示黑色。
- 1:工具栏,用于提供视角控制、目标设置、发布地点等工具。
- 2:显示项列表,用于显示当前选择的显示插件,可以配置每个插件的属性
- 3:视角设置区,用于选择多种观察视角
- 4:时间显示区,用于显示当前的系统时间和ROS时间。
4.4.2 数据可视化
假设需要可视化的数据以对应的消息类型发布,我们在rviz中使用相应的插件订阅该消息即可实现显示。
- 添加需要显示数据的插件。
点击rviz界面左侧下方的“Add”按钮,rviz会将默认支持的所有数据类型的显示插件罗列出来。
图4-11 rviz默认支持的显示插件
在上图所示的列表中选择需要的数据类型插件,然后在“Display Name”文本框中填入一个唯一的名称,用来识别显示的数据。
2. 添加完成后,rviz左侧的Displays中会列出已经添加的显示插件
点击插件列表前的加号,可以打开一个属性列表,根据需求设置属性。一般情况下,“Topic”属性较为重要,用来声明该显示插件所订阅的数据来源。如果订阅成功,在中间的显示区应该会出现可视化后的数据。
图4-12 点云数据的详情
- 如果显示有问题,请检查属性区域的“Status”状态。Status有四种状态:OK、Warning、Error和Disabled,如果显示的状态不是OK,那么请查看错误信息,并仔细检查数据发布是否正常。
图4-13 显示插件的Status信息
4.4.3 插件扩展机制
rviz是一个三维可视化平台,默认可以显示如表4-1所示的通用类型数据,其中包含坐标轴、摄像头图像、地图、激光等数据。
rviz默认支持显示的数据类型详见《ROS机器人开发实际》4.4.3节。
并且作为一个平台,rviz支持插件扩展机制,为默认显示的数据提供相应的插件。如果需要添加其他数据的显示,也可以通过编写插件的形式进行添加。我们甚至可以基于rviz打造一款自己的人机交互软件。
4.5 Gazebo仿真环境
Gazebo是一个功能强大的三维物理仿真平台,具备强大的物理引擎、高质量的图形渲染、方便的编程与图形接口,最重要的还有其具备开源免费的特性。虽然Gazebo中的机器人模型与rviz使用的模型相同,但是需要在模型中加入机器人和周围环境的物理属性,例如质量、摩擦系数、弹性系数等。机器人的传感器信息也可以通过插件的形式加入仿真环境、以可视化的方式显示。
4.5.1 Gazebo的特点
Gazebo是一个优秀的开源物理仿真环境,它具备如下特点:
- 动力学仿真:支持多种高性能的物理引擎,如ODE、Bullet、SimBody、DART等。
- 三维可视化环境:支持显示逼真的三维环境,包括光线、纹理、影子。
- 传感器仿真:支持传感器数据的仿真,同时可以仿真传感器噪声。
- 可扩展插件:用户可以定制化开发插件以扩展Gazebo的功能,满足个性化的需求。
- 多种机器人模型:官方提供PR2、Pioneer2 DX、TurtleBot等机器人模型,当然也可以使用自己创建的机器人模型。
- TCP/IP传输:Gazebo的后台仿真处理和前台图形显示可以通过网络通信实现远程仿真。
- 云仿真:Gazebo仿真可以在Amazon、Softlayer等云端运行,也可以在自己搭建的云服务器上运行。
- 终端工具:用户可以使用Gazebo提供的命令行工具在终端实现仿真控制。
Gazebo的社区维护非常积极,版本变化较大,但是在兼容性方面依然保证得较好。
4.5.2 安装并运行Gazebo
与rviz一样,如果已经安装了桌面完整版的ROS,可以直接跳过这一步。否则,使用如下命令安装:
sudo apt-get install ros-melodic-gazebo-ros-pkgs ros-melodic-gazebo-ros-control
安装完成后,在终端使用如下命令启动ROS和Gazebo:
roscore
rosrun gazebo_ros gazebo
主界面主要包含以下几个部分:
- 3D视图区
- 工具栏
- 模型列表
- 模型属性项
- 时间显示区
验证Gazebo是否与ROS系统连接成功,可以查看ROS的话题列表:
rostopic list
如果连接成功,应该可以看到Gazebo发布/订阅的话题列表。
当然,还有Gazebo提供的服务列表:
rosservice list
4.5.3 构建仿真环境
在仿真之前需要构建一个仿真环境。Gazebo中有两种创建仿真环境的方法。
-
直接插入模型
在Gazebo左侧的模型列表中,有一个insert选项罗列了所有可使用的模型。选择需要使用的模型,放置在主显示区中,就可以在仿真环境中添加机器人和外部物体等仿真实例。
备注:模型的加载需要连接国外网站,为了保证模型顺利加载,可以提前将模型文件下载并放置到本地路径“~/.gazebo/models
”下,模型文件的下载地址为“https://bitbucket.org/osrf/gazebo_models/downloads/
”。 -
Building Editor
第二种方法是使用Gazebo提供的Building Editor工具手动绘制地图。在Gazebo菜单栏中选择Edit——>Building Editor,选择左侧的绘制选项,然后在上侧窗口中使用鼠标绘制,下侧窗口中即可实时显示绘制的仿真环境。
模型创建完成后就可以加载机器人模型并进行仿真了。后续会详细学习机器人仿真的过程,这里先对Gazebo有一个整体的认识即可。
4.6 rosbag数据记录和回放
为了方便调试测试,ROS提供了数据记录与回放的功能包——rosbag,可以帮助开发者收集ROS系统运行时的消息数据,然后在离线状态下回放。
本节通过乌龟例程介绍rosbag数据记录和回放的实现方法。
4.6.1 记录数据
首先启动键盘控制乌龟例程所需的所有节点:
roscore
rosrun turtlesim turtlesim_node
rosrun turtlesim turtle_teleop_key
启动成功后,可以看到界面中的小乌龟,此时可以在终端中通过键盘控制乌龟移动。
查看当前ROS系统中的话题:
rostopic list -v
接下来使用rosbag抓取这些话题的消息,并且打包成一个文件放置到指定文件夹中:
mkdir ~/bagfiles
cd ~/bagfiles
rosbag record -a
rosbag record就是数据记录的命令,-a(all)参数意为记录所有发表的消息。现在,消息记录已经开始,我们可以在终端中控制小乌龟移动一段时间,然后在数据记录运行的终端中按下“Ctrl+C”,即可终止数据记录。新生成的数据记录文件保存在新建的~/bagfiles
文件夹中。
4.6.2 回放数据
数据记录完成后,可以使用该数据记录文件进行数据回放。rosbag功能包提供了info命令,可以查看数据记录文件的详细信息,命令的使用格式如下:
rosbag info <your bagfile>
使用该info
命令来查看之前生成的数据记录文件。
从以上信息中可以看到,数据记录包中包含的所有话题、消息类型、消息数量等信息。终止之前打开的turtle_teleop_key控制节点并重启turtlesim_node,使用如下命令回放所记录的话题数据:
rosbag play <your bagfile>
在短暂的等待时间后,数据开始回放,小乌龟的运动规矩应该与之前数据记录的状态完全相同。
4.7 本章小结
提问如下:
- 如果我们希望一次性启动并配置多个ROS节点,应该使用什么方法?
- ROS中的TF是如何管理系统中繁杂的坐标系的,我们又该如果使用TF广播、监听系统中的坐标变化的?
- Qt工具箱为我们提供了哪些可视化工具?
- rviz是什么,它又可以实现哪些功能?
- 如果我们没有真实机器人,那么有没有办法在ROS中通过仿真的方式来学习ROS开发呢?需要用到什么工具?
- 机器人往往涉及重复性调试工作,我们有没有办法使用ROS记录调试过程中的数据,并进行离线分析呢?