/* * Copyright (C) 2012 Open Source Robotics Foundation * * 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 "gazebo/physics/physics.hh" #include "gazebo/transport/transport.hh" #include "plugins/DiffDrivePlugin.hh" using namespace gazebo; GZ_REGISTER_MODEL_PLUGIN(DiffDrivePlugin) enum {RIGHT, LEFT}; ///////////////////////////////////////////////// DiffDrivePlugin::DiffDrivePlugin() { this->wheelSpeed[LEFT] = this->wheelSpeed[RIGHT] = 0; this->wheelSeparation = 1.0; this->wheelRadius = 1.0; } ///////////////////////////////////////////////// void DiffDrivePlugin::Load(physics::ModelPtr _model, sdf::ElementPtr _sdf) { this->model = _model; this->node = transport::NodePtr(new transport::Node()); this->node->Init(this->model->GetWorld()->GetName()); this->velSub = this->node->Subscribe(std::string("~/") + this->model->GetName() + "/vel_cmd", &DiffDrivePlugin::OnVelMsg, this); if (!_sdf->HasElement("left_joint")) gzerr << "DiffDrive plugin missing element\n"; if (!_sdf->HasElement("right_joint")) gzerr << "DiffDrive plugin missing element\n"; this->leftJoint = _model->GetJoint( _sdf->GetElement("left_joint")->Get()); this->rightJoint = _model->GetJoint( _sdf->GetElement("right_joint")->Get()); if (!this->leftJoint) gzerr << "Unable to find left joint[" << _sdf->GetElement("left_joint")->Get() << "]\n"; if (!this->rightJoint) gzerr << "Unable to find right joint[" << _sdf->GetElement("right_joint")->Get() << "]\n"; this->updateConnection = event::Events::ConnectWorldUpdateBegin( boost::bind(&DiffDrivePlugin::OnUpdate, this)); } ///////////////////////////////////////////////// void DiffDrivePlugin::Init() { this->wheelSeparation = this->leftJoint->GetAnchor(0).Distance( this->rightJoint->GetAnchor(0)); physics::EntityPtr parent = boost::dynamic_pointer_cast( this->leftJoint->GetChild()); math::Box bb = parent->GetBoundingBox(); // This assumes that the largest dimension of the wheel is the diameter this->wheelRadius = bb.GetSize().GetMax() * 0.5; } ///////////////////////////////////////////////// void DiffDrivePlugin::OnVelMsg(ConstPosePtr &_msg) { double vr, va; vr = _msg->position().x(); va = msgs::ConvertIgn(_msg->orientation()).Euler().Z(); this->wheelSpeed[LEFT] = vr + va * this->wheelSeparation / 2.0; this->wheelSpeed[RIGHT] = vr - va * this->wheelSeparation / 2.0; } ///////////////////////////////////////////////// void DiffDrivePlugin::OnUpdate() { /* double d1, d2; double dr, da; this->prevUpdateTime = currTime; // Distance travelled by front wheels d1 = stepTime.Double() * this->wheelRadius * this->leftJoint->GetVelocity(0); d2 = stepTime.Double() * this->wheelRadius * this->rightJoint->GetVelocity(0); dr = (d1 + d2) / 2; da = (d1 - d2) / this->wheelSeparation; common::Time currTime = this->model->GetWorld()->GetSimTime(); common::Time stepTime = currTime - this->prevUpdateTime; */ double leftVelDesired = (this->wheelSpeed[LEFT] / this->wheelRadius); double rightVelDesired = (this->wheelSpeed[RIGHT] / this->wheelRadius); this->leftJoint->SetVelocity(0, leftVelDesired); this->rightJoint->SetVelocity(0, rightVelDesired); }