-
Notifications
You must be signed in to change notification settings - Fork 44
Add SetStepDuration and TimeAdvanceModes #284
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,90 @@ | ||
| // SPDX-FileCopyrightText: 2024 Vector Informatik GmbH | ||
| // | ||
| // SPDX-License-Identifier: MIT | ||
|
|
||
| #include <iostream> | ||
| #include <random> | ||
|
|
||
| #include "silkit/SilKit.hpp" | ||
|
|
||
| using namespace std::chrono_literals; | ||
|
|
||
| std::ostream& operator<<(std::ostream& out, std::chrono::nanoseconds timestamp) | ||
| { | ||
| out << std::chrono::duration_cast<std::chrono::milliseconds>(timestamp).count() << "ms"; | ||
| return out; | ||
| } | ||
|
|
||
| int main(int argc, char** argv) | ||
| { | ||
| if (argc != 2) | ||
| { | ||
| std::cerr << "Wrong number of arguments! Start demo with: " << argv[0] << " <ParticipantName>" << std::endl; | ||
| return -1; | ||
| } | ||
| std::string participantName(argv[1]); | ||
|
|
||
| try | ||
| { | ||
| // Setup participant, lifecycle, time synchronization and logging. | ||
| const std::string registryUri = "silkit://localhost:8500"; | ||
| const std::string configString = R"({"Logging":{"Sinks":[{"Type":"Stdout","Level":"Info"}]}})"; | ||
| auto participantConfiguration = SilKit::Config::ParticipantConfigurationFromString(configString); | ||
|
|
||
| auto participant = SilKit::CreateParticipant(participantConfiguration, participantName, registryUri); | ||
| auto logger = participant->GetLogger(); | ||
|
|
||
| auto* lifecycleService = | ||
| participant->CreateLifecycleService({SilKit::Services::Orchestration::OperationMode::Coordinated}); | ||
|
|
||
| auto* timeSyncService = lifecycleService->CreateTimeSyncService(SilKit::Services::Orchestration::TimeAdvanceMode::ByMinimalDuration); | ||
|
|
||
| const auto stepSize = 10ms; | ||
| static int stepCounter = 0; | ||
| std::random_device rd; | ||
| std::mt19937 rng(rd()); | ||
| auto bounded_rand = [&rng](unsigned range) { | ||
| std::uniform_int_distribution<unsigned> dist(1, range); | ||
| return dist(rng); | ||
| }; | ||
|
|
||
|
|
||
| timeSyncService->SetSimulationStepHandler( | ||
| [logger, timeSyncService, participantName, bounded_rand](std::chrono::nanoseconds now, | ||
| std::chrono::nanoseconds duration) { | ||
| // The invocation of this handler marks the beginning of a simulation step. | ||
| { | ||
| std::stringstream ss; | ||
| ss << "--------- Simulation step T=" << now << ", duration=" << duration << " ---------"; | ||
| logger->Info(ss.str()); | ||
| } | ||
|
|
||
| if (bounded_rand(10) == 1)// && participantName == "P1") | ||
| { | ||
| auto rndStepDuration = bounded_rand(10); | ||
| timeSyncService->SetStepDuration(std::chrono::milliseconds(rndStepDuration)); | ||
| std::stringstream ss; | ||
| ss << "--------- Changing step size to " << rndStepDuration << "ms ---------"; | ||
| logger->Info(ss.str()); | ||
| } | ||
|
|
||
| std::this_thread::sleep_for(500ms); | ||
| // All messages sent here are guaranteed to arrive at other participants before their next simulation step is called. | ||
| // So here, we can rely on having received all messages from the past (< now). | ||
| // Note that this guarantee only holds for messages sent within a simulation step, | ||
| // not for messages send outside of this handler (e.g. directly in a reception handler). | ||
|
|
||
| // Returning from the handler marks the end of a simulation step. | ||
| }, stepSize); | ||
|
|
||
| auto finalStateFuture = lifecycleService->StartLifecycle(); | ||
| finalStateFuture.get(); | ||
| } | ||
| catch (const std::exception& error) | ||
| { | ||
| std::cerr << "Something went wrong: " << error.what() << std::endl; | ||
| return -2; | ||
| } | ||
|
|
||
| return 0; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -94,6 +94,12 @@ typedef int8_t SilKit_OperationMode; | |
| #define SilKit_OperationMode_Autonomous ((SilKit_OperationMode)20) | ||
|
|
||
|
|
||
| /*! The TimeAdvanceMode. */ | ||
| typedef int8_t SilKit_TimeAdvanceMode; | ||
|
|
||
| #define SilKit_TimeAdvanceMode_ByOwnDuration ((SilKit_TimeAdvanceMode)0) | ||
| #define SilKit_TimeAdvanceMode_ByMinimalDuration ((SilKit_TimeAdvanceMode)10) | ||
|
|
||
| /*! Details about a status change of a participant. */ | ||
| typedef struct | ||
| { | ||
|
|
@@ -452,6 +458,20 @@ SilKitAPI SilKit_ReturnCode SilKitCALL SilKit_TimeSyncService_Create(SilKit_Time | |
| typedef SilKit_ReturnCode(SilKitFPTR* SilKit_TimeSyncService_Create_t)(SilKit_TimeSyncService** outTimeSyncService, | ||
| SilKit_LifecycleService* lifecycleService); | ||
|
|
||
| /*! \brief Create a time sync service at this SIL Kit simulation participant. | ||
| * \param outTimeSyncService Pointer that refers to the resulting time sync service (out parameter). | ||
| * \param lifecycleService The lifecyle service at which the time sync service should be created. | ||
|
||
| * \param timeAdvanceMode The time advance mode for this time sync service. | ||
| * | ||
| * The object returned must not be deallocated using free()! | ||
| */ | ||
| SilKitAPI SilKit_ReturnCode SilKitCALL SilKit_TimeSyncService_Create_With_TimeAdvanceMode(SilKit_TimeSyncService** outTimeSyncService, | ||
| SilKit_LifecycleService* lifecycleService, SilKit_TimeAdvanceMode timeAdvanceMode); | ||
|
|
||
| typedef SilKit_ReturnCode(SilKitFPTR* SilKit_TimeSyncService_Create_With_TimeAdvanceMode_t)(SilKit_TimeSyncService** outTimeSyncService, | ||
| SilKit_LifecycleService* lifecycleService, | ||
| SilKit_TimeAdvanceMode timeAdvanceMode); | ||
|
|
||
| /*! \brief The handler to be called if the simulation task is due | ||
| * | ||
| * \param context The user provided context passed in \ref SilKit_TimeSyncService_SetSimulationStepHandler | ||
|
|
@@ -528,6 +548,18 @@ typedef SilKit_ReturnCode(SilKitFPTR* SilKit_TimeSyncService_Now_t)(SilKit_TimeS | |
| SilKit_NanosecondsTime* outNanosecondsTime); | ||
|
|
||
|
|
||
| /*! \brief Set the duration of the next simulation step | ||
| * | ||
| * \param timeSyncService The time sync service obtained via \ref SilKit_TimeSyncService_Create. | ||
| * \param stepDuration The step size in nanoseconds. | ||
| */ | ||
| SilKitAPI SilKit_ReturnCode SilKitCALL SilKit_TimeSyncService_SetStepDuration(SilKit_TimeSyncService* timeSyncService, | ||
| SilKit_NanosecondsTime stepDuration); | ||
|
|
||
| typedef SilKit_ReturnCode(SilKitFPTR* SilKit_TimeSyncService_SetStepDuration_t)(SilKit_TimeSyncService* timeSyncService, | ||
| SilKit_NanosecondsTime stepDuration); | ||
|
|
||
|
|
||
| /* | ||
| * | ||
| * System Monitor | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -66,6 +66,9 @@ class LifecycleService : public SilKit::Services::Orchestration::ILifecycleServi | |||||
|
|
||||||
| inline auto CreateTimeSyncService() -> SilKit::Services::Orchestration::ITimeSyncService* override; | ||||||
|
|
||||||
| inline auto CreateTimeSyncService(SilKit::Services::Orchestration::TimeAdvanceMode timeAdvanceMode) | ||||||
| -> SilKit::Services::Orchestration::ITimeSyncService* override; | ||||||
|
|
||||||
| private: | ||||||
| SilKit_LifecycleService* _lifecycleService{nullptr}; | ||||||
|
|
||||||
|
|
@@ -315,11 +318,22 @@ auto LifecycleService::Status() const -> const SilKit::Services::Orchestration:: | |||||
|
|
||||||
| auto LifecycleService::CreateTimeSyncService() -> SilKit::Services::Orchestration::ITimeSyncService* | ||||||
| { | ||||||
| _timeSyncService = std::make_unique<TimeSyncService>(_lifecycleService); | ||||||
| _timeSyncService = std::make_unique<TimeSyncService>( | ||||||
| _lifecycleService, SilKit::Services::Orchestration::TimeAdvanceMode::ByOwnDuration); | ||||||
|
|
||||||
| return _timeSyncService.get(); | ||||||
| } | ||||||
|
|
||||||
| // TODO bkd: Needed or can I use a default in the function above? | ||||||
|
||||||
| // TODO bkd: Needed or can I use a default in the function above? | |
| // Overload with explicit TimeAdvanceMode to allow callers to override the default used above. |
Copilot
AI
Dec 19, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unnecessary blank line added. Consider removing for consistency with the surrounding code style.
Uh oh!
There was an error while loading. Please reload this page.