Skip to content

Using HLA FOMs

Sen is able to use HLA FOMs to model types and classes.

Example of a diagram generated by Sen:

Screenshot

You can download the image to get a better look.

Sen can also generate markdown documentation (see the following section).

Put your HLA FOMs XMLs in folders (for example: rpr, netn).

In CMake you can do as follows to generate C++ code:

sen_generate_cpp(
  TARGET
    fom_lib
  HLA_FOM_DIRS
    rpr
    netn
  GEN_HDR_FILES
    fom_headers
  HLA_MAPPINGS_FILE
    mapping.xml
)

The HLA_MAPPINGS_FILE option is for dealing with interactions. More on that later.

You can also generate UML diagrams:

sen_generate_uml(
  TARGET
    fom_lib_uml
  OUT
    ${CMAKE_CURRENT_BINARY_DIR}/fom.plantuml
  HLA_FOM_DIRS
    rpr
    netn
  CLASSES_ONLY
)

Data Type Mappings

  • HLA Enumerations are mapped to Sen enumerations.
  • HLA Records are mapped to Sen structs.
  • HLA Variant Records are mapped to Sen variants.
  • HLA Arrays with ranges are mapped to Sen bounded sequences.
  • HLA Arrays without ranges are mapped to Sen unbounded sequences.
  • HLA Simple Types with units are mapped to Sen quantities.
  • Type names in HLA are transformed to UpperCamelCase.
  • Enumerator names in HLA are transformed to lowerCamelCase.

HLA data representations are mapped as follows:

HLA Representation Sen
HLAfloat32BE,HLAfloat32LE f32
HLAfloat64BE, HLAfloat64LE f64
HLAinteger16BE, HLAinteger16LE i16
HLAinteger32BE, HLAinteger32LE i32
HLAinteger64BE, HLAinteger64LE i64
HLAoctet u8

Some standards define their own data representations. Sen is able to interpret the following:

Data Representation Sen
RPRunsignedInteger16BE u16
RPRunsignedInteger32BE u32
RPRunsignedInteger64BE i64
RPRunsignedInteger8BE u8

Simple Types, are mapped as follows:

HLA Type Sen
HLAASCIIchar, HLAbyte u8
HLAunicodeChar u16
HLAcount, HLAseconds,HLAmsec,HLAindex i32
HLAinteger64Time i64
HLAfloat64Time f64
HLAboolean, RPRboolean bool
HLAASCIIstring, HLAunicodeString string

HLA does not define a standard for naming units, but the following mapping is applied:

HLA Unit Sen Unit
"meter per second squared (m/(s^2))" m_per_s_sq
"degree (deg)" deg
"radian (rad)" rad
"hour" h
"meter (m)" m
"hertz (Hz)", "interrogations/second" hz
"kilogram (kg)" kg
"degree Celsius (C)" degC
"microsecond" us
"millisecond (ms)" ms
"second(s)" s
"meter per second (m/s)" m_per_s
"micron" um
"revolutions per minute (RPM)", "RPM" rpm
"decimeter per second (dm/s)" dm_per_s

Class Mapping

The HLA class hierarchy inherits from the base class hla::ObjectRootBase (the HLAobjectRoot class is mapped to hla::ObjectRootBase, which inherits from Object).

The hla::ObjectRootBase contains the RTIObjectId provided by the HLA federate to all entities, which is completely independent of the identification provided by Sen, contained in the Object class.

The HLA class hierarchy is directly mapped (the HLAobjectRoot class is mapped to Sen Object).

HLA class attributes are mapped to Sen class properties. Property mode is mapped as follows:

updateType sharing Sen
"Static" PublishSubscribe or Publish staticRW
"Static" Subscribe staticRO
not "Static" Writeable dynamicRW
not "Static" not Writeable dynamicRO

Interaction Mapping

Interactions in HLA are broadcasts. As such they encode multiple communication patterns:

  • True broadcasts.
  • Requests made to one or multiple "back-ends" (where the receiver may or may not be defined, and a request ID is usually provided).
  • Responses to requests (where the request id is sent back to all potential senders for them to manually correlate).
  • Messages between participants.

In HLA, interactions are mapped as a hierarchy which is parallel to the class hierarchy.

In Sen we have:

  • Classes for objects that have properties, methods and can emit events.
  • Method calls, made to some specific instance, with arguments, and which might return a value.
  • Events, to which interested listeners can react to.

To map HLA interactions to the Sen world you need to provide an XML file defining how you want to map those interactions to Sen methods or events.

Methods that do not return.

If you want to map an interaction as a method that doesn't return anything, you need to define the class that will hold the method and the interaction from where the method name and the arguments will be obtained. For example:

<class name="WeaponServer">
    <method hlaInteraction="CreateMunition"/>
    <method hlaInteraction="DeleteMunition"/>
</class>

If you don't want your method to have all the parameters that are defined in the HLA interaction, you can ignore them as follows:

<class name="WeatherServer">
    <method hlaInteraction="METOC_Interaction.Request.RequestWeatherCondition">
        <ignore parameter="EventId"/>
        <ignore parameter="ServiceId"/>
    </method>
</class>

Methods that return.

You can use the definition of an interaction to define the return value of a method. For example:

<class name="WeatherServer">
    <method hlaInteraction="METOC_Interaction.Request.RequestLandSurfaceCondition">
        <ignore parameter="EventId"/>
        <ignore parameter="ServiceId"/>

        <return hlaInteraction="METOC_Interaction.Response.WeatherCondition.LandSurfaceCondition">
            <ignore parameter="EventId"/>
            <ignore parameter="Status"/>
        </return>
    </method>
</class>

In this case, the return type will be a Sen structure holding all the parameters of the interaction.

Methods that return errors.

If you don't want to return error codes, you can throw a std::exception, and Sen will propagate it to the caller.

Local-only methods.

Set the local attribute to true on the method node, for example:

<class name="MyClass">
    <method hlaInteraction="MyInteraction" local="true">
        <return hlaInteraction="MyResultInteraction"/>
    </method>
</class>

Events.

Events can be injected into classes in a similar way:

<class name="BaseEntity.PhysicalEntity">
    <event hlaInteraction="Collision">
        <ignore parameter="EventIdentifier"/>
        <ignore parameter="IssuingObjectIdentifier"/>
    </event>

    <event hlaInteraction="CollisionElastic">
        <ignore parameter="EventIdentifier"/>
        <ignore parameter="IssuingObjectIdentifier"/>
    </event>

    <event hlaInteraction="WeaponFire">
        <ignore parameter="EventIdentifier"/>
    </event>
</class>

Packing Arguments.

By default, each parameter in an interaction is mapped to an argument. If you want to pack them into a single structure, set the "pack" attribute to "true" (this works for methods and events). For example:

<class name="BaseEntity.PhysicalEntity.Munition">
    <event hlaInteraction="MunitionDetonation" pack="true">
        <ignore parameter="EventIdentifier"/>
        <ignore parameter="MunitionObjectIdentifier"/>
    </event>
</class>

Optionals.

There's no formal support for truly optional values in HLA. However, the Sen code generator helps by interpreting attributes as such when their documentation (semantics) start with the following strings:

  • "Optional."
  • "Optional ("
  • "Optional:"
  • "Optional,"

Customizing the generated code

Have a look at this section.