好久没写了,最近搞了辆小车,瞅了瞅ROS的相关内容,没有写ROS的内容,刚开始看,写的话基本就成了书本粘贴。。。不过最近由ROS引出来的一些Linux相关的东西,然后又回头撸了撸私房菜,还是有一些收获的。
先说一下此篇的起因,就是在创建了ROS 的workspace之后,需要将workspace中的setup.bash文件写入~/.bashrc 文件中,让其启动:
就像这个样子:
source /opt/ros/kinetic/setup.bash
这句的目的就是在开新的terminal的时候,运行这个setup.bash,而这个setup.bash的作用是让一些ROS* 开头的命令可以使用。同时还能够创建一些ROS开头的环境变量,比如:
ROS_PACKAGE_PATH
这个环境变量是一堆路径字符串:
ROS_PACKAGE_PATH="/opt/ros/kinetic/share"
用来表征ROS功能包路径,当你使用:
rospack find {packagename}
搜寻功能包所在的路径时,它会依据ROS_PACKAGE_PATH
所提供的功能包路径里去寻找,不在这个环境变量里的路径就不会去寻找了,即便你有这个功能包,也会显示找不到。
继续捯饬的过程中发现这么个现象:
假如我在~/.bashrc中加入这么一堆的source:
source /opt/ros/kinetic/setup.bash
source ~/catkin_ws/devel/setup.bash
source ~/robin_ws/devel/setup.bash
source ~/riki/tySDK/camport_ros-master/devel/setup.bash
source ~/riki/catkin_ws/devel/setup.bash
本来以为ROS_PACKAGE_PATH
会依次增加,把每一个功能包的路径都添加上,但是发现不是,貌似会有干扰。就是只有第一句的时候,ROS_PACKAGE_PATH="/opt/ros/kinetic/share"
加上后面的之后会变化,并不是加一句,增加一条,而是没有什么规律。。。
比如我只有这两句:
source /opt/ros/kinetic/setup.bash
source ~/catkin_ws/devel/setup.bash
的时候ROS_PACKAGE_PATH
是这样的:
robin@robin:~$ echo $ROS_PACKAGE_PATH
/home/robin/catkin_ws/src:/home/robin/robin_ws/src:/home/robin/riki/tySDK/camport_ros-master/src:/opt/ros/kinetic/share
但是,我再加一句:
source /opt/ros/kinetic/setup.bash
source ~/catkin_ws/devel/setup.bash
source ~/robin_ws/devel/setup.bash
再source一下:
robin@robin:~$ echo $ROS_PACKAGE_PATH
/home/robin/robin_ws/src:/home/robin/riki/tySDK/camport_ros-master/src:/opt/ros/kinetic/share
我的/home/robin/catkin_ws/src
竟然没了?!
一头雾水,猜测是不是这样source好多,他们之间会干扰,于是打开上面的setup.bash文件,看看究竟:
#!/usr/bin/env bash
# generated from catkin/cmake/templates/setup.bash.in
CATKIN_SHELL=bash
# source setup.sh from same directory as this file
_CATKIN_SETUP_DIR=$(builtin cd "`dirname "${BASH_SOURCE[0]}"`" > /dev/null && pwd)
. "$_CATKIN_SETUP_DIR/setup.sh"
整个_CATKIN_SETUP_DIR
其实就是获得当前正在执行的脚本的所在路径,然后第二句执行一下同路径下的setup.sh文件。
主要来解析一下这一句:
_CATKIN_SETUP_DIR=$(builtin cd "`dirname "${BASH_SOURCE[0]}"`" > /dev/null && pwd)
一步步拆解:
1、首先最内层的:${BASH_SOURCE[0]}
参见:https://www.cnblogs.com/sunfie/p/5943979.html
总体来说就是:BASH_SOURCE[0] , 取得当前执行的shell文件所在的路径及文件名。
举个栗子:比如你在~/test中有个test.sh文件,文件中有这么一句:echo ${BASH_SOURCE[0]}
运行结果是这样的:
robin@robin:~$ ./test/test.sh
./test/test.sh
会输出路径加文件名。
2、"${BASH_SOURCE[0]}"
这句会把双引号内的东西全部转换成字符串。不过这里貌似${BASH_SOURCE[0]}
的结果输出本身就是字符串吧。。。
3、dirname "${BASH_SOURCE[0]}"
参考:http://man.linuxde.net/dirname
总结就是去除字符串中的文件名称,只留路径部分。测试一哈,还是我们的~/test中有个test.sh文件,文件中之前的那句改一改:
echo `dirname ${BASH_SOURCE[0]}`
输出结果变为:
robin@robin:~$ ./test/test.sh
./test
只有test.sh所在的路径了。
3
`dirname "${BASH_SOURCE[0]}"`
这步比上面多了对反引号。
参考:http://blog.csdn.net/jackyechina/article/details/52813007
总结就是:【`】,学名叫“倒引号”, 如果被“倒引号”括起来, 表示里面需要执行的是命令。
因为整个整体在双引号中,若不夹这个反引号,diename会被变成字符串,加上倒引号后,表征倒引号中的内容是一行命令,主要是指dirname命令
"`dirname "${BASH_SOURCE[0]}"`"
4
builtin cd "`dirname "${BASH_SOURCE[0]}"`"
参看:http://man.linuxde.net/builtin
主要意思就是使用shell内建的cd命令进入当前脚本所在的目录。
5
builtin cd "`dirname "${BASH_SOURCE[0]}"`" > /dev/null
此步多了个 > /dev/null
参看:https://zhidao.baidu.com/question/223779994.html
大概意思就是不要输出任何东西吧,我猜的。。。
6
&&
参看:http://blog.csdn.net/a627088424/article/details/20360107
前一条执行成功后,执行后面的命令。
7 pwk
参看:http://man.linuxde.net/pwd
显示用户当前工作目录的绝对路径。
_CATKIN_SETUP_DIR=$(builtin cd "`dirname "${BASH_SOURCE[0]}"`" > /dev/null && pwd)
所以整个语句流程就是取得本shell的绝对路径和名称,然后dirname去掉名称只留路径,然后进入此路径,同时将cd 的输出扔掉,不予显示。然后这步执行成功的话pwk出绝对路径然后赋值给_CATKIN_SETUP_DIR
变量。
巴特!搞了这么久貌似还是没有找到为什么source之间会干扰。。。
后来又查询到底如何正规的修改环境变量:
export ROS_PACKAGE_PATH=${ROS_PACKAGE_PATH}:/home/robin/catkin_ws/src
直观上就是将环境变量再赋值一下,并在后面接上一段。。。