Getting Started with cf.PyControl

cf.PyControl is a high-level controller for Crazyflie drones with a web-based API.

At its core, drone behavior is governed by an internal state machine, which defines how the Crazyflie should act under various conditions. These state transitions and actions can be triggered externally via HTTP web endpoints, making the controller easy to integrate with other tools or platforms.

This page will guide you through installing and using cf.PyControl, which is provided in a reproducible and portable way using Docker containers.


Note: This page assumes that you know the radio URI of your Crazyflie drone.

  • The default radio URI for real Crazyflie probably is radio://0/80/2M/E7E7E7E7E7 or radio://0/80/2M/E7E7E7E7E1.
  • If you are using a virtual Crazyflie, the default radio URI is radio://0/80/2M/e7e7e7e701.

Note: Make sure you have at least the flow deck installed if you use a real Crazyflie drone.


Starting the Docker container

There are two Docker containers that provide the cf.PyControl web interface:

Standalone

You can start the cf.PyControl Docker container as follows:

$ cd ~/uniagent_ws/cps.asset.crazyflie/controller/cf.PyControl
$ sudo docker run --rm -it \
--device-cgroup-rule='c 189:* rmw' -v /run/udev:/run/udev:ro -v /dev:/dev \
--net=host --ipc=host --pid=host \
--env="DISPLAY" \
--volume /tmp/.X11-unix:/tmp/.X11-unix:rw \
cf-py-ctrl

This does not contain any simulation environment. Just the cf.PyControl web interface.

It also contains the cfclient tool to configure and control the Crazyflie.

Within sim_cf2 Gazebo simulation environment

The simulation asset featuring the sim_cf2 Gazebo simulation environment also includes cf.PyControl. This assumes that you have installed the cf2_ros2_simu Docker container as explained in the previous page. Start it like this:

$ cd ~/uniagent_ws/cps.asset.crazyflie/simulation/simulation-sim_cf2
$ sudo docker run --rm -it \
--device-cgroup-rule='c 189:* rmw' -v /run/udev:/run/udev:ro -v /dev:/dev \
--env ROS_DOMAIN_ID=30 \
--net=host --ipc=host --pid=host \
--env DISPLAY \
--volume /tmp/.X11-unix:/tmp/.X11-unix:rw \
cf2_ros2_simu

Place the Crazyflie on the Ground


Note: If you have a simulated Crazyflie, you can skip this step and proceed with the next section. Be sure to run a Crazyflie Firmware SITL Instance in the Docker container as described in Getting Started with Gazebo.


Place the Crazyflie securely on the ground and switch on the Crazyflie:

crazyflie on a orange landing pad

Start the Python Controller

Inside the Docker container execute the following command to start the Crazyflie controller:

# cd /home/user/dev_ws/libs/crazyflie-controller/bin
# ./cf.pycontrol-start.sh --uri radio://0/80/2M/E7E7E7E701 --port 5000 --wsendpoint --wsport 8765
# ./cf.pycontrol-start.sh --uri radio://0/80/2M/E7E7E7E702 --port 5001 --wsendpoint --wsport 8766 --sim
  • It is the same command inside the same folder for the Standalone Docker container and the Docker container with the sim_cf2 Gazebo simulation environment.
  • The ports are changed to avoid conflicts. The second variation uses the --sim flag, which enables the simulation mode.

Parameters

  • Adjust the radio address with --uri as needed or configure it with the tool cfclient.
  • The output of the command reveals the URL of the webservice at the end:
--[installed] cflib.crtp.init_drivers() ...
--[installed] SIM_MODE = False
--[installed] URI of drone = radio://0/80/2M/E7E7E7E7E1
--[installed] Installing software packages now ...
...
--[active] Hardware checks completed.
--[active] The drone is ready to take commands.
--[active] Check available commands here:
--[active] http://0.0.0.0:5000/routes
  • Adjust the webservice port with --port [PORT_NUMBER] when running multiple instances of the controller.
  • Adjust the websocket port with --wsendpoint --wsport [PORT_NUMBER] when running multiple instances of the controller.
  • Use the --sim flag to enable the simulation mode (to connect to a simulated Crazyflie).

Overview of the Actions of the Crazyflie

After opening the URL http://0.0.0.0:5000/routes in the browser, you will see all available commands of the Crazyflies internal state machine:

crazyflie actions as webservice

You can also use curl to inspect the available routes:

$ curl http://0.0.0.0:5000/routes

Note: As indicated by the $ sign in front of the curl command, we can communicate with the controller from the host system since the Docker container is connected to the host system via the --net=host flag.


State machine

A picture of the state machine governing the Crazyflie behavior is depicted below:

State machine of the Crazyflie drone

Basic Commands

A detailed list of all commands is available in the respective README of the cf.PyControl repository.

First, activate the drone to release the software-based security lock:

$ curl -d {} http://127.0.0.1:5000/activate_idle

Execute the following command to take off. The drone take offs to a height of 0.5 meters (default internal value).

$ curl -d {} http://127.0.0.1:5000/begin_takeoff

The next command will navigate the drone to the position (1.0, 1.0, 0.5)

$ curl -d {} http://localhost:5000/navigate/1.0/1.0/0.5

Sequential Commands

The following commands will take off the drone and then land it again. The commands are executed sequentially:

$ curl -d {} http://127.0.0.1:5000/activate_idle && \
  curl -d {} http://127.0.0.1:5000/begin_takeoff && \
  curl -d {} http://127.0.0.1:5000/begin_landing

The internal state machine will take care of the transition between the states. If one request fails, the state machine will remain in the last working state.

The ground effect is visible when landing the tiny drone.

Monitoring the Crazyflie

  • View the output of the controller in the terminal
  • Connect to the websocket server to receive the output of the Crazyflie status such as position, velocity, and battery level.

Websocket Server

The websocket server is started with the --wsendpoint --wsport flag. Therefore, open a new Docker container and connect to the websocket server:

$ cd ~/uniagent_ws/cps.asset.crazyflie/simulation/simulation-sim_cf2/test
$ chmod +x ./websocat
$ ./websocat ws://localhost:8765

Change the address to the port of the cf.PyControl websocket server.

The output will be similar to the following:

{"message": "Hello from server", "value": "[0.008031126111745834, 0.0044101448729634285, 0.016471806913614273]"}
{"message": "Hello from server", "value": "[0.008386319503188133, 0.004009794909507036, 0.017738545313477516]"}
{"message": "Hello from server", "value": "[0.008612623438239098, 0.0049172802828252316, 0.01688111387193203]"}
{"message": "Hello from server", "value": "[0.009156611748039722, 0.004726157523691654, 0.016807764768600464]"}

Troubleshooting

If you get connection errors such as "Too many packets lost":

--[starting] Connecting to drone now ...
Traceback (most recent call last):
  File "/home/user/dev_ws/libs/crazyflie-controller/src/cf-ctrl-service.py", line 281, in <module>
    with SyncCrazyflie(URI, cf=Crazyflie(rw_cache='./cache')) as scf:
  File "/usr/local/lib/python3.10/dist-packages/cflib/crazyflie/syncCrazyflie.py", line 119, in __enter__
    self.open_link()
  File "/usr/local/lib/python3.10/dist-packages/cflib/crazyflie/syncCrazyflie.py", line 95, in open_link
    raise Exception(self._error_message)
Exception: Too many packets lost

Try to:

  • Restart the Crazyflie
  • Unplug the Crazyradio PA from the USB port and plug it in again, then restart the Crazyflie
  • Check the battery status with cfclient and recharge if necessary.
  • When executed curl commands to communicate with the controller inside the Docker container, make sure to use the --net=host flag to connect to the host system.
Previous Next