    

 ## On this page

  

 

 # Implement and use a standalone activity 

 Last update: 16.07.2025 

Simulation Framework provides the possibility to inject any custom logic into a standalone activity , which is another process running outside the `simfwk_cli` , but is able to connect with the simfwk core and communication with other activities.

### <a class="anchor" id="autotoc_md7"></a>Interfaces and topic definition in RefSim

To implement one customized standalone activity, you need to have a look on essential interfaces: `<a class="el" href="base__activity_8h_source.xhtml">core/lifecycle/activity/base_activity.h</a>` , `<a class="el" href="standalone__activity__service_8h_source.xhtml">core/service/standalone_activity_service/standalone_activity_service.h</a>` , `<a class="el" href="i__standalone__activity__creator_8h_source.xhtml">core/service/standalone_activity_service/standalone_activity_creator/i_standalone_activity_creator.h</a>` and topic definitions `<a class="el" href="topic__registry_8h_source.xhtml">core/communication/topic_registry.h</a>` .

`BaseActivity` is the basic implementation of `IActivity` interface and used as base class of all customized activities. Inheriting classes, i.e. a concrete simulation activity, should implement their logic in `ExecuteStep()` and add needed pub/sub in `AddPublisherAndSubscriber()` method to achieve communications between others.

`IStandaloneActivityCreator` is the interface class for creating a standalone activity service. It defines how a customized activity needs to be instantiated through or not through `StandaloneInitData` .

`StandaloneActivityService` provides a running process of desired activity returned by interface `IStandaloneActivityCreator` and keeps it communicating and being scheduled by Simulation Framework core process.

`<a class="el" href="namespacetopic__registry.xhtml" title="The namespace for topic registry in communication module under namespace simulation_framework::core.">topic_registry</a>` is a dedicated namespace where defines list of concrete Topics that can be used for creation of communication channels with given underlying message. As default, DDS message/communication type will be applied. The name of Topic ( `TopicId` ), which is passed into constructor to Topic, is globally unique and represents one single Topic, the underlying message could be the same though.

Currently following Topics and Message Type are available to use with Simulation Framework core library:

Topic Id (string) C++ Topic Type Underlying DDS Message Type Info StringTestTopic `StringTopicType` `dds::core::StringTopicType` native DDS string message type only for testing purpose KpiLoggerTopic `KpiMessageTopicType` `rtidds::KpiMessage` Message to KpiLoggerActivity, each `KpiContent` inside `KpiMessage` will be logged into json SensorViewTopic `GenericBytesTopicType` `rtidds::GenericBytesMessage` Message to store osi `SensorView` protobuf message as bytes array TrafficUpdateTopic `GenericBytesTopicType` `rtidds::GenericBytesMessage` Message to store osi `TrafficUpdate` protobuf message as bytes array TrafficCommandTopic `GenericBytesTopicType` `rtidds::GenericBytesMessage` Message to store osi `TrafficCommand` protobuf message as bytes array ### <a class="anchor" id="autotoc_md8"></a>Limitation of topic

As mentioned in the sections above, activities can exchange data using messages through `Topics`. Users must be careful to ensure the deterministic behavior of the simulation. This means that one `Topic` should have only one publisher. The issue with having multiple publishers on the same topic is that the first message from the faster publisher may arrive on the subscriber side and get consumed, while the second message from the slower publisher might be neglected.

Currently, this restriction is not enforced by the Simulation Framework, especially when `Standalone Activities` are running in different processes. In the near future, the Simulation Framework will incorporate this limitation to prevent such issues from occurring at the beginning of runtime.

### <a class="anchor" id="autotoc_md9"></a>Customize your topic

By means of any existing message type provided by `<a class="el" href="topic__registry_8h_source.xhtml">core/communication/topic_registry.h</a>`, you can create any Topic you need for your simulations. Example of creating a new Topic with Message Type `rtidds::GenericBytesMessage` in one line:

auto your_topic = std::make_shared&lt;Topic&lt;rtidds::GenericBytesMessage&gt;&gt;("YourTopicId");



After that `your_topic` is ready to use for instanciate your activities.

### <a class="anchor" id="autotoc_md10"></a>Create a Topic using GenericBytesMessage

`rtidds::GenericBytesMessage` is a generic message type which allows the users put any content as serialized bytes array. E.g. `GenericBytesTopicType`, which stores the [OSI protobuf](https://github.com/OpenSimulationInterface/open-simulation-interface) message as underlying payload, is a good example to show how this mechanism works out. If you have a protobuf message which you want to send, you only need to call protobuf C++ API like following:

YourProtobufMessage protobuf_msg;

 

rtidds::GenericBytesMessage generic_msg{};

 

generic_msg.timestamp().seconds(1);

generic_msg.timestamp().nanoseconds(0)

 

size\_t size = protobuf_msg.ByteSizeLong();

std::vector&lt;unsigned char&gt; proto_data_in_bytes;

proto_data_in_bytes.resize(size);

 

protobuf_msg.SerializeToArray(proto_data_in_bytes.data(), size);

 

generic_msg.size(size);

generic_msg.bytes_array(proto_data_in_bytes);



Then you will have a filled `GenericBytesMessage` generic\_msg with your desired content and can publish it into the Topic defined with "YourTopicId".

On the subscriber side, you just need to decode the message from bytes array.

YourProtobufMessage protobuf_msg;

if (!protobuf_msg.ParseFromArray(generic_msg.bytes_array().data(),

 generic_msg.size()))

{

 throw std::runtime_error("Error parsing proto msg from bytes array in generic\_msg! ");

}

ProcessYourProtoMsg(protobuf_msg);



For complete implementation example into your simulation, please refer `/example/my_customized_topic/my_activities.h` after installation.

### <a class="anchor" id="autotoc_md11"></a>Example standalone activity

There is an example implementation of `Standalone Activity` provided by the Simulation Framework delivery, namely `simulation_framework/example/my_activity/my_activity.h` . This `Activity` can be executed independently from `simfwk_cli` , and they will wait for simulation requests from `simfwk_cli` if they are selected in the simulation config.

Following the code API documentation and instruction in the comments of this example implementation, you might understand how you can build your own `Activity` step by step and use it inside simulation.

### <a class="anchor" id="autotoc_md12"></a>Use one standalone activity

you can use the example standalone activity `my_test_activity` by defining this config `my_sim_config.json`

{

 "sim_instance_name": "simulation_config_uses_my_test_activity",

 "activities": [

 {

 "name": "groundtruth_generator_activity",

 "is_world_simulator": true,

 "topics_cycling_info": [

 {

 "topic_id": "__all__",

 "topic_cycle_time_in_ms": 100

 }

 ],

 "type": "built-in"

 },

 {

 "name": "driver_model_activity",

 "depends_on": [

 "groundtruth_generator_activity"

 ],

 "type": "built-in"

 },

 {

 "name": "my_test_activity",

 "depends_on": [

 "groundtruth_generator_activity"

 ],

 "type": "standalone"

 },

 {

 "name": "kpi_evaluator_activity",

 "depends_on": [

 "groundtruth_generator_activity"

 ],

 "type": "built-in"

 },

 {

 "name": "kpi_logger_activity",

 "depends_on": [

 "kpi_evaluator_activity"

 ],

 "type": "built-in"

 }

 ]

}



and use it in simulation by `simfwk_cli` :

./simfwk_cli -s &lt;your_scenario.xosc&gt; -o &lt;your_output_path&gt; -d my_sim_config.json