前言
无人机仿真主要分为两类:硬件在环仿真(HITL)和软件在环仿真(SITL全称Software in the loop)。
无人机软件在环仿真是指完全用计算机来模拟出无人机飞行时的状态,而硬件在环仿真是指计算机连接飞控板来测试飞控软件是否可以流畅运行。一般来说硬件在环仿真若没有加上真实的转台进行测试的话,其与软件在环仿真没有很大的区别。
在无须解决在研发过程中的硬件问题带来的麻烦,并且可以直观的调试代码,搭建一套无人机仿真系统,对于研发来说好处是数不剩数的。
功能包简介
RotorS 是一个MAV gazebo 仿真系统。
提供了几种多旋翼仿真模型,例如
- AscTec Hummingbird
- AscTec Pelican
- AscTec Firefly
但是仿真系统不限于使用这几种模型
AscTec 是 德国Ascending Technologies公司的缩写。
是很早的无人机了,实物张下面这个样子:
仿真系统中包含很多种仿真传感器,都可以安装在无人机上,例如:
- IMU
- 里程计
- 视觉惯导相机
功能包中包含了几种控制器,包含位置控制,游戏手柄控制灯
github的地址为:https://github.com/ethz-asl/rotors_simulator
功能包安装
系统环境:ubuntu16.04
ROS版本:kinetic
安装依赖包
sudo apt-get install ros-noetic-desktop-full ros-noetic-joy ros-noetic-octomap-ros python-wstool python-catkin-tools protobuf-compiler
sudo apt-get install libgeographic-dev ros-noetic-geographic-msgs # Required for mavros.
添加源和更新
$ sudo sh -c 'echo "deb http://packages.ros.org/ros/ubuntu `lsb_release -sc` main" > /etc/apt/sources.list.d/ros-latest.list'
$ wget http://packages.ros.org/ros.key -O - | sudo apt-key add -
$ sudo apt-get update
安装ros-kinetic-joy
sudo apt-get install ros-kinetic-joy
成功提示:
安装ros-kinetic-octomap-ros
sudo apt-get install ros-kinetic-octomap-ros
成功提示:
安装 ros-kinetic-mavlink
sudo apt-get install ros-kinetic-mavlink
成功提示:
安装 python-wstool
sudo apt-get install python-wstool
成功提示: (以前安装过)
安装 python-catkin-tools
sudo apt-get install python-catkin-tools
成功提示:
安装 protobuf-compiler
sudo apt-get install protobuf-compiler
成功提示:
安装libgoogle-glog-dev
sudo apt-get install libgoogle-glog-dev
成功提示: (以前安装过)
安装ros-kinetic-control-toolbox
sudo apt-get install ros-kinetic-control-toolbox
成功提示:
安装 ros-kinetic-mavros
sudo apt-get install ros-kinetic-mavros
成功提示:
下载源码
git clone https://github.com/ethz-asl/rotors_simulator.git
github不是很稳定,我是从win系统上下的压缩包,拷到的ROS工作空间下
第一次编译
catkin_make
报错
at /opt/ros/kinetic/share/catkin/cmake/catkinConfig.cmake:83 (find_package):
Could not find a package configuration file provided by “mav_msgs” with any
of the following names:
mav_msgsConfig.cmake
mav_msgs-config.cmake
rotors_simulator/rotors_control/CMakeLists.txt:6 (find_package)
来看 rotors_simulator/rotors_control/CMakeLists.txt:6
find_package(catkin REQUIRED COMPONENTS
geometry_msgs
mav_msgs
nav_msgs
roscpp
sensor_msgs
cmake_modules
)
是因为没有找到 mav_msgs 这个功能包
通过如下指令安装,解决该问题:
git clone https://github.com/ethz-asl/mav_comm.git
同样在ubuntu上没有下载下来,用win下载然后拷贝的
第二次编译
功能包的依赖已经ok,但是源码的编译出现报错:
In file included from /usr/include/gazebo-7/gazebo/rendering/ogre_gazebo.h:61:0,
from /usr/include/gazebo-7/gazebo/rendering/Camera.hh:50,
from /home/jone/jone_ws/src/rotors_simulator/rotors_gazebo_plugins/include/rotors_gazebo_plugins/external/gazebo_geotagged_images_plugin.h:25,
from /home/jone/jone_ws/src/rotors_simulator/rotors_gazebo_plugins/src/external/gazebo_geotagged_images_plugin.cpp:18:
/usr/include/OGRE/Terrain/OgreTerrainPaging.h:33:35: fatal error: OgrePagedWorldSection.h: 没有那个文件或目录
compilation terminated.
就是说通过文件 一层层的include 但是 到 OgrePagedWorldSection.h 这个文件的时候没有找到
这是因为 OGRE 这个路径没有包含进来
打开 rotors_simulator/rotors_gazebo_plugins/CMakeLists.txt
这个文件
在里面添加
include_directories(${ADDITIONAL_INCLUDE_DIRS} ${OGRE_INCLUDE_DIRS}/Paging)
第三次编译
之前的错误就没了
启动仿真
编写如下launch文件,来启动一个无人机悬停的仿真
<launch>
<arg name="mav_name" default="firefly"/>
<arg name="world_name" default="basic"/>
<arg name="enable_logging" default="false" />
<arg name="enable_ground_truth" default="true" />
<arg name="log_file" default="$(arg mav_name)" />
<arg name="debug" default="false"/>
<arg name="gui" default="true"/>
<arg name="paused" default="true"/>
<!-- The following line causes gzmsg and gzerr messages to be printed to the console
(even when Gazebo is started through roslaunch) -->
<arg name="verbose" default="false"/>
<env name="GAZEBO_MODEL_PATH" value="${GAZEBO_MODEL_PATH}:$(find rotors_gazebo)/models"/>
<env name="GAZEBO_RESOURCE_PATH" value="${GAZEBO_RESOURCE_PATH}:$(find rotors_gazebo)/models"/>
<include file="$(find gazebo_ros)/launch/empty_world.launch">
<arg name="world_name" value="$(find rotors_gazebo)/worlds/$(arg world_name).world" />
<arg name="debug" value="$(arg debug)" />
<arg name="paused" value="$(arg paused)" />
<arg name="gui" value="$(arg gui)" />
<arg name="verbose" value="$(arg verbose)"/>
</include>
<group ns="$(arg mav_name)">
<include file="$(find rotors_gazebo)/launch/spawn_mav.launch">
<arg name="mav_name" value="$(arg mav_name)" />
<arg name="model" value="$(find rotors_description)/urdf/mav_generic_odometry_sensor.gazebo" />
<arg name="enable_logging" value="$(arg enable_logging)" />
<arg name="enable_ground_truth" value="$(arg enable_ground_truth)" />
<arg name="log_file" value="$(arg log_file)"/>
</include>
<node name="lee_position_controller_node" pkg="rotors_control" type="lee_position_controller_node" output="screen">
<rosparam command="load" file="$(find rotors_gazebo)/resource/lee_controller_$(arg mav_name).yaml" />
<rosparam command="load" file="$(find rotors_gazebo)/resource/$(arg mav_name).yaml" />
<remap from="odometry" to="odometry_sensor1/odometry" />
</node>
<node name="hovering_example" pkg="rotors_gazebo" type="hovering_example" output="screen"/>
<node name="robot_state_publisher" pkg="robot_state_publisher" type="robot_state_publisher" />
<node name="joint_state_publisher" pkg="joint_state_publisher" type="joint_state_publisher" />
</group>
</launch>
其中world的配置还是非常多的,可以打开 rotors_gazebo 文件夹下的 worlds文件夹,里面有
- basic.world
- delta_wing.world
- empty.world
- hemicy.world
- house.world
- iris.world
- outdoor.world
- pelican.world
- plane.world
- rubble.world
等等
其中 launch文件启动的 lee_position_controller_node 节点的核心代码 就是下面
void LeePositionControllerNode::OdometryCallback(const nav_msgs::OdometryConstPtr& odometry_msg) {
ROS_INFO_ONCE("LeePositionController got first odometry message.");
EigenOdometry odometry;
eigenOdometryFromMsg(odometry_msg, &odometry);
lee_position_controller_.SetOdometry(odometry);
Eigen::VectorXd ref_rotor_velocities;
lee_position_controller_.CalculateRotorVelocities(&ref_rotor_velocities);
// Todo(ffurrer): Do this in the conversions header.
mav_msgs::ActuatorsPtr actuator_msg(new mav_msgs::Actuators);
actuator_msg->angular_velocities.clear();
for (int i = 0; i < ref_rotor_velocities.size(); i++)
actuator_msg->angular_velocities.push_back(ref_rotor_velocities[i]);
actuator_msg->header.stamp = odometry_msg->header.stamp;
motor_velocity_reference_pub_.publish(actuator_msg);
}
将位置偏差转换成速度
启动
roslaunch rotors_gazebo mav_hovering_example.launch mav_name:=firefly world_name:=basic