Search code examples
drake

Mechcat WebSocket Thread failed when simulator is launched within class


I am trying to use drake within the class of our code. I have declared the drake variables within the class. For this purpose, I initialized the drake variables within header files as

 drake::systems::DiagramBuilder<double> builder_;
 std::unique_ptr< MultibodyPlant< double > plant_;
 drake::multibody::MultibodyPlant<double>* plant_{};
 drake::geometry::SceneGraph<double>* scene_graph_{};


 std::unique_ptr<drake::systems::Diagram<double>> diagram_;
 std::unique_ptr<drake::systems::Context<double>> diagram_context_;
 drake::systems::Context<double> *plant_context_;
 std::unique_ptr<drake::systems::Simulator<double>> simulator_;

 double timestep_;
 double time_;

In the source file, I have initialized them as follow

drake::multibody::MultibodyPlantConfig plant_config;
plant_config.time_step = 1e-3;

std::tie(plant_, scene_graph_) = AddMultibodyPlant(plant_config,&builder_);

const std::string urdf = drake::FindResourceOrThrow("drake/urdf/iiwa_description/urdf/iiwa14_no_collision.urdf");
    
drake::multibody::Parser(plant_).AddModelFromFile(urdf);

const double static_friction = 0.5;
const Eigen::Matrix<double, 4, 1> green(0.5, 1.0, 0.5, 1.0);
plant_->RegisterVisualGeometry(plant_->world_body(), drake::math::RigidTransformd(),
                                drake::geometry::HalfSpace(), "GroundVisualGeometry", green);
    
//     // For a time-stepping model only static friction is used.
const drake::multibody::CoulombFriction<double> ground_friction(static_friction,
                                                                    static_friction);

plant_->RegisterCollisionGeometry(plant_->world_body(), RigidTransformd(),
                                    drake::geometry::HalfSpace(),
                                    "GroundCollisionGeometry", ground_friction);

Vector3d gravity;
gravity << 0.0, 0.0, -9.81;
plant_->mutable_gravity_field().set_gravity_vector(gravity);

plant_->WeldFrames(plant_->world_frame(), plant_->GetFrameByName("base"));
plant_->Finalize();
plant_->set_penetration_allowance(1e-3);
plant_->set_stiction_tolerance(1e-3);

// Publish contact results for visualization.
drake::visualization::AddDefaultVisualization(&builder_);

  
diagram_ = builder_.Build();

// // Create a context for this system:
diagram_context_ = diagram_->CreateDefaultContext();
drake::systems::Context<double>& plant_context = diagram_->GetMutableSubsystemContext(*plant_, diagram_context_.get());

plant_context_ = &(diagram_->GetMutableSubsystemContext(*plant_, diagram_context_.get()));
    
Eigen::VectorXd tau = Eigen::VectorXd::Zero(plant_->num_actuated_dofs());
plant_->get_actuation_input_port().FixValue(plant_context_, tau);
    
simulator_ = std::make_unique<drake::systems::Simulator<double>>(*diagram_, std::move(diagram_context_));
simulator_->set_publish_every_time_step(true);
simulator_->set_target_realtime_rate(1.0);
simulator_->Initialize();

timestep_ = 1e-3;
time_ = timestep_;

simulator_->AdvanceTo(time_);

Now it runs fine when simulator_->AdvanceTo(time_) is called within initializer. However, when I try to call simulator_->AdvanceTo(time_) within a callback function (where simulator_ is defined and is visible within the class function), it gives the following error

abort: Failure at geometry/meshcat.cc:606 in ThrowIfWebsocketThreadExited(): condition 'IsThread(main_thread_id_)' failed.

I looked at the code but it do not give much information why the websocketthread is dying. Any help and guidance will be highly appreciated.


Solution

  • The error message is saying that you tried to call the meshcat API from a different thread than the thread which created the meshcat instance. The meshcat class does some nontrivial data sharing with a networking thread, so we currently restrict that the meshcat API is only used from a single thread.