roslaunch工具十分方便,可以通过SSH远程启动节点以及本机的节点。roslaunch工具使用一个XML格式的文件,后缀名为.launch,可以指定节点的从参数和节点运行的机器。
在实现该功能之前需要实现多机之间的通信设置,首先是修改各机器的hosts文件(位于/etc/hosts),增加如下两行
192.168.1.30 tegra-ubuntu
192.168.1.31 bobin-ThinkPad-T450
...
注意需要把相互之间的通信的所有机器指定到每一个机器的hosts中,不过内容都是一样的。经过实验证明,只有这种方式是最简单的,一定要修改hosts,而不是显式赋值ROS_MASTER_URI和ROS_HOSTNAME为对应的IP。
launch文件中运行的每个节点可以指定该节点运行的machine,所以可以设置machine参数,格式如下
"tk1" address="tegra-ubuntu" user="ubuntu" env-loader="/home/ubuntu/Documents/ROS_WS/catkin_ws/src/uav_pose/config/ric_env.sh" default="true" />
password参数是强烈不推荐的。可以是使用ssh-keygen工具。
使用SSH免密码的方法,首先在本地机器产生key,包括private key和public key,生成key使用命令
ssh-keygen -t rsa
这样会生成两个文件,分别是.ssh/id_rsa.pub 和.ssh/id_rsa,后者为private key,前者为public key,之后将public key复制到远程的机器上即可,也就是TK1.
命令是
ssh-copy-id <username>@<host>
refer here
后边的env-loader对应的文件十分重要。格式如下
#!/bin/sh
export ROS_MASTER_URI=http://tegra-ubuntu:11311
export ROS_HOSTNAME=tegra-ubuntu
. /opt/ros/indigo/setup.sh
. ~/Documents/ROS_WS/catkin_ws/devel/setup.sh
exec "$@"
注意两点,一是要source ROS的自有包对应路径下的setup文件,还有就是自己的包所在路径中的setup文件,其次是要运行这个语句‘exec “$@”’。该文件存放于对应的机器上,在本例中存放于机器tegra-ubuntu。
launch文件第二步是指定在该机器上运行哪些节点,写法和本地运行的节点相同,注意指定machine的语句()中的参数default=true表示之后的节点如果不指定机器,默认是在该机器中运行。完整的launch文件如下
"tk1" address="tegra-ubuntu" user="ubuntu" password="ubuntu" env-loader="/home/ubuntu/Documents/ROS_WS/catkin_ws/src/uav_pose/config/ric_env.sh" default="true" />
"uav_pose" type="my_publisher" name="videoRead" output="screen" args = "0" />
"uav_pose" type="PattnRecg" name="pattrnRecg" output="screen" />
"uav_pose" type="GimbalControl" name="gimbalControl" output="screen" args ="/dev/ttyUSB0 115200" />
"$(find dji_sdk)/launch/sdk_manifold.launch" />
"ThinkPad" address="bobin-ThinkPad-T450" env-loader="$(find uav_pose)/config/base_config.sh" default="false" />
"ThinkPad" pkg="image_view" type="image_view" name="imageshow" >
"image" to="/camera/markedImage" />
"ThinkPad" pkg="rviz" type="rviz" name="rviz" />
"ThinkPad" pkg="uav_pose" type="menu" name="menu" output="screen" />
"ThinkPad" pkg="qgrnd" type="qgrnd" name="qgrnd" output="screen" />
指定了两个机器,远程机器tk1,本地机器对应ThinkPad。tk1是default=true,tk1上运行了一个读取视频、目标识别、云台控制和DJI的SDK节点。本地节点运行了一些GUI显示节点和菜单节点。
虽然远程机器运行的节点不在本机上,但是注意launch文件是在本机中运行的所以使用find等指令时注意查找的是本地的路径。另外注意在运行该launch文件之前应该设置本地机器的环境变量如下
#!/bin/bash
export ROS_MASTER_URI="http://tegra-ubuntu:11311"
export ROS_HOSTNAME=bobin-ThinkPad-T450
export ROSLAUNCH_SSH_UNKNOWN=1
. ~/catkin_ws/devel/setup.sh
注意其中ROSLAUNCH_SSH_UNKNOWN是必须的
总结一下,
- 远程的机器上只是运行了一个环境变量设置的文件,之后所有的节点在launch文件中指定。
- 本地的机器上首先要设置环境变量,进而启动launch文件。
顺序是这样的
- 本地的机器上设置境变量
- 启动launch文件,该文件指定了:
1. 远程节点的环境变量的设置。
2. 远程所需要运行的节点。
3. 本地机器所需要运行的节点。
摘取关键的原则
1. 可重用性好
2. 高层级的launch文件应该简短,利用include指令将系统的组成部分和ROS parameter引用过来即可。
3. 在决定应用需要多少个高层级的launch文件时,你要考虑利弊的权衡。
4. 使用 env 置换符可以使得launch文件的一部分依赖于环境变量的值。
5. 使用machine tags来平衡负载并控制节点在机器上的启动,同时也因考虑将机器配置文件(.machine)跟系统变量关联起来以便于重复利用。
6. 当一个给定类型的信息在不同的情况下发布在不同的topic上,我们可以使用topic remapping
优点: 我们可以少做几个 “打开新终端, roslaunch” 的步骤。
缺陷1: roslaunch一个launch文件会有一个持续一段时间的校准过程。如果2dnav_pr2 launch文件引用了机器人的launch文件,当我们用control-c终止这个roslaunch进程,然后又再次开启这个进程,校准过程还得再来一遍。
缺陷2: 一些导航node要求校准过程必须在它启动之前完成。roslaunch目前还没有对节点的启动时间和顺序进行控制。最完美的方案当然是让导航节点等到校准过程完成后再启动,但就目前的情况来看,把他们分别放在两个launch文件里,直到校准过程结束再启动导航节点是个可行的方案。
因此,对于是否应该把多个启动项放到一个launch文件里并没有一个统一的标准。就本教程的案例而言,我们把他们放到两个launch文件里。
object | setting1 | setting2 |
---|---|---|
node | explicit | local machine |
node | include file find | remote machine |
parameters | explicit | remap |
parameters | env | load from file |
- env require
export ROBOT=pre
from="odom" to="pr2_base_odometry/odom" />
```
- load from files
“`