.hack//tk

.hack//tk

yet another technology blog

Controlling simulated drones using ROS

ROS, the Robot Operating System, is a collection of frameworks for robot software development created in 2007. The development status is active, so they are actively releasing new versions of ROS. It provides tools and client library implementations in C++, Python, and Lisp. It is one of the biggest open source projects for robotics.

Today, we are going to control simulated drones, using ROS. A drone, also known as UAV, Unmanned Aerial Vehicle, is an aircraft without a human pilot aboard. The one we are going to operate is going to be a quadcopter, a multirotor helicopter propelled by four rotors.

For this tutorial also, we are going to replace the default SITL Copter simulator with one supplied by Gazebo and control the autopilot using the ROS (instead of Mavproxy or some other Ground Control System.

Installing ROS Jade

In this tutorial, we’re using Ubuntu 14.04 since ROS Jade only supports Trusty (14.04), Utopic (14.10) and Vivid (15.04).

Setup your sources.list and keys

Make sure Ubuntu restricted, universe and multiverse repositories are allowed.

1
2
sudo sh -c 'echo "deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/ros-latest.list'
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-key 0xB01FA116
Installation

desktop-full package provides us ROS, rqt, rviz, robot-generic libraries, 2D/3D simulators, navigation and 2D/3D perception.

1
2
3
sudo apt-get update
sudo apt-get upgrade
sudo apt-get install ros-jade-desktop-full ros-jade-octomap-msgs ros-jade-joy
Initialize rosdep

rosdep enables you to easily install system dependencies.

1
2
sudo rosdep init
rosdep update

Installing Gazebo

The major version of Gazebo present in ROS is selected at the beginning of the ROS release cycle and will be kept (due to binary compatibility reasons) during the whole life of the ROS distribution. ROS Jade is compatible with gazebo-5.x series. More information about this.

Setup your sources.list and keys

Make sure Ubuntu restricted, universe and multiverse repositories are allowed.

1
2
sudo sh -c 'echo "deb http://packages.osrfoundation.org/gazebo/ubuntu `lsb_release -cs` main" > /etc/apt/sources.list.d/gazebo-latest.list'
wget http://packages.osrfoundation.org/gazebo.key -O - | sudo apt-key add -
Installation
1
2
sudo apt-get update
sudo apt-get install gazebo5 libgazebo5-dev
Check your installation

The first time Gazebo is executed it will download some models and it could take some time until it finishes, the screen will remain black, please be patient.

1
gazebo

Configure ROS and Gazebo integration

Configuring ROS environment and workspace

It’s convenient if the ROS environment variables are automatically added to your bash session every time a new shell is launched:

1
2
echo "source /opt/ros/jade/setup.bash" >> ~/.bashrc
source ~/.bashrc

Let’s create a catkin workspace:

1
2
3
mkdir -p ~/catkin_ws/src
cd ~/catkin_ws/src
catkin_init_workspace

Even though the workspace is empty, you can still build the workspace:

1
2
cd ~/catkin_ws
catkin_make

Set ROS workspace variables automatically to your bash session:

1
2
echo "source ~/catkin_ws/devel/setup.bash" >> ~/.bashrc
source ~/.bashrc
Running ROS and Gazebo

The first time Gazebo is executed with ROS it may take some time, the screen will remain black, please be patient.

1
2
roscore &
rosrun gazebo_ros gazebo

The rostopic list command will give us a list of ROS topics, make sure Gazebo topics are on this list.

1
rostopic list

Drawing

The rosservice list command will give us a list of ROS services, make sure Gazebo services are on this list.

1
rosservice list

Drawing

Installing MAVROS and Ardupilot’s SITL

Install required packages
1
2
3
4
sudo apt-get install python-matplotlib python-serial python-wxgtk2.8 python-lxml python-scipy python-opencv ccache gawk git python-pip python-pexpect
sudo pip install pymavlink MAVProxy
echo "export PATH=/usr/lib/ccache:$PATH" >> ~/.bashrc
source ~/.bashrc
Installation

In this tutorial, we’ll use an Ardupilot’s fork that already contains SITL mode for ROS/Gazebo.

1
2
3
git clone https://github.com/alexbuyval/ardupilot -b RangeFinderSITL2 ~/ardupilot
echo "export PATH=$PATH:$HOME/ardupilot/Tools/autotest" >> ~/.bashrc
source ~/.bashrc

These are some other dependencies that we’ll install inside catkin workspace, some are forks that already contain modes for ROS/Gazebo.

1
2
3
4
5
6
7
8
9
10
11
cd ~/catkin_ws/src/
git clone https://alexbuyval@bitbucket.org/alexbuyval/arducopter_sitl_ros.git
cd arducopter_sitl_ros && sed -i '/teleop/d' launch/launcher.launch && cd ..
git clone https://github.com/PX4/mav_comm.git
git clone https://github.com/catkin/catkin_simple.git
git clone https://github.com/alexbuyval/mavros.git
cd ..
rosdep install --from-paths src --ignore-src --rosdistro jade -y
cd src
git clone https://github.com/alexbuyval/rotors_simulator.git -b sonar_plugin
git clone https://github.com/ethz-asl/glog_catkin.git

After downloading all required packages, build using ROS infrastructure catkin_make.

1
2
cd ..
catkin_make

Running

Start the simulation

Enter the ArduCopter directory and start the SITL simulation.

1
2
cd ~/ardupilot/ArduCopter
sim_vehicle.sh -f arducopter_sitl_ros --console

The first time you run this command Gazebo screen will be black for some time (it may take some minutes) until it loads the models. Be patient. You might need to reload Gazebo again.
If everything works properly you will see a Gazebo window similar to the one the below.

The rostopic list command will give us a list of ROS topics, make sure Gazebo, Mavros, and QuadX450 topics are on this list.

1
rostopic list

Drawing

The rosservice list command will give us a list of ROS services, make sure Gazebo, Mavros, and QuadX450 services are on this list.

1
rosservice list

Drawing

Controlling the simulation through ROS

Now we’ll control the simulation through a script that communicates with mavros node and controls the drone in the simulation.

First, make sure the drone in the simulation is ready to receive messages, the HEARTBEAT must be connected and the propellers must be moving.

This script is written in Python and teleoperates the drone using a keyboard. First, we’ll set drone mode to Guided Mode, then arm it and do a simple takeoff.

Note: This commands must be used only after the drone is ready to receive them, if you’re receiving RC or Compass warnings, the drone won’t fly. Make sure all the commands were successful by looking at the simulation terminal.

1
2
3
4
5
cd ~/catkin_ws/src/mavros/mavros_extras/scripts/
./mavkbteleop -rc
G (Guided Mode)
a (Arm)
t (Takeoff)

If everything works as expected, the drone will fly away (:

You can take a look at ROS Nodes graph by running rqt utility with Nodes Graph plugin.
Menu Bar -> Plugins -> Introspection -> Node Graph. The node graph must look like the one below.

Script code explained

The script we used to teleoperate the drone is written in Python and uses ROS API to send messages through topics and call services. If you’re not familiar with this concepts I highly recommend you to take a look at this ROS tutorials understanding topics and understanding services.

Once you’re familiar with ROS topics and services concepts we’ll start to see this in action in our teleoperation script. The full script can be found on Github.

1
rospy.init_node("mavteleop")

One of the first calls you will likely execute in a rospy program is the call to rospy.init_node(), which initializes the ROS node for the process. You can only have one node in a rospy process, so you can only call it once.

1
override_pub = rospy.Publisher(args.mavros_ns + "/rc/override", OverrideRCIn, queue_size=10)

rospy.Publisher() declares that your node is publishing to the /mavros/rc/override topic using the message type OverrideRCIn. The queue_size limits the amount of queued messages if any subscriber is not receiving them fast enough.

1
2
3
4
5
6
7
8
9
rc = OverrideRCIn()
rc.channels[0] = roll
rc.channels[1] = pitch
rc.channels[2] = throttle_ch
rc.channels[3] = yaw
rc.channels[4] = 1000
rc.channels[5] = 1000
rc.channels[6] = 1000
rc.channels[7] = 1000

OverrideRCIn() will create a message of type OverrideRCIn and we’ll fill it with information.

1
override_pub.publish(rc)

override_pub.publish(rc) actually publishes to /mavros/rc/override topic using a newly created rc message.

1
2
3
4
5
6
elif key == 'G':
set_mode(args, "GUIDED")
elif key == 'H':
set_mode(args, "ALT_HOLD")
elif key == 'L':
set_mode(args, "LOITER")

Here we’re using the key filter and set drone mode among GUIDED, ALT_HOLD and LOITER.

1
2
3
4
5
6
7
8
9
10
11
12
def set_mode(args, mode):
try:
setmode_cl = rospy.ServiceProxy(args.mavros_ns + "/set_mode", SetMode)

ret = setmode_cl(base_mode=0, custom_mode=mode)
except rospy.ServiceException as ex:
fault(ex)

if not ret.success:
rospy.loginfo("SET MODE Request failed.")
else:
rospy.loginfo("SET MODE Request success.")

Once the mode is selected, it’s time to set using a service. With rospy.ServiceProxy() we’ll get a container for the request and response type, in this case, service name is /mavros/set_mode and response type is SetMode. rospy.ServiceProxy instances are callable, which means that you can invoke them just as you would with methods, we call it and check its return.

Ready!

This concludes our tutorial on how to control simulated drones using ROS. If you are interested in this topic you can search for popular ROS repositories on Github. There are plenty of open source ROS projects.