首页 - 文章教程 - 正文

3.开机自启动ROS控制手柄节点

0x00 开机自启动需求

当程序调试差不多后,就可以来配置开机自启动了。因为该控制手柄需要在ubuntu系统上电启动后,一进入正常工作状态时就要自动加载运行。这样就能省去手动输入命令运行launch文件的步骤,这里使用的方法是编写一个开机自启动的服务。当然在本教程中的开机自启动方法也可以用在其他ROS项目中,只需要根据新项目的配置稍微进行修改一下即可。


0x01 项目代码架构

下面结合前面两篇教程编写的代码,来整体介绍下当前项目的目录结构,如下图所示:

Screenshot from 2018-12-19 14:09:33.png

由图可知,这里新增了一个control_handle_bringup的软件包。该软件包算是整个ROS项目的入口,这个软件包里面一般只有一个launch文件夹,里面的launch文件用来启动项目其他软件包的launch文件。以后需要注意,一般在ROS项目开发中,了解整个项目架构的入口就是由bringup软件包入手。由于该软件包没有其他实际功能,所以在创建该软件包时也就没有什么依赖项了。一般都是使用下面的命令来创建bringup软件包:

catkin_create_pkg control_handle_bringup

当创建好bringup软件包后,在其中在mkdir一个launch文件夹。在launch文件夹中再编写bringup的launch文件即可,这里我给launch文件命名为control_handle_bringup.launch,具体代码如下:

<!--
  Copyright: 2016-2018 ROS小课堂 www.corvin.cn
  Author: corvin
  Description:该启动文件负责启动控制手柄的所有节点,使其进入正常工作状态.
  History:
    20181218: Initial this launch file.
-->
<launch>
  <!--startup ros handle python node -->
  <include file="$(find ros_handle_python)/launch/ros_handle.launch" />
</launch>

由于该项目中只有一个ROS软件包负责解析下位机的数据帧,整个项目目前还比较简单,所以bringup中只启动一个launch文件。随着项目的不断扩大,这里的launch文件可以添加更多的要启动的launch文件。


0x02 编写自启动服务

首先来看下软件包目录下的scripts文件夹存储的文件,如下图所示:

Screenshot from 2018-12-19 15:36:56.png

在scripts文件夹中,新建了service文件夹。这是用来存储跟服务相关的脚本,其中ros_control_handle.service是自定义的服务文件,该文件源码如下:

[Unit]
Description=power on startup ros control handle node - by corvin
After=network.target

[Service]
Type=simple
Restart=always
RestartSec=10
ExecStart=/usr/bin/ros_control_handle_start
ExecStop=/usr/bin/ros_control_handle_stop
Restart=on-failure

[Install]
WantedBy=multi-user.target

在介绍这个服务文件前,我们需要先对systemd有个简单认识才行。systemd它是一个Linux系统基础组件的集合,它提供了一个系统和服务的管理器,运行的PID为1并负责启动其它程序。监视和控制systemd的主要命令是systemctl,该命令可用于查看系统状态和管理系统及服务。

在这里需要特别注意的是[Service]字段下的ExecStart和ExecStop两个参数,后面有对应的执行脚本。当启动该服务时,它就会自动调用ExecStart后面的脚本。当停止该服务时,它就会自动调用ExecStop后面的脚本。这里来分别介绍这两个脚本,下面先看ros_control_handle_start脚本,代码如下:

#!/bin/bash

# Copyright: 2016-2018 ROS小课堂 www.corvin.cn
# Author: corvin
# Description: when poweron auto launch ros control handle node.
# History:
#    20181214: initial this bash file.

source /opt/ros/kinetic/setup.bash
cd /home/corvin/ros_control_handle/ros_code/
catkin_make
source /home/corvin/ros_control_handle/ros_code/devel/setup.bash

export ROS_IP=192.168.138.227

roslaunch control_handle_bringup control_handle_bringup.launch

exit 0

该脚本中主要就是配置了下ROS的各环境变量,这里特别需要注意这个export ROS_IP,这个要根据自己ROS系统中手柄连接的主机IP地址来修改。最后就是通过roslaunch来启动相应项目的bringup.launch文件即可。

下面来看ros_control_handle_stop脚本,代码如下:

#!/bin/bash

# Copyright: 2016-2018 ROS小课堂 www.corvin.cn
# Author: corvin
# Description: Stop ros control handle node.
# History:
#    20181214: initial this bash file.

source /opt/ros/kinetic/setup.bash

pid=`ps -ef|grep control_handle_bringup.launch|grep -v grep|awk '{print $2}'`
if [ -n "$pid" ]
then
    rosnode kill /handle_python_node
    rosnode kill /handle_dynamic_reconfig

    echo "kill control_handle_bringup.launch pid:" $pid
    sudo kill -9 $pid
fi

exit 0

通过该脚本可以发现停止服务,其实就是停止启动的相应的ROS节点和launch文件。在调用rosnode这个ros系统提供的命令时,需要先source一下ros中的环境变量才行。否则可能会提示无法找到rosnode命令。


0x03 安装和卸载服务

为了方便的安装和卸载服务,这里编写了相应的脚本。这样就很方便了,下面先来介绍安装服务的脚本install_service.sh,脚本代码如下:

#!/bin/bash

# Copyright: 2016-2018 ROS小课堂 www.corvin.cn
# Author: corvin
# Description: install ros control handle service to /lib/systemd/system,this will
#    auto roslaunch handle when poweron.
# History:
#    20181214: initial this bash file.

sudo cp ./service/ros_control_handle_start /usr/bin/
sudo cp ./service/ros_control_handle_stop /usr/bin/

sudo cp ./service/ros_control_handle.service /lib/systemd/system/
sudo systemctl enable ros_control_handle.service
sudo systemctl start ros_control_handle.service

exit 0

由上述代码可以得知,其实安装配置服务就是将相应的脚本和服务文件,复制到指定的文件夹中。然后调用systemctl相应命令来使能和启动服务:

sudo systemctl enable ros_control_handle.service:这个是用来使能服务,这样该服务就可以在每次开机的时候自动加载服务运行。

sudo systemctl start ros_control_handle.service:这个是立刻启动服务,这样就可以立刻调用ros_control_handle_start脚本来启动bringup了。

下面来看卸载服务的脚本uninstall_service.sh,具体代码如下:

#!/bin/bash

# Copyright: 2016-2018 ROS小课堂 www.corvin.cn
# Author: corvin
# Description: Uninstall ros_control_handle.service.
# History:
#    20181214:initial this bash file.

pid=`ps -ef|grep control_handle_bringup|grep -v grep|awk '{print $2}'`
if [ -n "$pid" ]
then
    /usr/bin/ros_control_handle_stop
fi

sudo systemctl disable ros_control_handle.service

sudo rm /usr/bin/ros_control_handle_start
sudo rm /usr/bin/ros_control_handle_stop

sudo rm /lib/systemd/system/ros_control_handle.service

exit 0

由代码可知,卸载该服务其实就是先调用ros_control_handle_stop,停止当前运行的launch文件和ros节点。然后禁用该服务,这样该服务在下次开机时就不会自动启动运行了。然后再删除相应目录中的脚本和服务文件即可,这样我们就把该开机自启动服务给彻底卸载了。


0x04 运行测试

当编写好所有的脚本和服务后,接下来我们就可以来测试了。下面来分步依次测试所有的功能:

(1)测试安装服务脚本install_service.sh是否正常:

Screenshot from 2018-12-19 16:57:40.png

另外,还可以通过使用如下命令来查看是否开机自启动该服务了,命令如下:

systemctl is-enabled ros_control_handle.service

还可以通过如下命令来查看当前服务的运行状态,命令如下:

systemctl status ros_control_handle.service

Screenshot from 2018-12-19 17:03:29.png

(2)停止/启动当前服务的运行

有时候我们需要停止当前服务的运行,例如想要调试一下代码什么的。当调试好代码后,又需要立刻运行该服务。那么就需要运行如下命令,先介绍停止运行服务的命令:

sudo systemctl stop ros_control_handle.service

Screenshot from 2018-12-19 17:18:58.png

现在再来启动下服务,使用如下命令即可:

sudo systemctl start ros_control_handle.service

Screenshot from 2018-12-19 17:31:11.png

(3)使能/禁止服务开机启动

首先来介绍查看是否使能开机自启动服务,该命令前面介绍过,命令如下:

systemctl is-enabled ros_control_handle.service

使能开机自启动服务命令sudo systemctl enable ros_control_handle.service

禁用开机自启动服务命令sudo systemctl disable ros_control_handle.service

Screenshot from 2018-12-19 17:59:09.png

(4)使用journalctl查看Unit启动日志

systemd有自己的日志系统,被成为journal。使用systemd日志,无需安装额外的日志服务(syslog)。下面就来简单介绍下journalctl(journal + ctrl的缩写)命令:

  • 查看指定服务的日志

    journalctl -u ros_control_handle.service

    在-u参数后面加上需要查看日志的服务名称,在输入服务名时,可以使用tab键的自动补全功能,用起来很方便。

    Screenshot from 2018-12-20 09:03:25.png

  • 查看日志的最新几行

    随着服务的不断运行,日志肯定会越来越多。如果我们只使用上面那条命令的话,开始旧的日志在最上面,最新的日志会在最后面。这样每次查看的时候都要拉到最下面,这样很费时间。因此可以新增一个参数-n,这样就可以只查看最新几行的日志了。假如打算只查看最新10行ros_control_handle.service的日志,就可以使用如下的命令:

    journalctl -u ros_control_handle.service -n 10

    Screenshot from 2018-12-20 09:13:11.png

  • 要持续跟踪最新的输出日志

    上面命令中的-n参数,可以一下输出最新的几行日志。但这只是一次性的输出,没办法持续跟踪。如果要想持续不断的跟踪最新的日志输出,可以使用-f参数,只要不中断该命令,就会一直跟踪日志输出。假如想要持续跟踪查看ros_control_handl.service最新的日志,命令如下:

    journalctl -u ros_control_handle.service -f


0x05 References

[1]. corvin_zhang. 树莓派ubuntuMate系统中开机自启动ROS的launch文件. 

http://www.corvin.cn/707.html

[2]. archLinux wiki. systemd(简体中文). 

https://wiki.archlinux.org/index.php/systemd_(%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87)

[3]. 百度文库. linux编写systemd下服务脚本. 

https://wenku.baidu.com/view/a3d2f911f705cc17552709f4.html

[4]. 小李子博客. journalctl工具基础介绍. http://blog.51cto.com/13598893/2072212

[5]. ITer奋斗点滴(IT兄弟盟). systemd日志系统. 

https://www.cnblogs.com/itxdm/p/Systemd_log_system_journalctl.html


0x06 Feedback

大家在按照教程操作过程中有任何问题,可以直接在文章末尾给我留言,或者关注ROS小课堂的官方微信公众号,在公众号中给我发消息反馈问题也行。我基本上每天都会处理公众号中的留言!当然如果你要是顺便给ROS小课堂打个赏,我也会感激不尽的,打赏30块还会被邀请进ROS小课堂的微信群,与更多志同道合的小伙伴一起学习和交流!

1516851765432601.jpg

发表评论