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
Name | Ext | Read | Write |
---|---|---|---|
ForeFlight | FPL | ✅ | ✅* |
Garmin | FPL | ✅ | ✅* |
X-Plane FMS 11 | FMS | ❌ | ✅* |
*: 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.