The JAUS standard relies on a component based message passing architecture. This message passing mechanism is the fundamental method for communications within a distributed system.

Refer to the following for a more information on the JAUS message concept:

    Understanding JAUS Messages


This guide is intended to describe how OpenJAUS can be utilized to interpret incoming and create outgoing JAUS messages.


Interpreting JAUS Service Set message documentation for use with the OpenJAUS SDK

The JAUS Service Set documentation will describe the body of a message as a collection of fields known as Composite Fields.

These Composite fields are made up of the following types:

  • sequence
  • list
  • variant
  • record 
  • array


The message body can be comprised of one or more of these Composite field types.

The OpenJAUS SDK will have a class for each JAUS message type.These classes will have accessor methods related to the Composite types. The sequence type is an exception as there is no OpenJAUS accessor for this type as the sequence represents an arrangement of one or more Composite Fields.


Example from AS6091 - JAUS Unmanned Ground Vehicle Service Set documentation


SetParkingBrake Message Encoding




Record Name = parkingBrakeRec
Field #   
Name

Type
Units

Optional
Interpretation
1
<fixed_field>
parkingBrake
unsigned byte
one
false
Percentage of application. Zero means off, while 100% mean fully engaged.
(scale_range = [0, 100], rounded)



In this case, the message body contains a single Composite field of type record.

The OpenJAUS SDK provides a class for the message, SetParkingBrake (refer to SetParkingBrake.h).

As this message contains only one record, the class provides accessors to manipulate the fixed field element 'parkingBrake'.

    double getParkingBrake_percent(void);
    bool setParkingBrake_percent(double value);


If a message has more than one record (homogeneous records) then the list type Composite field will be used. OpenJAUS classes for these types of message will provide slightly different means to access these records.

This is demonstrated here, again using the AS6091 - JAUS Unmanned Ground Vehicle Service Set documentation.



ReportStabilizerPosition Message Encoding



Record Name = stabilizerPositionRec
Field #   
Name

Type
Units

Optional
Interpretation
1
<fixed_field>
StabilizerID
unsigned byte
one
false

2
<fixed_field>
CommandedPosition
unsigned short integer
radian
false
(scaled range = [-3.14159,3.14159], round )
3
<fixed_field>
ActualPosition
unsigned short integer
radian
false
(scaled range = [-3.14159,3.14159], round )



In this case, the message body contains multiple homogeneous Composite fields of type record.

The OpenJAUS SDK provides a class for the message, ReportStabilizerPositionMessage (refer to ReportStabilizerPositionMessage.h).

As this message contains a list of records, the class provides an accessor to obtain this list (stabilizerPosition).

    ReportStabilizerPositionList& getReportStabilizerPositionList(void);


This returns a class of type ReportStabilizerPositionList which provides methods to manipulate this list of stabilizerPositionRec records.

    void add(ReportStabilizerPositionRecord value);
    void remove(int index);
    bool empty();
    void clear();
    bool set(std::size_t index, ReportStabilizerPositionRecord value);
    ReportStabilizerPositionRecord &get(std::size_t index);
    std::size_t size();


The OpenJAUS SDK class ReportStabilizerPositionRecord represents the record name, stabilizerPositionRec, listed in the above table.

A particular record of the list can be obtained using the get() method for which the  ReportStabilizerPositionRecord class provides methods to access the elements of the record.

    uint8_t getStabilizerID(void);
    double getCommandedPosition_rad(void);
    double getActualPosition_rad(void);
    

A record can be created and its elements set using the ReportStabilizerPositionRecord class methods

    bool setStabilizerID(uint8_t value);
    bool setCommandedPosition_rad(double value);
    bool setActualPosition_rad(double value);


The record can then be added to the list using the ReportStabilizerPositionList methods void add(ReportStabilizerPositionRecord value) or bool set(std::size_t index, ReportStabilizerPositionRecord value).


NOTE: The ReportStabilizerPositionList class provides the method std::vector<ReportStabilizerPositionRecord>& getReportStabilizerPositionRec();

It is not recommended to use this method as the underlying data structure for the record may change in the future.




The variant field represents a composite field that can be one of several different types of pre-defined composite fields at run time.


QueryEvents Message Encoding


Record Name = MessageIDRec
Field #   
Name

Type
Units

Optional
Interpretation
1
<fixed_field>
MessageID
unsigned short integer
one
false
Query Message ID of the Event message that the receiving component is inquiring about.
Record Name = EventTypeRec
Field # 
Name
Type
Units
Optional
Interpretation
1
<fixed_field>
EventType
unsigned byte
one
false
value_enum
0 Periodic
1 Every change
Record Name = EventIDRec
Field # 
Name
Type
Units
Optional
Interpretation
1
<fixed_field>
EventID
unsigned byte
one
false
Event ID returned by Confirm Event for details on specific event.
Record Name = AllEventsRec
Field # 
Name
Type
Units
Optional
Interpretation
1
<fixed_field>
AllEvents
unsigned byte
one
false
All events should be reported.
value_range(0,0)


In this example from AS5710A - JAUS Core Service Set, the Query Events message is composed of a variant of the Composite field type record.

The meta field vtag_field is an index to indicate which record the message contains. In this case, the vtag_field would have a value between 0 and 3. Only one record will be present in the message.


The OpenJAUS SDK provides a class for the message, QueryEvents(refer to QueryEvents.h).

As this message contains a variant, the class provides an accessor to obtain this variant(QueryEventsVar).

    QueryEventsVariant& getQueryEventsVariant(void);


This returns a class of type QueryEventsVariant which provides methods to obtain or set the variant type index (enum).

    QueryEventsVariant::TypeEnum getType(void);
    void setType(QueryEventsVariant::TypeEnum type);    

    enum TypeEnum {MESSAGEID = 0, EVENTTYPE = 1, EVENTID = 2, ALLEVENTS = 3};


The QueryEventsVariant class provides methods to obtain or set the element values for a record specific to the variant type.

    uint16_t getMessageID(void);
    bool setMessageID(uint16_t value);

    EventTypeEnumeration::EventTypeEnum getEventType(void);
    bool setEventType(EventTypeEnumeration::EventTypeEnum value);
   
    uint8_t getEventID(void);
    bool setEventID(uint8_t value);

    uint8_t getAllEvents(void);
    bool setAllEvents(uint8_t value);




If a message has more than one variant then the list type Composite field will be used. OpenJAUS classes for these types of message will provide slightly different means to access these variants.

This is demonstrated here using the AS6057A - JAUS Manipulator Service Set documentation.


SetJointMotionProfile Message Encoding


Record Name = RevoluteJointMotionProfileRec
Field #   
Name

Type
Units

Optional
Interpretation
1
<fixed_field>
JointMaxSpeed
unsigned integer
radian per
Sec
false
Scaled Integer
Lower limit = 0 radian per second
Upper limit = +10pi radian per second
2
<fixed_field>
JointMaxAccelerationRate
unsigned integer
radian per
Sec2
false
Scaled Integer
Lower limit = 0 radian per second
Upper limit = +10pi radian per second
3
<fixed_field>
JointMaxDecelerationRate
unsigned integer
radian per
Sec2
false
Scaled Integer
Lower limit = 0 radian per second
Upper limit = +10pi radian per second
Record Name = PrismaticJointMotionProfileRec
Field # 
Name
Type
Units
Optional
Interpretation
1
<fixed_field>
JointMaxSpeed
unsigned integer
meter per second
false
Scaled Integer
Lower limit = 0 m/sec
Upper limit = +5 m/sec
2
<fixed_field>
JointMaxAccelerationRate
unsigned integer
meter per second2
false
Scaled Integer
Lower limit = 0 m/sec2
Upper limit = +20 m/sec2
3
<fixed_field>
JointMaxDecelerationRate
unsigned integer
meter per second2
false
Scaled Integer
Lower limit = 0 m/sec2
Upper limit = +20 m/sec2


In this case, the message body contains multiple Composite fields of type variant.

The OpenJAUS SDK provides a class for the message, SetJointMotionProfile(refer to SetJointMotionProfile.h).

As this message contains a list of variants, the class provides an accessor to obtain this list (JointMotionProfileList).

    JointMotionProfileList& getJointMotionProfileList(void);


This returns a class of type JointMotionProfileList which provides methods to manipulate this list of JointTypeVariant variants.

    void add(JointTypeVariant value);
    void remove(int index);
    bool empty();
    void clear();
    bool set(std::size_t index, JointTypeVariant value);
    JointTypeVariant &get(std::size_t index);
    std::size_t size();


This OpenJAUS SDK class JointTypeVariant provides methods to obtain or set the variant type index (enum).

    JointTypeVariant::TypeEnum getType(void);
    void setType(JointTypeVariant::TypeEnum type);

    enum TypeEnum {REVOLUTEJOINTMOTIONPROFILEREC = 0, PRISMATICJOINTMOTIONPROFILEREC = 1};


Once the variant is determined the JointTypeVariant class provides methods to obtain the record specific to the variant.

    RevoluteJointMotionProfileRecord& getRevoluteJointMotionProfileRec(void);
    PrismaticJointMotionProfileRecord& getPrismaticJointMotionProfileRec(void);


Each of these record classes provide methods to obtain or set the element values for the record

    RevoluteJointMotionProfileRecord

            double getRevoluteJointMaxSpeed_rps(void);
            bool setRevoluteJointMaxSpeed_rps(double value);
            double getRevoluteJointMaxAccelerationRate_rps2(void);
            bool setRevoluteJointMaxAccelerationRate_rps2(double value);
            double getRevoluteJointMaxDecelerationRate_rps2(void);
            bool setRevoluteJointMaxDecelerationRate_rps2(double value);


    PrismaticJointMotionProfileRecord

            double getPrismaticJointMaxSpeed_mps(void);
            bool setPrismaticJointMaxSpeed_mps(double value);
            double getPrismaticJointMaxAccelerationRate_mps2(void);
            bool setPrismaticJointMaxAccelerationRate_mps2(double value);
            double getPrismaticJointMaxDecelerationRate_mps2(void);
            bool setPrismaticJointMaxDecelerationRate_mps2(double value);


If a record is created it can be added to the variant list using the JointMotionProfileList methods void add(JointTypeVariant value) or bool set(std::size_t index, JointTypeVariant value).


Presence Vectors in OpenJAUS SDK

The OpenJAUS SDK JAUS message type classes will provide methods and macros to manipulate the presence vector of a message.

By default an object created from these classes will have its presence vector initialized  to have all of the bits in the field enabled. This would indicate that all of the elements in the record associated with that presence vector will have valid values.

Therefore, when creating a message that has a record defined by a presence vector it is important to configure the presence vector to indicate which elements of the record are actually valid.

The ReportDebrisBlowerConfigurationmessage class can be used as a typical example of a message the contains a record defined by a presence vector.

The ReportDebrisBlowerConfigurationmessage has one record (DebrisBlowerConfigurationRec) which has three elements; OnOffStatus, Azimuth, Elevation


One means to set the presence vector is a method that manipulates multiple bits of the field.

    void setPresenceVector(uint8_t value);


The following macros can be used to generate a desired bit field value:

    static const uint8_t PV_NO_FIELDS = 0x0;
    static const uint8_t PV_ONOFFSTATUS = 0x1;
    static const uint8_t PV_AZIMUTH = 0x2;
    static const uint8_t PV_ELEVATION = 0x4;
    static const uint8_t PV_ALL_FIELDS = PV_NO_FIELDS | PV_ONOFFSTATUS | PV_AZIMUTH | PV_ELEVATION;


Another means is to set or clear individual bits of the bit field.

The ReportDebrisBlowerConfigurationclass provides the following methods for this approach:

    void enableOnOffStatus(void);
    void disableOnOffStatus(void);
    void enableAzimuth(void);
    void disableAzimuth(void);
    void enableElevation(void);
    void disableElevation(void);

These methods will enable or disable the respective bit in the bit field.


The class also provides methods to obtain the whole bit field or determine the state of a particular bit.

    uint8_t getPresenceVector(void) const;

    bool isOnOffStatusEnabled(void) const;

    bool isAzimuthEnabled(void) const;

    bool isElevationEnabled(void) const;


When responding to query messages that provide a presence vector, the response message should provide a presence vector that is the result of a logical AND of the query message presence vector and the presence vector that is derived to indicate what elements of the record are actually valid. This will provide the requester with a presence vector that indicates the robot's valid elements for that record that the requester is interested in.


For system design considerations and best practices related to JAUS Messages see JAUS Messages.


Message Creation Example Using OpenJAUS SDK

For this example the Report Power Plant Capabilities message will be used.

Information about this message can be found in the AS6091 - JAUS Unmanned Ground Vehicle Service Set documentation.


ReportPowerPlantCapabilities Message Encoding



Record Name = powerPlantDescRec
Field #   
Name

Type
Units

Optional
Interpretation
1
<fixed_field>
powerPlantID
unsigned byte
one
false
Each powerplant has a unique ID associated with it. This ID is used in subsequent messages.
2
<fixed_field>
description
count_field = unsigned_byte
one
false
A human-readable string that can be used to disambiguate multiple powerplants.
Record Name = gasEngineCapabilitiesRec
Field # 
Name
Type
Units
Optional
Interpretation
1
<presence_vector>
unsigned byte



2
<fixed_field>
fuelCapacity
unsigned short integer
liter
true
(scaled range = [0.0,256.0], round )
3
<fixed_field>
oilCapacity
unsigned short integer
liter
true
(scaled range = [0.0,256.0], round )
4
<fixed_field>
maxOilPressure
unsigned short integer
bar
true
(scaled range = [0.0,256.0], round )
5
<fixed_field>
maxOilTemp
unsigned short integer
degree Celsius
true
(scaled range = [0.0,256.0], round )
6
<fixed_field>
maxEngineTemp
unsigned short integer
degree Celsius
true
(scaled range = [0.0,256.0], round )
7
<fixed_field>
maxCoolantLevel
unsigned short integer
liter
true
(scaled range = [0.0,256.0], round )
8
<fixed_field>
maxCoolantTemp
unsigned short integer
degree Celsius
true
(scaled range = [0.0,256.0], round )
Record Name = dieselEngineCapabilitiesRec
Field #
Name
Type
Units
Optional
Interpretation
1
<presence_vector>
unsigned short integer



2
<fixed_field>
fuelCapacity
unsigned short integer
liter
true
(scaled range = [0.0,256.0], round )
3
<fixed_field>
oilCapacity
unsigned short integer
liter
true
(scaled range = [0.0,256.0], round )
4
<fixed_field>
maxOilPressure
unsigned short integer
bar
true
(scaled range = [0.0,512.0], round )
5
<fixed_field>
maxOilTemp
unsigned short integer
degree
Celsius
true
(scaled range = [-75.0,180.0], round )
6
<fixed_field>
maxEngineTemp
unsigned short integer
degree
Celsius
true
(scaled range = [0.0,256.0], round )
7
<fixed_field>
maxCoolantLevel
unsigned short integer
liter
true
(scaled range = [0.0,256.0], round )
8
<fixed_field>
maxCoolantTemp
unsigned short integer
degree
Celsius
true
(scaled range = [-75.0,180.0], round )
9
<fixed_field>
maxGlowPlugTemp
unsigned short integer
degree
Celsius
true
(scaled range = [0.0,256.0], round )
10
<fixed_field>
glowPlugTime
unsigned short integer
second

true
(scaled range = [0.0,256.0], round )
Record Name = batteryCapabilitiesRec
Field #
Name
Type
Units
Optional
Interpretation
1
<presence_vector>
unsigned byte



2
<fixed_field>
nominalVoltage
unsigned short integer
volt
true
(scaled range = [0.0,1000.0], round )
3
<fixed_field>
maxCharge
unsigned integer
coulomb
true
(scaled range = [0.0,3600000.0], round )
4
<fixed_field>
maxCrankingAmps
unsigned short integer
ampere
true
(scaled range = [0.0,5000.0], round )
Record Name = hydraulicCapabilitiesRec
Field #
Name
Type
Units
Optional
Interpretation
1
<presence_vector>
unsigned byte



2
<fixed_field>
fluidCapacity
unsigned short integer
liter
true
(scaled range = [0.0,256.0], round )
3
<fixed_field>
maxPressure
unsigned short integer
bar
true
(scaled range = [0.0,512.0], round )
4
<fixed_field>
maxTemp
unsigned short integer
degree
Celsius
true
(scaled range = [-75.0,180.0], round )
Record Name = fuelCellCapabilitiesRec
Field #
Name
Type
Units
Optional
Interpretation
1
<presence_vector>
unsigned byte



2
<fixed_field>
fuelCapacity
unsigned short integer
kilograms
true
(scaled range = [0.0,256.0], round )


For this example a robot with two power plant types will be assumed.

  •     Diesel Engine power plant
  •     Battery power plant


The Diesel Engine power plant will have the following characteristics:

  •     A power plant ID of 20
  •     Fuel capacity capability
  •     Oil capacity capability
  •     Maximum Oil Pressure capability
  •     Maximum Oil Temperature capability


The Battery power plant will have the following characteristics:

  •     A power plant ID of 30
  •     4 Batteries
  •     Nominal Voltage capability
  •     Maximum Charge capability

        

The report Power Plant Capabilities messages is part of the JAUS Power Plant Manager service. The OpenJAUS SDK provides this service.

The OpenJAUS SDK classes needed for this message are:

  •     PowerPlantManager (PowerPlantManager.h)
  •     ReportPowerPlantCapabilities (ReportPowerPlantCapabilities.h)
  •     PowerPlantCapabilitiesList (PowerPlantCapabilitiesList.h)
  •     PowerPlantCapabilitiesRecord (PowerPlantCapabilitiesRecord.h)
  •     PowerPlantCapabilitiesVariant (PowerPlantCapabilitiesVariant.h)
  •     QueryPowerPlantCapabilities (QueryPowerPlantCapabilities.h)
  •     PowerPlantIdList (PowerPlantIdList.h)


Reporting of the message is triggered by the incoming message request, QueryPowerPlantCapabilities.

The  PowerPlantManager class provides the method for this and the developer will need to implement it.

    virtual ReportPowerPlantCapabilities getReportPowerPlantCapabilities(QueryPowerPlantCapabilities *queryPowerPlantCapabilities);


The parameter, queryPowerPlantCapabilities, is the incoming message request.

The AS6091 - JAUS Unmanned Ground Vehicle Service Set documentation describes the QueryPowerPlantCapabilities message as:



QueryPowerPlantCapabilitiesMessage Encoding

Record Name = powerPlantID
Field #   
Name

Type
Units

Optional
Interpretation
1
<fixed_field>
powerPlantID
unsigned byte
one
false
A list of IDs to query. If the list is empty (count_field=0), all vehicle powerplants will be returned.


The getReportPowerPlantCapabilities() method will need to examine the parameter list to determine how many Power Plant IDs are being requested to query. If the list is empty, then the requester is requesting that capabilities for all Power Plants on the robot be provided. If one or more unique Power Plant IDs are in the list then the method would check that the requested IDs match the IDs of the Power Plant(s) on the robot for which the the method would construct the message to provide the capabilities records for those Power Plants. In the event that the query list contains IDs that are not present on the robot, the method would end up with an empty ReportPowerPlantCapabilities message to send.

    

Source Code Example of Report Power Plant Capabilities Message Creation



    const uint8 GAS_ENGINE_POWER_PLANT = 20;
    const uint8 BATTERY_POWER_PLANT = 30;
    std::set<uint8> robotPowerPlantIds;
    robotPowerPlantIds.insert(GAS_ENGINE_POWER_PLANT);
    robotPowerPlantIds.insert(BATTERY_POWER_PLANT);


openjaus::ugv_v1_0::ReportPowerPlantCapabilities PowerPlantServiceGroup::getReportPowerPlantCapabilities(
                                            openjaus::ugv_v1_0::QueryPowerPlantCapabilities *queryPowerPlantCapabilities)
{
    // Create a ReportPowerPlantCapabilities object. This is what will be sent to the JAUS ID that sent the
    // QueryPowerPlantCapabilities message.
    openjaus::ugv_v1_0::ReportPowerPlantCapabilities message;

    // Obtain the Power Plant Id list from the incoming query message.
    openjaus::ugv_v1_0::PowerPlantIdList& requestedPowerPlantIdList = queryPowerPlantCapabilities->getPowerPlantIdList();

    // Determine the number of PowerPlants ID s to iterate over. If the incoming list size is 0, then
    // all Power Plant IDs on the robot should be iterated over.
    size_t powerPlantIdIterationSize = requestedPowerPlantIdList.size();
    bool iterateAll = false;
    if (powerPlantIdIterationSize == 0)
    {
        powerPlantIdIterationSize = robotPowerPlantIds.size();
        iterateAll = true;
    }

    for (uint8 powerPlantIdIndex = 0; powerPlantIdIndex < powerPlantIdIterationSize; ++powerPlantIdIndex)
    {
        uint8 currentPowerPlantId = 0;

        // If query message list is not 0, then get Power Plant ID at current index. If the ID is one that the robot has
        // set the current Power Plant ID to this value.
        if (!iterateAll)
        {
            openjaus::model::fields::UnsignedByte& requestedPowerPlantIdField = requestedPowerPlantIdList.get(powerPlantIdIndex);
            uint8 requestedPowerPlantId = requestedPowerPlantIdField.getValue();
            if (robotPowerPlantIds.count(requestedPowerPlantId))
            {
                currentPowerPlantId = requestedPowerPlantId;
            }
        }
        // Otherwise query list is 0. Report all Power Plant IDs on robot.
        else
        {
            std::set<uint8>::iterator iterator = robotPowerPlantIds.begin();
            std::advance(iterator, powerPlantIdIndex);
            currentPowerPlantId = *iterator;
        }

        // Obtain the Power Plant Capabilities list from the outgoing report message.
        // Note the use of a reference (&) as a local copy of the list should not be used.
        openjaus::ugv_v1_0::PowerPlantCapabilitiesList& reportedPowerPlantCapabilitiesList = message.getPowerPlantCapabilitiesList();

        // Create Power Plant Capabilities record object
        openjaus::ugv_v1_0::PowerPlantCapabilitiesRecord powerPlantCapabilitiesRecord;

        switch (currentPowerPlantId)
        {
            // Construct a report message for the Gas Engine Power Plant
            case GAS_ENGINE_POWER_PLANT :
            {
                // Set the Power Plant capabilities record ID and text description
                powerPlantCapabilitiesRecord.setPowerPlantID(GAS_ENGINE_POWER_PLANT);
                powerPlantCapabilitiesRecord.setDescription("OpenJAUS Robot Gas Engine");

                // Obtain the variant field of the Power Plant capabilities record.
                // Note the use of a reference (&) as a local copy of the list should not be used.
                openjaus::ugv_v1_0::PowerPlantCapabilitiesVariant& powerPlantCapabilitiesVariant = powerPlantCapabilitiesRecord.getPowerPlantCapabilitiesVariant();

                // Set the variant type to Gas Engine
                powerPlantCapabilitiesVariant.setType(openjaus::ugv_v1_0::PowerPlantCapabilitiesVariant::TypeEnum::GASENGINECAPABILITIESRECORD);

                // Obtain the gas engine capabilities record of the variant.
                // Note the use of a reference (&) as a local copy of the list should not be used.
                openjaus::ugv_v1_0::GasEngineCapabilitiesRecord& gasEngineCapabilitiesRecord = powerPlantCapabilitiesVariant.getGasEngineCapabilitiesRecord();

                // Clear the presence vector of this record.
                gasEngineCapabilitiesRecord.setPresenceVector(openjaus::ugv_v1_0::GasEngineCapabilitiesRecord::PV_NO_FIELDS);

                // Set the presence vector bits for the capabilities that the robot supports.
                gasEngineCapabilitiesRecord.enableFuelCapacity();
                gasEngineCapabilitiesRecord.enableOilCapacity();
                gasEngineCapabilitiesRecord.enableMaxOilPressure();
                gasEngineCapabilitiesRecord.enableMaxOilTemp();

                // Set the values for the reported capabilities
                gasEngineCapabilitiesRecord.setFuelCapacity_l(20.0);
                gasEngineCapabilitiesRecord.setOilCapacity_l(1.5);
                gasEngineCapabilitiesRecord.setMaxOilPressure_bar(100.0);
                gasEngineCapabilitiesRecord.setMaxOilTemp_degC(150.0);

                // Add the created capabilities record to the outgoing message capabilities list.
                reportedPowerPlantCapabilitiesList.add(powerPlantCapabilitiesRecord);
                break;
            }

            // Construct a report message for the Battery Power Plant
            case BATTERY_POWER_PLANT :
            {
                // Set the Power Plant capabilities record ID and text description
                powerPlantCapabilitiesRecord.setPowerPlantID(BATTERY_POWER_PLANT);
                powerPlantCapabilitiesRecord.setDescription("OpenJAUS Robot Battery");

                // Obtain the variant field of the Power Plant capabilities record.
                // Note the use of a reference (&) as a local copy of the list should not be used.
                openjaus::ugv_v1_0::PowerPlantCapabilitiesVariant& powerPlantCapabilitiesVariant = powerPlantCapabilitiesRecord.getPowerPlantCapabilitiesVariant();

                // Set the variant type to Battery
                powerPlantCapabilitiesVariant.setType(openjaus::ugv_v1_0::PowerPlantCapabilitiesVariant::TypeEnum::BATTERYCAPABILITIESLIST);

                // Obtain the battery capabilities list of the variant.
                // Note the use of a reference (&) as a local copy of the list should not be used.
                openjaus::ugv_v1_0::BatteryCapabilitiesList& batteryCapabilitiesList = powerPlantCapabilitiesVariant.getBatteryCapabilitiesList();

                // As the robot Battery Power Plant has 4 batteries, 4 records will be created and added to the Battery
                // Capabilities list. For this example, all batteries have the same capabilities and values.

                for (uint8 batteryIndex = 0; batteryIndex < 4; ++batteryIndex)
                {
                    // Create Battery Capabilities record object
                    openjaus::ugv_v1_0::BatteryCapabilitiesRecord batteryCapabilitiesRecord;

                    // Clear the presence vector of this record.
                    batteryCapabilitiesRecord.setPresenceVector(openjaus::ugv_v1_0::BatteryCapabilitiesRecord::PV_NO_FIELDS);

                    // Set the presence vector bits for the capabilities that the robot supports.
                    batteryCapabilitiesRecord.enableNominalVoltage();
                    batteryCapabilitiesRecord.enableMaxCharge();

                    // Set the values for the reported capabilities
                    batteryCapabilitiesRecord.setNominalVoltage_V(12.0);
                    batteryCapabilitiesRecord.setMaxCharge_C(5000.0);

                    // Add the record to the battery capabilities list.
                    batteryCapabilitiesList.add(batteryCapabilitiesRecord);
                }
                // Add the created capabilities record to the outgoing message capabilities list.
                reportedPowerPlantCapabilitiesList.add(powerPlantCapabilitiesRecord);
                break;
            }

            // No matching Power Plant ID was found. No record construction performed.
            default :
            {
                break;
            }

        }
    }
    return message;
}



For further information related to best practices regarding JAUS Messages see the following link:

Best Practices:JAUS Messages