From 014d8dac99b3b997a9747cd8f33994451ab8d2d4 Mon Sep 17 00:00:00 2001 From: "Marco A. Gutierrez" Date: Fri, 7 Oct 2022 10:18:01 +0000 Subject: [PATCH] Switching to gazebo upstream hydrynamics plugin --- .../models/tethys_equipped/model.sdf | 4 +- lrauv_gazebo_plugins/CMakeLists.txt | 1 - .../src/HydrodynamicsPlugin.cc | 368 ------------------ .../src/HydrodynamicsPlugin.hh | 63 --- 4 files changed, 2 insertions(+), 434 deletions(-) delete mode 100644 lrauv_gazebo_plugins/src/HydrodynamicsPlugin.cc delete mode 100644 lrauv_gazebo_plugins/src/HydrodynamicsPlugin.hh diff --git a/lrauv_description/models/tethys_equipped/model.sdf b/lrauv_description/models/tethys_equipped/model.sdf index 1dd1b802..ab942be7 100644 --- a/lrauv_description/models/tethys_equipped/model.sdf +++ b/lrauv_description/models/tethys_equipped/model.sdf @@ -348,8 +348,8 @@ 1025 + filename="ignition-gazebo-hydrodynamics-system" + name="ignition::gazebo::systems::Hydrodynamics"> base_link false -4.876161 diff --git a/lrauv_gazebo_plugins/CMakeLists.txt b/lrauv_gazebo_plugins/CMakeLists.txt index 4928bff1..bbeacec2 100644 --- a/lrauv_gazebo_plugins/CMakeLists.txt +++ b/lrauv_gazebo_plugins/CMakeLists.txt @@ -160,7 +160,6 @@ target_link_libraries(DopplerVelocityLog PUBLIC ${GZ_SENSORS}-rendering) add_lrauv_plugin(DopplerVelocityLogSystem RENDERING) target_link_libraries(DopplerVelocityLogSystem PUBLIC DopplerVelocityLog ${GZ_SENSORS}-rendering) -add_lrauv_plugin(HydrodynamicsPlugin) add_lrauv_plugin(RangeBearingPlugin PROTO lrauv_gazebo_messages diff --git a/lrauv_gazebo_plugins/src/HydrodynamicsPlugin.cc b/lrauv_gazebo_plugins/src/HydrodynamicsPlugin.cc deleted file mode 100644 index bf78b0c0..00000000 --- a/lrauv_gazebo_plugins/src/HydrodynamicsPlugin.cc +++ /dev/null @@ -1,368 +0,0 @@ -/* - * Copyright (C) 2021 Open Source Robotics Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -/* - * Development of this module has been funded by the Monterey Bay Aquarium - * Research Institute (MBARI) and the David and Lucile Packard Foundation - */ - -#include "HydrodynamicsPlugin.hh" - -#include - -#include - -namespace tethys -{ - -class HydrodynamicsPrivateData -{ - /// \brief Values to set via Plugin Parameters. - /// Plugin Parameter: Added mass in surge, X_\dot{u}. - public: double paramXdotU; - - /// \brief Plugin Parameter: Added mass in sway, Y_\dot{v}. - public: double paramYdotV; - - /// \brief Plugin Parameter: Added mass in heave, Z_\dot{w}. - public: double paramZdotW; - - /// \brief Plugin Parameter: Added mass in roll, K_\dot{p}. - public: double paramKdotP; - - /// \brief Plugin Parameter: Added mass in pitch, M_\dot{q}. - public: double paramMdotQ; - - /// \brief Plugin Parameter: Added mass in yaw, N_\dot{r}. - public: double paramNdotR; - - /// \brief Plugin Parameter: Linear drag in surge. - public: double paramXu; - - /// \brief Plugin Parameter: Quadratic drag in surge. - public: double paramXuu; - - /// \brief Plugin Parameter: Linear drag in sway. - public: double paramYv; - - /// \brief Plugin Parameter: Quadratic drag in sway. - public: double paramYvv; - - /// \brief Plugin Parameter: Linear drag in heave. - public: double paramZw; - - /// \brief Plugin Parameter: Quadratic drag in heave. - public: double paramZww; - - /// \brief Plugin Parameter: Linear drag in roll. - public: double paramKp; - - /// \brief Plugin Parameter: Quadratic drag in roll. - public: double paramKpp; - - /// \brief Plugin Parameter: Linear drag in pitch. - public: double paramMq; - - /// \brief Plugin Parameter: Quadratic drag in pitch. - public: double paramMqq; - - /// \brief Plugin Parameter: Linear drag in yaw. - public: double paramNr; - - /// \brief Plugin Parameter: Quadratic drag in yaw. - public: double paramNrr; - - /// \brief Plugin Parameter: Disable coriolis as part of equation. This is - /// occasionally useful for testing. - public: bool enableCoriolis = true; - - /// \brief Water density [kg/m^3]. - public: double waterDensity; - - /// \brief Water current [m/s]. - public: gz::math::Vector3d waterCurrent {0.0, 0.0, 0.0}; - - public: Eigen::VectorXd prevState; - - public: Eigen::VectorXd prevStateDot; - - /// \brief Update current during simulation - public: void UpdateCurrent( - const gz::msgs::Vector3d &_msg) - { - std::lock_guard lock(this->mtx); - this->waterCurrent = gz::msgs::Convert(_msg); - } - - /// Link entity - public: gz::sim::Entity linkEntity; - - public: gz::transport::Node node; - - public: std::mutex mtx; -}; - - -void AddAngularVelocityComponent( - const gz::sim::Entity &_entity, - gz::sim::EntityComponentManager &_ecm) -{ - if (!_ecm.Component( - _entity)) - { - _ecm.CreateComponent(_entity, - gz::sim::components::AngularVelocity()); - } - // Create an angular velocity component if one is not present. - if (!_ecm.Component( - _entity)) - { - _ecm.CreateComponent(_entity, - gz::sim::components::WorldAngularVelocity()); - } -} - -void AddWorldPose ( - const gz::sim::Entity &_entity, - gz::sim::EntityComponentManager &_ecm) -{ - if (!_ecm.Component( - _entity)) - { - _ecm.CreateComponent(_entity, - gz::sim::components::WorldPose()); - } -} - -void AddWorldLinearVelocity( - const gz::sim::Entity &_entity, - gz::sim::EntityComponentManager &_ecm) -{ - if (!_ecm.Component( - _entity)) - { - _ecm.CreateComponent(_entity, - gz::sim::components::WorldLinearVelocity()); - } -} - -double SdfParamDouble( - const std::shared_ptr &_sdf, - const std::string &_field, - double _default) -{ - if(!_sdf->HasElement(_field)) - { - return _default; - } - return _sdf->Get(_field); -} - - -HydrodynamicsPlugin::HydrodynamicsPlugin() - : dataPtr(std::make_unique()) -{ -} - -void HydrodynamicsPlugin::Configure( - const gz::sim::Entity &_entity, - const std::shared_ptr &_sdf, - gz::sim::EntityComponentManager &_ecm, - gz::sim::EventManager &/*_eventMgr*/ -) -{ - this->dataPtr->waterDensity = SdfParamDouble(_sdf, "waterDensity", 997.7735); - this->dataPtr->paramXdotU = SdfParamDouble(_sdf, "xDotU" , 5); - this->dataPtr->paramYdotV = SdfParamDouble(_sdf, "yDotV" , 5); - this->dataPtr->paramZdotW = SdfParamDouble(_sdf, "zDotW" , 0.1); - this->dataPtr->paramKdotP = SdfParamDouble(_sdf, "kDotP" , 0.1); - this->dataPtr->paramMdotQ = SdfParamDouble(_sdf, "mDotQ" , 0.1); - this->dataPtr->paramNdotR = SdfParamDouble(_sdf, "nDotR" , 1); - this->dataPtr->paramXu = SdfParamDouble(_sdf, "xU" , 20); - this->dataPtr->paramXuu = SdfParamDouble(_sdf, "xUU" , 0); - this->dataPtr->paramYv = SdfParamDouble(_sdf, "yV" , 20); - this->dataPtr->paramYvv = SdfParamDouble(_sdf, "yVV" , 0); - this->dataPtr->paramZw = SdfParamDouble(_sdf, "zW" , 20); - this->dataPtr->paramZww = SdfParamDouble(_sdf, "zWW" , 0); - this->dataPtr->paramKp = SdfParamDouble(_sdf, "kP" , 20); - this->dataPtr->paramKpp = SdfParamDouble(_sdf, "kPP" , 0); - this->dataPtr->paramMq = SdfParamDouble(_sdf, "mQ" , 20); - this->dataPtr->paramMqq = SdfParamDouble(_sdf, "mQQ" , 0); - this->dataPtr->paramNr = SdfParamDouble(_sdf, "nR" , 20); - this->dataPtr->paramNrr = SdfParamDouble(_sdf, "nRR" , 0); - - _sdf->Get("enable_coriolis", this->dataPtr->enableCoriolis, true); - - // Create model object, to access convenient functions - auto model = gz::sim::Model(_entity); - auto link_name = _sdf->Get("link_name"); - this->dataPtr->linkEntity = model.LinkByName(_ecm, link_name); - - if (gz::sim::kNullEntity == this->dataPtr->linkEntity) - { - gzerr << "Failed to find link named [" << link_name << "] in model [" - << model.Name(_ecm) << "]. Plugin failed to initialize." << std::endl; - return; - } - - this->dataPtr->prevState = Eigen::VectorXd::Zero(6); - this->dataPtr->prevStateDot = Eigen::VectorXd::Zero(6); - - AddWorldPose(this->dataPtr->linkEntity, _ecm); - AddAngularVelocityComponent(this->dataPtr->linkEntity, _ecm); - AddWorldLinearVelocity(this->dataPtr->linkEntity, _ecm); - - std::string ns; - std::string currentTopic {"/ocean_current"}; - if (_sdf->HasElement("namespace")) - { - ns = _sdf->Get("namespace"); - currentTopic = gz::transport::TopicUtils::AsValidTopic( - "/model/" + ns + "/ocean_current"); - } - - this->dataPtr->node.Subscribe( - currentTopic, - &HydrodynamicsPrivateData::UpdateCurrent, - this->dataPtr.get()); - - if(_sdf->HasElement("default_current")) - { - this->dataPtr->waterCurrent = - _sdf->Get("default_current"); - } -} - -void HydrodynamicsPlugin::PreUpdate( - const gz::sim::UpdateInfo &_info, - gz::sim::EntityComponentManager &_ecm) -{ - if(_info.paused) - return; - - // These variables are named following Fossen's scheme in "Guidance and Control - // of Ocean Vehicles." The `state` vector contains the ship's current velocity - // in the formate [x_vel, y_vel, z_vel, roll_vel, pitch_vel, yaw_vel]. - // `stateDot` consists of the first derivative in time of the state vector. - // `Cmat` corresponds to the Centripetal matrix - // `Dmat` is the drag matrix - // `Ma` is the added mass. - Eigen::VectorXd stateDot = Eigen::VectorXd(6); - Eigen::VectorXd state = Eigen::VectorXd(6); - Eigen::MatrixXd Cmat = Eigen::MatrixXd::Zero(6, 6); - Eigen::MatrixXd Dmat = Eigen::MatrixXd::Zero(6, 6); - Eigen::MatrixXd Ma = Eigen::MatrixXd::Zero(6,6); - - std::lock_guard lock(this->dataPtr->mtx); - // Get vehicle state - gz::sim::Link baseLink(this->dataPtr->linkEntity); - auto linearVelocity = - _ecm.Component(this->dataPtr->linkEntity); - auto rotationalVelocity = baseLink.WorldAngularVelocity(_ecm); - - if(!linearVelocity) - { - gzerr <<"no linear vel" <<"\n"; - return; - } - - // Transform state to local frame - auto pose = baseLink.WorldPose(_ecm); - // Since we are transforming angular and linear velocity we only care about - // rotation - auto localLinearVelocity = pose->Rot().Inverse() * - (linearVelocity->Data() - this->dataPtr->waterCurrent); - auto localRotationalVelocity = pose->Rot().Inverse() * *rotationalVelocity; - - state(0) = localLinearVelocity.X(); - state(1) = localLinearVelocity.Y(); - state(2) = localLinearVelocity.Z(); - - state(3) = localRotationalVelocity.X(); - state(4) = localRotationalVelocity.Y(); - state(5) = localRotationalVelocity.Z(); - - auto dt = (double)_info.dt.count()/1e9; - - auto alpha = 0.9; - stateDot = alpha * (state - this->dataPtr->prevState)/dt - + (1-alpha) * this->dataPtr->prevStateDot; - - this->dataPtr->prevStateDot = stateDot; - - this->dataPtr->prevState = state; - - // Added mass according to Fossen's equations (p 37) - Ma(0,0) = this->dataPtr->paramXdotU; - Ma(1,1) = this->dataPtr->paramYdotV; - Ma(2,2) = this->dataPtr->paramZdotW; - Ma(3,3) = this->dataPtr->paramKdotP; - Ma(4,4) = this->dataPtr->paramMdotQ; - Ma(5,5) = this->dataPtr->paramNdotR; - const Eigen::VectorXd kAmassVec = - Ma * stateDot; - - // Coriollis and Centripetal forces for under water vehicles (Fossen P. 37) - // Note: this is significantly different from VRX because we need to account - // for the under water vehicle's additional DOF - Cmat(0,4) = - this->dataPtr->paramZdotW * state(2); - Cmat(0,5) = - this->dataPtr->paramYdotV * state(1); - Cmat(1,3) = this->dataPtr->paramZdotW * state(2); - Cmat(1,5) = - this->dataPtr->paramXdotU * state(0); - Cmat(2,3) = - this->dataPtr->paramYdotV * state(1); - Cmat(2,4) = this->dataPtr->paramXdotU * state(0); - Cmat(3,1) = - this->dataPtr->paramZdotW * state(2); - Cmat(3,2) = this->dataPtr->paramYdotV * state(1); - Cmat(3,4) = - this->dataPtr->paramNdotR * state(5); - Cmat(3,5) = this->dataPtr->paramMdotQ * state(4); - Cmat(4,0) = this->dataPtr->paramZdotW * state(2); - Cmat(4,2) = - this->dataPtr->paramXdotU * state(0); - Cmat(4,3) = this->dataPtr->paramNdotR * state(5); - Cmat(4,5) = - this->dataPtr->paramKdotP * state(3); - Cmat(5,0) = this->dataPtr->paramZdotW * state(2); - Cmat(5,1) = this->dataPtr->paramXdotU * state(0); - Cmat(5,3) = - this->dataPtr->paramMdotQ * state(4); - Cmat(5,4) = this->dataPtr->paramKdotP * state(3); - const Eigen::VectorXd kCmatVec = - Cmat * state; - - // Damping forces (Fossen P. 43) - Dmat(0,0) = - this->dataPtr->paramXu - this->dataPtr->paramXuu * abs(state(0)); - Dmat(1,1) = - this->dataPtr->paramYv - this->dataPtr->paramYvv * abs(state(1)); - Dmat(2,2) = - this->dataPtr->paramZw - this->dataPtr->paramZww * abs(state(2)); - Dmat(3,3) = - this->dataPtr->paramKp - this->dataPtr->paramKpp * abs(state(3)); - Dmat(4,4) = - this->dataPtr->paramMq - this->dataPtr->paramMqq * abs(state(4)); - Dmat(5,5) = - this->dataPtr->paramNr - this->dataPtr->paramNrr * abs(state(5)); - - const Eigen::VectorXd kDvec = Dmat * state; - - Eigen::VectorXd kTotalWrench = kAmassVec + kDvec; - - if (this->dataPtr->enableCoriolis) - kTotalWrench += kCmatVec; - - gz::math::Vector3d totalForce(-kTotalWrench(0), -kTotalWrench(1), -kTotalWrench(2)); - gz::math::Vector3d totalTorque(-kTotalWrench(3), -kTotalWrench(4), -kTotalWrench(5)); - - baseLink.AddWorldWrench(_ecm, pose->Rot()*(totalForce), pose->Rot()*totalTorque); -} - -}; - -GZ_ADD_PLUGIN( - tethys::HydrodynamicsPlugin, - gz::sim::System, - tethys::HydrodynamicsPlugin::ISystemConfigure, - tethys::HydrodynamicsPlugin::ISystemPreUpdate) diff --git a/lrauv_gazebo_plugins/src/HydrodynamicsPlugin.hh b/lrauv_gazebo_plugins/src/HydrodynamicsPlugin.hh deleted file mode 100644 index 882db139..00000000 --- a/lrauv_gazebo_plugins/src/HydrodynamicsPlugin.hh +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2021 Open Source Robotics Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -/* - * Development of this module has been funded by the Monterey Bay Aquarium - * Research Institute (MBARI) and the David and Lucile Packard Foundation - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace tethys -{ - class HydrodynamicsPrivateData; - - /// This class provides hydrodynamic behaviour for underwater vehicles - /// It is shamelessly based off Brian Bingham's plugin for VRX - /// which in turn is based of fossen's equations. - class HydrodynamicsPlugin: - public gz::sim::System, - public gz::sim::ISystemConfigure, - public gz::sim::ISystemPreUpdate - { - public: HydrodynamicsPlugin(); - - public: ~HydrodynamicsPlugin() = default; - - public: void Configure( - const gz::sim::Entity &_entity, - const std::shared_ptr &_sdf, - gz::sim::EntityComponentManager &_ecm, - gz::sim::EventManager &/*_eventMgr*/ - ); - - public: void PreUpdate( - const gz::sim::UpdateInfo &_info, - gz::sim::EntityComponentManager &_ecm); - - private: std::unique_ptr dataPtr; - }; -}