背景
我最近开始使用mavros,按照官网的教程进行安装 采用二进制的方式安装,一切进行的很顺利,接下来我就按照PX4官网的去执行一个让无人机自动起飞的例子 ,完全按照官网的代码和配置到最后一步执行roslaunch offboard_py start_offb.launch 的时候不出意外的,我的终端提示我
Resource not found: px4 ROS path [0] = ... ...
然后就有一些ROS path的命令的提示...
教程下面也给出了解决方法:
source ~/PX4-Autopilot/Tools/simulation/gazebo/setup_gazebo.bash ~/PX4-Autopilot ~/PX4-Autopilot/build/px4_sitl_default
export ROS_PACKAGE_PATH=$ROS_PACKAGE_PATH:~/PX4-Autopilot
export ROS_PACKAGE_PATH=$ROS_PACKAGE_PATH:~/PX4-Autopilot/Tools/simulation/gazebo/sitl_gazebo
export GAZEBO_PLUGIN_PATH=$GAZEBO_PLUGIN_PATH:/usr/lib/x86_64-linux-gnu/gazebo-9/plugins
教程说把上面的命令加入到自己的.bashrc 下面去。
- 注意事项1:其中要注意的是
~/PX4-Autopilot 这个路径有可能你和别人的不一样,你需要指定到你自己的目录下。 - 注意事项2:最后一行
export GAZEBO_PLUGIN_PATH=$GAZEBO_PLUGIN_PATH:/usr/lib/x86_64-linux-gnu/gazebo-9/plugins 里的gazebo-9 也有可能和你的电脑不一样,有可能是gazwbo-11 你找到对应的目录,然后看看自己的目录下面到底是啥。
做到这里,按理说我们再次执行roslaunch offboard_py start_offb.launch 就可以把无人机起飞的程序跑起来了。但事与愿违,我的还是不成功。
问题追踪及解决方案
问题是经过上述的配置仍然报:
Resource not found: px4 ROS path [0] = ... ...
的错误,所以我就排查问题,首先,我在roslaunch offboard_py start_offb.launch 命令执行前手动在命令行中分别输入下面这几行,问题就解决了。
source ~/PX4-Autopilot/Tools/simulation/gazebo/setup_gazebo.bash ~/PX4-Autopilot ~/PX4-Autopilot/build/px4_sitl_default
export ROS_PACKAGE_PATH=$ROS_PACKAGE_PATH:~/PX4-Autopilot
export ROS_PACKAGE_PATH=$ROS_PACKAGE_PATH:~/PX4-Autopilot/Tools/simulation/gazebo/sitl_gazebo
export GAZEBO_PLUGIN_PATH=$GAZEBO_PLUGIN_PATH:/usr/lib/x86_64-linux-gnu/gazebo-9/plugins
所以我分析,在~/.bashrc 中设置的变量在哪里被冲掉了。
为了验证我的猜想,我又重新打开一个命令行,输入echo $ROS_PACKAGE_PATH 发现是有我设置的那些的。说明环境变量设置的没有问题,那问题就在接下来的步骤中。我想起来,我在执行roslaunch offboard_py start_offb.launch 之前先进行了source ~/catkin_ws/devel/setup.bash ,所以就是这个命令导致ROS_PACKAGE_PATH 环境变量被修改了。问题找到了,那为什么我电脑上工作空间的环境变量配置会影响ROS_PACKAGE_PATH 这个变量呢?
问题就在source */setup.bash 上,除了catkin_ws 工程中有这个操作,ROS启动也需要source /opt/ros/noetic/setup.bash 其中noetic 是我的ROS版本,你的可能不一样。
通过我的实验,我发现:
- 无论你之前的
ROS_PACKAGE_PATH 内容是什么,在执行source /opt/ros/noetic/setup.bash 后都只有/opt/ros/noetic/share 这一个结果,也就是会冲掉其他设置的内容。 - 无论你之前的
ROS_PACKAGE_PATH 内容是什么,在执行source ~/catkin_ws/devel/setup.bash 后都只有~/catkin_ws/src:/opt/ros/noetic/share ,相对于上面增加了 ~/catkin_ws/src ,也就是会冲掉其他设置的内容。注意~/catkin_ws 是我自己的ROS工作空间目录,你的可能和这个不一样。
根据上述分析,我发现,设置环境变量的操作是有顺序的,我原来的顺序是最后执行source ~/catkin_ws/devel/setup.bash 导致我在~/.bashrc 中设置的被冲掉。所以我最后总结了一个执行顺序:
- 第一步:
~/.bashrc 中添加source /opt/ros/noetic/setup.bash ROS的设置 - 第二步:
~/.bashrc 中添加source ~/catkin_ws/devel/setup.bash 工作空间的设置 - 第三步:
~/.bashrc 中添加下面的内容: PX4环境变量设置
source ~/PX4-Autopilot/Tools/simulation/gazebo/setup_gazebo.bash ~/PX4-Autopilot ~/PX4-Autopilot/build/px4_sitl_default
export ROS_PACKAGE_PATH=$ROS_PACKAGE_PATH:~/PX4-Autopilot
export ROS_PACKAGE_PATH=$ROS_PACKAGE_PATH:~/PX4-Autopilot/Tools/simulation/gazebo/sitl_gazebo
export GAZEBO_PLUGIN_PATH=$GAZEBO_PLUGIN_PATH:/usr/lib/x86_64-linux-gnu/gazebo-9/plugins
上面所有的设置请不要直接复制粘贴,根据实际情况修改你的设置,这样才不会出错。
深层分析
最后我想再了解一下,为什么source */setup.bash 会把原本ROS_PACKAGE_PATH 的设置冲掉,因此我打开了我工作空间中的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"
我发现这个文件没执行啥,就是再执行一遍setup.sh 文件,所以我们打开setup.sh 文件,内容如下:
#!/usr/bin/env sh
# generated from catkin/cmake/template/setup.sh.in
# Sets various environment variables and sources additional environment hooks.
# It tries it's best to undo changes from a previously sourced setup file before.
# Supported command line options:
# --extend: skips the undoing of changes from a previously sourced setup file
# --local: only considers this workspace but not the chained ones
# In plain sh shell which doesn't support arguments for sourced scripts you can
# set the environment variable `CATKIN_SETUP_UTIL_ARGS=--extend/--local` instead.
# since this file is sourced either use the provided _CATKIN_SETUP_DIR
# or fall back to the destination set at configure time
: ${_CATKIN_SETUP_DIR:=/home/facri/Documents/ROS/catkin_ws/devel}
_SETUP_UTIL="$_CATKIN_SETUP_DIR/_setup_util.py"
unset _CATKIN_SETUP_DIR
if [ ! -f "$_SETUP_UTIL" ]; then
echo "Missing Python script: $_SETUP_UTIL"
return 22
fi
# detect if running on Darwin platform
_UNAME=`uname -s`
_IS_DARWIN=0
if [ "$_UNAME" = "Darwin" ]; then
_IS_DARWIN=1
fi
unset _UNAME
# make sure to export all environment variables
export CMAKE_PREFIX_PATH
if [ $_IS_DARWIN -eq 0 ]; then
export LD_LIBRARY_PATH
else
export DYLD_LIBRARY_PATH
fi
unset _IS_DARWIN
export PATH
export PKG_CONFIG_PATH
export PYTHONPATH
# remember type of shell if not already set
if [ -z "$CATKIN_SHELL" ]; then
CATKIN_SHELL=sh
fi
# invoke Python script to generate necessary exports of environment variables
# use TMPDIR if it exists, otherwise fall back to /tmp
if [ -d "${TMPDIR:-}" ]; then
_TMPDIR="${TMPDIR}"
else
_TMPDIR=/tmp
fi
_SETUP_TMP=`mktemp "${_TMPDIR}/setup.sh.XXXXXXXXXX"`
unset _TMPDIR
if [ $? -ne 0 -o ! -f "$_SETUP_TMP" ]; then
echo "Could not create temporary file: $_SETUP_TMP"
return 1
fi
CATKIN_SHELL=$CATKIN_SHELL "$_SETUP_UTIL" $@ ${CATKIN_SETUP_UTIL_ARGS:-} >> "$_SETUP_TMP"
_RC=$?
if [ $_RC -ne 0 ]; then
if [ $_RC -eq 2 ]; then
echo "Could not write the output of '$_SETUP_UTIL' to temporary file '$_SETUP_TMP': may be the disk if full?"
else
echo "Failed to run '\"$_SETUP_UTIL\" $@': return code $_RC"
fi
unset _RC
unset _SETUP_UTIL
rm -f "$_SETUP_TMP"
unset _SETUP_TMP
return 1
fi
unset _RC
unset _SETUP_UTIL
. "$_SETUP_TMP"
rm -f "$_SETUP_TMP"
unset _SETUP_TMP
# source all environment hooks
_i=0
while [ $_i -lt $_CATKIN_ENVIRONMENT_HOOKS_COUNT ]; do
eval _envfile=\$_CATKIN_ENVIRONMENT_HOOKS_$_i
unset _CATKIN_ENVIRONMENT_HOOKS_$_i
eval _envfile_workspace=\$_CATKIN_ENVIRONMENT_HOOKS_${_i}_WORKSPACE
unset _CATKIN_ENVIRONMENT_HOOKS_${_i}_WORKSPACE
# set workspace for environment hook
CATKIN_ENV_HOOK_WORKSPACE=$_envfile_workspace
. "$_envfile"
unset CATKIN_ENV_HOOK_WORKSPACE
_i=$((_i + 1))
done
unset _i
unset _CATKIN_ENVIRONMENT_HOOKS_COUNT
内容挺多是吧,但我觉得核心只有一行
CATKIN_SHELL=$CATKIN_SHELL "$_SETUP_UTIL" $@ ${CATKIN_SETUP_UTIL_ARGS:-} >> "$_SETUP_TMP"
意思是去执行当前目录下的python 脚本。 我上网上搜了一下这位博主也分析到这里了:链接,但是也没找到最终原因,那接下来让我们分析分析这个文件里面具体执行的信息。我发现这个功能好深呀,后面又调用了pyton脚本,python脚本的内容也很多。有哪位大神可以帮我分析分析,通过注释看,这些配置文件都是通过其他配置文件自动生成的,一环套一环。
如果有人研究明白了上面的流程可以留言交流,我暂时先不去深究了,奥卡姆剃刀,先解决问题就行。总之,今天的问题解决了,总结了设置环境变量的顺序,大家一定要记住。
|