Home > Net >  Drake-Ros2: Multibody Plant returns wrong values or node dies in subscriber
Drake-Ros2: Multibody Plant returns wrong values or node dies in subscriber

Time:10-11

I am trying to use Drake in Ros2. The problem is that after defining my robot plant in my class constructor, some weird behavior occurs in the subscriber callback and I can't call any plant functions without the node dying. Here's what I have

class Foo : public rclcpp::Node{

    public:
        Foo() : Node("foo_node") {
            
            auto [plant_, scene_graph_] = drake::multibody::AddMultibodyPlantSceneGraph(&builder, 0.0);

            plant = &plant_;
            scene_graph = &scene_graph_;
            auto parser = drake::multibody::Parser(plant, scene_graph);

            parser.package_map().AddPackageXml(pkg_xml_dir);
            auto model_ = parser.AddModelFromFile(model_path);
            model = &model_;
            plant->WeldFrames(plant->world_frame(), plant->GetFrameByName("base"));
            plant->Finalize();

            std::unique_ptr<drake::systems::Diagram<double>> diagram = builder.Build();
            context = diagram->CreateDefaultContext();

            plant_context = &plant->GetMyMutableContextFromRoot(context.get());

            // first print
            std::cout << "--------------" << std::endl;
            std::cout << plant->is_finalized() << std::endl;
            std::cout << plant->HasFrameNamed("link_3") << std::endl; // prints 1
            std::cout << plant->HasFrameNamed("link_3", *model) << std::endl; // prints 1
            std::cout << plant->HasFrameNamed("base", *model) << std::endl;   // prints 1
            std::cout << plant->num_frames() << std::endl; // prints N
            std::cout << "--------------" << std::endl;
            
            // Subscriber to update current state
            state_current_sub = this->create_subscription<sensor_msgs::msg::JointState>("/joint_states", 10, std::bind(&Foo::update_current_state, this, _1));

    private:

        rclcpp::Subscription<sensor_msgs::msg::JointState>::SharedPtr state_current_sub;
        drake::systems::DiagramBuilder<double> builder;
        drake::multibody::MultibodyPlant<double>* plant;
        drake::geometry::SceneGraph<double>* scene_graph;
        std::string pkg_xml_dir = "/path/to/package.xml";
        std::string model_path = "/path/to/robot.urdf";
        drake::systems::Context<double>* plant_context;
        std::unique_ptr<drake::systems::Context<double>> context;
        drake::TypeSafeIndex<drake::multibody::ModelInstanceTag>* model;

        void update_current_state(const sensor_msgs::msg::JointState::SharedPtr msg){

            // Second print
            std::cout << "--------------" << std::endl;
            std::cout << plant->is_finalized() << std::endl; // prints 1
            std::cout << plant->HasFrameNamed("link_3") << std::endl; // prints 0
            std::cout << plant->HasFrameNamed("link_3", *model) << std::endl; // Dies with  'there is no model instance id 0/2/(random number) in the model.'
            std::cout << plant->HasFrameNamed("base", *model) << std::endl; // 
            std::cout << plant->num_frames() << std::endl; // prints N
            std::cout << "--------------" << std::endl;

            auto & ee_frame = plant->GetFrameByName("link_3"); // Can't find frame with that name
            auto G = plant->CalcGravityGeneralizedForces(*plant_context); // Dies with exit code -11
        }

}

In the second print everything goes wrong. Calling the same functions as before, for example to check if a frame exists, won't work, even though it does the first time. My node either prints something wrong (that the frame doesn't exists), or dies with exit code -11 or with there is no model instance id 0/2/(random number) in the model., depending on which functions I use.

My guess is that there is some problem with the plant definition and usage. Any ideas on what should I change ?

CodePudding user response:

First off, have you been able to briefly peruse drake-ros?
https://github.com/RobotLocomotion/drake-ros/tree/develop
It's still under development, but may have useful tidbits / utilities. It is mentioned at the bottom of Drake's website: https://drake.mit.edu/

Second off, I believe your plant is going out of scope.

Please note that diagram is actually the new owner of plant, scene_graph once builder.Build() is called. You must store that as a member variable.

If you do that, then plant should stay in scope, and it should resolve this issue.

For more info, see: https://drake.mit.edu/doxygen_cxx/classdrake_1_1systems_1_1_diagram_builder.html
Specifically:

It is single use: after calling Build or BuildInto, DiagramBuilder gives up ownership of the constituent systems, and should therefore be discarded

  • Related