Table of Contents

Editor: Using Messages

Description

A message is the standard device used to communicate data between components in the Nominal simulation suite. Messages are composed of properties that can be edited and read from data and messages are connected as the link between different modules. Modules can have one of two different message inputs:

  1. In_Msg: An input message is a reference to a message that is required to be linked by the software or the user, as a way to specify a targeted set of data, that will change over the simulation.
  2. Out_Msg: An output message is a message instance that is managed by the component it is connected to. It controls the data that exists on the message and outputs the state after each update state.

This guide will cover how to utilize messages in Unreal using Nominal’s architecture and how to manage the data within messages.


Linking Messages

Each message, generally, has an owner component for the message. This is the component that predominantly writes data to the message parameters and changes the data over the simulation time. A single output message can be linked to zero-many other components, assuming they have the same message input type. Input messages are used as reference reading parameters, and those components should not be adjusting the values within those messages. An example of how messages can be linked together is shown in the guidance computer chain shown below:

Untitled

Note

A guidance computer has several software chains that each link many messages between the chains; ensuring that the data can flow correctly between the nodes.

In Unreal, the terminology for messages uses the In_ and Out_ standard syntax, indicating which message is an input and which is an output message. The type of message is also within the name; specifying the message type after the prefix. For example:

  • Out_NavTransMsg: [OUTPUT] Navigation Translation Message
  • Out_AttRefMsg: [OUTPUT] Attitude Reference Message
  • In_RWSpeedMsg: [INPUT] Reaction Wheel Speed Message
  • In_DeviceStatusMsg: [INPUT] Device Status Message

In Unreal, each of the messages is shown in a teal-green colour, indicating they are of type int64. The type specifies that it is a reference to an object. Unreal will allow for messages of different types to be connected, but this will throw errors in the back-end simulation. Ensure that the suffixes of the message (excluding the In_ and Out_) are identical. This is a general rule of thumb to ensure the message types are valid.

Although many components can be linked with messages, the most common example is linking flight software modes when developing a custom flight software chain. More information on constructing these chains can be found in the Flight Software Operator Guide. For example, take the following snippet of a software chain found in Demo_SunPointing:

Untitled

In this case, each of the software modules has several input and output messages that can be exposed and linked together. The suffixes of the message names must match with each other for a valid link to be created. Additionally, for certain modules, certain messages can be left disconnected. The value will appear as a 0 reference in the input message to disconnect a message reference. A ‘0’ value states that no message has been connected as an input.


Getting Messages

For many components in Unreal, the standard terminology for fetching all of the output messages from a component is using the Get Out Messages function, which, if existing, will return a list of all message references managed by that component. This works on all components, including the spacecraft. Searching for ‘Get Out’ will result in a list of different out messages available for the component. There are sometimes multiple functions due to the different levels of inheritance that may result in outputting messages from the component.

Untitled

All components will use the ‘Get Out Messages’ standard for returning the list of output messages from that component or class, provided it is a Nominal managed class.

Untitled

In some cases, the specific messages can also be fetched from the component. In these examples, those messages that can be read from the component also exist in the ‘Get Out Messages’ function, but only provide that specific message instead of the others.

Untitled


Setting Messages

Similarly, all components that have input messages have a similar function for setting the messages. This is the ‘Set In Messages' function and exists on several components. This is useful for connecting the message references from some output messages to the function node.

Untitled

Note

Not all components have input messages though, and those that don’t will not have the function present.

Similar to the output messages, each of the input messages can often be set individually, rather than by setting all the messages at once. However, any messages left as a 0 reference will not be set and the value will not be replaced with a nullptr. These two methods above are identical; both allow the setting of the In_SoftwareChainMsg parameter.

Untitled


Printing Messages

Messages can be printed using the Message to String function, which can output all of the data within the message and convert it to an appropriate string type. This can be useful for debugging and printing to the screen when something is going wrong. The function requires the int64 reference pointer to be passed in. It will throw an error warning if the pointer is invalid or zero.

Untitled

Depending on the message, the data will be displayed on the screen in different forms, based on what parameters are available on the individual message. For example. the following show a reaction wheel message and a body state message being printed respectively.

Untitled

Untitled


Reading Messages

For each message, a dedicated read function has been created to allow for reading the individual data of the message. Each message is of a different type and requires a different function to read the individual parameters. The name of the message type is usually found in the message name. For example, with the Out_BodyStatesMsg value, the message type is a Body States Message. To read the message, searching for the static function Read Body States Message can return the value as a struct.

Untitled

From there, a payload struct will be returned. By Breaking the struct, the full set of parameters can be exposed and used for calculations or within the level blueprint.

Untitled

Each message will be different and have a different set of structure values and parameters that get returned from the message. Often, FDouble and FDouble3 value types are returned over the Unreal conventional float and FVector. These are more useful as they are double-precision data and correctly store that within the back-end architecture. In the Solar Panel’s example, the two output messages can have several different values based on what form of message they are.

Untitled


Writing Messages

Messages can also be updated from within blueprints. Messages that are updated should only be done when the messages are managed from within Unreal, but more information on creating messages can be found in the section below. To write a message, a similar process is followed to reading them. Each message has a dedicated static function called Write Message and takes in the reference to the message to write the data for. Each of the ‘write’ message functions also takes in a structure suitable for that message that needs to be filled with the data that is being written.

Untitled

The structure can be built using the Make structure function, which exists for all message types. Once written to the message, the data within that message is synced with all components that have the same message reference as their input messages, allowing a seamless transfer of data.

Untitled


Creating Messages

Sometimes, new messages are required to be created and inserted into the system. The messages are created in Blueprints and connected to the input messages of other components. This ensures that the output messages are not being overridden, whilst providing full control for the user to update the data correctly and manage the data over time. Each message has a dedicated Create message function that exists for creating a message of that type. These functions only take in the structure with the data for that message. The create message functions return the reference to the message that exists in the backend that was newly created. No component owns these messages and are owned by the user.

Untitled

Once created, the messages can be handled in the same way as before, allowing for reading, writing and linking to other components. The following example shows replacing the Attitude Guidance Message with a new custom message that can be defined in Blueprints.

Untitled


Storing Messages

Due to the nature of how Unreal deals with pointers to data objects, simply storing the int64 value to the message will not work. Unreal will often shuffle the memory to optimize the runtime and will result in the pointers changing. When dealing with pointers to messages over a single timestep in the level blueprint, the int64 value is enough to connect up messages. However, with multiple timesteps or attempting to update data after some time from creating a new message, a different storage system needs to be implemented to save the message. This is done by storing the message as a Mono Object structure.

Untitled

There are a couple of options when creating a Mono Object reference; an object ref and a pinned ref. An object reference creates a weak reference that is suitable for managing the message within the same blueprint. However, for multi-blueprint messages, a pinned reference is the preferable method of creating the Mono object. This will pin the data in memory and ensure the data is not swapped and is accessible anywhere. Once as an object reference, the value can be stored as a variable.

Untitled

Note

The FMonoObject structure can be stored as a variable in Unreal blueprints and ensures that the address of the data (in this case a message) does not get deleted.

This method is usually only used when creating new messages. When getting the messages from the Get Out Messages function, the message is always pulled from the correct location in memory and does not require a Mono object reference to be correct. To then get the pointer back from the message, the Mono Object Handle can be requested and used from the reference. This number may be different throughout the simulation but the object should return the correct reference each time.

Untitled