moveit / moveit_task_constructor

A hierarchical multi-stage manipulation planner
https://moveit.github.io/moveit_task_constructor
BSD 3-Clause "New" or "Revised" License
183 stars 152 forks source link

Forward properties to a SerialContainer #575

Closed DaniGarciaLopez closed 6 months ago

DaniGarciaLopez commented 6 months ago

I'm trying to pass properties declared in the task to a SerialContainer defined in another function:

Task& t = *task_;
t.setProperty("group", "panda_arm");
t.setProperty("eef", "hand");
...
t.add(std::move(Pick("object")));
std::unique_ptr<mtc::SerialContainer> Pick(const std::string& object_name) {
  auto serial_container = std::make_unique<mtc::SerialContainer>("pick");
  grasp->properties().configureInitFrom(Stage::PARENT, {"eef", "group"});

  {
    auto stage = std::make_unique<stages::MoveRelative>("approach object", cartesian_planner);
    stage->properties().configureInitFrom(Stage::PARENT, {"group"});
    ...

When doing this, the stage MoveRelative reports that the property group is not declared. I think what is missing is a call to exposeTo as shown in the demo:

t.properties().exposeTo(serial_container->properties(), {"eef", "group"});

However, this requires passing a reference to the task within the Pick function, which I would like to avoid if possible. I tried the following approach, but it seems that the parent stage is empty:

serial_container->parent()->properties().exposeTo(serial_container->properties(), {"eef", "group"});

I found that there is a function named forwardProperties which might be what I need, but I couldn't find enough information on how to use it.

Thanks!

rhaschke commented 6 months ago

You just need to manually declare the properties in your SerialContainer. Have a look at the PickPlaceBase class for an example: https://github.com/moveit/moveit_task_constructor/blob/a8896e4e5d76d37726278eeb3328daa2c71156e5/core/src/stages/pick.cpp#L23 https://github.com/moveit/moveit_task_constructor/blob/a8896e4e5d76d37726278eeb3328daa2c71156e5/core/src/stages/pick.cpp#L45

DaniGarciaLopez commented 6 months ago

Thanks @rhaschke. Adding the following lines I can correctly see the property in the SerialContainer:

serial_container->properties().declare<std::string>("group"); 
serial_container->properties().property("group").configureInitFrom(mtc::Stage::PARENT, "group"); 

However, how to propagate the property to child stages of the SerialContainer? I tried to add the following but it has no effect:

stage->properties().configureInitFrom(mtc::Stage::PARENT, {"group"});

I can set the property declaring and configuring it from parent (as you pointed out) in each stage:

stage->properties().declare<std::string>("group"); 
stage->properties().property("group").configureInitFrom(mtc::Stage::PARENT, "group"); 

But I think this is too much boilerplate if I have several properties that I want to be accessible to all children, right? Is there a simpler way to inherit all properties from the parent?

rhaschke commented 6 months ago

No, there is no simpler way. It was a deliberative design decision to require explicit declaration and forwarding of properties to each child.