ppovb5fc7/gazebo/plugins/SkidSteerDrivePlugin.cc

130 lines
4.2 KiB
C++

/*
* 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 <string>
#include "gazebo/physics/physics.hh"
#include "gazebo/transport/transport.hh"
#include "plugins/SkidSteerDrivePlugin.hh"
using namespace gazebo;
GZ_REGISTER_MODEL_PLUGIN(SkidSteerDrivePlugin)
/////////////////////////////////////////////////
SkidSteerDrivePlugin::SkidSteerDrivePlugin()
{
this->wheelRadius = 0.0;
this->wheelSeparation = 0.0;
}
/////////////////////////////////////////////////
int SkidSteerDrivePlugin::RegisterJoint(int _index, const std::string &_name)
{
// Bounds checking on index
if (_index < 0 || _index >= NUMBER_OF_WHEELS)
{
gzerr << "Joint index " << _index << " out of bounds [0, "
<< NUMBER_OF_WHEELS << "] in model " << this->model->GetName()
<< "." << std::endl;
return 1;
}
// Find the specified joint and add it to out list
this->joints[_index] = this->model->GetJoint(_name);
if (!this->joints[_index])
{
gzerr << "Unable to find the " << _name
<< " joint in model " << this->model->GetName() << "." << std::endl;
return 1;
}
// Success!
return 0;
}
/////////////////////////////////////////////////
void SkidSteerDrivePlugin::Load(physics::ModelPtr _model,
sdf::ElementPtr /*_sdf*/)
{
this->model = _model;
this->node = transport::NodePtr(new transport::Node());
this->node->Init(this->model->GetWorld()->GetName());
int err = 0;
err += RegisterJoint(RIGHT_FRONT, "right_front");
err += RegisterJoint(RIGHT_REAR, "right_rear");
err += RegisterJoint(LEFT_FRONT, "left_front");
err += RegisterJoint(LEFT_REAR, "left_rear");
if (err > 0)
return;
// This assumes that front and rear wheel spacing is identical
this->wheelSeparation = this->joints[RIGHT_FRONT]->GetAnchor(0).Distance(
this->joints[LEFT_FRONT]->GetAnchor(0));
// This assumes that the largest dimension of the wheel is the diameter
// and that all wheels have the same diameter
physics::EntityPtr wheelLink = boost::dynamic_pointer_cast<physics::Entity>(
this->joints[RIGHT_FRONT]->GetChild() );
if (wheelLink)
{
math::Box bb = wheelLink->GetBoundingBox();
this->wheelRadius = bb.GetSize().GetMax() * 0.5;
}
// Validity checks...
if (this->wheelSeparation <= 0)
{
gzerr << "Unable to find the wheel separation distance." << std::endl
<< " This could mean that the right_front link and the left_front "
<< "link are overlapping." << std::endl;
return;
}
if (this->wheelRadius <= 0)
{
gzerr << "Unable to find the wheel radius." << std::endl
<< " This could mean that the sdf is missing a wheel link on "
<< "the right_front joint." << std::endl;
return;
}
this->velSub = this->node->Subscribe(
std::string("~/") + this->model->GetName() + std::string("/vel_cmd"),
&SkidSteerDrivePlugin::OnVelMsg, this);
}
/////////////////////////////////////////////////
void SkidSteerDrivePlugin::OnVelMsg(ConstPosePtr &_msg)
{
// gzmsg << "cmd_vel: " << msg->position().x() << ", "
// << msgs::Convert(msg->orientation()).GetAsEuler().z << std::endl;
double vel_lin = _msg->position().x() / this->wheelRadius;
double vel_rot = -1 * msgs::ConvertIgn(_msg->orientation()).Euler().Z()
* (this->wheelSeparation / this->wheelRadius);
this->joints[RIGHT_FRONT]->SetVelocity(0, vel_lin - vel_rot);
this->joints[RIGHT_REAR ]->SetVelocity(0, vel_lin - vel_rot);
this->joints[LEFT_FRONT ]->SetVelocity(0, vel_lin + vel_rot);
this->joints[LEFT_REAR ]->SetVelocity(0, vel_lin + vel_rot);
}