Home

Awesome

libflightplan (Zig and C)

libflightplan is a library for reading and writing flight plans in various formats. Flight plans are used in aviation to save properties of one or more flights such as route (waypoints), altitude, source and departure airport, etc. This library is written primarily in Zig but exports a C ABI compatible shared and static library so that any programming language that can interface with C can interface with this library.

Warning! If you use this library with the intention of using the flight plan for actual flight, be very careful to verify the plan in your avionics or EFB. Never trust the output of this library for actual flight.

Library status: Unstable. This library is brand new and was built for hobby purposes. It only supports a handful of formats, with limitations. My primary interest at the time of writing this is ForeFlight flight plans and being able to use them to build supporting tools, but I'm interested in supporting more formats over time.

Formats

NameExtReadWrite
ForeFlightFPL✅*
GarminFPL✅*
X-Plane FMS 11FMS✅*

*: The C API doesn't support creating flight plans from scratch or modifying existing flight plans. But you can read in one format and encode in another. The Zig API supports full creation and modification.

Usage

libflightplan can be used from C and Zig. Examples for each are shown below.

C

The C API is documented as man pages as well as the flightplan.h header file. An example program is available in examples/basic.c, and a simplified version is reproduced below. This example shows how to read and extract information from a ForeFlight flight plan.

The C API is available as both a static and shared library. To build them, install Zig and run zig build install. This also installs pkg-config files so the header and libraries can be easily found and integrated with other build systems.

#include <stddef.h>
#include <stdio.h>
#include <flightplan.h>

int main() {
	// Parse our flight plan from an FPL file out of ForeFlight.
	flightplan *fpl = fpl_garmin_parse_file("./test/basic.fpl");
	if (fpl == NULL) {
		// We can get a more detailed error.
		flightplan_error *err = fpl_last_error();
		printf("error: %s\n", fpl_error_message(err));
		fpl_cleanup();
		return 1;
	}

	// Iterate and output the full ordered route.
	int max = fpl_route_points_count(fpl);
	printf("\nroute: \"%s\" (points: %d)\n", fpl_route_name(fpl), max);
	for (int i = 0; i < max; i++) {
		flightplan_route_point *point = fpl_route_points_get(fpl, i);
		printf("  %s\n", fpl_route_point_identifier(point));
	}

	// Convert this to an X-Plane 11 flight plan.
	fpl_xplane11_write_to_file(fpl, "./copy.fms");

	fpl_free(fpl);
	fpl_cleanup();
	return 0;
}

Zig

const std = @import("std");
const flightplan = @import("flightplan");

fn main() !void {
	defer flightplan.deinit();

	var alloc = std.heap.ArenaAllocator.init(std.heap.page_allocator);
	defer alloc.deinit();

	var fpl = try flightplan.Format.Garmin.initFromFile(alloc, "./test/basic.fpl");
	defer fpl.deinit();

	std.debug.print("route: \"{s}\" (points: {d})\n", .{
		fpl.route.name.?,
		fpl.route.points.items.len,
	});
	for (fpl.route.points.items) |point| {
		std.debug.print("  {s}\n", .{point});
	}

	// Convert to an X-Plane 11 flight plan format
	flightplan.Format.XPlaneFMS11.Format.writeToFile("./copy.fms", fpl);
}

Build

To build libflightplan, you need to have the following installed:

With the dependencies installed, you can run zig build to make a local build of the libraries. You can run zig build install to build and install the libraries and headers to your standard prefix. And you can run zig build test to run all the tests.

A Nix flake is also provided. If you are a Nix user, you can easily build this library, depend on it, etc. You know who you are and you know what to do.