ROS机器人开机自启动(systemd 版本)

配置/etc/rc.local的内容如下:

#!/bin/bash -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.
source /opt/ros/kinetic/setup.bash
source ~/zfak_ws/install/setup.bash

echo "y" | rosclean purge
du -sh ~/.ros

#-------------------Route Model--------------------#
export ROS_IP=192.168.1.101
export ROS_HOSTNAME=$ROS_IP
export ROS_MASTER_URI=http://192.168.1.101:11311
#--------------------------------------------------#

#-------------------Default WS---------------------#
cd ~/zfak_ws/install/lib/system_scripts
echo 4 | ./start_choose.sh
#--------------------------------------------------#

exit 0

注意:原始的为/bin/sh -e,ROS的应该修改为 /bin/bash -e.

在 /lib/systemd/system/rc-local.service 的【service】中添加User属性为你当前登录的session,如果不设置,默认使用的是root。完整内容如下:

#  This file is part of systemd.
#
#  systemd is free software; you can redistribute it and/or modify it
#  under the terms of the GNU Lesser General Public License as published by
#  the Free Software Foundation; either version 2.1 of the License, or
#  (at your option) any later version.

# This unit gets pulled automatically into multi-user.target by
# systemd-rc-local-generator if /etc/rc.local is executable.
[Unit]
Description=/etc/rc.local Compatibility
ConditionFileIsExecutable=/etc/rc.local
After=network.target

[Service]
Type=forking
User=jld
ExecStart=/etc/rc.local start
TimeoutSec=0
RemainAfterExit=yes

其中jld为你当前登录的session.

-------------------------------------开机自动启动遇到最大的坑-------------------------------------------------

1.bash和sh的区别

在shell脚本的开头往往有一句话来定义使用哪种sh解释器来解释脚本。

2.bad file descriptor

最开始在ubuntu desktop版本可以通过Startup Applications配置sh脚本能够正常启动机器人所需要的所有进程(包括:定位、导航、激光、串口交互等),但是使用ubuntu server后没有Startup Applications,所以需要更换一种开机自启动的策略,所以选择Systemd

然后,遇到了问题。在/etc/rc.local中配置sh脚本,其中两个进程都存在打开串口失败的问题。最开始把该问题归结于权限的问题,查找了几天,参考了stackoverflow的问题描述等。

链接:https://stackoverflow.com/questions/11422639/opening-dev-ttyusb0-returns-bad-file-descriptor

后来尝试使用root编译catkin_ws,给串口交互的这个Node节点赋予root权限。还是同样的错误。

bad file descriptor

也尝试其他自启动的方式:How to run ROS on startup (bootup),发现和我的策略以及实现方式一样。

链接:https://blog.roverrobotics.com/how-to-run-ros-on-startup-bootup/

实在想不出哪个地方有问题了,难道是我不清楚systemd的启动顺序和流程,(确实不清楚

是不是系统开机自启动的时候,串口还没有准备好,roslaunch就去打开这个串口设备,导致bad file descriptor

也有可能,是吧??? 

最终,我开始去从代码端入手去查找问题,先看打印perror的地方在哪里?哪一部分导致了这个错误。

open串口正常,设置串口属性的位置出错,说明fd不正常。往前查。。。fd来自于哪里?

if (tcgetattr(fd,&newtio) < 0) {
    perror("tcgetattr error");
    return -1;
}

原始返回fd的代码,如下:

int open_port(char *comport)
{
    int fd;
    fd = open(comport, O_RDWR|O_NOCTTY|O_NDELAY);
    if (-1 == fd)
    {
        perror("Can't Open Serial Port");
        return(-1);
    }

    if(fcntl(fd, F_SETFL, 0)<0)
        printf("fcntl failed!\n");
    else
        //printf("fcntl=%d\n",fcntl(fd, F_SETFL,0));
    if(isatty(STDIN_FILENO)==0)
        printf("standard input is not a terminal device\n");
    else
        //printf("isatty success!\n");
        //printf("fd-open=%d\n",fd);
    return fd;
}

看着有啥问题没有?仔细分析这个open_port函数到底有没有问题。

 

 

 

 

 

 

 

你可能感兴趣的:(ROS小技巧)