Go to the documentation of this file.00001
00026 #include <gazebo/common/Events.hh>
00027 #include <gazebo/common/Plugin.hh>
00028 #include <gazebo/physics/ode/ODESurfaceParams.hh>
00029 #include <gazebo/physics/physics.hh>
00030 #include <ros/console.h>
00031
00032 #include <string>
00033
00034
00035 namespace gazebo
00036 {
00037
00038 class MecanumPlugin : public ModelPlugin
00039 {
00040 public:
00041 void Load(physics::ModelPtr _parent, sdf::ElementPtr _sdf);
00042
00043 protected:
00044 virtual void GazeboUpdate();
00045
00046 private:
00047 event::ConnectionPtr update_connection_;
00048 physics::ModelPtr model_;
00049 physics::LinkPtr wheel_link_;
00050 physics::LinkPtr fixed_link_;
00051 double roller_angle_;
00052 double roller_friction_;
00053 double roller_skid_friction_;
00054 };
00055
00056
00057 GZ_REGISTER_MODEL_PLUGIN(MecanumPlugin);
00058
00059 void MecanumPlugin::Load(physics::ModelPtr _parent, sdf::ElementPtr _sdf)
00060 {
00061
00062 model_ = _parent;
00063
00064 std::string link_name;
00065
00066 if (_sdf->HasElement("wheelLinkName"))
00067 {
00068 link_name = _sdf->Get<std::string>("wheelLinkName");
00069 wheel_link_ = model_->GetLink(link_name);
00070 if (!wheel_link_)
00071 {
00072 ROS_FATAL_STREAM("Wheel link [" << link_name << "] not found!");
00073 return;
00074 }
00075 }
00076 else
00077 {
00078 ROS_FATAL("The mecanum plugin requires a `wheelLinkName` parameter.");
00079 return;
00080 }
00081
00082 if (_sdf->HasElement("fixedLinkName"))
00083 {
00084 link_name = _sdf->Get<std::string>("fixedLinkName");
00085 fixed_link_ = model_->GetLink(link_name);
00086 if (!fixed_link_)
00087 {
00088 ROS_FATAL_STREAM("Fixed link [" << link_name << "] not found!");
00089 return;
00090 }
00091 }
00092 else
00093 {
00094 ROS_FATAL("The mecanum plugin requires a `fixedLinkName` parameter.");
00095 return;
00096 }
00097
00098 if (_sdf->HasElement("rollerAngle"))
00099 {
00100 roller_angle_ = _sdf->Get<double>("rollerAngle");
00101 }
00102 else
00103 {
00104 roller_angle_ = M_PI / 4;
00105 }
00106
00107 if (_sdf->HasElement("rollerFriction"))
00108 {
00109 roller_friction_ = _sdf->Get<double>("rollerFriction");
00110 }
00111 else
00112 {
00113 roller_friction_ = 100;
00114 }
00115
00116 if (_sdf->HasElement("rollerSkidFriction"))
00117 {
00118 roller_skid_friction_ = _sdf->Get<double>("rollerSkidFriction");
00119 }
00120 else
00121 {
00122 roller_skid_friction_ = 100000;
00123 }
00124
00125 ROS_INFO_STREAM("Mecanum plugin initialized for " << wheel_link_->GetName() <<
00126 ", referenced to " << fixed_link_->GetName() << ", with a roller " <<
00127 "angle of " << roller_angle_ << " radians.");
00128
00129
00130 this->update_connection_ = event::Events::ConnectWorldUpdateBegin(
00131 boost::bind(&MecanumPlugin::GazeboUpdate, this));
00132 }
00133
00134 void MecanumPlugin::GazeboUpdate()
00135 {
00136 math::Pose wheel_pose = wheel_link_->GetWorldCoGPose();
00137 math::Pose fixed_pose = fixed_link_->GetWorldCoGPose();
00138 math::Quaternion wheel_orientation = wheel_pose.CoordRotationSub(fixed_pose.rot);
00139 double wheel_angle = wheel_orientation.GetPitch();
00140 ROS_DEBUG_STREAM(wheel_link_->GetName() << " angle is " << wheel_angle << " radians.");
00141
00142
00143 unsigned int collision_index = 0;
00144 physics::SurfaceParamsPtr surface = wheel_link_->GetCollision(collision_index)->GetSurface();
00145
00146
00147 physics::ODESurfaceParams* ode_surface = dynamic_cast<physics::ODESurfaceParams*>(surface.get());
00148 physics::FrictionPyramid& fric(ode_surface->frictionPyramid);
00149
00150
00151 fric.SetMuPrimary(roller_skid_friction_);
00152 fric.SetMuSecondary(roller_friction_);
00153
00154
00155
00156 fric.direction1.x = cos(roller_angle_) * cos(wheel_angle);
00157 fric.direction1.y = sin(roller_angle_);
00158 fric.direction1.z = cos(roller_angle_) * sin(wheel_angle);
00159 }
00160
00161 }