Bebop Drone ROS 1 in Docker
Bebop Drone ROS 1 in Docker
Whoever has worked with ROS notices that it takes some time to install it on a new machine. So to containerize it allows you to run ROS on any machine without having to actually install it. This is very useful if you want to run ROS on multiple machines, or you want to have a homogen environment for your ROS project.
Introduction
“it just works on this one computer”
In this post I am showing that it is possible to run the bebop Drone diver together with ROS 1 in a docker container. The docker container is based on the ROS docker image. For this project we are going to use ros:melodic
. The drone driver is based on the Parrot Bebop driver
Prerequisites
- Computer (Linux, Mac or Windows)
- Bebop drone
- Docker and docker compose
- ROS Melodic
- the python library bebop_autonomy
Architecture
┌─────────────────────────────────────────┐
│ Docker compose │
│ ┌──────────────┐ │
│ ┌─►│ ROS Master │◄──┐ │
│ │ └──────────────┘ │ │
│ │ ROS │ ROS │
│ ▼ ▼ │
│ ┌───────────────┐ ROS ┌────────┐ │
│ │ Beebop Driver │◄─────►│ Python │ │
│ └───────────────┘ └────────┘ │
│ │ UDP │
└────────┼────────────────────────────────┘
│ wifi
xx xx
xx xx
xx
xx xx
xx xx
Beebop Drone
The Beebop drone is connected to the computer via wifi. the ROS master, the Beebop driver and the python script each one of them runs in thier own docker container. The Beebop driver is a ROS node that is responsible for the communication with the drone, while python script is a ROS node that is responsible for the control of the drone.
To make this architecture woking we need to make sure that the docker containers can communicate with each other. So all containers are going to be in the same network. Furthermore we need to make sure that the drone connector can communicate directly with the drone. So we have to export the UDP port 43210
from the docker container to the host machine.
Otherwise we get the following error:
connector | [ERROR] [1673947830.046306262]: [ARNETWORK_Sender] 09:30:30:045 | ARNETWORK_Sender_ProcessBufferToSend:405 - [0xffff7c0033d0] Timeout waiting for ack in buffer 11
connector | [ERROR] [1673947830.046451179]: [ARNETWORK_Sender] 09:30:30:046 | ARNETWORK_Sender_ProcessBufferToSend:421 - [0xffff7c0033d0] Will retry sending data of buffer 11
connector | [ERROR] [1673947830.198080554]: [ARNETWORK_Sender] 09:30:30:197 | ARNETWORK_Sender_ProcessBufferToSend:405 - [0xffff7c0033d0] Timeout waiting for ack in buffer 11
connector | [ERROR] [1673947830.198203429]: [ARNETWORK_Sender] 09:30:30:198 | ARNETWORK_Sender_ProcessBufferToSend:421 - [0xffff7c0033d0] Will retry sending data of buffer 11
Docker compose file
The docker compose file is a yaml file that defines the docker containers and the network that they are going to be in. The docker compose file is going to be in the root of the project. The docker compose file is going to look like this:
version: "3"
services:
drone-connector:
container_name: connector
hostname: drone-connector
build: ./ros-drone
environment:
- ROS_HOSTNAME=drone-connector
- ROS_MASTER_URI=http://rosmaster:11311
command: /bin/bash -c "source /entrypoint.sh; sleep 3; roslaunch bebop_driver bebop_node.launch"
ports:
- 43210:43210/udp
networks:
- ros
rosmaster:
container_name: master
hostname: rosmaster
image: ros:melodic
command: roscore
networks:
- ros
controller:
container_name: controller
hostname: controller
build: ./ros-commander
environment:
- ROS_HOSTNAME=controller
- ROS_MASTER_URI=http://rosmaster:11311
command: sleep infinity
volumes:
- ./code:/root/code
networks:
- ros
networks:
ros:
driver: bridge
Unfortunatly there is no image for the bebop driver on docker hub. So we need to build the image ourselves. The docker compose file is going to build the image from the docker file in the ros-drone
folder. The docker file is going to look like this:
FROM ros:melodic
RUN apt-get update && apt-get install build-essential python3-rosdep python3-catkin-tools -y
RUN mkdir -p ~/bebop_ws/src
WORKDIR /root/bebop_ws
RUN git clone https://github.com/AutonomyLab/bebop_autonomy.git src/bebop_autonomy
RUN . /opt/ros/melodic/setup.sh &&\
catkin_init_workspace
RUN rosdep update
RUN rosdep install --from-paths src -i -y
RUN . /opt/ros/melodic/setup.sh &&\
catkin build
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
For the rest we are just going to use the unmodified ROS docker image from docker hub. Although if you need to recieve packages in the python script you would have to use the beeop driver image. There the different types are already installed.
To launch the drone now, we just need to run the following command:
docker-compose up -d
sleep 10 # wait till eveything is up and running
docker exec -it controller /bin/bash -c "source /entrypoint.sh; rostopic pub --once /bebop/takeoff std_msgs/Empty"
sleep 10 # wait till drone is in the air
docker exec -it controller /bin/bash -c "source /entrypoint.sh; rostopic pub --once /bebop/land std_msgs/Empty"
Summary
So we can see, it is possible to run applications like that in a Dockercontainer. Unfortunatly it can get a bit messy using the beebop costum ROS messages in the python, but also doable.
Source code
A working demo can be found here: https://github.com/dscso/drone-control/tree/master/docker