Using HLA FOMs¶
Sen is able to use HLA FOMs to model types and classes.
Example of a diagram generated by Sen:
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.