引
Gazebo-classic 在 Ubuntu 22.04 上已停止维护,但是新版的 Gazebo 无论从性能上还是体验上都不佳。PX4 1.13 也是最后一个支持 Gazebo-classic 的版本,并且我们依旧可以在 Ubuntu 22.04 上运行 PX4 1.13 仿真,并手动编写其启动脚本。
准备
由于 linux 的 sudo 默认是隔离环境变量的,所以即使开了魔法,并配置了 http_proxy
和 https_proxy
,也无法正常在 sudo 下使用。所以我们先进行魔法的额外配置。
sudo visudo
找到有一堆的 Defaults
开头的地方,就在最前面,跟在它后面写一行:
Defaults env_keep+="https_proxy http_proxy"
然后保存。Ubuntu 发行版大概率是用 nano
作为编辑器的,那就 Ctrl+S 保存,Ctrl+X 退出。
接着安装构建用的工具链以及 gazebo 。
sudo apt install -y ninja-build exiftool protobuf-compiler libeigen3-dev genromfs xmlstarlet libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libopencv-dev python3-pip gawk cmake gazebo libgazebo-dev
pip3 install packaging numpy empy==3.3.4 toml pyyaml jinja2 pyargparse kconfiglib jsonschema future pyros-genmsg
编译
找一个合适的位置开始克隆并编译 PX4 。
git clone --recurse -j$(nproc) -b v1.13.2 --depth 1 https://github.com/PX4/PX4-Autopilot
cd PX4-Autopilot
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin
make px4_sitl_default gazebo
编译完后会弹出一个 gazebo 的界面,不用管它,在终端内 Ctrl+C 关掉。
编译完后里面有好多是根本没用的,徒占空间。我们删掉这些无用的东西,只留精华。
cd ..
mv PX4-Autopilot PX4-Autopilot_
mkdir -p PX4-Autopilot/build/px4_sitl_default/build_gazebo
mkdir -p PX4-Autopilot/Tools/sitl_gazebo
cp -r PX4-Autopilot_/build/px4_sitl_default/bin PX4-Autopilot/build/px4_sitl_default
cp -r PX4-Autopilot_/build/px4_sitl_default/build_gazebo/*.so PX4-Autopilot/build/px4_sitl_default/build_gazebo
cp -r PX4-Autopilot_/build/px4_sitl_default/etc PX4-Autopilot/build/px4_sitl_default
cp -r PX4-Autopilot_/Tools/sitl_gazebo/models PX4-Autopilot/Tools/sitl_gazebo
cp -r PX4-Autopilot_/Tools/sitl_gazebo/worlds PX4-Autopilot/Tools/sitl_gazebo
rm -rf PX4-Autopilot_
然后往 .bashrc 里加一些内容。注意,如果你是 Nvidia 显卡,记得添加倒数第二行。如果你的电脑没有 N 卡只有 Intel 核显,则建议添加最后一行。(最后一行注释不算一行)
export PX4_DIR=你的 PX4 仿真目录
export GAZEBO_PLUGIN_PATH=$PX4_DIR/build/px4_sitl_default/build_gazebo
export GAZEBO_MODEL_PATH=$PX4_DIR/Tools/sitl_gazebo/models
export LD_LIBRARY_PATH=$PX4_DIR/build/px4_sitl_default/build_gazebo:$LD_LIBRARY_PATH
# export MESA_D3D12_DEFAULT_ADAPTER_NAME=NVIDIA # 如果你是 Nvidia 显卡
# export LIBGL_ALWAYS_SOFTWARE=1 # 如果你是 Intel 核显用户,建议添加
# AMD yes
启动!
PX4 的编译就算完了,现在安装 humble 版的 mavros 。
sudo apt install -y ros-humble-mavros ros-humble-mavros-extras
curl -sL https://github.com/mavlink/mavros/raw/ros2/mavros/scripts/install_geographiclib_datasets.sh | sudo bash
PX4-Autopilot 项目里有写好的有 ROS1 的 launch 文件,可以直接启动,但是没有提供 ROS2 版的,所以我们可以写一个简单的 px4 启动脚本。
nano px4
里面写上:
#!/bin/bash
mkdir -p ~/.gazebo/models
mkdir -p ~/.gazebo/worlds
MODEL="$PX4_DIR/Tools/sitl_gazebo/models/iris/iris.sdf"
MODEL_NAME="iris"
WORLD="$PX4_DIR/Tools/sitl_gazebo/worlds/empty.world"
while [[ $# -gt 0 ]]; do
case $1 in
--model)
MODEL="$2"
shift 2
;;
--model-name)
MODEL_NAME="$2"
shift 2
;;
--world)
WORLD="$2"
shift 2
;;
*)
echo "Unknown option: $1"
exit 1
;;
esac
done
export PX4_SIM_MODEL="iris"
if [[ ! "$MODEL" =~ ^/ ]]; then
MODEL="$HOME/.gazebo/models/$MODEL"
fi
if [[ ! "$WORLD" =~ ^/ ]]; then
WORLD="$HOME/.gazebo/worlds/$WORLD"
fi
gzserver --verbose "$WORLD" &
GZSERVER_PID=$!
gz model --spawn-file="$MODEL" --model-name="$MODEL_NAME" -z 1.0
gzclient &
GZCLIENT_PID=$!
ros2 run mavros mavros_node --ros-args -p fcu_url:=udp://:14540@:14580 &
MAVROS_PID=$!
cd $PX4_DIR/build/px4_sitl_default
./bin/px4 -s etc/init.d-posix/rcS
kill -9 $GZSERVER_PID 2>/dev/null
kill -9 $GZCLIENT_PID 2>/dev/null
kill -9 $MAVROS_PID 2>/dev/null
Ctrl+S 保存,Ctrl+X 退出。
然后把 px4
作为命令安装。
sudo install px4 /usr/local/bin/px4
rm px4
最后记得 source 一下 .bashrc
,或者直接重新打开终端,之后就可以用 px4
命令直接启动了!
. ~/.bashrc
px4
在 px4 的 mavlink 控制台内输入:
param set COM_RCL_EXCEPT 4
param save
这样就可以用 mavlink 来让飞机进入 Offboard 模式了!
摄像头模拟
gazebo 内有摄像头模组,px4 基于它做了一个转发到 mavros 的插件。在 ROS1 下,编译 PX4-Autopilot 时会自动编译这个插件,而现在我们用的 ROS2 ,需要手动安装。
sudo apt install -y ros-humble-gazebo-ros-pkgs
然后再启动带有摄像头的 px4 模型仿真:
px4 --model $PX4_DIR/Tools/sitl_gazebo/models/iris_fpv_cam/iris_fpv_cam.sdf
在另外一个终端中就可以看到摄像头的图像了:
ros2 topic list # 可以看到有 /camera/camera_info 和 /camera/image_raw 两个话题
rviz2 # rviz2 内添加一个 Image 类型的话题,选择 topic 为 /camera/image_raw 就可以看到图像了
摄像头话题
按照上一节的步骤,我们已经可以成功发布摄像头话题了,但是如果我们在模型中添加两个及以上摄像头的话,就必须想办法修改每个摄像头的话题了。不然的话,两个摄像头的画面数据就会混在一个话题里面,当然这种情况在 ROS2 中是被允许的。
由于 gazebo-ros-pkgs 中 gazebo-plugins 代码的 ROS1 版本和 ROS2 版本差异巨大,处理话题发布部分的代码也大相径庭。具体可以查看源码链接 ROS1 版本 ROS2 版本 。
查看代码后不难发现,使用 ROS1 版本的 gazebo-ros-pkgs 时,摄像头话题可以通过模型文件里面 camera_plugin
插件的配置项 cameraName
和 imageTopicName
来配置。而在 ROS2 版本中,代码有明显重写过。简单来讲,所有的配置项都从原来的「小驼峰命名法」变成了「蛇形命名法」,并且只支持用 camera_name
配置项来配置话题的前缀,后缀则固定为 /image_raw
,不能通过类似 image_topic_name
配置项配置。
这边给出一个对地摄像头的示例配置:
<sensor name='camera' type='camera'>
<camera name='__default__'>
<horizontal_fov>1.571</horizontal_fov>
<image>
<width>640</width>
<height>480</height>
</image>
<clip>
<near>0.1</near>
<far>100</far>
</clip>
<lens>
<type>custom</type>
<custom_function>
<c1>1.05</c1>
<c2>4</c2>
<f>1</f>
<fun>tan</fun>
</custom_function>
<scale_to_hfov>1</scale_to_hfov>
<cutoff_angle>3.1415</cutoff_angle>
<env_texture_size>1080</env_texture_size>
</lens>
</camera>
<always_on>1</always_on>
<update_rate>30</update_rate>
<visualize>1</visualize>
<plugin name='camera_plugin' filename='libgazebo_ros_camera.so'>
<camera_name>camera/ground_camera</camera_name>
<frame_name>/robot_camera_link</frame_name>
<P_cx>320.5</P_cx>
<cx>320.5</cx>
<cy>240.5</cy>
<hack_baseline>0</hack_baseline>
<focal_length>277.191356</focal_length>
<distortion_k1>0.0</distortion_k1>
<distortion_k2>0.0</distortion_k2>
<distortion_k3>0.0</distortion_k3>
<distortion_t1>0.0</distortion_t1>
<distortion_t2>0.0</distortion_t2>
</plugin>
</sensor>
使用带该摄像头模型的飞机模型启动 gazebo :
ros2 topic list # 可以看到有 /camera/ground_camera/camera_info 和 /camera/ground_camera/image_raw 两个话题
rviz2 # rviz2 内添加一个 Image 类型的话题,选择 topic 为 /camera/ground_camera/image_raw 就可以看到图像了
这样就可以实现摄像头话题的分离了。
如果你一定要使用完全自定义的话题名的话,我们可以用 topic-tools
工具来转发话题。比如我们可以编辑刚才我们创建的 px4 一键启动程序。
🖊 Info
由于前面我们已经使用 install
命令将 px4
作为脚本安装在系统里了,所以我们需要直接编辑这个安装过的脚本。你也可以选择重复「启动!」一节里的步骤重新创建脚本,做好编辑之后再次运行 sudo install px4 /usr/local/bin/px4
命令安装。
先安装 topic-tools
sudo apt install -y ros-humble-topic-tools
接着用 sudo
权限编辑 /usr/local/bin/px4
,在启动 mavros 节点和 px4 的命令之间插入:
ros2 run topic_tools relay /camera/ground_camera/image_raw /video/ground_camera &
保存退出,再次用带这个摄像头模型的飞机模型启动 gazebo
:
ros2 topic list # 可以看到有 /video/ground_camera 这个话题
rviz2 # rviz2 内添加一个 Image 类型的话题,选择 topic 为 /video/ground_camera 就可以看到图像了
写在最后
我写了一个 px4 启动脚本来实现仿真的启动,这个脚本可以直接通过参数来指定飞机模型(model)和世界(world),具体使用方法是:
px4 --model $PX4_DIR/Tools/sitl_gazebo/models/iris/iris.sdf --model-name iris --world $PX4_DIR/Tools/sitl_gazebo/worlds/empty.world
这样就可以启动自定义飞机模型在自定义世界了。由于 gazebo 不支持读取带 ~
的路径的模型,所以指定参数时请使用完整路径。
--model
参数的默认相对路径是 ~/.gazebo/models/
,--world
参数的默认相对路径是 ~/.gazebo/worlds/
,如果你将模型或者世界放在了这两个目录下,也可以直接使用相对路径,例如:
px4 --model iris/iris.sdf --model-name iris --world empty.world