2 #include <nav_msgs/Odometry.h> 3 #include <geometry_msgs/Twist.h> 14 wheel_speed_right_(0.0),
15 wheel_speed_left_(0.0)
35 ROS_FATAL(
"Gazebo_ROS_Create controller requires a Model as its parent");
43 if (_sdf->HasElement(
"robotNamespace"))
44 this->
node_namespace_ = _sdf->GetElement(
"robotNamespace")->Get<std::string>() +
"/";
48 if (_sdf->HasElement(
"cmd_vel_topic_name"))
49 cmd_vel_topic_name_ = _sdf->GetElement(
"cmd_vel_topic_name")->Get<std::string>();
52 if (_sdf->HasElement(
"odom_topic_name"))
53 odom_topic_name_ = _sdf->GetElement(
"odom_topic_name")->Get<std::string>();
56 if (_sdf->HasElement(
"joint_states_topic_name"))
57 joint_states_topic_name_ = _sdf->GetElement(
"joint_states_topic_name")->Get<std::string>();
82 std::vector<std::string> joint_names(6);
84 joint_names[LF] =
"left_front_wheel_joint";
85 joint_names[LM] =
"left_middle_wheel_joint";
86 joint_names[LR] =
"left_rear_wheel_joint";
87 joint_names[RF] =
"right_front_wheel_joint",
88 joint_names[RM] =
"right_middle_wheel_joint";
89 joint_names[RR] =
"right_rear_wheel_joint";
91 std::vector<physics::JointPtr> joints_tmp(6);
93 for(
size_t i=0; i<joint_names.size(); i++)
96 if(_sdf->HasElement(joint_names[i]))
98 joint_names[i] = _sdf->GetElement(joint_names[i])->Get<std::string>();
102 joints_tmp[i] =
my_parent_->GetJoint(joint_names[i]);
107 std::vector<int> missing_joints;
110 if(!joints_tmp[LF]) missing_joints.push_back(LF);
111 if(!joints_tmp[LR]) missing_joints.push_back(LR);
112 if(!joints_tmp[RF]) missing_joints.push_back(RF);
113 if(!joints_tmp[RR]) missing_joints.push_back(RR);
116 if( !joints_tmp[LM] != !joints_tmp[RM] )
118 missing_joints.push_back(LM);
119 missing_joints.push_back(RM);
122 if(!missing_joints.empty())
125 std::string missing_err =
"The controller couldn't get the joint(s): ";
126 for(
size_t i=0; i<missing_joints.size(); i++)
128 missing_err += joint_names[missing_joints[i]] + (i != missing_joints.size()-1 ?
", " :
"");
130 gzthrow(
"This plugin supports either a four or a six wheeled robot, due to that the middle wheels are optional. " 135 bool six_wheeled = joints_tmp[LM] && joints_tmp[RM];
138 int six_wheels[] = {LF, LM, LR, RF, RM, RR};
139 int four_wheels[] = {LF, LR, RF, RR};
140 int* wheels = six_wheeled ? six_wheels : four_wheels;
145 left = six_wheeled ? 1 : 0;
146 right = six_wheeled ? 4 : 2;
159 js_.name[i] = joint_names[wheels[i]];
160 joints_[i] = joints_tmp[wheels[i]];
164 if (_sdf->HasElement(
"wheel_separation"))
165 wheel_sep_ = _sdf->GetElement(
"wheel_separation")->Get<
double>();
168 if (_sdf->HasElement(
"turning_adaptation"))
169 turning_adaptation_ = _sdf->GetElement(
"turning_adaptation")->Get<
double>();
172 if (_sdf->HasElement(
"wheel_diameter"))
173 wheel_diam_ = _sdf->GetElement(
"wheel_diameter")->Get<
double>();
176 if (_sdf->HasElement(
"torque"))
177 torque_ = _sdf->GetElement(
"torque")->Get<
double>();
180 if (_sdf->HasElement(
"max_velocity"))
181 max_velocity_ = _sdf->GetElement(
"max_velocity")->Get<
double>();
184 #if GAZEBO_MAJOR_VERSION > 8 194 std::string modelName = _sdf->GetParent()->Get<std::string>(
"name");
200 gzdbg <<
"plugin model name: " << modelName <<
"\n";
207 #if GAZEBO_MAJOR_VERSION > 8 208 common::Time time_now = this->
my_world_->SimTime();
210 common::Time time_now = this->
my_world_->GetSimTime();
213 prev_update_time_ = time_now;
218 double turning_adaptation;
228 d1 = step_time.Double() * (wd / 2) *
joints_[
left]->GetVelocity(0);
229 d2 = step_time.Double() * (wd / 2) *
joints_[
right]->GetVelocity(0);
232 if (std::isnan(d1)) {
233 ROS_WARN_THROTTLE(0.1,
"gazebo_ros_diffdrive_uos: NaN in d1. Step time: %.2f. WD: %.2f. Velocity: %.2f", step_time.Double(), wd,
joints_[
left]->GetVelocity(0));
237 if (std::isnan(d2)) {
238 ROS_WARN_THROTTLE(0.1,
"gazebo_ros_diffdrive_uos: NaN in d2. Step time: %.2f. WD: %.2f. Velocity: %.2f", step_time.Double(), wd,
joints_[
right]->GetVelocity(0));
243 da = (d2 - d1) / ws * turning_adaptation;
255 #if GAZEBO_MAJOR_VERSION > 8 261 #if GAZEBO_MAJOR_VERSION > 8 275 #if GAZEBO_MAJOR_VERSION < 5 284 #if GAZEBO_MAJOR_VERSION < 5 289 nav_msgs::Odometry odom;
290 odom.header.stamp.sec = time_now.sec;
291 odom.header.stamp.nsec = time_now.nsec;
292 odom.header.frame_id =
"odom_combined";
293 odom.child_frame_id =
"base_footprint";
296 odom.pose.pose.position.z = 0;
301 odom.pose.pose.orientation.x = qt.getX();
302 odom.pose.pose.orientation.y = qt.getY();
303 odom.pose.pose.orientation.z = qt.getZ();
304 odom.pose.pose.orientation.w = qt.
getW();
306 double pose_cov[36] = { 1e-3, 0, 0, 0, 0, 0,
313 memcpy(&odom.pose.covariance[0], pose_cov,
sizeof(
double) * 36);
314 memcpy(&odom.twist.covariance[0], pose_cov,
sizeof(
double) * 36);
316 odom.twist.twist.linear.x =
odom_vel_[0];
317 odom.twist.twist.linear.y = 0;
318 odom.twist.twist.linear.z = 0;
320 odom.twist.twist.angular.x = 0;
321 odom.twist.twist.angular.y = 0;
322 odom.twist.twist.angular.z =
odom_vel_[2];
326 js_.header.stamp.sec = time_now.sec;
327 js_.header.stamp.nsec = time_now.nsec;
331 #if GAZEBO_MAJOR_VERSION > 8 334 js_.position[i] =
joints_[i]->GetAngle(0).Radian();
344 #if GAZEBO_MAJOR_VERSION > 8 std::string cmd_vel_topic_name_
std::string node_namespace_
sensor_msgs::JointState js_
virtual void Load(physics::ModelPtr _parent, sdf::ElementPtr _sdf)
#define ROS_WARN_THROTTLE(rate,...)
void publish(const boost::shared_ptr< M > &message) const
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
std::string joint_states_topic_name_
ROSCPP_DECL bool isInitialized()
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
physics::WorldPtr my_world_
float torque_
maximum torque applied to the wheels [Nm]
TFSIMD_FORCE_INLINE const tfScalar & getW() const
float wheel_speed_right_
Desired speeds of the wheels.
virtual void UpdateChild()
ros::Publisher joint_state_pub_
boost::thread * spinner_thread_
common::Time prev_update_time_
GZ_REGISTER_MODEL_PLUGIN(GazeboRosDiffdrive)
float wheel_sep_
Separation between the wheels.
event::ConnectionPtr updateConnection
physics::ModelPtr my_parent_
float turning_adaptation_
Turning adaptation for odometry.
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
static const double CMD_VEL_TIMEOUT
std::string odom_topic_name_
void setEuler(const tfScalar &yaw, const tfScalar &pitch, const tfScalar &roll)
float wheel_diam_
Diameter of the wheels.
ros::NodeHandle * rosnode_
common::Time last_cmd_vel_time_
#define ROS_INFO_STREAM(args)
virtual ~GazeboRosDiffdrive()
std::vector< physics::JointPtr > joints_
ros::Subscriber cmd_vel_sub_
ROSCPP_DECL void spinOnce()
void OnCmdVel(const geometry_msgs::TwistConstPtr &msg)
float max_velocity_
maximum linear speed of the robot [m/s]