Skip to content

Refactor and wrap part of the walking logic as a BlockFactory block? #30

@traversaro

Description

@traversaro

As most of walking-controllers developers probably know I have a secret plan for streamlining our software infrastructure, ensuring that the software we develop can be composed easily with no runtime additional latency due to the component composition, and to be able to have reproducible simulation regardless of the computational load of the simulating machine.

One thing that I think would definitely boost the re-usability of the awesome walking algorithm(s) contained in this repo is to wrap its core "Walking" logic in a discrete system form, to simplify the following use cases:

  • Run the walking algorithm as part of complex simulation scheme made up by smaller discrete systems, think for example a Simulink model, a complex Adams simulation or a Creo simulation for a co-design purpouse.
  • Programmatically run simulations of the walking algorithm coupled with a simulated robot and environment, for performing automatic gain tuning or to exploit the latest fancy reinforcement learning algorithm on the top of the existing walking infrastructure.

To wrap an existing C++ code as a discrete system, several possible interfaces exists, such as Drake, FMI, Simulink S-Functions . However, I think the most suitable option is to use our actively developed BlockFactory library, mainly because we control it, and so we can eventually modify it to suit any kind of crazy requirement could emerge from our research, because is extremely lightweight (no dependencies), and because we add new targets in the future to it, see for example robotology/blockfactory#5 for a discussion on adding FMI export support to it (TL;DR: we need to wait for FMIv3 that will support the features that we need).
An example of using BlockFactory to wrap an instantaneous system can be found in https://robotology.github.io/blockfactory/mkdocs/create_new_library/ . The issue discussing support for discrete time systems and the workaround currently used to implement them can be found in robotology/blockfactory#8 .

At this point you may think:
but porting the walking controller to BlockFactory will probably means that we need to rewrite it, and we cannot used it anymore as a normal YARP module!
based on my preliminary assessment of the code, this is probably not true, mostly due to the awesome work of everyone involved in writing the controller (kudos everyone, really).

The only small refactoring steps that I think are necessary are the following:

  1. separate the logic of the controller when in it is "Walking" state, from the rest of the WalkingModule logic. The logic of switching control modes, reaching the initial position with the position control, checkMotionDone, etc etc is IMHO too complex/different to wrap as a discrete system, but the juicy part is the one of the Walking state, that is more and less what is described in a block diagram such as the one reported in the README.
    All that logic should be refactored in a different class (something like WalkingDiscreteSystem, any better name suggestion is welcome) together with most of the attributes of WalkingModule that are just used/accessed in the Walking state. Ideally, the outcome of this refactor would be that the part of the updateModule method related to the Walking state would be simplified to:
else if(m_robotState == WalkingFSM::Walking)
{
    m_walkingDiscreteSystem->advance(); // This is tipically step, but we agreed that it is not the best name in a walking context
}
  1. Refactor the classes that handle the interaction with the rest of the YARP infrastructure (that are already confined in RobotHelper and WalkingPIDHandler ❤️) in inheriting from a series of C++ interface classes (i.e. a pure virtual classes), and just use a pointer to those interfaces inside WalkingDiscreteSystem. The implementation of this interfaces to communicate
    with YARP (the existing RobotHelper and WalkingPIDHandler, that it would make sense to rename YARPRobotHelper and YARPWalkingPIDHandler) will need to be created inside the WalkingModule class, and passed to the WalkingDiscreteSystem just as pointers to the generic interface, to ensure that no network related logic is contained in WalkingDiscreteSystem.

  2. Once WalkingDiscreteSystem will be YARP-network-free, it will be possible to use it also inside a BlockFactory block. To modify at least as possible
    its internal structure (to share it with the YARP module, that will continue to work as usual) the trick would be to reimplement the RobotHelper and WalkingPIDHandler interfaces to
    interact with BlockFactory's ports. For example, getFeedbacksRaw will not read anymore from the YARP network, but from some BlockFactory ports that indicate the "measured joint positions" and
    "measured joint velocities", using the getInputPortSignal methods of BlockFactory (see https://github.com/robotology/blockfactory/blob/master/example/src/SignalMath.cpp#L133). Similarly,
    setDirectPositionReferences will set some value on some output port. Non-relevant methods (such as checkMotionDone) can be simply left not implemented, as long as they are not called
    inside WalkingDiscreteSystem.

  3. Profit!

One cool thing is that it is not necessary to change is the nice configuration system that is currently in place: the WalkingDiscreteSystem can be configure with a yarp::os::ResourceFinder object, and the only additional that will be necessary to have in the BlockFactory's Block will be a string, to indicate the .ini configuration file that contains all the parameters (that could be shared with no problems between the YARP module and the BlockFactory's block.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestquestionFurther information is requested

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions