48 if (!sdf->HasElement(
"robotNamespace"))
50 ROS_INFO_NAMED(
"planar_move",
"PlanarMovePlugin missing <robotNamespace>, " 56 sdf->GetElement(
"robotNamespace")->Get<std::string>();
60 if (!sdf->HasElement (
"enableYAxis"))
62 ROS_INFO_NAMED(
"planar_move",
"PlanarMovePlugin missing <enableYAxis>, " 63 "defaults to \"%d\"", enable_y_axis_);
67 enable_y_axis_ = sdf->GetElement(
"enableYAxis")->Get<
bool>();
71 if (!sdf->HasElement(
"commandTopic"))
73 ROS_WARN_NAMED(
"planar_move",
"PlanarMovePlugin (ns = %s) missing <commandTopic>, " 79 command_topic_ = sdf->GetElement(
"commandTopic")->Get<std::string>();
83 if (!sdf->HasElement(
"odometryTopic"))
85 ROS_WARN_NAMED(
"planar_move",
"PlanarMovePlugin (ns = %s) missing <odometryTopic>, " 91 odometry_topic_ = sdf->GetElement(
"odometryTopic")->Get<std::string>();
95 if (!sdf->HasElement(
"odometryFrame"))
97 ROS_WARN_NAMED(
"planar_move",
"PlanarMovePlugin (ns = %s) missing <odometryFrame>, " 103 odometry_frame_ = sdf->GetElement(
"odometryFrame")->Get<std::string>();
107 if (!sdf->HasElement(
"robotBaseFrame"))
109 ROS_WARN_NAMED(
"planar_move",
"PlanarMovePlugin (ns = %s) missing <robotBaseFrame>, " 110 "defaults to \"%s\"",
115 robot_base_frame_ = sdf->GetElement(
"robotBaseFrame")->Get<std::string>();
119 if (!sdf->HasElement(
"odometryRate"))
121 ROS_WARN_NAMED(
"planar_move",
"PlanarMovePlugin (ns = %s) missing <odometryRate>, " 127 odometry_rate_ = sdf->GetElement(
"odometryRate")->Get<
double>();
131 if (!sdf->HasElement (
"useForceFeedback"))
133 ROS_INFO_NAMED(
"planar_move",
"PlanarMovePlugin missing <useForceFeedback>, " 134 "defaults to \"%d\"", use_force_feedback_);
138 use_force_feedback_ = sdf->GetElement(
"useForceFeedback")->Get<
bool>();
141 if (use_force_feedback_) {
142 std::string applied_force_link =
"base_link";
143 if (!sdf->HasElement(
"appliedForceLink"))
145 ROS_WARN_NAMED(
"planar_move",
"PlanarMovePlugin (ns = %s) missing <appliedForceLink>, " 146 "defaults to \"%s\"",
151 applied_force_link = sdf->GetElement(
"appliedForceLink")->Get<std::string>();
153 physics::LinkPtr lnk =
parent_->GetLink(applied_force_link);
155 physics::Link_V ll =
parent_->GetLinks();
156 std::string
nm = ll[0]->GetName();
158 ROS_WARN_NAMED(
"planar_move",
"robot model does not have the link named '%s'" 159 ", use '%s' instead of it",
160 applied_force_link.c_str(), nm.c_str());
167 if (sdf->HasElement (
"forceGainX"))
169 gain_x_ = sdf->GetElement(
"forceGainX")->Get<
double>();
171 if (sdf->HasElement (
"forceGainY"))
173 gain_y_ = sdf->GetElement(
"forceGainY")->Get<
double>();
175 if (sdf->HasElement (
"forceGainRot"))
177 gain_rot_ = sdf->GetElement(
"forceGainRot")->Get<
double>();
181 if (sdf->HasElement (
"velocityDeadZone"))
183 v_dead_zone_ = sdf->GetElement(
"velocityDeadZone")->Get<
double>();
187 "use force feedback to %s with (gain_x, gain_y, gain_rot) = (%f, %f, %f)",
189 robot_link_->GetName().c_str(),
193 #if GAZEBO_MAJOR_VERSION >= 8 196 last_odom_publish_time_ =
parent_->GetWorld()->GetSimTime();
198 #if GAZEBO_MAJOR_VERSION >= 8 217 <<
"). A ROS node for Gazebo has not been initialized, " 218 <<
"unable to load plugin. Load the Gazebo system plugin " 219 <<
"'libgazebo_ros_api_plugin.so' in the gazebo_ros package)");
232 ros::SubscribeOptions::create<geometry_msgs::Twist>(
command_topic_, 1,
245 event::Events::ConnectWorldUpdateBegin(
253 boost::mutex::scoped_lock scoped_lock(
lock);
255 #if GAZEBO_MAJOR_VERSION >= 8 256 ignition::math::Pose3d
pose =
parent_->WorldPose();
258 ignition::math::Pose3d pose =
parent_->GetWorldPose().Ign();
263 #if GAZEBO_MAJOR_VERSION >= 8 264 ignition::math::Vector3d rlin =
robot_link_->RelativeLinearVel();
265 ignition::math::Vector3d rang =
robot_link_->RelativeAngularVel();
267 ignition::math::Vector3d rlin =
robot_link_->GetRelativeLinearVel().Ign();
268 ignition::math::Vector3d rang =
robot_link_->GetRelativeAngularVel().Ign();
271 double f_x, f_y, t_rot;
287 ignition::math::Vector3d wfv(f_x, f_y, 0);
288 ignition::math::Vector3d lfv = pose.Rot().RotateVectorReverse(wfv);
296 f_x += (x_ - rlin.X()) *
gain_x_ * 0.3;
297 f_y += (y_ - rlin.Y()) *
gain_y_ * 0.3;
298 t_rot += (rot_ - rang.Z()) *
gain_rot_ * 0.3;
304 f_x = (x_ - rlin.X()) *
gain_x_;
305 f_y = (y_ - rlin.Y()) *
gain_y_;
308 ignition::math::Vector3d rfc(f_x, f_y, 0);
309 ignition::math::Vector3d rtq(0, 0, t_rot);
316 float yaw = pose.Rot().Yaw();
317 parent_->SetLinearVel(ignition::math::Vector3d(
318 x_ * cosf(yaw) -
y_ * sinf(yaw),
319 y_ * cosf(yaw) +
x_ * sinf(yaw),
321 parent_->SetAngularVel(ignition::math::Vector3d(0, 0,
rot_));
325 #if GAZEBO_MAJOR_VERSION >= 8 326 common::Time current_time =
parent_->GetWorld()->SimTime();
328 common::Time current_time =
parent_->GetWorld()->GetSimTime();
330 double seconds_since_last_update =
349 const geometry_msgs::Twist::ConstPtr& cmd_msg)
351 boost::mutex::scoped_lock scoped_lock(
lock);
352 x_ = cmd_msg->linear.x;
355 y_ = cmd_msg->linear.y;
357 rot_ = cmd_msg->angular.z;
362 static const double timeout = 0.01;
374 std::string base_footprint_frame =
378 #if GAZEBO_MAJOR_VERSION >= 8 379 ignition::math::Pose3d
pose = this->
parent_->WorldPose();
381 ignition::math::Pose3d pose = this->
parent_->GetWorldPose().Ign();
384 tf::Quaternion qt(pose.Rot().X(), pose.Rot().Y(), pose.Rot().Z(), pose.Rot().W());
385 tf::Vector3 vt(pose.Pos().X(), pose.Pos().Y(), pose.Pos().Z());
390 base_footprint_frame));
393 odom_.pose.pose.position.x = pose.Pos().X();
394 odom_.pose.pose.position.y = pose.Pos().Y();
396 odom_.pose.pose.orientation.x = pose.Rot().X();
397 odom_.pose.pose.orientation.y = pose.Rot().Y();
398 odom_.pose.pose.orientation.z = pose.Rot().Z();
399 odom_.pose.pose.orientation.w = pose.Rot().W();
400 odom_.pose.covariance[0] = 0.00001;
401 odom_.pose.covariance[7] = 0.00001;
402 odom_.pose.covariance[14] = 1000000000000.0;
403 odom_.pose.covariance[21] = 1000000000000.0;
404 odom_.pose.covariance[28] = 1000000000000.0;
405 odom_.pose.covariance[35] = 0.001;
408 ignition::math::Vector3d linear;
419 float current_yaw = pose.Rot().Yaw();
420 while (current_yaw < last_yaw -
M_PI) current_yaw += 2 *
M_PI;
421 while (current_yaw > last_yaw +
M_PI) current_yaw -= 2 *
M_PI;
422 float angular_diff = current_yaw - last_yaw;
423 odom_.twist.twist.angular.z = angular_diff / step_time;
428 float yaw = pose.Rot().Yaw();
429 odom_.twist.twist.linear.x = cosf(yaw) * linear.X() + sinf(yaw) * linear.Y();
430 odom_.twist.twist.linear.y = cosf(yaw) * linear.Y() - sinf(yaw) * linear.X();
432 odom_.header.stamp = current_time;
433 odom_.header.frame_id = odom_frame;
434 odom_.child_frame_id = base_footprint_frame;
void cmdVelCallback(const geometry_msgs::Twist::ConstPtr &cmd_msg)
boost::shared_ptr< ros::NodeHandle > rosnode_
#define ROS_INFO_NAMED(name,...)
event::ConnectionPtr update_connection_
void publish(const boost::shared_ptr< M > &message) const
std::string getPrefixParam(ros::NodeHandle &nh)
#define ROS_WARN_NAMED(name,...)
void Load(physics::ModelPtr parent, sdf::ElementPtr sdf)
boost::shared_ptr< tf::TransformBroadcaster > transform_broadcaster_
std::string command_topic_
ROSCPP_DECL bool isInitialized()
ros::CallbackQueue queue_
virtual void UpdateChild()
GazeboRosPlanarForceMove()
ignition::math::Pose3d last_odom_pose_
std::string resolve(const std::string &prefix, const std::string &frame_name)
#define ROS_DEBUG_NAMED(name,...)
physics::LinkPtr robot_link_
#define ROS_FATAL_STREAM_NAMED(name, args)
std::string robot_base_frame_
ros::Publisher odometry_pub_
std::string odometry_frame_
void publishOdometry(double step_time)
boost::thread callback_queue_thread_
std::string robot_namespace_
common::Time last_odom_publish_time_
~GazeboRosPlanarForceMove()
GZ_REGISTER_MODEL_PLUGIN(GazeboRosP3D)
boost::shared_ptr< void > VoidPtr
bool enable_y_axis_
Enable Y-axis movement.
physics::ModelPtr parent_
std::string odometry_topic_