Try Live
Add Docs
Rankings
Pricing
Enterprise
Docs
Install
Install
Docs
Pricing
Enterprise
More...
More...
Try Live
Rankings
Add Docs
Mission Planner
https://github.com/ardupilot/missionplanner
Admin
Mission Planner is a ground control station for ArduPilot that enables planning, monitoring, and
...
Tokens:
46,046
Snippets:
885
Trust Score:
9.3
Update:
3 weeks ago
Context
Skills
Chat
Benchmark
60.4
Suggestions
Latest
Show doc for...
Code
Info
Show Results
Context Summary (auto-generated)
Raw
Copy
Link
# Mission Planner Mission Planner is a full-featured ground control station (GCS) for ArduPilot-based autonomous vehicles, including copters, planes, rovers, and submarines. It provides real-time telemetry display, mission planning with waypoints and geofences, firmware updates, sensor calibration, log analysis, and support for multiple vehicle types through the MAVLink protocol. The application is built with C# and Windows Forms, supporting both Windows and Linux (via Mono), with experimental macOS/iOS support. Mission Planner communicates with flight controllers over serial, TCP, UDP, and Bluetooth connections, offering comprehensive vehicle configuration through parameter management, HUD (Heads-Up Display) visualization, and extensive plugin support for customization. ## Core MAVLink Interface The MAVLinkInterface class is the primary communication layer between Mission Planner and ArduPilot flight controllers. It handles connection establishment, heartbeat detection, message parsing, and provides access to vehicle state and parameters. ```csharp using MissionPlanner; using MissionPlanner.Comms; // Create MAVLink interface instance MAVLinkInterface mavlink = new MAVLinkInterface(); // Configure serial port connection SerialPort serialPort = new SerialPort("COM3", 115200); mavlink.BaseStream = serialPort; // Subscribe to packet received events mavlink.OnPacketReceived += (sender, message) => { Console.WriteLine($"Received: {message.msgid} from {message.sysid}/{message.compid}"); if (message.msgid == (uint)MAVLink.MAVLINK_MSG_ID.HEARTBEAT) { var heartbeat = message.ToStructure<MAVLink.mavlink_heartbeat_t>(); Console.WriteLine($"Vehicle Type: {heartbeat.type}, Autopilot: {heartbeat.autopilot}"); } }; // Open connection with parameter download mavlink.Open(getparams: true); // Access current vehicle state CurrentState cs = mavlink.MAV.cs; Console.WriteLine($"Position: {cs.lat}, {cs.lng}, Alt: {cs.alt}m"); Console.WriteLine($"Attitude: Roll={cs.roll}, Pitch={cs.pitch}, Yaw={cs.yaw}"); Console.WriteLine($"Battery: {cs.battery_voltage}V, {cs.battery_remaining}%"); // Close connection when done mavlink.Close(); ``` ## CurrentState Telemetry Access The CurrentState class provides real-time access to all vehicle telemetry data including position, attitude, battery status, GPS info, and sensor readings. It automatically updates from incoming MAVLink messages. ```csharp using MissionPlanner; // Access the current state through the active connection CurrentState cs = MainV2.comPort.MAV.cs; // Position data double latitude = cs.lat; // Latitude in decimal degrees double longitude = cs.lng; // Longitude in decimal degrees float altitude = cs.alt; // Altitude relative to home (meters) float altitudeASL = cs.altasl; // Altitude above sea level (meters) float groundSpeed = cs.groundspeed; // Ground speed (m/s) float airSpeed = cs.airspeed; // Air speed (m/s) float climbRate = cs.climbrate; // Vertical speed (m/s) // Attitude data float roll = cs.roll; // Roll angle (degrees) float pitch = cs.pitch; // Pitch angle (degrees) float yaw = cs.yaw; // Heading (degrees, 0-360) float groundCourse = cs.groundcourse; // Ground track heading (degrees) // Battery information double batteryVoltage = cs.battery_voltage; // Battery voltage (V) double batteryCurrent = cs.current; // Current draw (A) int batteryRemaining = cs.battery_remaining; // Battery percentage // GPS status float gpsStatus = cs.gpsstatus; // GPS fix type (0-6) float gpsHDOP = cs.gpshdop; // GPS horizontal dilution of precision float satCount = cs.satcount; // Number of satellites // Flight mode string mode = cs.mode; // Current flight mode name bool armed = cs.armed; // Armed status bool connected = cs.connected; // Connection status // Home location PointLatLngAlt home = cs.HomeLocation; Console.WriteLine($"Home: {home.Lat}, {home.Lng}, Alt: {home.Alt}m"); // Distance and bearing to home float distToHome = cs.DistToHome; // Distance in configured units float dirToHome = cs.DirToHome; // Bearing to home (degrees) ``` ## Mission Upload and Download The mav_mission class provides async methods for uploading and downloading waypoint missions, geofences, and rally points to/from the flight controller. ```csharp using MissionPlanner; using MissionPlanner.ArduPilot; using MissionPlanner.Utilities; using System.Collections.Generic; using System.Threading.Tasks; // Download mission waypoints from vehicle async Task<List<Locationwp>> DownloadMission(MAVLinkInterface port) { byte sysid = port.MAV.sysid; byte compid = port.MAV.compid; var waypoints = await mav_mission.download( port, sysid, compid, MAVLink.MAV_MISSION_TYPE.MISSION, (progress, status) => Console.WriteLine($"{progress}%: {status}") ); foreach (var wp in waypoints) { Console.WriteLine($"WP {wp.id}: Lat={wp.lat}, Lng={wp.lng}, Alt={wp.alt}m, Cmd={wp.id}"); } return waypoints; } // Create and upload a mission async Task UploadMission(MAVLinkInterface port) { var mission = new List<Locationwp>(); // Home position (WP 0) mission.Add(new Locationwp { id = (ushort)MAVLink.MAV_CMD.WAYPOINT, lat = -35.363261, lng = 149.165230, alt = 0, frame = (byte)MAVLink.MAV_FRAME.GLOBAL_RELATIVE_ALT }); // Takeoff command mission.Add(new Locationwp { id = (ushort)MAVLink.MAV_CMD.TAKEOFF, lat = 0, lng = 0, alt = 20, // Takeoff to 20m p1 = 15, // Pitch angle frame = (byte)MAVLink.MAV_FRAME.GLOBAL_RELATIVE_ALT }); // Waypoint 1 mission.Add(new Locationwp { id = (ushort)MAVLink.MAV_CMD.WAYPOINT, lat = -35.362500, lng = 149.166000, alt = 30, frame = (byte)MAVLink.MAV_FRAME.GLOBAL_RELATIVE_ALT }); // Return to launch mission.Add(new Locationwp { id = (ushort)MAVLink.MAV_CMD.RETURN_TO_LAUNCH, lat = 0, lng = 0, alt = 0, frame = (byte)MAVLink.MAV_FRAME.GLOBAL_RELATIVE_ALT }); // Upload mission await mav_mission.upload( port, port.MAV.sysid, port.MAV.compid, MAVLink.MAV_MISSION_TYPE.MISSION, mission, (progress, status) => Console.WriteLine($"{progress}%: {status}") ); } ``` ## Geofence Management The Fence class provides methods for downloading, uploading, and managing geofence boundaries including inclusion/exclusion polygons and circles. ```csharp using MissionPlanner; using MissionPlanner.Utilities; using MissionPlanner.ArduPilot; using System.Collections.Generic; // Initialize fence manager Fence fence = new Fence(); // Download existing fence from vehicle fence.DownloadFence(MainV2.comPort, (progress, status) => { Console.WriteLine($"Fence download: {progress}% - {status}"); }); // Create new fence configuration fence.Fences.Clear(); // Add inclusion polygon (vehicle must stay inside) var inclusionPoly = new FencePolygon { Mode = FencePolygon.PolyType.Inclusive }; inclusionPoly.Points.Add(new PointLatLngAlt(-35.360, 149.160)); inclusionPoly.Points.Add(new PointLatLngAlt(-35.360, 149.170)); inclusionPoly.Points.Add(new PointLatLngAlt(-35.370, 149.170)); inclusionPoly.Points.Add(new PointLatLngAlt(-35.370, 149.160)); fence.Fences.Add(inclusionPoly); // Add exclusion circle (no-fly zone) var exclusionCircle = new FenceCircle { Mode = FenceCircle.PolyType.Exclusive, Center = new PointLatLngAlt(-35.365, 149.165), Radius = 50 // 50 meter radius }; fence.Fences.Add(exclusionCircle); // Add return point var returnPoint = new FenceReturn { Return = new PointLatLngAlt(-35.363, 149.165) }; fence.Fences.Add(returnPoint); // Upload fence to vehicle fence.UploadFence(MainV2.comPort, (progress, status) => { Console.WriteLine($"Fence upload: {progress}% - {status}"); }); // Convert fence to mission items for inspection List<Locationwp> fenceItems = fence.FenceToLocation(); foreach (var item in fenceItems) { Console.WriteLine($"Fence item: CMD={item.id}, Lat={item.lat}, Lng={item.lng}"); } ``` ## Plugin Development Mission Planner supports a plugin architecture allowing developers to extend functionality. Plugins have access to vehicle state, MAVLink interface, map controls, and UI elements. ```csharp using MissionPlanner.Plugin; using MissionPlanner; using MissionPlanner.Utilities; using System.Windows.Forms; using GMap.NET; public class MyCustomPlugin : Plugin { public override string Name => "My Custom Plugin"; public override string Version => "1.0.0"; public override string Author => "Developer Name"; // Called when plugin is first loaded public override bool Init() { // Verify plugin can run return true; } // Called once after Init, set up your plugin here public override bool Loaded() { // Add menu item to Flight Data map context menu var menuItem = new ToolStripMenuItem("Custom Action"); menuItem.Click += (s, e) => { PointLatLng clickPos = Host.FDMenuMapPosition; MessageBox.Show($"Clicked at: {clickPos.Lat}, {clickPos.Lng}"); }; Host.FDMenuMap.Items.Add(menuItem); // Subscribe to device changes Host.DeviceChanged += (dc) => { Console.WriteLine($"Device change: {dc}"); }; return true; } // Set loop rate in Hz (called repeatedly in background) public override float loopratehz { get; set; } = 1; // 1 Hz // Background loop - runs at loopratehz public override bool Loop() { // Access current vehicle state CurrentState cs = Host.cs; if (cs.connected && cs.armed) { Console.WriteLine($"Vehicle at {cs.lat}, {cs.lng}, Alt: {cs.alt}m"); // Access MAVLink interface MAVLinkInterface comPort = Host.comPort; // Read a parameter float paramValue = comPort.MAV.param["WPNAV_SPEED"]?.Value ?? 0; Console.WriteLine($"WPNAV_SPEED = {paramValue}"); } return true; } // Add waypoint programmatically public void AddWaypoint(double lat, double lng, double alt) { Host.AddWPtoList( MAVLink.MAV_CMD.WAYPOINT, 0, // p1 - hold time 0, // p2 - acceptance radius 0, // p3 - pass through 0, // p4 - yaw lat, // x - latitude lng, // y - longitude alt // z - altitude ); } public override bool Exit() { // Clean up resources return true; } } ``` ## MAVLink Message Parsing The MavlinkParse class handles parsing of raw MAVLink protocol streams into structured message objects, supporting both MAVLink v1 and v2 protocols. ```csharp using System; using System.IO; // Create parser instance (with timestamp for log files, without for live streams) MAVLink.MavlinkParse parser = new MAVLink.MavlinkParse(hasTimestamp: false); // Parse from stream (serial port, file, network) Stream dataStream = GetDataStream(); // Your data source while (true) { try { MAVLinkMessage message = parser.ReadPacket(dataStream); if (message == null) continue; Console.WriteLine($"Message ID: {message.msgid}"); Console.WriteLine($"System ID: {message.sysid}, Component: {message.compid}"); Console.WriteLine($"Sequence: {message.seq}"); // Handle specific message types switch (message.msgid) { case (uint)MAVLink.MAVLINK_MSG_ID.HEARTBEAT: var hb = message.ToStructure<MAVLink.mavlink_heartbeat_t>(); Console.WriteLine($"Heartbeat - Type: {hb.type}, Mode: {hb.custom_mode}"); break; case (uint)MAVLink.MAVLINK_MSG_ID.GLOBAL_POSITION_INT: var pos = message.ToStructure<MAVLink.mavlink_global_position_int_t>(); double lat = pos.lat / 1e7; double lon = pos.lon / 1e7; float alt = pos.alt / 1000f; Console.WriteLine($"Position: {lat}, {lon}, Alt: {alt}m"); break; case (uint)MAVLink.MAVLINK_MSG_ID.ATTITUDE: var att = message.ToStructure<MAVLink.mavlink_attitude_t>(); Console.WriteLine($"Attitude - Roll: {att.roll * 57.3}deg, Pitch: {att.pitch * 57.3}deg"); break; case (uint)MAVLink.MAVLINK_MSG_ID.SYS_STATUS: var sys = message.ToStructure<MAVLink.mavlink_sys_status_t>(); Console.WriteLine($"Battery: {sys.voltage_battery}mV, {sys.current_battery}mA"); break; } } catch (TimeoutException) { Console.WriteLine("Read timeout"); } catch (EndOfStreamException) { Console.WriteLine("End of stream"); break; } } // Check parser statistics Console.WriteLine($"Packets parsed: {parser.packetcount}"); Console.WriteLine($"CRC errors: {parser.badCRC}"); Console.WriteLine($"Length errors: {parser.badLength}"); ``` ## Serial Port Communication The SerialPort wrapper class provides platform-independent serial communication with automatic driver handling for various flight controller hardware. ```csharp using MissionPlanner.Comms; using System; // Create serial port SerialPort port = new SerialPort("COM3", 115200); // Configure port settings port.ReadTimeout = 500; // Read timeout in ms port.WriteTimeout = 500; // Write timeout in ms port.DtrEnable = true; // Enable DTR for bootloader port.RtsEnable = false; // RTS control try { // Open the port port.Open(); if (port.IsOpen) { Console.WriteLine($"Opened {port.PortName} at {port.BaudRate} baud"); // Clear input buffer port.DiscardInBuffer(); // Read data byte[] buffer = new byte[1024]; while (port.BytesToRead > 0) { int bytesRead = port.Read(buffer, 0, Math.Min(buffer.Length, port.BytesToRead)); Console.WriteLine($"Read {bytesRead} bytes"); } // Write data byte[] dataToSend = new byte[] { 0xFE, 0x09, 0x00, 0xFF, 0x00 }; port.Write(dataToSend, 0, dataToSend.Length); // Access underlying stream for advanced operations var stream = port.BaseStream; } } catch (Exception ex) { Console.WriteLine($"Error: {ex.Message}"); } finally { if (port.IsOpen) port.Close(); port.Dispose(); } // List available serial ports string[] ports = System.IO.Ports.SerialPort.GetPortNames(); foreach (var p in ports) { Console.WriteLine($"Available port: {p}"); } ``` ## DataFlash Log Analysis The DFLog class provides functionality for parsing and analyzing ArduPilot DataFlash binary logs, extracting flight data for post-flight review. ```csharp using MissionPlanner.Utilities; using System; using System.IO; using System.Collections.Generic; // Load a DataFlash log file string logFile = "00000001.BIN"; using (var stream = File.OpenRead(logFile)) { DFLogBuffer logBuffer = new DFLogBuffer(stream); DFLog dfLog = new DFLog(logBuffer); // Get available message types foreach (var format in dfLog.logformat) { Console.WriteLine($"Message: {format.Key}, Fields: {string.Join(", ", format.Value.FieldNames)}"); } // Iterate through log items foreach (DFLog.DFItem item in dfLog.GetEnumerator()) { // Filter by message type if (item.msgtype == "GPS") { // Access fields by name int statusIndex = dfLog.FindMessageOffset("GPS", "Status"); int latIndex = dfLog.FindMessageOffset("GPS", "Lat"); int lngIndex = dfLog.FindMessageOffset("GPS", "Lng"); if (statusIndex >= 0 && latIndex >= 0 && lngIndex >= 0) { var status = item.items[statusIndex]; var lat = item.items[latIndex]; var lng = item.items[lngIndex]; Console.WriteLine($"GPS: Status={status}, Lat={lat}, Lng={lng}"); } } else if (item.msgtype == "ATT") { // Attitude data int rollIndex = dfLog.FindMessageOffset("ATT", "Roll"); int pitchIndex = dfLog.FindMessageOffset("ATT", "Pitch"); int yawIndex = dfLog.FindMessageOffset("ATT", "Yaw"); if (rollIndex >= 0) { Console.WriteLine($"Time: {item.time}, Roll: {item.items[rollIndex]}"); } } else if (item.msgtype == "BAT") { // Battery data Console.WriteLine($"Battery log entry at line {item.lineno}"); } } // Access log start time Console.WriteLine($"Log start time: {dfLog.gpsstarttime}"); } ``` ## Firmware Update The Firmware class handles downloading and flashing firmware to ArduPilot-compatible flight controllers, supporting various board types and firmware versions. ```csharp using MissionPlanner.Utilities; using MissionPlanner.ArduPilot; using System; using System.Collections.Generic; using System.Threading.Tasks; // Get firmware manifest APFirmware.GetList(); // Downloads manifest from firmware.ardupilot.org // Find firmware for specific board var firmware = APFirmware.Manifest?.Firmware .Where(f => f.Platform == "Pixhawk1" && f.VehicleType == "Copter" && f.MavFirmwareVersionType == "OFFICIAL") .OrderByDescending(f => f.MavFirmwareVersion) .FirstOrDefault(); if (firmware != null) { Console.WriteLine($"Found: {firmware.VehicleType} v{firmware.MavFirmwareVersionStr}"); Console.WriteLine($"URL: {firmware.Url}"); Console.WriteLine($"Board ID: {firmware.BoardId}"); } // Create firmware updater instance Firmware fw = new Firmware(); // Subscribe to progress updates fw.Progress += (progress, status) => { Console.WriteLine($"[{progress}%] {status}"); }; // Example board detection and firmware upload workflow // (Actual implementation requires UI interaction) /* // Detect connected board var detected = BoardDetect.DetectBoard(portName); Console.WriteLine($"Detected board: {detected}"); // Download and flash firmware string firmwarePath = await DownloadFirmware(firmware.Url); bool success = fw.UploadFlash(portName, firmwarePath, detected); if (success) { Console.WriteLine("Firmware update complete!"); } */ // Get nice display names for firmware types foreach (var name in Firmware.niceNames) { Console.WriteLine($"{name.Key}: {name.Value}"); } ``` ## PointLatLngAlt Geographic Utilities The PointLatLngAlt class provides geographic point representation with coordinate transformation, distance calculations, and various utility methods for mission planning. ```csharp using MissionPlanner.Utilities; using GMap.NET; // Create points var home = new PointLatLngAlt(-35.363261, 149.165230, 584); var waypoint = new PointLatLngAlt(-35.362500, 149.166000, 600); // Calculate distance between points (returns meters) double distance = home.GetDistance(waypoint); Console.WriteLine($"Distance: {distance:F2} meters"); // Calculate bearing to waypoint (returns degrees) double bearing = home.GetBearing(waypoint); Console.WriteLine($"Bearing: {bearing:F1} degrees"); // Create new point at distance and bearing from origin var newPoint = home.newpos(bearing, distance / 2); // Halfway point Console.WriteLine($"Midpoint: {newPoint.Lat}, {newPoint.Lng}"); // Convert to GMap.NET PointLatLng (implicit conversion) PointLatLng gmapPoint = home; // Convert from GMap.NET PointLatLng PointLatLngAlt fromGmap = new PointLatLngAlt(gmapPoint); // Array conversion double[] coords = home; // Returns [Lng, Lat] PointLatLngAlt fromArray = new double[] { 149.165230, -35.363261, 584 }; // UTM conversion var utm = home.ToUTM(); Console.WriteLine($"UTM: Zone {utm.Zone}, E:{utm.East}, N:{utm.North}"); // Check if point is within polygon var polygon = new List<PointLatLngAlt> { new PointLatLngAlt(-35.360, 149.160), new PointLatLngAlt(-35.360, 149.170), new PointLatLngAlt(-35.370, 149.170), new PointLatLngAlt(-35.370, 149.160) }; bool isInside = PointLatLngAlt.IsInsidePolygon(polygon, home); Console.WriteLine($"Home is inside polygon: {isInside}"); // Tag points for identification home.Tag = "Home"; waypoint.Tag = "WP1"; waypoint.color = System.Drawing.Color.Red; ``` ## Joystick Input Handling The JoystickBase class provides joystick/gamepad input for manual RC override control of vehicles, with configurable axis mappings and button functions. ```csharp using MissionPlanner.Joystick; using MissionPlanner; using System; // Create joystick with MAVLink interface accessor JoystickBase joystick = JoystickFactory.Create(() => MainV2.comPort); // Configure joystick settings joystick.enabled = true; joystick.elevons = false; // Elevon mixing joystick.manual_control = true; // Use MANUAL_CONTROL message // Load joystick configuration joystick.loadconfig("joystickbuttons.xml", "joystickaxis.xml"); // Configure channels (example) // JoyChannels[0] = Roll // JoyChannels[1] = Pitch // JoyChannels[2] = Throttle // JoyChannels[3] = Yaw // Configure button actions // JoyButtons[0].buttonno = 0; // JoyButtons[0].function = buttonfunction.ChangeMode; // JoyButtons[0].mode = "LOITER"; // Save configuration joystick.saveconfig("joystickbuttons.xml", "joystickaxis.xml"); // In your update loop, the joystick automatically sends RC overrides // when enabled and connected // Handle joystick disconnection joystick.LostAction = () => { Console.WriteLine("Joystick disconnected!"); // Disable joystick control joystick.enabled = false; }; // Clean up joystick.Dispose(); ``` ## Summary Mission Planner serves as a comprehensive ground control station for ArduPilot vehicles, offering complete mission planning capabilities including waypoint creation, geofence definition, and rally point management. The software excels at real-time telemetry monitoring through its HUD display and map integration, while providing extensive configuration options for vehicle parameters, sensor calibration, and firmware updates. Its plugin architecture enables custom extensions for specialized use cases. Integration with Mission Planner typically involves using the MAVLinkInterface for communication, CurrentState for telemetry access, and the mission management APIs for autonomous flight planning. Developers can create custom plugins that hook into the application's event system and UI components, or build standalone applications using the ExtLibs libraries for MAVLink communication, log analysis, and geographic calculations. The codebase supports multiple connection types (serial, TCP, UDP) and handles the complexity of MAVLink protocol versioning, message signing, and multi-vehicle coordination.