Lightweight Pixhawk/ArduPilot controller utilities using pymavlink
Project description
pixhawkcontroller
Lightweight Python utilities to connect and control Pixhawk / ArduPilot flight controllers using pymavlink.
Supports Serial/UDP/TCP, quick telemetry, mission helpers, servo/relay/motor tests, tones, and common MAV_CMD wrappers.
✨ Features
- 🔌 Auto-detect Pixhawk/Cube over USB by VID/PID (configurable defaults).
- 🌐 Serial / UDP / TCP connection strings (
COMx,/dev/ttyUSB*,udp:127.0.0.1:14550,tcp:…). - 🛰 INFO decode from
AUTOPILOT_VERSION+ boot banners (vendor/product, FW/OS git hashes, capabilities). - 🧭 Mode control with family auto-selection (Copter/Plane/Rover).
- 🛠 Servo + RC override helpers with safe reset.
- 🔁 Relay repeat & motor test wrappers.
- 🗺 Mission helpers: start, pause/continue, guided reposition, guided limits, condition delay.
- 🛫/🛬 NAV takeoff / land / RTL shortcuts.
- 🛑 Flight termination (emergency stop — dangerous).
- 🎶 Buzzer tones with QBasic-style strings & optional auto tones.
📦 Installation
# (Optional) virtual environment
python3 -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
# From source (editable)
git clone https://github.com/Shahriar88/pixhawkcontroller.git
cd pixhawkcontroller
pip install -e .
Core dependencies:
pymavlink >= 2.4.41
pyserial >= 3.5
Build/packaging dependencies:
build == 1.3.0
setuptools == 80.9.0
wheel == 0.45.1
twine == 6.2.0
packaging == 25.0
🧩 Project layout
pixhawkcontroller/main.py— main implementation (class, helpers, demos).pixhawkcontroller/__init__.py— public API (exports classes andfind_usb_vid_pid).README.md— this documentation.
🚀 Quick Start
1) List available USB serial devices
Before connecting, you can quickly list all detected USB serial devices with VID/PID information:
from pixhawkcontroller import find_usb_vid_pid
find_usb_vid_pid()
Example output:
USB Serial Devices:
{'port': 'COM5', 'vid': '2dae', 'pid': '1058', 'location': '1-1', 'description': 'CubeOrange+'}
{'port': 'COM6', 'vid': '0483', 'pid': '5740', 'location': '2-3', 'description': 'Pixhawk 2.4.8'}
Use this to identify your Pixhawk/Cube device’s correct VID/PID or port before connecting.
2) Import & connect
from pixhawkcontroller import FlightControllerInterface, TonesQb
# Auto-detect (USB VID/PID)
fc = FlightControllerInterface()
fc.connect()
# Or explicit serial:
# fc = FlightControllerInterface(device='COM3', baudrate=115200) # Windows
# fc = FlightControllerInterface(device='/dev/ttyUSB0', baudrate=115200) # Linux
# fc = FlightControllerInterface(device='/dev/tty.usbmodem14101', baudrate=115200) # macOS
# Or SITL via UDP:
# fc = FlightControllerInterface(device='udp:127.0.0.1:14550')
# fc.connect()
# Or TCP:
# fc = FlightControllerInterface(device='tcp:192.168.1.100:5760')
# fc.connect()
The constructor defaults include a VID/PID pair (CubePilot Orange+ by default) and will auto-scan serial ports when device is not provided.
3) Print board info & telemetry
fc.print_info() # vendor/product, FW/OS hashes, capabilities, IDs
fc.print_telemetry() # mode, family, armed, GPS fix, location, battery
These use AUTOPILOT_VERSION and recent messages (HEARTBEAT, GPS_RAW_INT, GLOBAL_POSITION_INT, SYS_STATUS).
🔌 VID/PID: explicit examples
# ArduPilot Bootloader (USB-CDC) — same as Pixhawk 2.4.8
# Vendor: 0x1209 Product: 0x5741
fc = FlightControllerInterface(vid='1209', pid='5741') # bootloader mode
fc.connect()
# Pixhawk 2.4.8 (STMicroelectronics VCP, ChibiOS)
# Vendor: 0x0483 Product: 0x5740
fc = FlightControllerInterface(vid='0483', pid='5740')
fc.connect()
# Cube+ family (CubePilot)
# Vendor: 0x2DAE Product: 0x1101 (CubeBlack+) or 0x1058 (CubeOrange+)
fc = FlightControllerInterface(vid='2DAE', pid='1058') # CubeOrange+
# fc = FlightControllerInterface(vid='2DAE', pid='1101') # CubeBlack+
fc.connect()
These match the VID/PID map included in the code.
🛰 Mode control (auto family)
fc.set_mode("GUIDED")
fc.set_mode("AUTO")
fc.set_mode("RTL")
fc.set_mode("SMART_RTL")
# Plane example: fc.set_mode("MANUAL") / "FBWA" / "CRUISE"
Vehicle family (copter/plane/rover) is inferred from HEARTBEAT.type.
The method retries via SET_MODE, then falls back to MAV_CMD_DO_SET_MODE if needed.
🛠 Servo / RC override
# Direct servo output (PWM µs)
fc.set_servo(9, 900); time.sleep(2)
fc.set_servo(9, 1500); time.sleep(2)
fc.set_servo(9, 1900)
# RC override (ch1..8). Example: throttle mid for 2 s, then clear.
if not fc.check_arm_status():
fc.arm() # use fc.arm(force=True) to override prechecks (dangerous)
fc.set_rc_pwm(3, 1500)
time.sleep(2)
fc.clear_rc_overrides()
fc.disarm()
Servo uses MAV_CMD_DO_SET_SERVO; RC override uses RC_CHANNELS_OVERRIDE;
check_arm_status() reads MAV_MODE_FLAG_SAFETY_ARMED.
🔁 Relay / Motor test
# Toggle a relay repeatedly (index/count/period)
fc.repeat_relay(relay_number=0, count=10, period_s=2.0)
# Spin motor #1 at 20% for 3 seconds (type=0 → percent)
fc.motor_test(motor_index=1, throttle_type=0, throttle_value=20.0, duration_s=3.0)
Relay uses MAV_CMD_DO_REPEAT_RELAY; motor test uses MAV_CMD_DO_MOTOR_TEST.
🗺 Mission helpers
# Start mission (requires AUTO)
fc.set_mode("AUTO")
fc.mission_start()
# Pause & resume mission
fc.pause_continue_mission(True) # pause
time.sleep(5)
fc.pause_continue_mission(False) # continue
# Reposition in GUIDED (lat, lon, alt), optional speed and auto-switch to GUIDED
lat, lon, alt = 23.911222, 90.254833, 46
fc.do_reposition(lat, lon, alt, speed_m_s=3.0, change_mode_to_guided=True)
# Apply guided limits (timeout and leash)
fc.do_guided_limits(timeout_s=60, horiz_max_m=50)
# Insert condition delay (useful inside a mission)
fc.condition_delay(5)
Covers MAV_CMD_MISSION_START, MAV_CMD_DO_PAUSE_CONTINUE,
MAV_CMD_DO_REPOSITION, MAV_CMD_DO_GUIDED_LIMITS, MAV_CMD_CONDITION_DELAY.
🛫 Takeoff / 🛬 Land / 🔁 RTL / 🛑 Termination
# Takeoff (Copter/Plane; Rover usually ignores)
fc.nav_takeoff(target_alt_m=20.0, min_pitch_deg=0.0)
# Land now (current location by default)
fc.nav_land()
# Return to Launch
fc.return_to_launch()
# Emergency stop (dangerous!)
# fc.flight_termination(True)
Implements MAV_CMD_NAV_TAKEOFF, MAV_CMD_NAV_LAND,
MAV_CMD_NAV_RETURN_TO_LAUNCH, MAV_CMD_DO_FLIGHTTERMINATION.
Use termination only in emergencies — it cuts actuators immediately.
🔊 Tones & auto cues
# Manual tones
from pixhawkcontroller import TonesQb
fc.play_tune(TonesQb.def_tone)
time.sleep(1)
fc.play_tune(TonesQb.twinkle_little_star)
# Optional audible cues on events:
fc.auto_play_tune = True # or False to disable sounds
# (connect/arm/close paths in the code play short cues if enabled)
Tone strings are QBasic-style and compatible with ArduPilot’s tone parser.
🧪 Demo blocks (safe by default)
main.py ships with demo sections gated by flags:
SAFE_DEMO = False— full, commented walkthrough (flip toTrueto run).- A second mini-demo (SITL-friendly) under another
if False:block.
Both demonstrate connection, info/telemetry, modes, servo/RC, mission helpers, guided controls, and cleanup.
🧰 Utility: list USB serials (again)
from pixhawkcontroller import find_usb_vid_pid
find_usb_vid_pid() # prints all USB serial devices with VID/PID/port/description
Use this to identify what VID/PID your board exposes on your OS.
🛡 Safety
- Test in SITL first (no props):
sim_vehicle.py -v Rover --console --map(or Copter/Plane). - Commands like
.arm(),.set_servo(),.set_rc_pwm()can move actuators. - Flight termination immediately stops actuators — only for emergencies.
📘 Examples
List USB serials (before connecting)
from pixhawkcontroller import find_usb_vid_pid
find_usb_vid_pid()
# → prints dicts with port, vid/pid, location, description
Connect (auto-detect or explicit)
from pixhawkcontroller import FlightControllerInterface
# Auto-detect over USB (uses default VID/PID scanning)
fc = FlightControllerInterface()
fc.connect()
# Or explicit serial:
# fc = FlightControllerInterface(device="COM3", baudrate=115200) # Windows
# fc = FlightControllerInterface(device="/dev/ttyUSB0", baudrate=115200) # Linux
# fc = FlightControllerInterface(device="/dev/tty.usbmodem14101", baudrate=115200) # macOS
# fc.connect()
# Or SITL:
# fc = FlightControllerInterface(device="udp:127.0.0.1:14550"); fc.connect()
Board info & quick telemetry
fc.print_info() # Vendor/Product, FW/OS git hashes, capabilities, IDs
fc.print_telemetry() # Mode/Family, Armed, GPS fix, Location, Battery
Explicit VID/PID examples
# Bootloader (USB-CDC) — same vendor/product seen on many Pixhawk bootloaders
fc = FlightControllerInterface(vid="1209", pid="5741"); fc.connect()
# Pixhawk 2.4.8 (ST VCP / ChibiOS)
fc = FlightControllerInterface(vid="0483", pid="5740"); fc.connect()
# Cube+ family (CubePilot)
fc = FlightControllerInterface(vid="2DAE", pid="1058"); fc.connect() # CubeOrange+
# fc = FlightControllerInterface(vid="2DAE", pid="1101"); fc.connect() # CubeBlack+
Change modes (auto family: copter/plane/rover)
fc.set_mode("GUIDED")
fc.set_mode("AUTO")
fc.set_mode("RTL")
fc.set_mode("SMART_RTL")
Arm / RC override (use with caution)
# Arm only if not already armed
if not fc.check_arm_status():
fc.arm() # use fc.arm(force=True) to override prechecks (dangerous)
# Override throttle (ch3) to 1500 µs for 2 seconds, then clear
fc.set_rc_pwm(3, 1500)
import time; time.sleep(2)
fc.clear_rc_overrides()
# Disarm when done
fc.disarm()
Servo control (PWM µs)
import time
fc.set_servo(9, 900); time.sleep(1.5)
fc.set_servo(9, 1500); time.sleep(1.5)
fc.set_servo(9, 1900)
Relay & Motor test
# Toggle relay #0 → 10 cycles, 2.0 s period
fc.repeat_relay(relay_number=0, count=10, period_s=2.0)
# Run motor #1 at 20% for 3s (type=0 → percent)
fc.motor_test(motor_index=1, throttle_type=0, throttle_value=20.0, duration_s=3.0)
Mission helpers
# Start current mission (set AUTO first)
fc.set_mode("AUTO")
fc.mission_start()
# Pause / continue (in AUTO)
fc.pause_continue_mission(True)
time.sleep(5)
fc.pause_continue_mission(False)
Guided reposition & yaw
# Move in GUIDED to a lat/lon/alt at 3 m/s and auto-switch to GUIDED
lat, lon, alt = 23.911222, 90.254833, 46
fc.do_reposition(lat, lon, alt, speed_m_s=3.0, change_mode_to_guided=True)
# Yaw to heading 90° at 30°/s (absolute)
fc.set_yaw_speed(90.0, 30.0, absolute=True)
Guided limits & condition delay
# Limit GUIDED motion (timeout=60s, horizontal leash=50m)
fc.do_guided_limits(timeout_s=60, horiz_max_m=50)
# Insert a 5s delay (useful inside AUTO missions)
fc.condition_delay(5)
Takeoff / Land / RTL / (Emergency) Termination
# Takeoff to 20m (Copter/Plane; Rover usually ignores)
fc.nav_takeoff(target_alt_m=20.0, min_pitch_deg=0.0)
# Land at current location
fc.nav_land()
# Return To Launch
fc.return_to_launch()
# Emergency stop (cuts actuators immediately) — DANGEROUS
# fc.flight_termination(True)
Rover-specific: reverse direction
# Reverse on, wait, then off (Rover only)
fc.set_reverse(True)
time.sleep(1.0)
fc.set_reverse(False)
Tones (QBasic-style) & optional auto cues
from pixhawkcontroller import TonesQb
# Manual tunes
fc.play_tune(TonesQb.def_tone)
time.sleep(1)
fc.play_tune(TonesQb.twinkle_little_star)
# Optional audible cues for events in your methods
fc.auto_play_tune = True # set False to silence
Clean shutdown
# Final snapshot then close
fc.print_telemetry()
if fc.check_arm_status():
fc.disarm()
fc.close()
❓ Troubleshooting
- No device found / auto-detect fails: run
find_usb_vid_pid()and use explicit VID/PID. On Linux, add your user todialoutand re-log. - Mode won’t change: ensure TX mode switch isn’t overriding; check pre-arm checks and link quality (
STATUSTEXT). - No
AUTOPILOT_VERSION: ensureSERIAL0_PROTOCOL=2and you’re connected to the MAVLink port.
📚 References
- ArduPilot MAVLink Commands & Mission Items
- MAVLink Message Definitions
- ArduPilot ToneTester (for previewing tunes)
📜 License
MIT License © 2025 Md Shahriar Forhad See the LICENSE file for full terms.
⚠️ Disclaimer
This software is provided as-is for educational and experimental use only. Use it at your own risk. The author assumes no liability for any damage, injury, or loss resulting from its use.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pixhawkcontroller-0.0.2.tar.gz.
File metadata
- Download URL: pixhawkcontroller-0.0.2.tar.gz
- Upload date:
- Size: 28.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.21
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bce6d6be0cf8ca99e76ddad3a0e449f8051f99ff95eb790cb012e42693de02d2
|
|
| MD5 |
fca56e953c80a172154e4e16de0c2bf4
|
|
| BLAKE2b-256 |
468477018982d63c321c693b69e27e35e7503b86c09e46d2825581a062dae2a3
|
File details
Details for the file pixhawkcontroller-0.0.2-py3-none-any.whl.
File metadata
- Download URL: pixhawkcontroller-0.0.2-py3-none-any.whl
- Upload date:
- Size: 24.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.21
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c4ae6ffb57fba45baa867297da9cb487410c96d3d1358ca3ca22d4e1dc4b4c36
|
|
| MD5 |
1a8ce3349aa1033947d0e4ab402994f5
|
|
| BLAKE2b-256 |
c6b6e3a53132622615e41ab52ac6e8aa2b3beb68549f81eb154e7b29b364cd53
|