Skip to content
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

Query simulation clock #3

Open
githubfrond opened this issue Mar 19, 2020 · 6 comments
Open

Query simulation clock #3

githubfrond opened this issue Mar 19, 2020 · 6 comments

Comments

@githubfrond
Copy link

Apologies Dr/Mr Lange,
I am only new to GitHub and unsure how to communicate best with you. This is more of a feature suggestion than an issue. I hope I am not being too presumptuous by making suggestions. Feel free to ignore me :-)
regards, Craig

Do your libraries include a facility to drive the /clock topic when the launch file sets the simulation parameter ?

If not, I can teach myself how to manually do this, but it would seem a natural extension to your library might be a modelica based facility that would allow this. This facility could allow one to execute the FMU's in faster/slower than real time for testing purposes, without the developer having to know how to construct an external ROS Clock Server.

@ralph-lange
Copy link
Collaborator

Hi Craig, just call me Ralph, please. Opening an issue for such a feature request is absolutely fine.
Just to recap, to ensure that we have the same understanding:

  • When using the fmi_adapter library only (i.e. the class fmi_adapter::FMIAdapter from include/fmi_adapter/FMIAdapter.h), you’ll have to trigger the simulation steps from your application code. In this case, you have full control over the simulation speed.
  • When using the fmi_adapter node (see src/fmi_adapter_node.cpp), the simulation is triggered automatically using a normal ROS timer (http://wiki.ros.org/roscpp/Overview/Timers). The step-size can be adjusted by the parameter update_period. The ROS Timer uses the ROS Clock, from /clock, when available. Hence, the fmi_adapter node will automatically run according to simulation time.

Extending the fmi_adapter library and node with a function to run the simulation time is fairly easy. I regularly speed up the clock in my unit-tests:

std::shared_ptr<std::thread> runner(new std::thread([&enabledFlag]() {
  const ros::Duration SIM_STEP(0.010);
  const double SIM_SPEED = 5;  // 5x faster than real-time
  while (enabledFlag) {
    std::this_thread::sleep_for(
        std::chrono::nanoseconds(static_cast<std::int64_t>(SIM_STEP.nsec / SIM_SPEED)));
    ros::Time::setNow(ros::Time::now() + SIM_STEP);
  }
}));

I'm hesitating to put such functionality directly in the fmi_adapter library and node. As explained above, the library has no built-in functionality to trigger the simulation steps at all. The fmi_adapter node has such functionality, but for separation of concerns, I would place it in a separate node of the fmi_adapter package. Of course, I may provide a launch file that starts both nodes together. What do you think about this architecture?
Best regards, Ralph

@ralph-lange
Copy link
Collaborator

@githubfrond, a question about your use-case: Is the FMI-based simulation dominating the computing time, i.e. should be simulation time be slowed down depending on the FMI-based simulation?
In this case if fully agree with you that the simulation clock (topic /clock) should be published directly from the fmi_adapter node and not be factored out in a separate node.

@githubfrond
Copy link
Author

githubfrond commented Mar 19, 2020 via email

@githubfrond
Copy link
Author

Hi Ralph, in answer to your query, I am looking at using ROS in a rather unusual way. I am modelling a system that is comprised of various conceptually separate subsystems, each of which I can model individually. I'm using ROS to interconnect the different subsystem models in the overall system model, and this allows me to easily assemble subsystems, switch out different compments, or simply switch off/on different components without having to re-architect the overall model. Hence, at this stage, all of my work is in simulation time...no wallclocks.

@githubfrond
Copy link
Author

Hi Ralph,
I have created two launch files now, similar to your suggestion. One in Python with /use_sim_time FALSE which picks up the wall clock and accelerates time to push into the /clock topic, and the second is my collection of FMU built from your adapater tools and connected up with /use_sim_time TRUE so that they respond to the /clock.
Now I am trying to learn how to adjust both ROS normal update period, as well as how to suitably adjust the step sizes used natively by the FMU. I'll let you know if I have trouble understanding the documentation. Thanks for your patience. Craig

@ralph-lange
Copy link
Collaborator

Hi Craig, I created a super-simple node named sim_clock_node, which runs the given FMU at maximum speed and advances the ROS time on /clock accordingly. Please find it in the branch prototype/sim_clock_node at https://github.com/boschresearch/fmi_adapter/blob/prototype/sim_clock_node/fmi_adapter/src/fmi_adapter_sim_clock_node.cpp.
The implementation does not provide any mechanisms to synchronize or wait for other fmi_adapter nodes or normal ROS nodes. A good solution for such synchronization should consider dependencies between the different FMUs, potential cycles, different step sizes, and many more aspects. That's exactly the task of a master algorithm according to the FMI standard. For the use-case of simulating multiple subsystems together, it might be useful to look into relevant FMI tools or frameworks before building a similar framework based on ROS from scratch. (Please note that the FMI standard does not define the master algorithm itself, but only the interface between an FMU and any master algorithm.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants