14,970,849 members
Articles / General Programming / Algorithms
Article
Posted 22 Jan 2014

16K views
18 bookmarked

# Automatic Conversion of Physical Units

Rate me:

## 1 Introduction.

Any advanced software contains a third-party software. Usually third party software should be adapted to own software. Different software can use different physical units. For example Empirical, global model of the Earth's atmosphere from ground to space (NRLMSISE-00) source code is very convenient for research of atmospheric physics, but it is not convenient for ballistics because ballistics uses other physical units. Conversion of physical units is very a important task.

++++++++++++++++++++++

One example of the importance of agreed units is the failure of the NASA Mars Climate Orbiter, which was accidentally destroyed on a mission to Mars in September 1999 instead of entering orbit due to miscommunications about the value of forces: different computer programs used different units of measurement (newton versus pound force). Considerable amounts of effort, time, and money were wasted.[6][7]

On April 15, 1999 Korean Air cargo flight 6316Chinese-{大韓航空6316號班機空難}- from Shanghai to Seoul was lost due to the crew confusing tower instructions (in metres) and altimeter readings (in feet). Three crew and five people on the ground were killed. Thirty seven were injured.[8][9]

In 1983, a Boeing 767 (which came to be known as the Gimli Glider) ran out of fuel in mid-flight because of two mistakes in figuring the fuel supply of Air Canada's first aircraft to use metric measurements.[10] This accident is apparently the result of confusion both due to the simultaneous use of metric & Imperial measures as well as mass & volume measures.

Cited from here.

++++++++++++++++++++

Sometimes conversion of physical units requires a lot of work, however this work can be particulary or fully automated. This article is devoted to physical unit automatization issues. My article contains very many details because some of my modules can be interested for some readers. This article can be also regarded as practical guide of low cohesion.

## 2 Background

Internet contains a lot of useful information. However as rule this information should be adapted, to own purposes. This article is devoted to automatic conversion of physical units. If we have provider and consumer of information

and physical units of consumer are different from provider's one then we should supply conversion of units. My soft makes this operation particulary or fully automatic.

### 2.1 Theoretic issues

Theoretic issues are explained here, following formula represent logarithm of a conversion coefficient.

.

I used exponential version of the above formula.

### 2.2 Calculation of coefficients

Following code contains enumerations of physical units.

``` /// <summary>
/// Types of angle
/// </summary>
public enum AngleType
{
Circle, // Circle
Degree  // Degree
}

/// <summary>
/// Types of length
/// </summary>
public enum LengthType
{
Meter,      // Meter
Centimeter, // Centimeter
Kilometer   // Kilometer
}

/// <summary>
/// Types of time
/// </summary>
public enum TimeType
{
Second, // Second
Day     // Day
}

/// <summary>
/// Types of mass
/// </summary>
public enum MassType
{
Kilogram,   // Kilogram
Gram        // Gram
}
```

Following attribute contains information about usage of physical units.

```/// <summary>
/// Attribute of physical parameters
/// </summary>
[Serializable()]
public class PhysicalUnitTypeAttribute : Attribute, ISerializable
{

#region Fields

static internal readonly Dictionary<Type, PropertyInfo> Properties =
new Dictionary<Type, PropertyInfo>();

/// <summary>
/// Type of angle
/// </summary>
private AngleType angleUnit;

/// <summary>
/// Type of length
/// </summary>
private LengthType lengthUnit;

/// <summary>
/// Type of time
/// </summary>
private TimeType timeUnit;

/// <summary>
/// Type of mass
/// </summary>
private MassType massUnit;

private event Action change = () => { };

#endregion

#region Ctor

/// <summary>
/// Constructor
/// </summary>
/// <param name="angleType">Type of angle</param>
/// <param name="lengthType">Type of length</param>
/// <param name="timeType">Type of time</param>
/// <param name="massType">Type of mass</param>
LengthType lengthType = LengthType.Meter,
TimeType timeType = TimeType.Second,
MassType massType = MassType.Kilogram)
{
this.angleUnit = angleType;
this.lengthUnit = lengthType;
this.timeUnit = timeType;
this.massUnit = massType;
}

/// <summary>
/// Default constructor
/// </summary>
public PhysicalUnitTypeAttribute()
{
lengthUnit = LengthType.Meter;
timeUnit = TimeType.Second;
massUnit = MassType.Kilogram;
}

/// <summary>
/// Deserialization constructor
/// </summary>
/// <param name="info">Serialization info</param>
/// <param name="context">Streaming context</param>
protected PhysicalUnitTypeAttribute(SerializationInfo info, StreamingContext context)
{
angleUnit = (AngleType)info.GetValue("AngleType", typeof(AngleType));
lengthUnit = (LengthType)info.GetValue("LengthType", typeof(LengthType));
timeUnit = (TimeType)info.GetValue("TimeType", typeof(TimeType));
massUnit = (MassType)info.GetValue("MassType", typeof(MassType));
}

/// <summary>
/// Constructor
/// </summary>
static PhysicalUnitTypeAttribute()
{
PropertyInfo[] pi = typeof(PhysicalUnitTypeAttribute).GetProperties();
foreach (PropertyInfo i in pi)
{
Type t = i.PropertyType;
if (!t.Equals(typeof(object)))
{
Properties[i.PropertyType] = i;
}
}
}

#endregion

#region ISerializable Members

void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
{
}

#endregion

#region Public

/// <summary>
/// Change event
/// </summary>
public event Action Change
{
add { change += value; }
remove { change -= value; }
}

/// <summary>
/// Type of angle
/// </summary>
public AngleType AngleType
{
get
{
return angleUnit;
}
set
{
angleUnit = value;
change();
}
}

/// <summary>
/// Type of length
/// </summary>
public LengthType LengthType
{
get
{
return lengthUnit;
}
set
{
lengthUnit = value;
change();
}
}

/// <summary>
/// Type of time
/// </summary>
public TimeType TimeType
{
get
{
return timeUnit;
}
set
{
timeUnit = value;
change();
}
}

/// <summary>
/// Type of mass
/// </summary>
public MassType MassType
{
get
{
return massUnit;
}
set
{
massUnit = value;
change();
}
}

#endregion

}
```

If we have a type with constant physical units then above class is used as an attribute, otherwise it is used as a property of the following interface.

``` /// <summary>
/// Holder of attribute of physical parameters
/// </summary>
public interface IPhysicalUnitTypeAttribute
{
/// <summary>
/// Attribute of physical parameters
/// </summary>
PhysicalUnitTypeAttribute PhysicalUnitTypeAttribute
{
get;
set;
}
}
```

Following dictionaries are used for calculation of coefficients.

``` /// <summary>
/// Dictionaries which contain coefficients
/// </summary>
private static readonly Dictionary<Type, object> dCoefficients = new Dictionary<Type, object>()
{
{typeof(AngleType),   new Dictionary<AngleType, double>()
{
{AngleType.Degree, 180 / Math.PI},
{AngleType.Circle, 2 * Math.PI}
}
},
{typeof(LengthType),    new Dictionary<LengthType, double>()
{
{LengthType.Meter, 1},
{LengthType.Kilometer, 1000},
{LengthType.Centimeter, 0.01}
}
},
{typeof(MassType),   new Dictionary<MassType, double>()
{
{MassType.Kilogram, 1},
{MassType.Gram, 0.001}
}
},
{typeof(TimeType),   new Dictionary<TimeType, double>()
{
{TimeType.Day, 1},
{TimeType.Second, 86400}
}
}
};
```

Meaning of these dictionaries is clear, following functions use these dictionaries.

```  /// <summary>
/// Coefficient of physical unit
/// </summary>
/// <typeparam name="T">From</typeparam>
/// <param name="source">From unit</param>
/// <param name="target">To unit</param>
/// <returns>Coefficient</returns>
public static double Coefficient<T>(this T source, T target)
{
Dictionary<T, double> d = dCoefficients[typeof(T)] as Dictionary<T, double>;
double kFrom = d[source];
double kTo = d[target];
return kTo / kFrom;
}
```

These coefficients are used for more general transformations by following way.

``` /// <summary>
/// Coefficient functions
/// </summary>
private static readonly Dictionary<Type, Func<object, object, double>> functions = new Dictionary<Type, Func<object, object, double>>()
{
{typeof(AngleType), (object a, object b) =>
{ return Coefficient<AngleType>((AngleType)a, (AngleType)b);} },
{typeof(LengthType), (object a, object b) =>
{ return Coefficient<LengthType>((LengthType)a, (LengthType)b);} },
{typeof(MassType), (object a, object b) =>
{ return Coefficient<MassType>((MassType)a, (MassType)b);} },
{typeof(TimeType), (object a, object b) =>
{ return Coefficient<TimeType>((TimeType)a, (TimeType)b);} }
};

/// <summary>
/// Gets coefficients
/// </summary>
/// <param name="source">Source</param>
/// <param name="target">Target</param>
/// <param name="dictionary" />Physical unit dictionary</param>
/// <returns>Coefficient</returns>
public static double Coefficient(this PhysicalUnitTypeAttribute source,
PhysicalUnitTypeAttribute target, Dictionary<Type, int> dictionary)
{
if (dictionary == null)
{
return 1;
}
double a = 1;
Dictionary<Type, PropertyInfo> p =  PhysicalUnitTypeAttribute.Properties;
foreach (Type t in dictionary.Keys)
{
Func<object, object, double> f = functions[t];
PropertyInfo pi = p[t];
object from = pi.GetValue(source);
object to = pi.GetValue(target);
double k = f(from, to);
if (k == 1)
{
continue;
}
int m = dictionary[t];
if (m < 0)
{
m = -m;
k = 1.0 / k;
}
for (int i = 0; i < m; i++)
{
a *= k;
}
}
return a;
}
```

The dictionary parameter of the `Coefficient` function, which is commented as Physical unit dictionary can be easy explained by following example. The gravitational constant is expressed by following way.

Following Physical unit dictionary corresponds to the gravitational constant.

``` /// <summary>
/// Gravitational constant physical unit dictionary
/// </summary>
private static readonly Dictionary<Type, int> GravityConstUnit =
new Dictionary<Type, int>()
{
{typeof(LengthType), 3},
{typeof(MassType), -1},
{typeof(TimeType), -2},
};
```

### 2.3 Automatic calculations

There is a set of interfaces which are intended for automatic conversion. Following interface is used for an exchange of parameters.

``` /// <summary>
/// Collection on named data units
/// </summary>
public interface IAlias : IAliasBase
{
/// <summary>
/// Names of all data units
/// </summary>
IList<string> AliasNames
{
get;
}

/// <summary>
/// </summary>
object this[string name]
{
get;
set;
}

/// <summary>
/// Gets unit type
/// </summary>
/// <param name="name">Unit name</param>
/// <returns>Type of unit</returns>
object GetType(string name);

/// <summary>
/// Change alias event
/// </summary>
event Action<IAlias, string> OnChange;

}
```

One object exports parameters to another object, names and types of the parameters should coincide. If above `IAlias ` interface is extended by a physical units manifest (physical unit dictionary) then conversion of units can be given automatically. Following interface represents manifest of a physical unit dictionary.

``` /// <summary>
/// Physical unit dictionary
/// </summary>
public interface IPhysicalUnitAlias
{
/// <summary>
/// Gets dictionary of an alias
/// </summary>
/// <param name="name">Name</param>
/// <returns>Physical unit dictionary</returns>
Dictionary<Type, int> this[string name]
{
get;
}
}
```

The `name` parameter of provider should correspond to name of consumer. Following function uses above interfaces for an automatic conversion of physical parameters.

``` /// <summary>
/// Conversion of physical units
/// </summary>
/// <param name="alias">Alias</param>
/// <param name="source">Source</param>
/// <param name="target">Target</param>
/// <returns>Conversion result</returns>
public static Dictionary<string, double> ConvertPhysicalUnits
(this IAlias alias, BaseTypes.Attributes.PhysicalUnitTypeAttribute source,
BaseTypes.Attributes.PhysicalUnitTypeAttribute target)
{
Dictionary<string, double> d = new Dictionary<string, double>();
BaseTypes.Interfaces.IPhysicalUnitAlias a = alias as
BaseTypes.Interfaces.IPhysicalUnitAlias;
IList<string> l = alias.AliasNames;
foreach (string key in l)
{
if (!l.Contains(key))
{
continue;
}
object t = alias.GetType(key);
if (!t.Equals(BaseTypes.FixedTypes.Double))
{
continue;
}
double x = (double)alias[key];
Dictionary<Type, int> dt = a[key];
if (dt != null)
{
x *=  Coefficient(source,
target, dt);
}
d[key] = x;
}
return d;
}
```

Above function gets parameters from provider, calculates conversion coefficients, multiplies parameters by coefficients and exports results to the consumer.

### 2.4 User interface.

There is clear and unified user control for all objects which implement the `IPhysicalUnitTypeAttribute` interface.

Above user control corresponds to the `UserControlPhysicalUnit` class which is contained in my source code.

## 3. Samples

### 3.1 Manual adaptation of physical units

My description of this task looks too long, but this sample has independent interest for some readers. Motion of artificial Earth's satellites depends on Earth's atmosphere. There is an Empirical, global model of the Earth's atmosphere from ground to space (NRLMSISE-00) source code. However this code is static. I would like use it for many simultaneous calculations and so I developed the `Msise` C++ class (`MSISEAtmosphere` project). This class has independent interest and can be used without .NET. The `MSISEAtmosphere` project is a .NET wrapper of the `Msise` class. The `DynamicAtmosphere.MSISE` project is a C# extension of `MSISEAtmosphere` which supplies following additional facilities:

• Conversion of physical units;
• Integrated calculation of position of the Sun.

Atmospheric parameters depend on position of the Sun. However I did not integrate calculation of Sun position into `MSISEAtmosphere` by following reason. Suppose a user have got own soft for the Sun position calculation. If I would integrate my algorithm then user should have two algorithms of the Sun position calculation. Calculation of Sun position is also independent, it is contained in the `SunPosition` project. The `SunPosition` is a refactoring of of Plataforma Solar de Almería C++ project to C#. Position of the Sun has indepentent interest, the Plataforma Solar de Almería uses it for solar facilities. Maybe my soft would also be used for solar facilities without atmospheric calculations. Maybe my soft would be used for a task which contains two subtasks: solar facilities and artificial Earth's satellites monitoring. Then the single `SunPosition` will be used for both subtasks. The `DynamicAtmosphere.MSISE.Wrapper` is next extension for integration with my software. My software can use this class for different purposes, for example for determination of orbits of artificial satellites. The `DynamicAtmosphere.MSISE.Wrapper` contains pure business logic layer. So it be used in my Web projects, Windows Forms projects and WPF projects. The `DynamicAtmosphere.MSISE.Wrapper.UI` project supplies following System.Windows.Forms user interface.

The Parameters tab page is responsible for space weather indices F10.7, Ap, F10.7 average. The Physical units tab page is responsible for physical units. This object is used in motion equations of a satellite such that kilometer, second and kilogram are used as physical units. We can select any physical units and outputs of this project should correspond these units.

### 3.2 Automatic export of physical parameters

Above example implies manual input of space weather indices. Manual input is undoubtedly useful for research tasks. But in case of real-time simulation the space weather indices can be automatically given by Internet. The `DynamicAtmosphere.Web` is a project which provides space weather indices from the http://www.nwra.com/spawx/env_latest.html and http://www.spaceweather.ca/data-donnee/sol_flux/sx-5-mavg-eng.php. The `DynamicAtmosphere.Web.Wrapper` extends the `DynamicAtmosphere.Web` for interopreability with my framework. Both these projects are independent from MSISE-90 atmosphere model, so they can be used with Russian Federation model of atmosphere. Main type of the `DynamicAtmosphere.Web.Wrapper` is the `DynamicAtmosphere.Web.Wrapper.Atmosphere` class. An object of this class can be independent and can have an integrated child. If object is independent then it is a provider of information for many consumers as it is displayed below.

All consumers of information should use the same physical units. If this object contains an integrated child then it provides information for single child only. Following two constructors explain usage of these options.

``` /// <summary>
/// Constructor of an independent object
/// </summary>
public Atmosphere()
{

}

/// <summary>
/// Constructor with child
/// </summary>
/// <param name="childType">Type of child</param>
public Atmosphere(string childType)
: this()
{
Type t = Type.GetType(childType); // Type of the child object
child = t.GetConstructor(new Type[0]).Invoke(new object[0]) as IAlias; // Child object
// Children
children = new IAssociatedObject[] { child as IAssociatedObject };
if (child is IAliasConsumer)
{
// Adaption of this object by its child
IAliasConsumer aliasConsumer = child as IAliasConsumer;
aliasConsumer.Add(this);  // Child object consumes information
}
}
```

So `child` object consumes information from parent. Following code contains implementation of the `Add` method of the `IAliasConsumer`.

``` void IAliasConsumer.Add(IAlias alias)
{
// ================ Import of parameters ==================
IAlias al = this;
List<string> own = al.AliasNames.ToList<string>();
List<string> external = alias.AliasNames.ToList<string>();
for (int i = 0; i < external.Count; i++)
{
string n = external[i];
if (dAlias.ContainsKey(n))
{
if (al.GetType(n).Equals(alias.GetType(n)))
{
al[n] = alias[n];
}
}
}
//=============== Export of event handler  ==================
alias.OnChange += Change;
}
```

Export of event handler means that changing of Internet atmospheric parameters forces simultaneous changing of parameters of the child. Names of aliases of the child object coincide with parent ones.

``` /// <summary>
/// Names of aliases
/// </summary>
private readonly string[] Names = new string[] { "F10_7", "Ap", "F10_7A" };
```

The names are names of space weather indices.

Described above objects are very special, so they should be used as plug-ins. The `Containers.xml` file contains manifest of plugins.

```<Root>
<Assemblies>
<Assembly file="SunPosition.dll"/>
<Assembly file="DynamicAtmosphere.MSISE.dll"/>
<Assembly file="DynamicAtmosphere.MSISE.Wrapper.dll"/>
<Assembly file="DynamicAtmosphere.MSISE.Wrapper.UI.dll"/>
<Assembly file="DynamicAtmosphere.Web.dll"/>
<Assembly file="DynamicAtmosphere.Web.Wrapper.dll"/>
</Assemblies>
<Page pageName="Orbital" pageHint="Orbital services">
<Object icon="Containers\Atmosphere.ico"
type="DynamicAtmosphere.MSISE.Wrapper.Atmosphere,DynamicAtmosphere.MSISE.Wrapper, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
param="" hint="Earth's atmosphere" arrow="false" />
<Object icon="Containers\AtmosphereWeb.ico"
type="DynamicAtmosphere.Web.Wrapper.Atmosphere,DynamicAtmosphere.Web.Wrapper, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
param="" hint="Earth's atmosphere Web" arrow="false" />
<Object icon="Containers\AtmosphereWebChild.ico"
type="DynamicAtmosphere.Web.Wrapper.Atmosphere,DynamicAtmosphere.Web.Wrapper, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
param="DynamicAtmosphere.MSISE.Wrapper.Atmosphere,DynamicAtmosphere.MSISE.Wrapper, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
hint="Earth's atmosphere Web + child" arrow="false" />
</Page>
</Root>```

Any `Object` tag corresponds to a plug-in object. Following table explains above XML code.

 N Creation of the object Comment 1 `new DynamicAtmosphere.MSISE.Wrapper.Atmosphere()` MSISE Atmospheric model 2 `new DynamicAtmosphere.Web.Wrapper.Atmosphere()` Atmospheric parameters from Web 3 `new DynamicAtmosphere.Web.Wrapper.Atmosphere(new DynamicAtmosphere.MSISE.Wrapper.Atmosphere())` Atmospheric parameters from Web + MSISE Atmospheric model

Following picture displays these objects.

If Web atmosphere contains an integrated child then editor form contains additional tab. Following two pictures contains properties of Web atmosphere with a child and without it. The child just imports space weather indices, physical units of child's outputs depend on settings.

### 3.3 Automatic export and physical units conversion

There are Keplerian orbit prediction algorithm and two-line element set (TLE) is a data format used to convey sets of orbital elements that describe the orbits of Earth-orbiting satellites. Both this objects can be aggregated to a single object. or used independently. For example Keplerian orbit prediction algorithm can be used for simulation of stars' motion. Two-line element set (TLE), can be used by more accurate methods of orbit prediction (See here). I have developed special soft for extracting data from NORAD Two-Line Element Sets Current Data. This soft contains 3 projects. First project `Celestrak.NORAD.Satellites` contains business logic only. Main class of this project is presented below.

``` /// <summary>
/// Data of satellite
/// </summary>
[Serializable()]
[PhysicalUnitType(AngleType = AngleType.Degree, LengthType = LengthType.Meter,
MassType = MassType.Kilogram, TimeType = TimeType.Day)]
public class SatelliteData : CategoryObject, IChildrenObject, IMeasurements, IPropertiesEditor,
ISeparatedAssemblyEditedObject, IAlias, ISerializable, IPhysicalUnitAlias, IEventHandler
```

The

```PhysicalUnitType(AngleType = AngleType.Degree, LengthType = LengthType.Meter,
MassType = MassType.Kilogram, TimeType = TimeType.Day)```
means that this type used fixed physical units. Following code contains implementation of both `IAlias` and `IPhysicalUnitAlias`.

```  /// <summary>
/// Physical unit dictionary
/// </summary>
internal static readonly Dictionary<string, Dictionary<Type, int>> AliasNames =
new Dictionary<string, Dictionary<Type, int>>()
{
{"Eccentricity", null},
{"Inclination", new Dictionary<Type, int>(){{typeof(AngleType), 1}}},
{"Ascending Node",  new Dictionary<Type, int>(){{typeof(AngleType), 1}}},
{"Argument Of Periapsis",  new Dictionary<Type, int>(){{typeof(AngleType), 1}}},
{"Mean Anomaly At Epoch",  new Dictionary<Type, int>(){{typeof(AngleType), 1}}},
{"Mean Motion", new Dictionary<Type, int>{{typeof(AngleType), 1}, {typeof(TimeType), -1}}},
{"FD MeanMotion", null},
{"SD MeanMotion", null},
{"Perturbation", null},
{"Mass", new Dictionary<Type, int>(){{typeof(MassType), 1}}},
{"Epoch",  null}
};

#region IPhysicalUnitAlias Members

Dictionary<Type, int> IPhysicalUnitAlias.this[string name]
{
get
{
if (AliasNames.ContainsKey(name))
{
return AliasNames[name];
}
return null;
}
}

#endregion

#region IAlias Members

IList<string> IAlias.AliasNames
{
get { return AliasNames.Keys.ToList<string>(); }
}

object IAlias.this[string name]
{
get
{
return aliases[name];
}
set
{
}
}

object IAlias.GetType(string name)
{
if (name.Equals("Epoch"))
{
return  FixedTypes.DateTime;
}
return FixedTypes.Double;
}

event Action<IAlias, string> IAlias.OnChange
{
add { onChange += value; }
remove { onChange -= value; }
}

#endregion
```

The `AliasNames` represents physical unit dictionary. The `Celestrak.NORAD.Satellites.Wpf.UI` project supplies WPF user interface which which is used in both WPF and System.Windows.Forms applications. The `Celestrak.NORAD.Satellites.UI` contains a System.Windows.Forms user interface. As well as DynamicAtmosphere.Web.Wrapper.Atmosphere data of this class can be exported to its integrated child. The Keplerian orbit prediction algorithm can be used as the child. The Keplerian orbit prediction algorithm is implemented in Celestia. Real-time 3D visualization of space project, I developed C# version of it. The `CelestialMechanics` project contains fully independent version of the algorithm. The `CelestialMechanics.Wrapper` is intended for compatibility with my framework. Names of aliases in `CelestialMechanics.Wrapper.CelestialMechanics.Wrapper.Classes.Orbit` class coincide with `Celestrak.NORAD.Satellites.SatelliteData` ones. Since `Celestrak.NORAD.Satellites.SatelliteData` implements the IPhysicalUnitAlias interface then besides export of data it implements automatic conversion of physical units. The ConvertPhysicalUnits function is used for this purpose. Following picture contains tree objects.

Following table explains meaning of these objects.

 N Name Creation of the object Comment 1 NORAD `new Celestrak.NORAD.Satellites.SatelliteData()` NORAD data 2 Orbital `new CelestialMechanics.Wrapper.Classes.Orbit()` Keplerian orbit prediction algorithm 3 NORAD + Orbital `new Celestrak.NORAD.Satellites.SatelliteData(new CelestialMechanics.Wrapper.Classes.Orbit())` NORAD data + Keplerian orbit prediction algorithm

Following two pictures display user interface of the NORAD object.

Above interfface is clear and explains business logics. Following pictures display user interface of the Orbital object.

Above user interface contais an editor of physical units. Following pictures displays propetrites of the NORAD + Orbital object.

Last two pictures contain properties of the child. Parameters of orbit depend on parent, i.e. they coincide with parameters of a selected satellite. So this parameters are not editable. If child does not depend on parent then parameters of orbit are editable. However if we change physical units then numerical values shall be changed as it is displayed below:

## Points of Interest

Sometimes a physical units conversion is more complicated then other parts of an engineering task.

## History

I had tried manually convert Fortran version of MSISE-90 to C++. I think that the code of this model is not clear for its developers. My attempt was unsuccessful. Then I found f2c to convert Fortran 77 to C code. However I found a bug. Two calls of the same function occur different result. Then I found C code of MSISE-90. This code is not clear also. My colleagues told me that Aerospace has a lot of unclear Fortran code. Then I asked myself:

• Is my own code clear?
• Can I make my own code clear?

I translated a Celestia. Real-time 3D visualization of space I found that this project contains folowing code:

`const double astro::G = 6.672e-11; // N m^2 / kg^2`
(See here), however present day value of gravity constat is equal to 6.674 28 (+/- 0.000 67) x 10-11 m3 kg-1 s -2.

This fact inspires me for modification of my own code. Now my model of Earth's gravity field can be automatically updated. User interface of my new gravity field is presented below

Above picture means that parameters of a gravity field model is stored in the http://mathframe.com/databases/gravity/GEM-T3.FLD file.

## Share

 Architect Russian Federation
Ph. D. Petr Ivankov worked as scientific researcher at Russian Mission Control Centre since 1978 up to 2000. Now he is engaged by Aviation training simulators http://dinamika-avia.com/ . His additional interests are:

1) Noncommutative geometry

http://front.math.ucdavis.edu/author/P.Ivankov

2) Literary work (Russian only)

http://zhurnal.lib.ru/editors/3/3d_m/

3) Scientific articles
http://arxiv.org/find/all/1/au:+Ivankov_Petr/0/1/0/all/0/1