The Importance of Using Units… Or, how to not lose a spacecraft with Meadow

In late September, 1999, Nasa’s Mars Climate Orbiter prepared to enter a stable orbit around the Red Planet to serve as a comms relay for the 1998 Mars Polar Lander and monitor climate on the planet below. 

Launched December the year before, the USD$125MM orbiter had spent nine months in transit and something had gone wrong; it passed behind Mars almost a full minute earlier than expected, and never reestablished comms back to NASA.

Later analysis would reveal that the orbiter was lost due to a units mismatch; NASA was using metric units, and the software created by Lockheed Martin that calculated the orbital insertion thrust vector was using imperial units. The discrepancy caused more than a 4x error in thrust, putting the spacecraft only 57km above the planet’s surface, rather than the 226km orbital distance it should have been.

It’s thought that the orbiter either burned up in the Martian atmosphere, or bounced out into an orbit around the sun, never to be recovered, along with the mission cost of almost $330MM.

The 20th century passed out of existence a few months later, but the lesson of that mission never left me, and with the beta 5.0 release of Meadow, I’m excited to say that with Meadow, this kind of mistake will never happen.

Units are now a first-class feature in Meadow.

Starting in b5.0, we’ve built strong unitization into the entire stack of Meadow. No more ambiguous float returns for temperature, pressure, distance, voltage, or other units. Instead sensors return strongly-typed units such as Temperature and Voltage, with properties that do automatic conversions to the various representations, such as Celsius or Fahrenheit.

Consider the following AnalogTemperatureSensor sample:

analogTemperature.TemperatureUpdated += (object sender, IChangeResult<Temperature> result) => {
    Console.WriteLine($"Temp Changed, temp: {result.New.Celsius:N2}C, old: {result.Old?.Celsius:N2}C");
};

When the TemperatureUpdated event is raised, it passes an IChangeResult<Temperature> parameter. That result has a New and Old property of type Temperature, whose value can be accessed via a direct conversion to Celsius, Fahrenheit, or Kelvin on properties of the same name.

And Nullable Everywhere

Not also that Meadow b5.0 fully embraces C# 8’s nullable features, so the result’s Old property is nullable, and in fact, on the first reading, it will be null because there isn’t a previous reading to populate it with.

For more information about unitization and Meadow b5.0, check out the release notes, which go into extensive detail.

We’re super excited about this release, and stoked that if you crash a spacecraft with Meadow, at least it won’t be due to ambiguous units!