From 899f3161563d2a0875894beb796d944b9c4e67fb Mon Sep 17 00:00:00 2001 From: Tomas Baca Date: Mon, 14 Aug 2023 17:40:35 +0200 Subject: [PATCH 01/12] removed schedulled workflow --- .github/workflows/noetic.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/noetic.yml b/.github/workflows/noetic.yml index de7a43e..0151fcc 100644 --- a/.github/workflows/noetic.yml +++ b/.github/workflows/noetic.yml @@ -10,9 +10,6 @@ on: pull_request: branches: [ master ] - schedule: - - cron: '0 0 * * *' # at the end of every day - # Allows you to run this workflow manually from the Actions tab workflow_dispatch: From 98d7da99093905e5ff1fa1f123383610b80b568a Mon Sep 17 00:00:00 2001 From: ondra Date: Wed, 13 Sep 2023 16:03:19 +0200 Subject: [PATCH 02/12] Added linear fluid resistance plugin. --- CMakeLists.txt | 12 + .../fluid_resistance_plugin.cpp | 288 ++++++++++++++++++ 2 files changed, 300 insertions(+) create mode 100644 src/physics_plugins/fluid_resistance_plugin.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 03bee06..ce138a3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -94,6 +94,7 @@ set(LIBRARIES MrsGazeboCommonResources_ServoCameraPlugin MrsGazeboCommonResources_DynamicModelPlugin MrsGazeboCommonResources_SafetyLedPlugin + MrsGazeboCommonResources_FluidResistancePlugin ) catkin_package( @@ -326,6 +327,17 @@ target_link_libraries(MrsGazeboCommonResources_SafetyLedPlugin ${Boost_LIBRARIES} ) +# FluidResistancePlugin + +add_library(MrsGazeboCommonResources_FluidResistancePlugin SHARED + src/physics_plugins/fluid_resistance_plugin.cpp + ) + +target_link_libraries(MrsGazeboCommonResources_FluidResistancePlugin + ${GAZEBO_LIBRARIES} + ${catkin_LIBRARIES} + ${Boost_LIBRARIES} + ) ## -------------------------------------------------------------- ## | Install | ## -------------------------------------------------------------- diff --git a/src/physics_plugins/fluid_resistance_plugin.cpp b/src/physics_plugins/fluid_resistance_plugin.cpp new file mode 100644 index 0000000..bc03b32 --- /dev/null +++ b/src/physics_plugins/fluid_resistance_plugin.cpp @@ -0,0 +1,288 @@ +/** \file + \brief Defines class that applies linear drag force to the uav body. + \inspiration https://www.theconstructsim.com/q-a-190-air-drag-in-gazebo/ + \author Ondrej Prochazka - prochon4@fel.cvut.cz + */ + +#include +#include +#include +#include + +#include + +#include + +#include + +#include + +#include + +#include +#include + +#include + +#include + +#include + +namespace gazebo +{ + +/* Class definition //{ */ +class FluidResistancePlugin : public ModelPlugin { +public: + void Load(physics::ModelPtr _parent, sdf::ElementPtr _sdf); + void OnUpdate(); + void UpdateLinearVel(); + void OnRosMsg(const geometry_msgs::Vector3ConstPtr &_msg); + + void ApplyResistance(); + +private: + void QueueThread(); + +private: + physics::ModelPtr model; // Pointer to the model + +private: + event::ConnectionPtr updateConnection; // Pointer to the update event connection + + // TODO: remove this variable and exchange it for x_res, ... to be abel update by topic + double fluid_resistance_index = 1.0; + +private: + std::unique_ptr rosNode; // node use for ROS transport + +private: + ros::Subscriber rosSub; // ROS subscriber +private: + ros::CallbackQueue rosQueue; // ROS callbackqueue that helps process messages +private: + std::thread rosQueueThread; // thread the keeps running the rosQueue + +private: + physics::LinkPtr link_to_apply_resistance; // ROS subscriber + +private: + std::string fluid_resistanceTopicName = "fluid_resistance"; + +private: + std::string NameLinkToApplyResistance = "base_link"; + +private: +#if (GAZEBO_MAJOR_VERSION >= 8) + ignition::math::Vector3d now_lin_vel; +#else + math::Vector3 now_lin_vel; +#endif + +private: + double rate = 1.0; + double res_x = 1.0; + double res_y = 1.0; + double res_z = 1.0; + +private: + float last_time = 0.0; + +private: + physics::WorldPtr world; // The parent World +}; + +//} + +/* Load() //{ */ +void FluidResistancePlugin::Load(physics::ModelPtr _parent, sdf::ElementPtr _sdf) { + + std::cout << "Using Fluid Resistance PLugin" << std::endl; + + /* load elements //{ */ + if (_sdf->HasElement("fluid_resistanceTopicName")) { + fluid_resistanceTopicName = _sdf->Get("fluid_resistanceTopicName"); + } else { + ROS_WARN("No Topic Given name given, setting default name %s", fluid_resistanceTopicName.c_str()); + } + + if (_sdf->HasElement("NameLinkToApplyResistance")) { + NameLinkToApplyResistance = _sdf->Get("NameLinkToApplyResistance"); + } else { + ROS_WARN( + "No NameLinkToApplyResistance Given name given, setting default " + "name %s", + NameLinkToApplyResistance.c_str()); + } + + if (_sdf->HasElement("rate")) { + rate = _sdf->Get("rate"); + } else { + ROS_WARN( + "No rate Given name given, setting default " + "name %f", + rate); + } + + if (_sdf->HasElement("res_x")) { + res_x = _sdf->Get("res_x"); + } else { + ROS_WARN( + "No res_x Given name given, setting default " + "name %f", + res_x); + } + + if (_sdf->HasElement("res_y")) { + res_y = _sdf->Get("res_y"); + } else { + ROS_WARN( + "No res_y Given name given, setting default " + "name %f", + res_y); + } + + if (_sdf->HasElement("res_z")) { + res_z = _sdf->Get("res_z"); + } else { + ROS_WARN( + "No res_z Given name given, setting default " + "name %f", + res_z); + } + + ROS_WARN("All elements loaded successfully!"); + + //} + + // Store the pointer to the model + model = _parent; + world = model->GetWorld(); + link_to_apply_resistance = model->GetLink(NameLinkToApplyResistance); + + // Listen to the update event. This event is broadcast every + // simulation iteration. + updateConnection = event::Events::ConnectWorldUpdateBegin(std::bind(&FluidResistancePlugin::OnUpdate, this)); + + // Create a topic name + // std::string fluid_resistance_index_topicName = "/fluid_resistance_index"; + + // Initialize ros, if it has not already bee initialized. + if (!ros::isInitialized()) { + int argc = 0; + char **argv = NULL; + ros::init(argc, argv, "fluid_resistance_node", ros::init_options::NoSigintHandler); + } + + // Create our ROS node. This acts in a similar manner to + // the Gazebo node + rosNode.reset(new ros::NodeHandle("fluid_resistance_node")); + +#if (GAZEBO_MAJOR_VERSION >= 8) + last_time = world->SimTime().Float(); +#else + last_time = world->GetSimTime().Float(); +#endif + + // Freq + ros::SubscribeOptions so = ros::SubscribeOptions::create( + fluid_resistanceTopicName, 1, boost::bind(&FluidResistancePlugin::OnRosMsg, this, _1), ros::VoidPtr(), &rosQueue); + rosSub = rosNode->subscribe(so); + + // Spin up the queue helper thread. + rosQueueThread = std::thread(std::bind(&FluidResistancePlugin::QueueThread, this)); + + ROS_WARN( + "Loaded FluidResistance Plugin with parent...%s, With Fluid " + "Resistance = %f " + "Started ", + model->GetName().c_str(), fluid_resistance_index); +} +//} + +/* OnUpdate() //{ */ +// Called by the world update start event +void FluidResistancePlugin::OnUpdate() { + float period = 1.0 / rate; + + // Get simulator time +#if (GAZEBO_MAJOR_VERSION >= 8) + float current_time = world->SimTime().Float(); +#else + float current_time = world->GetSimTime().Float(); +#endif + float dt = current_time - last_time; + + if (dt <= period) { + ROS_DEBUG(">>>>>>>>>>TimePassed = %f, TimePeriod =%f ", dt, period); + return; + } else { + last_time = current_time; + ApplyResistance(); + } +} +//} + +/* UpdateLinearVel() //{ */ +void FluidResistancePlugin::UpdateLinearVel() { +#if (GAZEBO_MAJOR_VERSION >= 8) + now_lin_vel = model->RelativeLinearVel(); +#else + now_lin_vel = model->GetRelativeLinearVel(); +#endif +} +//} + +/* ApplyResistance() //{ */ +void FluidResistancePlugin::ApplyResistance() { + + UpdateLinearVel(); + +#if (GAZEBO_MAJOR_VERSION >= 8) + ignition::math::Vector3d force, torque; +#else + math::Vector3 force, torque; +#endif + + ROS_WARN("LinearSpeed = [%f,%f,%f] ", now_lin_vel.X(), now_lin_vel.Y(), now_lin_vel.Z()); + + force.X(-1.0 * res_x * now_lin_vel.X()); + force.Y(-1.0 * res_y * now_lin_vel.Y()); + force.Z(-1.0 * res_z * now_lin_vel.Z()); + + // Applying force to uav + link_to_apply_resistance->AddRelativeForce(force); +#if (GAZEBO_MAJOR_VERSION >= 8) + link_to_apply_resistance->AddRelativeTorque(torque - link_to_apply_resistance->GetInertial()->CoG().Cross(force)); +#else + link_to_apply_resistance->AddRelativeTorque(torque - link_to_apply_resistance->GetInertial()->GetCoG().Cross(force)); +#endif + + ROS_WARN("FluidResistanceApplying = [%f,%f,%f] ", force.X(), force.Y(), force.Z()); +} +//} + +/* OnRosMsg() //{ */ +void FluidResistancePlugin::OnRosMsg(const geometry_msgs::Vector3ConstPtr &_msg) { + /* UpdateResistanceValues(_msg->data); */ + res_x = _msg->x; + res_y = _msg->y; + res_z = _msg->z; + ROS_WARN("fluid resistance changed!!"); +} +//} + +/* QueueThread() //{ */ +/// \brief ROS helper function that processes messages +void FluidResistancePlugin::QueueThread() { + static const double timeout = 0.01; + while (rosNode->ok()) { + rosQueue.callAvailable(ros::WallDuration(timeout)); + } +} +//} + +// Register this plugin with the simulator +GZ_REGISTER_MODEL_PLUGIN(FluidResistancePlugin) + +} // namespace gazebo From dbbbcf7c4d72f17c6f779191dcc663e00755fd50 Mon Sep 17 00:00:00 2001 From: ondra Date: Thu, 14 Sep 2023 13:16:48 +0200 Subject: [PATCH 03/12] Added nicer prints into fluid plugin and updated README. --- src/physics_plugins/README.md | 19 +++++++++ .../fluid_resistance_plugin.cpp | 39 +++++++++---------- 2 files changed, 37 insertions(+), 21 deletions(-) create mode 100644 src/physics_plugins/README.md diff --git a/src/physics_plugins/README.md b/src/physics_plugins/README.md new file mode 100644 index 0000000..1b17757 --- /dev/null +++ b/src/physics_plugins/README.md @@ -0,0 +1,19 @@ +# Physics plugins for Gazebo + +This directory includes plugins that somehow modify the physics behavior of the UAV or its parts. + +## Plugins +* fluid_resistace_plugin + +### Fluid Resistance +This plugin models linear resistance of the air (Fd = resistance_constant * linear_body_velocity). +You can set resistance coefficientsa (for every axis in body frame) in model definition using fluid resistance macro. +It is also possible to change fluid resistance while simulation is running using topic */fluid_resistance*. +``` +rostopic pub /fluid_resistance geometry_msgs/Vector3 "x: 0.0 +y: 0.0 +z: 0.0" +``` + + + diff --git a/src/physics_plugins/fluid_resistance_plugin.cpp b/src/physics_plugins/fluid_resistance_plugin.cpp index bc03b32..00d2f56 100644 --- a/src/physics_plugins/fluid_resistance_plugin.cpp +++ b/src/physics_plugins/fluid_resistance_plugin.cpp @@ -50,9 +50,6 @@ class FluidResistancePlugin : public ModelPlugin { private: event::ConnectionPtr updateConnection; // Pointer to the update event connection - // TODO: remove this variable and exchange it for x_res, ... to be abel update by topic - double fluid_resistance_index = 1.0; - private: std::unique_ptr rosNode; // node use for ROS transport @@ -67,7 +64,7 @@ class FluidResistancePlugin : public ModelPlugin { physics::LinkPtr link_to_apply_resistance; // ROS subscriber private: - std::string fluid_resistanceTopicName = "fluid_resistance"; + std::string FluidResistanceTopicName = "fluid_resistance"; private: std::string NameLinkToApplyResistance = "base_link"; @@ -100,17 +97,17 @@ void FluidResistancePlugin::Load(physics::ModelPtr _parent, sdf::ElementPtr _sdf std::cout << "Using Fluid Resistance PLugin" << std::endl; /* load elements //{ */ - if (_sdf->HasElement("fluid_resistanceTopicName")) { - fluid_resistanceTopicName = _sdf->Get("fluid_resistanceTopicName"); + if (_sdf->HasElement("FluidResistanceTopicName")) { + FluidResistanceTopicName = _sdf->Get("FluidResistanceTopicName"); } else { - ROS_WARN("No Topic Given name given, setting default name %s", fluid_resistanceTopicName.c_str()); + ROS_WARN("[FluidResistancePlugin]: No Topic Given name given, setting default name %s", FluidResistanceTopicName.c_str()); } if (_sdf->HasElement("NameLinkToApplyResistance")) { NameLinkToApplyResistance = _sdf->Get("NameLinkToApplyResistance"); } else { ROS_WARN( - "No NameLinkToApplyResistance Given name given, setting default " + "[FluidResistancePlugin]: No NameLinkToApplyResistance Given name given, setting default " "name %s", NameLinkToApplyResistance.c_str()); } @@ -119,7 +116,7 @@ void FluidResistancePlugin::Load(physics::ModelPtr _parent, sdf::ElementPtr _sdf rate = _sdf->Get("rate"); } else { ROS_WARN( - "No rate Given name given, setting default " + "[FluidResistancePlugin]: No rate Given name given, setting default " "name %f", rate); } @@ -128,7 +125,7 @@ void FluidResistancePlugin::Load(physics::ModelPtr _parent, sdf::ElementPtr _sdf res_x = _sdf->Get("res_x"); } else { ROS_WARN( - "No res_x Given name given, setting default " + "[FluidResistancePlugin]: No res_x Given name given, setting default " "name %f", res_x); } @@ -137,7 +134,7 @@ void FluidResistancePlugin::Load(physics::ModelPtr _parent, sdf::ElementPtr _sdf res_y = _sdf->Get("res_y"); } else { ROS_WARN( - "No res_y Given name given, setting default " + "[FluidResistancePlugin]: No res_y Given name given, setting default " "name %f", res_y); } @@ -146,12 +143,12 @@ void FluidResistancePlugin::Load(physics::ModelPtr _parent, sdf::ElementPtr _sdf res_z = _sdf->Get("res_z"); } else { ROS_WARN( - "No res_z Given name given, setting default " + "[FluidResistancePlugin]: No res_z Given name given, setting default " "name %f", res_z); } - ROS_WARN("All elements loaded successfully!"); + ROS_INFO("[FluidResistancePlugin]: All elements loaded successfully!"); //} @@ -186,17 +183,17 @@ void FluidResistancePlugin::Load(physics::ModelPtr _parent, sdf::ElementPtr _sdf // Freq ros::SubscribeOptions so = ros::SubscribeOptions::create( - fluid_resistanceTopicName, 1, boost::bind(&FluidResistancePlugin::OnRosMsg, this, _1), ros::VoidPtr(), &rosQueue); + FluidResistanceTopicName, 1, boost::bind(&FluidResistancePlugin::OnRosMsg, this, _1), ros::VoidPtr(), &rosQueue); rosSub = rosNode->subscribe(so); // Spin up the queue helper thread. rosQueueThread = std::thread(std::bind(&FluidResistancePlugin::QueueThread, this)); ROS_WARN( - "Loaded FluidResistance Plugin with parent...%s, With Fluid " - "Resistance = %f " + "[FluidResistancePlugin]: Loaded FluidResistance Plugin with parent...%s, With Fluid " + "Resistance = ( %f, %f, %f) " "Started ", - model->GetName().c_str(), fluid_resistance_index); + model->GetName().c_str(), res_x, res_y, res_z); } //} @@ -214,7 +211,7 @@ void FluidResistancePlugin::OnUpdate() { float dt = current_time - last_time; if (dt <= period) { - ROS_DEBUG(">>>>>>>>>>TimePassed = %f, TimePeriod =%f ", dt, period); + ROS_DEBUG("[FluidResistancePlugin]: >>>>>>>>>>TimePassed = %f, TimePeriod =%f ", dt, period); return; } else { last_time = current_time; @@ -244,7 +241,7 @@ void FluidResistancePlugin::ApplyResistance() { math::Vector3 force, torque; #endif - ROS_WARN("LinearSpeed = [%f,%f,%f] ", now_lin_vel.X(), now_lin_vel.Y(), now_lin_vel.Z()); + /* ROS_WARN("[FluidResistancePlugin]: LinearSpeed = [%f,%f,%f] ", now_lin_vel.X(), now_lin_vel.Y(), now_lin_vel.Z()); */ force.X(-1.0 * res_x * now_lin_vel.X()); force.Y(-1.0 * res_y * now_lin_vel.Y()); @@ -258,7 +255,7 @@ void FluidResistancePlugin::ApplyResistance() { link_to_apply_resistance->AddRelativeTorque(torque - link_to_apply_resistance->GetInertial()->GetCoG().Cross(force)); #endif - ROS_WARN("FluidResistanceApplying = [%f,%f,%f] ", force.X(), force.Y(), force.Z()); + /* ROS_WARN("[FluidResistancePlugin]: FluidResistanceApplying = [%f,%f,%f] ", force.X(), force.Y(), force.Z()); */ } //} @@ -268,7 +265,7 @@ void FluidResistancePlugin::OnRosMsg(const geometry_msgs::Vector3ConstPtr &_msg) res_x = _msg->x; res_y = _msg->y; res_z = _msg->z; - ROS_WARN("fluid resistance changed!!"); + ROS_WARN("[FluidResistancePlugin]: Fluid resistance changed to (%f, %f, %f)!!", res_x, res_y, res_z); } //} From 62e4ed002217ba0d93959a1ab40af77030393f73 Mon Sep 17 00:00:00 2001 From: ondra Date: Thu, 14 Sep 2023 13:26:22 +0200 Subject: [PATCH 04/12] Moved motor model from mavlink_sitl_gazebo and modified for a300 drone. --- CMakeLists.txt | 36 +- include/motor_prop_model.h | 157 ++++++++ include/rotors_model/motor_model.hpp | 60 ++++ msgs/CommandMotorSpeed.proto | 7 + msgs/MotorSpeed.proto | 7 + msgs/Wind.proto | 10 + package.xml | 1 + src/physics_plugins/README.md | 8 + .../motor_prop_model_plugin.cpp | 334 ++++++++++++++++++ 9 files changed, 597 insertions(+), 23 deletions(-) create mode 100644 include/motor_prop_model.h create mode 100644 include/rotors_model/motor_model.hpp create mode 100644 msgs/CommandMotorSpeed.proto create mode 100644 msgs/MotorSpeed.proto create mode 100644 msgs/Wind.proto create mode 100644 src/physics_plugins/motor_prop_model_plugin.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 990b9d0..f78df94 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -60,25 +60,17 @@ endforeach() # PROTOBUF_IMPORT_DIRS has to be set before find_package(Protobuf REQUIRED) -# set(mav_msgs -# msgs/CommandMotorSpeed.proto -# msgs/MotorSpeed.proto -# ) - -# set(physics_msgs -# msgs/Wind.proto -# ) - set(sensor_msgs msgs/SITLGps.proto msgs/Groundtruth.proto msgs/MagneticField.proto msgs/Float.proto + msgs/CommandMotorSpeed.proto + msgs/MotorSpeed.proto + msgs/Wind.proto ) PROTOBUF_GENERATE_CPP(SEN_PROTO_SRCS SEN_PROTO_HDRS ${sensor_msgs}) -# PROTOBUF_GENERATE_CPP(MAV_PROTO_SRCS MAV_PROTO_HDRS ${mav_msgs}) -# PROTOBUF_GENERATE_CPP(PHY_PROTO_SRCS PHY_PROTO_HDRS ${physics_msgs}) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) @@ -108,7 +100,7 @@ set(LIBRARIES MrsGazeboCommonResources_SafetyLedPlugin MrsGazeboCommonResources_FluidResistancePlugin MrsGazeboCommonResources_MotorSpeedRepublisherPlugin - # MrsGazeboCommonResources_MotorPropModelPlugin + MrsGazeboCommonResources_MotorPropModelPlugin ) catkin_package( @@ -367,18 +359,16 @@ target_link_libraries(MrsGazeboCommonResources_MotorSpeedRepublisherPlugin # MotorPropModelPlugin -# add_library(mav_msgs SHARED ${MAV_PROTO_SRCS}) -# add_library(physics_msgs SHARED ${PHY_PROTO_SRCS}) - -# add_library(MrsGazeboCommonResources_MotorPropModelPlugin SHARED -# src/physics_plugins/motor_prop_model_plugin.cpp -# ) +add_library(MrsGazeboCommonResources_MotorPropModelPlugin SHARED + src/physics_plugins/motor_prop_model_plugin.cpp + ${SEN_PROTO_SRCS} + ) -# target_link_libraries(MrsGazeboCommonResources_MotorPropModelPlugin -# ${GAZEBO_LIBRARIES} -# ${catkin_LIBRARIES} -# ${Boost_LIBRARIES} -# ) +target_link_libraries(MrsGazeboCommonResources_MotorPropModelPlugin + ${GAZEBO_LIBRARIES} + ${catkin_LIBRARIES} + ${Boost_LIBRARIES} + ) ## -------------------------------------------------------------- ## | Install | diff --git a/include/motor_prop_model.h b/include/motor_prop_model.h new file mode 100644 index 0000000..05f7c67 --- /dev/null +++ b/include/motor_prop_model.h @@ -0,0 +1,157 @@ +/* + * Copyright 2015 Fadri Furrer, ASL, ETH Zurich, Switzerland + * Copyright 2015 Michael Burri, ASL, ETH Zurich, Switzerland + * Copyright 2015 Mina Kamel, ASL, ETH Zurich, Switzerland + * Copyright 2015 Janosch Nikolic, ASL, ETH Zurich, Switzerland + * Copyright 2015 Markus Achtelik, ASL, ETH Zurich, Switzerland + * + * 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. + */ + + + +#include + +#include +#include +#include +#include +#include +#include +#include +#include "CommandMotorSpeed.pb.h" +#include "gazebo/transport/transport.hh" +#include "gazebo/msgs/msgs.hh" +#include "MotorSpeed.pb.h" +#include "Float.pb.h" +#include "Wind.pb.h" + +#include "common.h" + + +namespace turning_direction { +const static int CCW = 1; +const static int CW = -1; +} + +namespace gazebo { +// Default values +static const std::string kDefaultNamespace = ""; +static const std::string kDefaultCommandSubTopic = "/gazebo/command/motor_speed"; +static const std::string kDefaultMotorFailureNumSubTopic = "/gazebo/motor_failure_num"; +static const std::string kDefaultMotorVelocityPubTopic = "/motor_speed"; +std::string wind_sub_topic_ = "/world_wind"; + +typedef const boost::shared_ptr CommandMotorSpeedPtr; +typedef const boost::shared_ptr WindPtr; +/* +// Protobuf test +typedef const boost::shared_ptr MotorSpeedPtr; +static const std::string kDefaultMotorTestSubTopic = "motors"; +*/ + +// Set the max_force_ to the max double value. The limitations get handled by the FirstOrderFilter. +static constexpr double kDefaultMaxForce = std::numeric_limits::max(); +static constexpr double kDefaultMotorConstant = 8.54858e-06; +static constexpr double kDefaultMomentConstant = 0.016; +static constexpr double kDefaultTimeConstantUp = 1.0 / 80.0; +static constexpr double kDefaultTimeConstantDown = 1.0 / 40.0; +static constexpr double kDefaulMaxRotVelocity = 838.0; +static constexpr double kDefaultRotorDragCoefficient = 1.0e-4; +static constexpr double kDefaultRollingMomentCoefficient = 1.0e-6; +static constexpr double kDefaultRotorVelocitySlowdownSim = 10.0; + +class GazeboMotorPropModel : public MotorPropModel, public ModelPlugin { + public: + GazeboMotorPropModel() + : MotorPropModel(), + ModelPlugin(){ + } + + virtual ~GazeboMotorPropModel(); + + virtual void InitializeParams(); + virtual void Publish(); + //void testProto(MotorSpeedPtr &msg); + protected: + virtual void UpdateForcesAndMoments(); + /// \brief A function to check the motor_Failure_Number_ and stimulate motor fail + /// \details Doing joint_->SetVelocity(0,0) for the flagged motor to fail + virtual void UpdateMotorFail(); + virtual void Load(physics::ModelPtr _model, sdf::ElementPtr _sdf); + virtual void OnUpdate(const common::UpdateInfo & /*_info*/); + + private: + std::string command_sub_topic_{kDefaultCommandSubTopic}; + std::string motor_failure_sub_topic_{kDefaultMotorFailureNumSubTopic}; + std::string joint_name_; + std::string link_name_; + std::string motor_speed_pub_topic_{kDefaultMotorVelocityPubTopic}; + std::string namespace_; + + int motor_number_{0}; + int turning_direction_{turning_direction::CW}; + + int motor_Failure_Number_{0}; /*!< motor_Failure_Number is (motor_number_ + 1) as (0) is considered no_fail. Publish accordingly */ + int tmp_motor_num; // A temporary variable used to print msg + + int screen_msg_flag = 1; + + bool motor_ok_flag_ = true; + bool enable_motor_crash_ = true; + double last_motor_speed_ = 0.0; + + double max_force_{kDefaultMaxForce}; + double max_rot_velocity_{kDefaulMaxRotVelocity}; + double moment_constant_{kDefaultMomentConstant}; + double motor_constant_{kDefaultMotorConstant}; + double ref_motor_rot_vel_{0.0}; + double rolling_moment_coefficient_{kDefaultRollingMomentCoefficient}; + double rotor_drag_coefficient_{kDefaultRotorDragCoefficient}; + double rotor_velocity_slowdown_sim_{kDefaultRotorVelocitySlowdownSim}; + double time_constant_down_{kDefaultTimeConstantDown}; + double time_constant_up_{kDefaultTimeConstantUp}; + + bool reversible_{false}; + + transport::NodePtr node_handle_; + transport::PublisherPtr motor_velocity_pub_; + transport::SubscriberPtr command_sub_; + transport::SubscriberPtr motor_failure_sub_; /*!< Subscribing to motor_failure_sub_topic_; receiving motor number to fail, as an integer */ + transport::SubscriberPtr wind_sub_; + + ignition::math::Vector3d wind_vel_; + + physics::ModelPtr model_; + physics::JointPtr joint_; + common::PID pid_; + bool use_pid_; + physics::LinkPtr link_; + /// \brief Pointer to the update event connection. + event::ConnectionPtr updateConnection_; + + boost::thread callback_queue_thread_; + void QueueThread(); + std_msgs::msgs::Float turning_velocity_msg_; + void VelocityCallback(CommandMotorSpeedPtr &rot_velocities); + void MotorFailureCallback(const boost::shared_ptr &fail_msg); /*!< Callback for the motor_failure_sub_ subscriber */ + void WindVelocityCallback(const boost::shared_ptr &msg); + + std::unique_ptr> rotor_velocity_filter_; +/* + // Protobuf test + std::string motor_test_sub_topic_; + transport::SubscriberPtr motor_sub_; +*/ +}; +} diff --git a/include/rotors_model/motor_model.hpp b/include/rotors_model/motor_model.hpp new file mode 100644 index 0000000..56fe226 --- /dev/null +++ b/include/rotors_model/motor_model.hpp @@ -0,0 +1,60 @@ +/* + * Copyright 2015 Fadri Furrer, ASL, ETH Zurich, Switzerland + * Copyright 2015 Michael Burri, ASL, ETH Zurich, Switzerland + * Copyright 2015 Mina Kamel, ASL, ETH Zurich, Switzerland + * Copyright 2015 Janosch Nikolic, ASL, ETH Zurich, Switzerland + * Copyright 2015 Markus Achtelik, ASL, ETH Zurich, Switzerland + * + * 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. + */ + + +#ifndef ROTORS_MODEL_MOTOR_MODEL_H +#define ROTORS_MODEL_MOTOR_MODEL_H + +#include + +class MotorPropModel +{ + public: + MotorPropModel() + : motor_rot_vel_(0), + ref_motor_rot_vel_(0), + prev_sim_time_(0), + sampling_time_(0.01) {} + virtual ~MotorPropModel() {} + + void GetMotorVelocity(double &result) const { + result = motor_rot_vel_; + } + + void SetReferenceMotorVelocity(double ref_motor_rot_vel) { + ref_motor_rot_vel_ = ref_motor_rot_vel; + } + + virtual void InitializeParams() = 0; + + virtual void Publish() = 0; + + protected: + double motor_rot_vel_; + double ref_motor_rot_vel_; + double prev_ref_motor_rot_vel_; + double prev_sim_time_; + double sampling_time_; + + + virtual void UpdateForcesAndMoments() = 0; +}; + +#endif // ROTORS_MODEL_MOTOR_MODEL_H diff --git a/msgs/CommandMotorSpeed.proto b/msgs/CommandMotorSpeed.proto new file mode 100644 index 0000000..29ec4f2 --- /dev/null +++ b/msgs/CommandMotorSpeed.proto @@ -0,0 +1,7 @@ +syntax = "proto2"; +package mav_msgs.msgs; + +message CommandMotorSpeed +{ + repeated float motor_speed = 1 [packed=true]; +} diff --git a/msgs/MotorSpeed.proto b/msgs/MotorSpeed.proto new file mode 100644 index 0000000..35009ac --- /dev/null +++ b/msgs/MotorSpeed.proto @@ -0,0 +1,7 @@ +syntax = "proto2"; +package mav_msgs.msgs; + +message MotorSpeed +{ + repeated float motor_speed = 1 [packed=true]; +} diff --git a/msgs/Wind.proto b/msgs/Wind.proto new file mode 100644 index 0000000..9cd1216 --- /dev/null +++ b/msgs/Wind.proto @@ -0,0 +1,10 @@ +syntax = "proto2"; +package physics_msgs.msgs; +import "vector3d.proto"; + +message Wind +{ + required string frame_id = 1; + required int64 time_usec = 2; + required gazebo.msgs.Vector3d velocity = 3; +} diff --git a/package.xml b/package.xml index 95128dc..5bc650f 100644 --- a/package.xml +++ b/package.xml @@ -24,6 +24,7 @@ gazebo boost libqt5-widgets + mav_msgs