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

Simulink Coder needs the robot plugged (either real or simulated) #97

Open
diegoferigo opened this issue Mar 8, 2018 · 11 comments
Open

Comments

@diegoferigo
Copy link
Member

When generating the code, Simulink Coder executes all the callbacks at least up to mdlStart, that calls the Block::initialize() method of our toolbox.

This is a big problem, because Block::initialize() allocates the RemoteControlBoardRemapper device for the first block that needs it. This means that the robot must be plugged for generating code from a Simulink model.

It is somehow related to #15.

We should think how to tackle this issue also keeping in mind #94 that would require changing how the retain / release of the RemoteControlBoardRemapper is handled.

@diegoferigo
Copy link
Member Author

A new logic to handle the singleton logic has been implemented in #115, but this change does not affect the dependency between the Block::initialize() step and the opening of the RemoteControlBoardRemapper device.

At the current moment I still don't see any way to exclude the call of block's initialize() method (which is not necessary for the code generation) during the generation phase.

It would be great if Simulink would provide a #define to differentiate when the GUI clicked the play button for simulating or the build button for generating. After some digging, I didn't find anything similar.

cc @pattacini

@diegoferigo
Copy link
Member Author

diegoferigo commented Apr 25, 2019

I didn't find any solution to this problem.

A possible workaround is to generated code targeting the real robot using the correct gains and a "fake" name matching the Gazebo robot. In this was the gains are loaded in the workspace and embedded in the generated code. Then, in the generated cpp, all the occurrences of the gazebo robot name (e.g. iCubGazeboV2_5 has to be replaced by iCubGenova04).

Putting this issue in the backlog.

cc @aikolina

@diegoferigo diegoferigo self-assigned this Apr 25, 2019
@traversaro
Copy link
Member

This is a big problem, because Block::initialize() allocates the RemoteControlBoardRemapper device for the first block that needs it.

Which block(s) actually require the remotecontrolboardremapper device to be open in their initialize method? I checked a few but I could not find anything that required the device to be up.

@diegoferigo
Copy link
Member Author

The first example I can recall is:

// Get the interface
yarp::dev::IPositionControl* interface = nullptr;
if (!getRobotInterface()->getInterface(interface) || !interface) {
bfError << "Failed to get IPositionControl interface.";
return false;
}

Not sure if it is the only one. We might move this piece of code in the Block::initializeInitialConditions method, though. It's an attempt, if this is the only occurrence it is worth a try.

@traversaro
Copy link
Member

traversaro commented Apr 26, 2019

We might move this piece of code in the Block::initializeInitialConditions method, though. It's an attempt, if this is the only occurrence it is worth a try.

I think this is a good idea, even because anything that reduce the uncertainty related to the duration of the time passed between when the control mode has switched and the first real reference sent to the real system is highly beneficial. After all, we have no info about the time that simulink will take between the initialize call and the first output call, and the fact that it has been working until now it is probably due to the kind of model we have used. For these reason, it could also make sense to just keep all the resetting control mode logic in the first run of the output function, using the existing logic related to the resetControlMode attribute.

@diegoferigo
Copy link
Member Author

A minor clarification about this. The control mode is switched in the first call of the output method. We delayed it as much as possible long time ago precisely for those reasons. The code involving yarp interfaces in the initialize step only configures reference speeds / accelerations, and this yes, could be safely moved to initializeInitialConditions.

@traversaro
Copy link
Member

Ah, great, I misread the code. If you are sure that initializeInitialConditions is enough to avoid being called during code generation, then I think it is ok.

@diegoferigo
Copy link
Member Author

@traversaro I did a quick test and initializeInitialConditions is called also during the code generation process. This is another blind path then.

The only solution would be to initialize all these resources during the first call of the output method, but it would be too hacky, I don't like it much.

@traversaro
Copy link
Member

Alternative solutions that probably take some more work:

  • Add in BlockFactory a method that is executed only on the first call to a "simulation" method such as updateDiscreteState/outputs. That is equivalent to the solution that you suggest, but handled at a lower level that will result in a clear implementation at the wb-toolbox level.
  • Add a new BlockFactory method that is executed for some of the Simulink's methods that are currently not mapped in BlockFactory and could be useful for this use case (perhaps mdlEnable is always called at the start, but it is not executed during code generation?

@diegoferigo
Copy link
Member Author

Add in BlockFactory a method that is executed only on the first call to a "simulation" method such as updateDiscreteState/outputs. That is equivalent to the solution that you suggest, but handled at a lower level that will result in a clear implementation at the wb-toolbox level.

Yes, I would rather go to a more clear preOutput and postOutput if we decide for this option.

Add a new BlockFactory method that is executed for some of the Simulink's methods that are currently not mapped in BlockFactory and could be useful for this use case (perhaps mdlEnable is always called at the start, but it is not executed during code generation?

mdlEnable is called too during the generation process.

What's strange is that here it says:

f you use the Simulink Coder™ product to generate code for a model containing S-functions, the Simulink engine does not execute the entire calling sequence outlined above. Initialization proceeds as outlined above until the engine reaches the mdlStart method. The engine then calls the S-function methods shown in the following figure, where the mdlRTW method is unique to the Simulink Coder product.

But when I run a model I see that also the initializeInitialCondition (that is supposed to be called after mdlStart) is executed.

@traversaro
Copy link
Member

Yes, I would rather go to a more clear preOutput and postOutput if we decide for this option.

preOutput is a bit ambiguous as a name, as it does not seems to convey the fact that is just run on the first output call.

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

No branches or pull requests

2 participants