Skip to main content

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 and find_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 to True to 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 to dialout and re-log.
  • Mode won’t change: ensure TX mode switch isn’t overriding; check pre-arm checks and link quality (STATUSTEXT).
  • No AUTOPILOT_VERSION: ensure SERIAL0_PROTOCOL=2 and you’re connected to the MAVLink port.

📚 References


📜 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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pixhawkcontroller-0.0.2.tar.gz (28.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pixhawkcontroller-0.0.2-py3-none-any.whl (24.5 kB view details)

Uploaded Python 3

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

Hashes for pixhawkcontroller-0.0.2.tar.gz
Algorithm Hash digest
SHA256 bce6d6be0cf8ca99e76ddad3a0e449f8051f99ff95eb790cb012e42693de02d2
MD5 fca56e953c80a172154e4e16de0c2bf4
BLAKE2b-256 468477018982d63c321c693b69e27e35e7503b86c09e46d2825581a062dae2a3

See more details on using hashes here.

File details

Details for the file pixhawkcontroller-0.0.2-py3-none-any.whl.

File metadata

File hashes

Hashes for pixhawkcontroller-0.0.2-py3-none-any.whl
Algorithm Hash digest
SHA256 c4ae6ffb57fba45baa867297da9cb487410c96d3d1358ca3ca22d4e1dc4b4c36
MD5 1a8ce3349aa1033947d0e4ab402994f5
BLAKE2b-256 c6b6e3a53132622615e41ab52ac6e8aa2b3beb68549f81eb154e7b29b364cd53

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page