vectorgrp / sil-kit

Vector SIL Kit – Open-Source Library for Connecting Software-in-the-Loop Environments
https://vectorgrp.github.io/sil-kit-docs
MIT License
107 stars 32 forks source link

Silkit integration in fmu #12

Closed abhisheksajnani closed 7 months ago

abhisheksajnani commented 7 months ago

I am trying to integrate sil-kit (CAN apis) in a sample virtual ECU code and create an fmu out of it. In this way I am trying to create 2 fmus, FMU1 will Tx the CAN frames and FMU2 will Rx the CAN frames.

I am able to generate the fmus and they are running in co-simulation environment however I could notice that the CAN communication happens only once in the init step only and during the do-step CAN message is not transmitted / received.

The structure of my code looks like this:

void FrameHandler(const SilKit::Services::Can::CanFrameEvent& frameEvent)
{
 /*extract the data from frameevent frame and pass to upper layer software (code not shared here)*/
}

init()
{
    _registryUri = "silkit://localhost:8500";
    CANParticipant = SilKit::CreateParticipant(SilKit::Config::ParticipantConfigurationFromString(""), "RestBus", _registryUri);
    CanController = CANParticipant->CreateCanController("CAN1", "CAN1");

    CanController->AddFrameHandler(
        [](SilKit::Services::Can::ICanController* ctrl, const SilKit::Services::Can::CanFrameEvent& frameEvent) {
            FrameHandler(frameEvent);
        });

    CanController->Start();

    LifecycleService = CANParticipant->CreateLifecycleService({SilKit::Services::Orchestration::OperationMode::Autonomous});

    LifecycleService->StartLifecycle();
}

step()
{
/* pack the payload in frame42 (code is not shared here)*/
    CanController->SendFrame(std::move(frame42));
}

terminate()
{
 LifecycleService->Stop("User requested to stop the simulation");
}

where is the issue?

VDanielEdwards commented 7 months ago

Hello @abhisheksajnani. To diagnose your issue, you can activate logging in your applications by using the configuration string below:

Logging:
  Sinks:
    - Level: Debug
      Type: Stdout

I don't see any issue in the code you have shown, off the top of my head.

VDanielEdwards commented 7 months ago

I took the liberty to edit your issue and use the code-block.

abhisheksajnani commented 7 months ago

Hello @VDanielEdwards, thanks a lot for your quick response. I have a new observation today, the CAN communication is working when I chose the simulation mode as real time. As SiL can run in adaptive time also (faster or slower than real time) and in this mode the CAN communication is not working.

My new question is whether SiLkit supports adaptive time and if yes then how to enable it? In most of the demos i have seen from vector, it is always based on async mode. How to make silkit registry in sync with fmus running in adaptive time?

One more observation is that during the terminate function from my code the simulation is crashing because of Null pointer defrence. is there any other way to stop the communication or I am doing something wrong here?

Thanks in advance!

VDanielEdwards commented 7 months ago

Hello @abhisheksajnani!

Regarding the simulation mode, are you using CANoe? In this case you might not need to package your code as an FMU, but you can build you application similar to the demo applications.

Apart from that, if you use the Trace log-level in the configuration you will get a log message whenever a CanFrame is sent or received. Utilizing this, you can check if the issue is at the sender or the receiver end.

Regarding adaptive time, take a look at the documentation on time-sync and, e.g., the CAN demo application which shows how to use it to synchronize time across SIL Kit participants.

The registry is not involved in the time-synchronization mechanism.

Regarding the null-pointer dereference, is it possible that the CANParticipant object is destroyed before the call to terminate? The pointers retrieved from (e.g.) CreateLifecycleService and CreateCanController have the same lifetime as the participant object they are retrieved from.

abhisheksajnani commented 7 months ago

Hello @VDanielEdwards , I had a look at the documentation on time-sync and i have a doubt. Is "timeSyncService->SetSimulationStepHandler()" is called automatically as a call back function or we need to call it under fmi step function?

is it possible for you to create a dummy code structure (init, step and terminate) like i did for coordinated mode and this would be a great reference for me.

Thanks in advance!

VDanielEdwards commented 7 months ago

Hello @abhisheksajnani.

First of all, did you try to run your original code (without time-sync) with the logging enabled? If you can, please post the output then we can help you analysing it.

Regarding the time-synchronization:

The function set with the SetSimulationStepHandler call is called from within SIL Kit whenever a simulation step starts.

Synchronization of SIL Kits simulation-step can be achieved using the SetSimulationStepHandlerAsync call and the corresponding CompleteSimulationStep call. This allows you to return from the callback function and explicitly complete the simulation step after your code has run. This also means that you will have to synchronize the two steps using, e.g., a std::condition_variable.

In pseude-code this would look like the following:

YourSimulationStepHandler(...):
  // signal simulation-step

tick():
  // wait for SIL Kit simulation-step signal and reset it
  // ... execute tick ...
  // call CompleteSimulationStep

As I'm not particularly familiar with FMUs, maybe @DominikHerr has additional insigths regarding your issue.

DominikHerr commented 7 months ago

Hello @abhisheksajnani,

I cannot provide much more feedback regarding a solution with your implementation based on the currently available information than @VDanielEdwards, but I was wondering if there is a reason to use CAN frames instead of DataPublishers and DataSubscribers (which do not require to additional data wrapping).

We also provide an open source solution called "FMU Importer" that allows to run an FMU as a participant in a SIL Kit setup. It handles the time synchronization and data exchange between FMI 2.0/3.0 FMUs and SIL Kit. It is also available on GitHub (https://github.com/vectorgrp/sil-kit-fmu-importer). Maybe the FMU Importer can solve your issues or provide you with some ideas how to do the synchronization based on its documentation.

Let us know if that works for you.

VDanielEdwards commented 7 months ago

Closing this issue due to inactivity. Please feel to re-open it.