epfl-lasa / control-libraries

A collection of library modules to facilitate the creation of full control loop algorithms, including state representation, motion planning, kinematics, dynamics and control.
https://epfl-lasa.github.io/control-libraries
GNU General Public License v3.0
27 stars 2 forks source link

Updates to make inheritance in python work #268

Closed domire8 closed 2 years ago

domire8 commented 2 years ago

This PR tweaks the pybindings such that @buschbapti can inherit from ParameterMap in python for the optimizers. The following code snippet shows how to do that:

class ParamMap(sr.ParameterMap):
    def __init__(self):
        stiffness = sr.Parameter("stiffness", 4, sr.StateType.PARAMETER_DOUBLE)
        super().__init__([stiffness])

    def validate_and_set_parameter(self, param):
        parameter = sr.Parameter(param)
        super().set_parameter(parameter)

class TestParameters(unittest.TestCase):

    def test_ds(self):
        map = ParamMap()
        print(map.get_parameters())
        map.set_parameter(sr.Parameter("stiffness", 1, sr.StateType.PARAMETER_INT))
        print(map.get_parameter("stiffness"))

As you can see there is an intermediate step parameter = sr.Parameter(param) in validate_and_set_parameter because the the input type of validate and set parameters is actually std::shared_ptr<ParameterInterface> and not ParameterContainer as we have in python. Therefore, you need to convert that shared ptr to the python parameter type. Afterwards everything works as expected. To facilitate that step, I added a new constructor in python such that you can create a new Parameter from a ParamterInterface pointer directly. I'm not sure if that makes sense and if thats allowed by good programming principles but apart from that everything seems to work out quite nicely!

buschbapti commented 2 years ago

This seems good then. Just a question about that:

map.set_parameter(sr.Parameter("stiffness", 1, sr.StateType.PARAMETER_INT))

What is going on here? Because the original parameter is a double so what is the type of the parameter once set. Sorry if that is something that is also in C++ and that I have missed.

domire8 commented 2 years ago

What is going on here? Because the original parameter is a double so what is the type of the parameter once set. Sorry if that is something that is also in C++ and that I have missed.

Okay so in super().set_parameter what happens is that:

void ParameterMap::set_parameter(const std::shared_ptr<ParameterInterface>& parameter) {
  this->validate_and_set_parameter(parameter);
}

and what happens in validate and set parameter:

void
ParameterMap::validate_and_set_parameter(const std::shared_ptr<ParameterInterface>& parameter) {
  this->parameters_[parameter->get_name()] = parameter;
}

And because its all parameter interface pointers, you can replace the type of parameter easily, hence it didnt complain when I set a double parameter as an int parameter. However, this is just the base class, of course the validate and set parameter of your derived class has to check that the parameter is valid. Because I didn't do that in my dummy class, i can replace a double with an int parameter but that wouldn't be possible anymore once you do proper parameter validation

buschbapti commented 2 years ago

Right yes I see. All good then.