diff --git a/examples/worlds/pendulum_links.sdf b/examples/worlds/pendulum_links.sdf index ff187802c7..b212918a3a 100644 --- a/examples/worlds/pendulum_links.sdf +++ b/examples/worlds/pendulum_links.sdf @@ -341,9 +341,10 @@ + base upper_link lower_link - \ No newline at end of file + diff --git a/src/systems/physics/Physics.cc b/src/systems/physics/Physics.cc index c506c5f3f1..3abd103389 100644 --- a/src/systems/physics/Physics.cc +++ b/src/systems/physics/Physics.cc @@ -1641,7 +1641,7 @@ void PhysicsPrivate::UpdatePhysics(EntityComponentManager &_ecm) return true; }); - // Update link angular velocity + // Update link angular velocity _ecm.Each( [&](const Entity &_entity, const components::Link *, const components::AngularVelocityCmd *_angularVelocityCmd) @@ -1652,10 +1652,7 @@ void PhysicsPrivate::UpdatePhysics(EntityComponentManager &_ecm) auto freeGroup = linkIt->second->FindFreeGroup(); if (!freeGroup) return true; - const components::Pose *poseComp = - _ecm.Component(_entity); - math::Vector3d worldAngularVel = poseComp->Data().Rot() * - _angularVelocityCmd->Data(); + auto worldAngularVelFeature = entityCast(_entity, freeGroup, this->entityWorldVelocityCommandMap); if (!worldAngularVelFeature) @@ -1671,7 +1668,14 @@ void PhysicsPrivate::UpdatePhysics(EntityComponentManager &_ecm) } return true; } - + // velocity in world frame = world_to_model_tf * model_to_link_tf * vel + Entity modelEntity = topLevelModel(_entity, _ecm); + const components::Pose *modelEntityPoseComp = + _ecm.Component(modelEntity); + math::Pose3d modelToLinkTransform = this->RelativePose( + modelEntity, _entity, _ecm); + math::Vector3d worldAngularVel = modelEntityPoseComp->Data().Rot() + * modelToLinkTransform.Rot() * _angularVelocityCmd->Data(); worldAngularVelFeature->SetWorldAngularVelocity( math::eigen3::convert(worldAngularVel)); @@ -1691,11 +1695,6 @@ void PhysicsPrivate::UpdatePhysics(EntityComponentManager &_ecm) if (!freeGroup) return true; - const components::Pose *poseComp = - _ecm.Component(_entity); - math::Vector3d worldLinearVel = poseComp->Data().Rot() * - _linearVelocityCmd->Data(); - auto worldLinearVelFeature = entityCast(_entity, freeGroup, this->entityWorldVelocityCommandMap); if (!worldLinearVelFeature) @@ -1712,6 +1711,14 @@ void PhysicsPrivate::UpdatePhysics(EntityComponentManager &_ecm) return true; } + // velocity in world frame = world_to_model_tf * model_to_link_tf * vel + Entity modelEntity = topLevelModel(_entity, _ecm); + const components::Pose *modelEntityPoseComp = + _ecm.Component(modelEntity); + math::Pose3d modelToLinkTransform = this->RelativePose( + modelEntity, _entity, _ecm); + math::Vector3d worldLinearVel = modelEntityPoseComp->Data().Rot() + * modelToLinkTransform.Rot() * _linearVelocityCmd->Data(); worldLinearVelFeature->SetWorldLinearVelocity( math::eigen3::convert(worldLinearVel)); diff --git a/src/systems/velocity_control/VelocityControl.cc b/src/systems/velocity_control/VelocityControl.cc index c14347c6e7..5c09063ddc 100644 --- a/src/systems/velocity_control/VelocityControl.cc +++ b/src/systems/velocity_control/VelocityControl.cc @@ -81,16 +81,16 @@ class ignition::gazebo::systems::VelocityControlPrivate public: std::vector linkNames; /// \brief Link entities in a model - public: std::map links; + public: std::unordered_map links; /// \brief Angular velocities of links - public: std::map angularVelocities; + public: std::unordered_map angularVelocities; /// \brief Linear velocities of links - public: std::map linearVelocities; + public: std::unordered_map linearVelocities; /// \brief all link velocites - public: std::map linkVels; + public: std::unordered_map linkVels; }; ////////////////////////////////////////////////// @@ -144,7 +144,7 @@ void VelocityControl::Configure(const Entity &_entity, std::string linkTopic{"/model/" + this->dataPtr->model.Name(_ecm) + "/link/" + linkName + "/cmd_vel"}; this->dataPtr->node.Subscribe( - linkTopic, &VelocityControlPrivate::OnLinkCmdVel, this->dataPtr.get()); + linkTopic, &VelocityControlPrivate::OnLinkCmdVel, this->dataPtr.get()); ignmsg << "VelocityControl subscribing to twist messages on [" << linkTopic << "]" << std::endl; @@ -210,54 +210,72 @@ void VelocityControl::PreUpdate(const ignition::gazebo::UpdateInfo &_info, if (this->dataPtr->linkNames.empty()) return; - for (const auto &linkName : this->dataPtr->linkNames) + + // find all the link entity ids + if (this->dataPtr->links.size() != this->dataPtr->linkNames.size()) { - if (this->dataPtr->links.find(linkName) == this->dataPtr->links.end()) + for (const auto &linkName : this->dataPtr->linkNames) { - Entity link = this->dataPtr->model.LinkByName(_ecm, linkName); - if (link != kNullEntity) - this->dataPtr->links.insert({linkName, link}); - else + if (this->dataPtr->links.find(linkName) == this->dataPtr->links.end()) { - ignwarn << "Failed to find link [" << linkName - << "] for model [" << modelName << "]" << std::endl; + Entity link = this->dataPtr->model.LinkByName(_ecm, linkName); + if (link != kNullEntity) + this->dataPtr->links.insert({linkName, link}); + else + { + ignwarn << "Failed to find link [" << linkName + << "] for model [" << modelName << "]" << std::endl; + } } } } - if (this->dataPtr->links.empty()) - return; // update link velocities - for (const auto& [linkName, link] : this->dataPtr->links) + for (const auto& [linkName, angularVel] : this->dataPtr->angularVelocities) { - // update angular velocity - auto linkAngularVel = _ecm.Component(link); - auto it = this->dataPtr->angularVelocities.find(linkName); - if (it != this->dataPtr->angularVelocities.end()) + auto it = this->dataPtr->links.find(linkName); + if (it != this->dataPtr->links.end()) { - if (linkAngularVel == nullptr) - _ecm.CreateComponent(link, components::AngularVelocityCmd({it->second})); + auto linkAngularVelComp = + _ecm.Component(it->second); + if (!linkAngularVelComp) + { + _ecm.CreateComponent(it->second, + components::AngularVelocityCmd({angularVel})); + } else - *linkAngularVel = components::AngularVelocityCmd(it->second); + { + *linkAngularVelComp = components::AngularVelocityCmd(angularVel); + } } else { - ignwarn << "No angular velocity found for link [" << linkName << "]" << std::endl; + ignwarn << "No link found for angular velocity cmd [" + << linkName << "]" << std::endl; } + } - // update linear velocity - auto linkLinearVel = _ecm.Component(link); - it = this->dataPtr->linearVelocities.find(linkName); - if (it != this->dataPtr->linearVelocities.end()) + for (const auto& [linkName, linearVel] : this->dataPtr->linearVelocities) + { + auto it = this->dataPtr->links.find(linkName); + if (it != this->dataPtr->links.end()) { - if (linkLinearVel == nullptr) - _ecm.CreateComponent(link, components::LinearVelocityCmd({it->second})); + auto linkLinearVelComp = + _ecm.Component(it->second); + if (!linkLinearVelComp) + { + _ecm.CreateComponent(it->second, + components::LinearVelocityCmd({linearVel})); + } else - *linkLinearVel = components::LinearVelocityCmd({it->second}); + { + *linkLinearVelComp = components::LinearVelocityCmd(linearVel); + } } else { - ignwarn << "No linear velocity found for link [" << linkName << "]" << std::endl; + ignwarn << "No link found for linear velocity cmd [" + << linkName << "]" << std::endl; } } } @@ -305,13 +323,16 @@ void VelocityControlPrivate::UpdateLinkVelocity( { IGN_PROFILE("VeocityControl::UpdateLinkVelocity"); + std::lock_guard lock(this->mutex); for (const auto& [linkName, msg] : this->linkVels) { - auto linearVel = math::Vector3d(msg.linear().x(), msg.linear().y(), msg.linear().z()); - auto angularVel = math::Vector3d(msg.angular().x(), msg.angular().y(), msg.angular().z()); - this->linearVelocities.insert({linkName, linearVel}); - this->angularVelocities.insert({linkName, angularVel}); + auto linearVel = msgs::Convert(msg.linear()); + auto angularVel = msgs::Convert(msg.angular()); + this->linearVelocities[linkName] = linearVel; + this->angularVelocities[linkName] = angularVel; + std::cerr << "got new link vel " << linkName << " " << linearVel << " | " << angularVel << std::endl; } + this->linkVels.clear(); } ////////////////////////////////////////////////// @@ -325,11 +346,13 @@ void VelocityControlPrivate::OnCmdVel(const msgs::Twist &_msg) void VelocityControlPrivate::OnLinkCmdVel(const msgs::Twist &_msg, const transport::MessageInfo &_info) { + std::lock_guard lock(this->mutex); for (const auto &linkName : this->linkNames) { - if (_info.Topic().find(linkName) != std::string::npos) + if (_info.Topic().find("/" + linkName + "/cmd_vel") != std::string::npos) { this->linkVels.insert({linkName, _msg}); + break; } } }