Outdoor testing of fixed-wing uncrewed aerial vehicles (UAVs) remains inherently risky, as winged platforms cannot rapidly transition to a safe hover state following malfunction. Existing safety approaches, including wind-tunnel confinement and onboard parachute systems, either restrict the flight envelope or are impractical for lightweight aircraft. We present the Winged Aircraft Safety Platform (WASP), a motorized, cable-guided robotic system designed to enable safe, tethered outdoor flight testing of fixed-wing UAVs. The WASP autonomously tracks a UAV using onboard vision and positions itself above the aircraft, maintaining a lightweight safety tether (< 5 g) capable of preventing ground impact in the event of failure. Beyond safety, the system functions as a mobile measurement platform. By integrating encoder-based motion sensing, vision-based pose estimation, and real-time three-dimensional wind measurements from an ultrasonic anemometer, the WASP reconstructs the UAV’s full flight state, including position, velocity, attitude, airspeed, angle of attack, and sideslip angle. Outdoor experiments conducted over a 70 m cable span demonstrate stable tracking at speeds up to 14 m/s with accelerations of 8 m/s², and close agreement between WASP-derived aerodynamic estimates and onboard sensor measurements. By combining safety and data collection, WASP accelerates the development of next-generation winged UAVs.
The full CAD model of the WASP is available on Onshape. The robot structure is primarily made from 2 mm folded aluminum sheets, while the custom functional parts are 3D-printed in PLA. The outer ring of the drive wheel is printed in TPU, which provides friction between the drivetrain and the 2 mm diameter steel cable. Because this TPU layer gradually wears out after repeated runs, it may need to be replaced occasionally. Without listing all standard hardware components such as screws, nuts, bearings, hooks, and magnets, the main elements of the system are summarized below:
Once fully assembled, the platform looks as follows:
![]() |
![]() |
![]() |
![]() |
-
Connect the Raspberry Pi to a Wi-Fi network. For outdoor use, a smartphone hotspot is recommended. This initial setup requires a screen, keyboard, and mouse connected to the Raspberry Pi.
-
Connect a laptop to the same network, then access the Raspberry Pi via SSH:
ssh lis@raspberrypi.local
(Once the Raspberry Pi reconnects automatically to the same hotspot, it can be used as a standalone system without a screen, keyboard, or mouse.)
-
Optional: in VS Code on your laptop, use the Remote SSH extension for easier access to the Raspberry Pi files and code.
-
From the Raspberry Pi (accessed through SSH), clone this repository to the desired location. For the installation steps below, a wired internet connection is recommended if available.
git clone https://github.com/your-username/safe-outdoor-flight.git -
Navigate to the project directory, create a virtual environment, and activate it.
cd Documents/safe-outdoor-flight python -m venv myenv source myenv/bin/activate -
Install the project dependencies:
pip install -r requirements.txt
-
Print the calibration checkerboard located at
src/camera_calib/checker_200x150_5x8_24.pdf. -
Run the following command and move the checkerboard in front of the camera so that it covers as much of the field of view as possible. For more details, see the OpenCV documentation.
python3 camera_ctrl.py calibrate_camera -
Once calibration is complete, the file
src/camera_calib/calib_data/calib_data.npzis generated and can be used to undistort the captured images.If you encounter some issues with the camera, the following resources may be helpful: [1], [2].
-
Run the following command on the Raspberry Pi to install the ODrive USB device rules, grant non-root access permissions, and allow Python to communicate with the ODrive without using sudo:
sudo bash -c "curl https://cdn.odriverobotics.com/files/odrive-udev-rules.rules > /etc/udev/rules.d/91-odrive.rules && udevadm control --reload-rules && udevadm trigger" -
Make sure the motor shaft, magnet, and encoder are properly aligned, and that there is no mechanical play in the assembly.
-
Power the ODrive S1 from an external battery, connect it to the laptop via the USB isolator, open the ODrive GUI, and follow the calibration procedure. Using Google Chrome is recommended for this step. For more details, refer to the ODrive documentation.
This section describes how to deploy the WASP system and run a tracking experiment.
-
Print the ArUco marker located at:
src/camera_calib/DICT_4X4_50_ID_7_SIZE_400px.png. -
Attach the marker to the UAV that the WASP should track.
If you want to generate a different marker, see the
generate_markers()function incamera_ctrl.py.
On the laptop connected via SSH to the WASP, create a
tmux session so the program can keep running even if the SSH connection drops:
tmuxIf you become detached from the session, reattach with:
tmux a -t0
Place the WASP on the cable and run:
python3 main.py
When the program starts, the system enters calibration mode.
The WASP must first learn the limits of the cable on which it moves.
If another flight is performed on the same day, the saved calibration can be reused. To do so, move the WASP directly to the start of the cable and set only the start position (turn calibration wheel counter-clockwise). Setting a new end position will overwrite the previously saved calibration.
During hand launch, the UAV may accelerate faster than the perception pipeline can react. To address this, a dedicated takeoff sequence is implemented. In this mode:
- the WASP first performs a short back-and-forth motion to allow the operator to synchronize the launch (3 times),
- it then accelerates automatically to a user-defined velocity (4th back-and-forth motion),
- once this velocity is reached, the controller automatically transitions to normal tracking mode.
This mode can be activated using the dedicated switch on the remote controller.
If the assisted takeoff duration appears incorrect, or if the ArUco detection becomes inconsistent, the relevant parameters can be tuned using the dedicated knobs on the remote controller.
When the program is terminated, all recorded data are automatically saved as .csv files. If multiple runs are required without stopping the program, the calibration/reset wheel can be used to start a new log file. When not in calibration mode, turning the wheel to its minimum or maximum position will save the current dataset to .csv files and create new files for the upcoming run.
After each run, the system automatically saves the recorded data in the following files:
-
data/run_YYYY-MM-DD_HH-MM-SS/data_YYYY-MM-DD_HH-MM-SS.csv: containing encoder measurements and vision-based tracking data, -
data/run_YYYY-MM-DD_HH-MM-SS/wind_data_YYYY-MM-DD_HH-MM-SS.csv: containing all measurements from the wind sensor.
To analyze a run, the script utils/run_analysis.py can be used. This script:
- merges the encoder, vision, and wind sensor datasets,
- computes the airspeed, angle of attack, and angle of sideslip of the tracked UAV,
- generates plots of the relevant flight data for post-flight analysis.
- Authors: Cyril Goffin & Simon Jeger
- Affiliation: Laboratory of Intelligent Systems (LIS), EPFL
- Publication: Winged Aircraft Safety Platform (WASP) Enables Safe Outdoor Flight Test





