前言

无人机仿真主要分为两类:硬件在环仿真(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

在这里插入图片描述