编写sh脚本文件启动多个launch文件
使用ROS时,经常需要启动多个launch文件,有时一个个启动太麻烦,可以通过编写sh脚本实现快捷启动。
使用ROS时,经常需要启动多个launch文件,有时一个个启动太麻烦,可以通过编写sh脚本实现快捷启动。
1 编写sh脚本文件启动多个launch文件(方式一)
该种方式是为每一个launch文件单独打开一个终端,且一般情况下同一launch文件中所有node的输出信息会显示在同一个终端中,除另有说明(详见本文章节 3)。
例代码如下:
#! /bin/bash
gnome-terminal -- bash -c "cd /home/hahaha/ws_ego; source devel/setup.bash; roslaunch ego_planner rviz.launch; exec bash"
echo “launch1 successfully started”
# 两个roslauch之间需要间隔一段时间,否则会相互抢占roscore,导致其中一个roslaunch失败,报runid错误
sleep 0.7s
gnome-terminal -- bash -c "cd /home/hahaha/ws_ego; source devel/setup.bash; roslaunch ego_planner run_in_sim.launch; exec bash"
echo “launch2 successfully started”
说明:
- #! /bin/bash: 第一行一定要是这句话,指明此脚本使用
/bin/bash
解释执行 - gnome-terminal: 打开一个新的终端窗口,几个launch文件就写几个gnome-terminal
- -c: 后面写需要执行的命令,用分号
:
分隔相邻的命令 - exec bash: 可以确保执行脚本后保持窗口不消失,还需要配合前面的
-- bash
使用 - sleep: 连续启动两个launch之间需要相隔一定时间,否则会相互抢占roscore,导致其中一个roslaunch失败,报runid错误
-t '
是指定新建窗口或标签页的名称,但是不知道为啥在这里没有作用。
2 编写sh脚本文件启动多个launch文件(方式二)
该种方式是将所有launch文件都在一个相同的终端中打开,且一般情况下所有launch文件中所有node的输出信息会显示在该终端中,除另有说明(详见本文章节 3)。
示例代码如下:
roslaunch phy_simulator rviz.launch & sleep 1; # vis
roslaunch phy_simulator phy_simulator_parking.launch & sleep 1; # simulator
roslaunch ai_agent_planner moving_obstacle.launch & sleep 1.0;
roslaunch planning_integrated map.launch & sleep 1; # just for visualization
roslaunch planning_integrated park.launch & sleep 1; # focus this!
wait
说明:
(1)脚本首行不是 #!/bin/bash
的原因说明
在 Unix 和 Linux 系统中,脚本文件必须以 #! 开头,并指定解释器路径,才能正确地被系统识别为可执行的脚本文件。例如,如果要使用 Bash 解释器来执行脚本文件,就需要在文件的第一行添加 #!/bin/bash。
然而,在这个脚本中,既没有使用 #!/bin/bash 指定 Bash 解释器,也没有使用其他解释器路径。实际上,这个脚本的开头并不是以 #! 开头,因此系统会默认将其作为一个普通的文本文件进行处理。然后,当用户在终端中执行该脚本时,会使用当前终端所使用的 Shell 解释器来运行这个脚本。
因此,这个脚本可以在不使用 #!/bin/bash 的情况下成功执行,但这种做法并不推荐。在编写脚本文件时,应该始终使用 #! 语法来指定脚本所需的解释器,以确保脚本能够正确地被系统识别和执行。
(2)脚本中 &
符号和 wait
命令的使用说明
在 shell 脚本中,wait
命令的作用是等待所有在当前 shell 中启动的进程都结束后再退出脚本。它通常与 &
符号一起使用,也就是将某个命令放在后台运行,并立即返回控制权给 shell,使脚本可以继续执行后续的其他命令,然后通过 wait
命令等待后台进程执行完毕。
在本例程中,&
符号将 roslaunch 命令放到后台运行,同时脚本继续执行接下来的命令。sleep
命令会暂停脚本执行指定的时间,以确保前面的命令已经完成了启动工作。最后,wait
命令会等待所有后台进程都结束后才退出脚本,以避免可能出现未完成的进程或僵尸进程等问题。
(3)脚本中 &
符号用法补充说明
&
符号如果放置在命令的最后面,那么它表示将该命令放到后台运行,例如: roslaunch phy_simulator rviz.launch &
;
如果放置在两个命令之间,那么它表示同时执行这两个命令,而且前一个命令在后台运行,后一个命令在前台运行,例如:roslaunch phy_simulator rviz.launch & sleep 1
。
(4)程序后台运行时其仍会将信息输出到当前终端显示
当一个命令被放到后台运行时,它的标准输出仍然会被发送到当前终端,并且可能会与其它正在运行的程序的输出混合。
如果希望将后台进程的输出保存到文件中,可以使用重定向符号 > 或者 >> 将输出重定向到文件中,例如:
$ ./my_program > output.log &
这样,my_program 程序的标准输出就会被重定向到名为 output.log 的文件中,而不是显示在终端上。如果希望同时重定向标准输出和标准错误流,可以使用 2>&1 将标准错误流重定向到标准输出,例如:
$ ./my_program > output.log 2>&1 &
这样,my_program 程序的标准输出和标准错误流都会被重定向到名为 output.log 的文件中。
(5)后台执行程序相关命令补充知识
-
jobs -------------- 查看在后台执行的进程
-
fg %n ------------ 将后台执行进程n调到前台执行,n表示jobnumber(通过jobs查看的进程编号,而非pid)
-
ctrl+z ------------ 将在前台执行的进程,放到后台并挂起
-
bg %n ----------- 将在后台挂起的进程,继续执行
-
ctrl+c ------------ 前台进程终止
-
kill %n ----------- 杀掉后台运行的进程,n表示jobnumber(通过jobs查看的进程编号,而非pid)
3 单一launch文件为某node单独新开一个终端运行的方法
运行 roslaunch 时,所有的 node 共用一个相同的 terminal,这对于一些需要从控制台输入的 node 很不方便。可以使用 node
标签下的 launch-prefix
属性,来使得某个节点在另一个新开的 terminal中运行。该属性相当于在执行启动命令时加上一段命令前缀。
launch-prefix="gnome-terminal --"
,即等价于 gnome-terminal -- rosrun beginner_tutorials listener
实际应用例子如下:
<launch>
<!-- 该 node 在当前的终端中输出结果 -->
<node name = "talker" pkg = "beginner_tutorials" type = "talker" output = "screen">
</node>
<!-- 该 node 在新开的终端中输出结果 -->
<node name = "listener" pkg = "beginner_tutorials" type = "listener" output = "screen" launch-prefix="gnome-terminal --">
</node>
</launch>
说明:
launch-prefix="gnome-terminal --tab -t 'new terminal' --"
, --tab
是新建标签页, --window
是新建窗口(默认情况),-t 'new terminal'
是指定新建窗口或标签页的名称。
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)