Gazebo | Ignition | Community
Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

How to modify a model plugin to publish data to a rostopic or ros node?

I am trying to work with gazebo_motor_model.cpp. I need to visual some data that is calculated inside the plugin such a force, drag_torque etc. Is there a way i can publish this data to a topic or node so that i can visualize it using rqt.

P.S. - I am working on ROS kinetic with gazebo 7

How to modify a model plugin to publish data to a rostopic or ros node?

I am trying to work with gazebo_motor_model.cpp. I need to visual some data that is calculated inside the plugin such a force, drag_torque etc. Is there a way i can publish this data to a topic or node so that i can visualize it using rqt.

P.S. - I am working on ROS kinetic with gazebo 7

#include "gazebo_motor_model.h"

#include "ignition/math.hh"

namespace gazebo {

GazeboMotorModel::~GazeboMotorModel() { updateConnection_->~Connection(); use_pid_ = false; }

void GazeboMotorModel::InitializeParams() {}

void GazeboMotorModel::Publish() { turning_velocity_msg_.set_data(joint_->GetVelocity(0)); motor_velocity_pub_->Publish(turning_velocity_msg_); }

void GazeboMotorModel::Load(physics::ModelPtr _model, sdf::ElementPtr _sdf) { model_ = _model;

namespace_.clear();

if (_sdf->HasElement("robotNamespace")) namespace_ = _sdf->GetElement("robotNamespace")->Get<std::string>(); else gzerr << "[gazebo_motor_model] Please specify a robotNamespace.\n"; node_handle_ = transport::NodePtr(new transport::Node()); node_handle_->Init(namespace_);

if (_sdf->HasElement("jointName")) joint_name_ = _sdf->GetElement("jointName")->Get<std::string>(); else gzerr << "[gazebo_motor_model] Please specify a jointName, where the rotor is attached.\n"; // Get the pointer to the joint. joint_ = model_->GetJoint(joint_name_); if (joint_ == NULL) gzthrow("[gazebo_motor_model] Couldn't find specified joint \"" << joint_name_ << "\".");

// setup joint control pid to control joint if (_sdf->HasElement("joint_control_pid")) { sdf::ElementPtr pid = _sdf->GetElement("joint_control_pid"); double p = 0.1; if (pid->HasElement("p")) p = pid->Get<double>("p"); double i = 0; if (pid->HasElement("i")) i = pid->Get<double>("i"); double d = 0; if (pid->HasElement("d")) d = pid->Get<double>("d"); double iMax = 0; if (pid->HasElement("iMax")) iMax = pid->Get<double>("iMax"); double iMin = 0; if (pid->HasElement("iMin")) iMin = pid->Get<double>("iMin"); double cmdMax = 3; if (pid->HasElement("cmdMax")) cmdMax = pid->Get<double>("cmdMax"); double cmdMin = -3; if (pid->HasElement("cmdMin")) cmdMin = pid->Get<double>("cmdMin"); pid_.Init(p, i, d, iMax, iMin, cmdMax, cmdMin); use_pid_ = true; } else { use_pid_ = false; }

if (_sdf->HasElement("linkName")) link_name_ = _sdf->GetElement("linkName")->Get<std::string>(); else gzerr << "[gazebo_motor_model] Please specify a linkName of the rotor.\n"; link_ = model_->GetLink(link_name_); if (link_ == NULL) gzthrow("[gazebo_motor_model] Couldn't find specified link \"" << link_name_ << "\".");

if (_sdf->HasElement("motorNumber")) motor_number_ = _sdf->GetElement("motorNumber")->Get<int>(); else gzerr << "[gazebo_motor_model] Please specify a motorNumber.\n";

if (_sdf->HasElement("turningDirection")) { std::string turning_direction = _sdf->GetElement("turningDirection")->Get<std::string>(); if (turning_direction == "cw") turning_direction_ = turning_direction::CW; else if (turning_direction == "ccw") turning_direction_ = turning_direction::CCW; else gzerr << "[gazebo_motor_model] Please only use 'cw' or 'ccw' as turningDirection.\n"; } else gzerr << "[gazebo_motor_model] Please specify a turning direction ('cw' or 'ccw').\n";

getSdfParam<std::string>(_sdf, "commandSubTopic", command_sub_topic_, command_sub_topic_); getSdfParam<std::string>(_sdf, "motorSpeedPubTopic", motor_speed_pub_topic_, motor_speed_pub_topic_);

getSdfParam<double>(_sdf, "rotorDragCoefficient", rotor_drag_coefficient_, rotor_drag_coefficient_); getSdfParam<double>(_sdf, "rollingMomentCoefficient", rolling_moment_coefficient_, rolling_moment_coefficient_); getSdfParam<double>(_sdf, "maxRotVelocity", max_rot_velocity_, max_rot_velocity_); getSdfParam<double>(_sdf, "motorConstant", motor_constant_, motor_constant_); getSdfParam<double>(_sdf, "momentConstant", moment_constant_, moment_constant_);

getSdfParam<double>(_sdf, "timeConstantUp", time_constant_up_, time_constant_up_); getSdfParam<double>(_sdf, "timeConstantDown", time_constant_down_, time_constant_down_); getSdfParam<double>(_sdf, "rotorVelocitySlowdownSim", rotor_velocity_slowdown_sim_, 10);

/* std::cout << "Subscribing to: " << motor_test_sub_topic_ << std::endl; motor_sub_ = node_handle_->Subscribe<mav_msgs::msgs::motorspeed>("~/" + model_->GetName() + motor_test_sub_topic_, &GazeboMotorModel::testProto, this); */

// Set the maximumForce on the joint. This is deprecated from V5 on, and the joint won't move.

if GAZEBO_MAJOR_VERSION < 5

joint_->SetMaxForce(0, max_force_);

endif

// Listen to the update event. This event is broadcast every // simulation iteration. if (!ros::isInitialized()) { int argc = 0; char **argv = NULL;

    ros::init(argc, argv, "force",
        ros::init_options::NoSigintHandler);
}

// Create ROS node.
this->rosNode.reset(new ros::NodeHandle( "force" ));
this->rosPub = this->rosNode->advertise<std_msgs::Float64>("force_pub",1);

updateConnection_ = event::Events::ConnectWorldUpdateBegin(boost::bind(&GazeboMotorModel::OnUpdate, this, _1));

std_msgs::Float64 force_pub; force_pub.data = 15.3; this->rosPub.publish(force_pub);

command_sub_ = node_handle_->Subscribe<mav_msgs::msgs::commandmotorspeed>("~/" + model_->GetName() + command_sub_topic_, &GazeboMotorModel::VelocityCallback, this); //std::cout << "[gazebo_motor_model]: Subscribe to gz topic: "<< motor_failure_sub_topic_ << std::endl; motor_failure_sub_ = node_handle_->Subscribe<msgs::int>(motor_failure_sub_topic_, &GazeboMotorModel::MotorFailureCallback, this); motor_velocity_pub_ = node_handle_->Advertise<std_msgs::msgs::float>("~/" + model_->GetName() + motor_speed_pub_topic_, 1);

// Create the first order filter. rotor_velocity_filter_.reset(new FirstOrderFilter<double>(time_constant_up_, time_constant_down_, ref_motor_rot_vel_)); }

// Protobuf test /* void GazeboMotorModel::testProto(MotorSpeedPtr &msg) { std::cout << "Received message" << std::endl; std::cout << msg->motor_speed_size()<< std::endl; for(int i; i < msg->motor_speed_size(); i++){ std::cout << msg->motor_speed(i) <<" "; } std::cout << std::endl; } */

// This gets called by the world update start event. void GazeboMotorModel::OnUpdate(const common::UpdateInfo& _info) { sampling_time_ = _info.simTime.Double() - prev_sim_time_; prev_sim_time_ = _info.simTime.Double(); UpdateForcesAndMoments(); UpdateMotorFail(); Publish(); std_msgs::Float64 msg; msg.data = 15.3; this->rosPub.publish(msg);

}

void GazeboMotorModel::VelocityCallback(CommandMotorSpeedPtr &rot_velocities) { if(rot_velocities->motor_speed_size() < motor_number_) { std::cout << "You tried to access index " << motor_number_ << " of the MotorSpeed message array which is of size " << rot_velocities->motor_speed_size() << "." << std::endl; } else ref_motor_rot_vel_ = std::min(static_cast<double>(rot_velocities->motor_speed(motor_number_)), static_cast<double>(max_rot_velocity_)); }

void GazeboMotorModel::MotorFailureCallback(const boost::shared_ptr<const msgs::int=""> &fail_msg) { motor_Failure_Number_ = fail_msg->data(); }

void GazeboMotorModel::UpdateForcesAndMoments() { motor_rot_vel_ = joint_->GetVelocity(0); if (motor_rot_vel_ / (2 * M_PI) > 1 / (2 * sampling_time_)) { gzerr << "Aliasing on motor [" << motor_number_ << "] might occur. Consider making smaller simulation time steps or raising the rotor_velocity_slowdown_sim_ param.\n"; } double real_motor_velocity = motor_rot_vel_ * rotor_velocity_slowdown_sim_; double force = real_motor_velocity * real_motor_velocity * motor_constant_; std::cout << "motor_rot_vel_"<< motor_rot_vel_ << " " << "force" << force << " " << "real_motor_velocity" << real_motor_velocity << std::endl;

// scale down force linearly with forward speed // XXX this has to be modelled better //

if GAZEBO_MAJOR_VERSION >= 9

ignition::math::Vector3d body_velocity = link_->WorldLinearVel();

else

ignition::math::Vector3d body_velocity = ignitionFromGazeboMath(link_->GetWorldLinearVel());

endif

double vel = body_velocity.Length(); double scalar = 1 - vel / 25.0; // at 50 m/s the rotor will not produce any force anymore scalar = ignition::math::clamp(scalar, 0.0, 1.0); // Apply a force to the link. link_->AddRelativeForce(ignition::math::Vector3d(0, 0, force * scalar));

// Forces from Philppe Martin's and Erwan Salaün's // 2010 IEEE Conference on Robotics and Automation paper // The True Role of Accelerometer Feedback in Quadrotor Control // - \omega * \lambda_1 * V_A^{\perp}

if GAZEBO_MAJOR_VERSION >= 9

ignition::math::Vector3d joint_axis = joint_->GlobalAxis(0);

else

ignition::math::Vector3d joint_axis = ignitionFromGazeboMath(joint_->GetGlobalAxis(0));

endif

//ignition::math::Vector3d body_velocity = link_->WorldLinearVel(); ignition::math::Vector3d body_velocity_perpendicular = body_velocity - (body_velocity * joint_axis) * joint_axis; ignition::math::Vector3d air_drag = -std::abs(real_motor_velocity) * rotor_drag_coefficient_ * body_velocity_perpendicular; // Apply air_drag to link. link_->AddForce(air_drag); // Moments // Getting the parent link, such that the resulting torques can be applied to it. physics::Link_V parent_links = link_->GetParentJointsLinks(); // The tansformation from the parent_link to the link_.

if GAZEBO_MAJOR_VERSION >= 9

ignition::math::Pose3d pose_difference = link_->WorldCoGPose() - parent_links.at(0)->WorldCoGPose();

else

ignition::math::Pose3d pose_difference = ignitionFromGazeboMath(link_->GetWorldCoGPose() - parent_links.at(0)->GetWorldCoGPose());

endif

ignition::math::Vector3d drag_torque(0, 0, -turning_direction_ * force * moment_constant_); // Transforming the drag torque into the parent frame to handle arbitrary rotor orientations. ignition::math::Vector3d drag_torque_parent_frame = pose_difference.Rot().RotateVector(drag_torque); parent_links.at(0)->AddRelativeTorque(drag_torque_parent_frame);

ignition::math::Vector3d rolling_moment; // - \omega * \mu_1 * V_A^{\perp} rolling_moment = -std::abs(real_motor_velocity) * rolling_moment_coefficient_ * body_velocity_perpendicular; parent_links.at(0)->AddTorque(rolling_moment); // Apply the filter on the motor's velocity. double ref_motor_rot_vel; ref_motor_rot_vel = rotor_velocity_filter_->updateFilter(ref_motor_rot_vel_, sampling_time_);

if 0 //FIXME: disable PID for now, it does not play nice with the PX4 CI system.

if (use_pid_) { double err = joint_->GetVelocity(0) - turning_direction_ * ref_motor_rot_vel / rotor_velocity_slowdown_sim_; double rotorForce = pid_.Update(err, sampling_time_); joint_->SetForce(0, rotorForce); // gzerr << "rotor " << joint_->GetName() << " : " << rotorForce << "\n"; } else {

if GAZEBO_MAJOR_VERSION >= 7

// Not desirable to use SetVelocity for parts of a moving model
// impact on rest of the dynamic system is non-physical.
joint_->SetVelocity(0, turning_direction_ * ref_motor_rot_vel / rotor_velocity_slowdown_sim_);

elif GAZEBO_MAJOR_VERSION >= 6

// Not ideal as the approach could result in unrealistic impulses, and
// is only available in ODE
joint_->SetParam("fmax", 0, 2.0);
joint_->SetParam("vel", 0, turning_direction_ * ref_motor_rot_vel / rotor_velocity_slowdown_sim_);

endif

}

else

joint_->SetVelocity(0, turning_direction_ * ref_motor_rot_vel / rotor_velocity_slowdown_sim_);

endif /* if 0 */

}

void GazeboMotorModel::UpdateMotorFail() { if (motor_number_ == motor_Failure_Number_ - 1){ // motor_constant_ = 0.0; joint_->SetVelocity(0,0); if (screen_msg_flag){ std::cout << "Motor number [" << motor_Failure_Number_ <<"] failed! [Motor thrust = 0]" << std::endl; tmp_motor_num = motor_Failure_Number_;

  screen_msg_flag = 0;
}

}else if (motor_Failure_Number_ == 0 && motor_number_ == tmp_motor_num - 1){ if (!screen_msg_flag){ //motor_constant_ = kDefaultMotorConstant; std::cout << "Motor number [" << tmp_motor_num <<"] running! [Motor thrust = (default)]" << std::endl; screen_msg_flag = 1; } } }

GZ_REGISTER_MODEL_PLUGIN(GazeboMotorModel); }

How to modify a model plugin to publish data to a rostopic or ros node?

I am trying to work with gazebo_motor_model.cpp. I need to visual some data that is calculated inside the plugin such a force, drag_torque etc. Is there a way i can publish this data to a topic or node so that i can visualize it using rqt.

P.S. - I am working on ROS kinetic with gazebo 7

#include "gazebo_motor_model.h"

#include "ignition/math.hh"

namespace gazebo {

GazeboMotorModel::~GazeboMotorModel() { updateConnection_->~Connection(); use_pid_ = false; }

void GazeboMotorModel::InitializeParams() {}

void GazeboMotorModel::Publish() { turning_velocity_msg_.set_data(joint_->GetVelocity(0)); motor_velocity_pub_->Publish(turning_velocity_msg_); }

void GazeboMotorModel::Load(physics::ModelPtr _model, sdf::ElementPtr _sdf) { model_ = _model;

namespace_.clear();

if (_sdf->HasElement("robotNamespace")) namespace_ = _sdf->GetElement("robotNamespace")->Get<std::string>(); else gzerr << "[gazebo_motor_model] Please specify a robotNamespace.\n"; node_handle_ = transport::NodePtr(new transport::Node()); node_handle_->Init(namespace_);

if (_sdf->HasElement("jointName")) joint_name_ = _sdf->GetElement("jointName")->Get<std::string>(); else gzerr << "[gazebo_motor_model] Please specify a jointName, where the rotor is attached.\n"; // Get the pointer to the joint. joint_ = model_->GetJoint(joint_name_); if (joint_ == NULL) gzthrow("[gazebo_motor_model] Couldn't find specified joint \"" << joint_name_ << "\".");

// setup joint control pid to control joint if (_sdf->HasElement("joint_control_pid")) { sdf::ElementPtr pid = _sdf->GetElement("joint_control_pid"); double p = 0.1; if (pid->HasElement("p")) p = pid->Get<double>("p"); double i = 0; if (pid->HasElement("i")) i = pid->Get<double>("i"); double d = 0; if (pid->HasElement("d")) d = pid->Get<double>("d"); double iMax = 0; if (pid->HasElement("iMax")) iMax = pid->Get<double>("iMax"); double iMin = 0; if (pid->HasElement("iMin")) iMin = pid->Get<double>("iMin"); double cmdMax = 3; if (pid->HasElement("cmdMax")) cmdMax = pid->Get<double>("cmdMax"); double cmdMin = -3; if (pid->HasElement("cmdMin")) cmdMin = pid->Get<double>("cmdMin"); pid_.Init(p, i, d, iMax, iMin, cmdMax, cmdMin); use_pid_ = true; } else { use_pid_ = false; }

if (_sdf->HasElement("linkName")) link_name_ = _sdf->GetElement("linkName")->Get<std::string>(); else gzerr << "[gazebo_motor_model] Please specify a linkName of the rotor.\n"; link_ = model_->GetLink(link_name_); if (link_ == NULL) gzthrow("[gazebo_motor_model] Couldn't find specified link \"" << link_name_ << "\".");

if (_sdf->HasElement("motorNumber")) motor_number_ = _sdf->GetElement("motorNumber")->Get<int>(); else gzerr << "[gazebo_motor_model] Please specify a motorNumber.\n";

if (_sdf->HasElement("turningDirection")) { std::string turning_direction = _sdf->GetElement("turningDirection")->Get<std::string>(); if (turning_direction == "cw") turning_direction_ = turning_direction::CW; else if (turning_direction == "ccw") turning_direction_ = turning_direction::CCW; else gzerr << "[gazebo_motor_model] Please only use 'cw' or 'ccw' as turningDirection.\n"; } else gzerr << "[gazebo_motor_model] Please specify a turning direction ('cw' or 'ccw').\n";

getSdfParam<std::string>(_sdf, "commandSubTopic", command_sub_topic_, command_sub_topic_); getSdfParam<std::string>(_sdf, "motorSpeedPubTopic", motor_speed_pub_topic_, motor_speed_pub_topic_);

getSdfParam<double>(_sdf, "rotorDragCoefficient", rotor_drag_coefficient_, rotor_drag_coefficient_); getSdfParam<double>(_sdf, "rollingMomentCoefficient", rolling_moment_coefficient_, rolling_moment_coefficient_); getSdfParam<double>(_sdf, "maxRotVelocity", max_rot_velocity_, max_rot_velocity_); getSdfParam<double>(_sdf, "motorConstant", motor_constant_, motor_constant_); getSdfParam<double>(_sdf, "momentConstant", moment_constant_, moment_constant_);

getSdfParam<double>(_sdf, "timeConstantUp", time_constant_up_, time_constant_up_); getSdfParam<double>(_sdf, "timeConstantDown", time_constant_down_, time_constant_down_); getSdfParam<double>(_sdf, "rotorVelocitySlowdownSim", rotor_velocity_slowdown_sim_, 10);

/* std::cout << "Subscribing to: " << motor_test_sub_topic_ << std::endl; motor_sub_ = node_handle_->Subscribe<mav_msgs::msgs::motorspeed>("~/" + model_->GetName() + motor_test_sub_topic_, &GazeboMotorModel::testProto, this); */

// Set the maximumForce on the joint. This is deprecated from V5 on, and the joint won't move.

if GAZEBO_MAJOR_VERSION < 5

joint_->SetMaxForce(0, max_force_);

endif

// Listen to the update event. This event is broadcast every // simulation iteration. if (!ros::isInitialized()) { int argc = 0; char **argv = NULL;

    ros::init(argc, argv, "force",
        ros::init_options::NoSigintHandler);
}

// Create ROS node.
this->rosNode.reset(new ros::NodeHandle( "force" ));
this->rosPub = this->rosNode->advertise<std_msgs::Float64>("force_pub",1);

updateConnection_ = event::Events::ConnectWorldUpdateBegin(boost::bind(&GazeboMotorModel::OnUpdate, this, _1));

std_msgs::Float64 force_pub; force_pub.data = 15.3; this->rosPub.publish(force_pub);

command_sub_ = node_handle_->Subscribe<mav_msgs::msgs::commandmotorspeed>("~/" + model_->GetName() + command_sub_topic_, &GazeboMotorModel::VelocityCallback, this); //std::cout << "[gazebo_motor_model]: Subscribe to gz topic: "<< motor_failure_sub_topic_ << std::endl; motor_failure_sub_ = node_handle_->Subscribe<msgs::int>(motor_failure_sub_topic_, &GazeboMotorModel::MotorFailureCallback, this); motor_velocity_pub_ = node_handle_->Advertise<std_msgs::msgs::float>("~/" + model_->GetName() + motor_speed_pub_topic_, 1);

// Create the first order filter. rotor_velocity_filter_.reset(new FirstOrderFilter<double>(time_constant_up_, time_constant_down_, ref_motor_rot_vel_)); }

// Protobuf test /* void GazeboMotorModel::testProto(MotorSpeedPtr &msg) { std::cout << "Received message" << std::endl; std::cout << msg->motor_speed_size()<< std::endl; for(int i; i < msg->motor_speed_size(); i++){ std::cout << msg->motor_speed(i) <<" "; } std::cout << std::endl; } */

// This gets called by the world update start event. void GazeboMotorModel::OnUpdate(const common::UpdateInfo& _info) { sampling_time_ = _info.simTime.Double() - prev_sim_time_; prev_sim_time_ = _info.simTime.Double(); UpdateForcesAndMoments(); UpdateMotorFail(); Publish(); std_msgs::Float64 msg; msg.data = 15.3; this->rosPub.publish(msg);

}

void GazeboMotorModel::VelocityCallback(CommandMotorSpeedPtr &rot_velocities) { if(rot_velocities->motor_speed_size() < motor_number_) { std::cout << "You tried to access index " << motor_number_ << " of the MotorSpeed message array which is of size " << rot_velocities->motor_speed_size() << "." << std::endl; } else ref_motor_rot_vel_ = std::min(static_cast<double>(rot_velocities->motor_speed(motor_number_)), static_cast<double>(max_rot_velocity_)); }

void GazeboMotorModel::MotorFailureCallback(const boost::shared_ptr<const msgs::int=""> &fail_msg) { motor_Failure_Number_ = fail_msg->data(); }

void GazeboMotorModel::UpdateForcesAndMoments() { motor_rot_vel_ = joint_->GetVelocity(0); if (motor_rot_vel_ / (2 * M_PI) > 1 / (2 * sampling_time_)) { gzerr << "Aliasing on motor [" << motor_number_ << "] might occur. Consider making smaller simulation time steps or raising the rotor_velocity_slowdown_sim_ param.\n"; } double real_motor_velocity = motor_rot_vel_ * rotor_velocity_slowdown_sim_; double force = real_motor_velocity * real_motor_velocity * motor_constant_; std::cout << "motor_rot_vel_"<< motor_rot_vel_ << " " << "force" << force << " " << "real_motor_velocity" << real_motor_velocity << std::endl;

// scale down force linearly with forward speed // XXX this has to be modelled better //

if GAZEBO_MAJOR_VERSION >= 9

ignition::math::Vector3d body_velocity = link_->WorldLinearVel();

else

ignition::math::Vector3d body_velocity = ignitionFromGazeboMath(link_->GetWorldLinearVel());

endif

double vel = body_velocity.Length(); double scalar = 1 - vel / 25.0; // at 50 m/s the rotor will not produce any force anymore scalar = ignition::math::clamp(scalar, 0.0, 1.0); // Apply a force to the link. link_->AddRelativeForce(ignition::math::Vector3d(0, 0, force * scalar));

// Forces from Philppe Martin's and Erwan Salaün's // 2010 IEEE Conference on Robotics and Automation paper // The True Role of Accelerometer Feedback in Quadrotor Control // - \omega * \lambda_1 * V_A^{\perp}

if GAZEBO_MAJOR_VERSION >= 9

ignition::math::Vector3d joint_axis = joint_->GlobalAxis(0);

else

ignition::math::Vector3d joint_axis = ignitionFromGazeboMath(joint_->GetGlobalAxis(0));

endif

//ignition::math::Vector3d body_velocity = link_->WorldLinearVel(); ignition::math::Vector3d body_velocity_perpendicular = body_velocity - (body_velocity * joint_axis) * joint_axis; ignition::math::Vector3d air_drag = -std::abs(real_motor_velocity) * rotor_drag_coefficient_ * body_velocity_perpendicular; // Apply air_drag to link. link_->AddForce(air_drag); // Moments // Getting the parent link, such that the resulting torques can be applied to it. physics::Link_V parent_links = link_->GetParentJointsLinks(); // The tansformation from the parent_link to the link_.

if GAZEBO_MAJOR_VERSION >= 9

ignition::math::Pose3d pose_difference = link_->WorldCoGPose() - parent_links.at(0)->WorldCoGPose();

else

ignition::math::Pose3d pose_difference = ignitionFromGazeboMath(link_->GetWorldCoGPose() - parent_links.at(0)->GetWorldCoGPose());

endif

ignition::math::Vector3d drag_torque(0, 0, -turning_direction_ * force * moment_constant_); // Transforming the drag torque into the parent frame to handle arbitrary rotor orientations. ignition::math::Vector3d drag_torque_parent_frame = pose_difference.Rot().RotateVector(drag_torque); parent_links.at(0)->AddRelativeTorque(drag_torque_parent_frame);

ignition::math::Vector3d rolling_moment; // - \omega * \mu_1 * V_A^{\perp} rolling_moment = -std::abs(real_motor_velocity) * rolling_moment_coefficient_ * body_velocity_perpendicular; parent_links.at(0)->AddTorque(rolling_moment); // Apply the filter on the motor's velocity. double ref_motor_rot_vel; ref_motor_rot_vel = rotor_velocity_filter_->updateFilter(ref_motor_rot_vel_, sampling_time_);

if 0 //FIXME: disable PID for now, it does not play nice with the PX4 CI system.

if (use_pid_) { double err = joint_->GetVelocity(0) - turning_direction_ * ref_motor_rot_vel / rotor_velocity_slowdown_sim_; double rotorForce = pid_.Update(err, sampling_time_); joint_->SetForce(0, rotorForce); // gzerr << "rotor " << joint_->GetName() << " : " << rotorForce << "\n"; } else {

if GAZEBO_MAJOR_VERSION >= 7

// Not desirable to use SetVelocity for parts of a moving model
// impact on rest of the dynamic system is non-physical.
joint_->SetVelocity(0, turning_direction_ * ref_motor_rot_vel / rotor_velocity_slowdown_sim_);

elif GAZEBO_MAJOR_VERSION >= 6

// Not ideal as the approach could result in unrealistic impulses, and
// is only available in ODE
joint_->SetParam("fmax", 0, 2.0);
joint_->SetParam("vel", 0, turning_direction_ * ref_motor_rot_vel / rotor_velocity_slowdown_sim_);

endif

}

else

joint_->SetVelocity(0, turning_direction_ * ref_motor_rot_vel / rotor_velocity_slowdown_sim_);

endif /* if 0 */

}

void GazeboMotorModel::UpdateMotorFail() { if (motor_number_ == motor_Failure_Number_ - 1){ // motor_constant_ = 0.0; joint_->SetVelocity(0,0); if (screen_msg_flag){ std::cout << "Motor number [" << motor_Failure_Number_ <<"] failed! [Motor thrust = 0]" << std::endl; tmp_motor_num = motor_Failure_Number_;

  screen_msg_flag = 0;
}

}else if (motor_Failure_Number_ == 0 && motor_number_ == tmp_motor_num - 1){ if (!screen_msg_flag){ //motor_constant_ = kDefaultMotorConstant; std::cout << "Motor number [" << tmp_motor_num <<"] running! [Motor thrust = (default)]" << std::endl; screen_msg_flag = 1; } } }

GZ_REGISTER_MODEL_PLUGIN(GazeboMotorModel); }C:\fakepath\gazebo_motor_model.cpp

How to modify a model plugin to publish data to a rostopic or ros node?

I am trying to work with gazebo_motor_model.cpp. I need to visual some data that is calculated inside the plugin such a force, drag_torque etc. Is there a way i can publish this data to a topic or node so that i can visualize it using rqt.

P.S. - I am working on ROS kinetic with gazebo 7

Adding the .cpp file for reference. C:\fakepath\gazebo_motor_model.cpp