⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pioneer2at.cc

📁 机器人人3D仿真工具,可以加入到Simbad仿真环境下应用。
💻 CC
字号:
/* *  Gazebo - Outdoor Multi-Robot Simulator *  Copyright (C) 2003   *     Nate Koenig & Andrew Howard * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2 of the License, or *  (at your option) any later version. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *  You should have received a copy of the GNU General Public License *  along with this program; if not, write to the Free Software *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA * *//* Desc: Model for a Pioneer2AT * Author: Andrew Howard * Date: 8 May 2003 * CVS: $Id: Pioneer2AT.cc,v 1.52 2006/02/22 14:58:57 natepak Exp $ *//// @addtogroup models /// @{/** @defgroup Pioneer2AT Pioneer 2 AT@htmlinclude Pioneer2AT_view.htmlThe Pioneer2AT model simulates an ActivMedia Pioneer2AT mobile robotbase with 16 sonars.@par libgazebo interfaces- Position information is available through the @ref position interface.- Power information is available through the @ref power interface.- Sonar information is available through the @ref sonar interface.@par Player drivers- Position information is available through the %gz_position driver.- Power information is available through the %gz_power driver.- Sonar information is available through the %gz_sonar driver.@par AttributesThe following attributes are supported.@htmlinclude default_attr_include.html- updateRate (float, Hz)  - Updates per second  - Default: 10- batteryLevel (float, volts)  - Initial battery level  - Default: 12.4- batteryCurve (float)  - Discharge curve: about one hour quiescent  - Default: 2/3600  2/1e4@par BodiesThe following bodies are created by this model.@htmlinclude default_body_include.html@par Example@verbatim<model:Pioneer2AT>  <xyz>0 0 0</xyz></model:Pioneer2AT>@endverbatim@par Views@htmlinclude Pioneer2AT_more_views.html@par AuthorsAndrew Howard, Nate Koenig*//// @} #include <assert.h>#include "gazebo.h"#include "World.hh"#include "WorldFile.hh"#include "ModelFactory.hh"#include "Body.hh"#include "BoxGeom.hh"#include "SphereGeom.hh"#include "WheelGeom.hh"#include "HingeJoint.hh"#include "RayProximity/RayProximity.hh"#include "Pioneer2AT.hh"//////////////////////////////////////////////////////////////////////////////// Register this modelGZ_REGISTER_STATIC("Pioneer2AT", Pioneer2AT);//////////////////////////////////////////////////////////////////////////////// ConstructorPioneer2AT::Pioneer2AT( World *world )    : Model( world ){  int i;  this->chassis = NULL;  for (i=0; i<4; i++)  {    this->wheels[i] = NULL;    this->wheelJoints[i] = NULL;  }  return;}//////////////////////////////////////////////////////////////////////////////// DestructorPioneer2AT::~Pioneer2AT(){  int i;  if (this->chassis)    delete this->chassis;  this->chassis = NULL;  for (i=0; i<4; i++)  {    if (this->wheels[i])      delete this->wheels[i];    if (this->wheelJoints[i])      delete this->wheelJoints[i];    this->wheels[i] = NULL;    this->wheelJoints[i] = NULL;  }  return;}//////////////////////////////////////////////////////////////////////////////// Load the modelint Pioneer2AT::Load( WorldFile *file, WorldFileNode *node ){  this->wheelSep = 0.381;  this->wheelDiam = 0.20;  this->updatePeriod = 1.0 / (node->GetDouble("updateRate", 10) + 1e-6);  this->updateTime = -updatePeriod;  // Create the ODE objects  if (this->OdeLoad(file, node) != 0)    return -1;  // Create the sonar sensor  if (this->LoadSonar(file, node) != 0)    return -1;  // Initial battery level  this->batteryLevel = node->GetDouble("batteryLevel", 12.4);  // Discharge curve: about one hour quiescent  this->batteryCurve[0] = node->GetTupleDouble("batteryCurve", 0, 2 / 3600.0);  this->batteryCurve[1] = node->GetTupleDouble("batteryCurve", 1, 2 / 1e4);    return 0;}//////////////////////////////////////////////////////////////////////////////// Load ODE objectsint Pioneer2AT::OdeLoad( WorldFile *file, WorldFileNode *node ){  int i;  double length, width, height, oz;  double mass;  double wheelSep, wheelDiam, wheelThick;  Geom *geom;  length = 0.5334;  width = 0.381;  height = 0.1905;  mass = 10.0;  wheelSep = this->wheelSep;  wheelDiam = this->wheelDiam;  wheelThick = 0.07;  oz = wheelDiam / 2 + height / 2;    // Create the main chassis of the robot  this->chassis = new Body( this->world );  geom = new BoxGeom( this->chassis, this->modelSpaceId, 0.9 * length, 0.9 * width, height);  geom->SetRelativePosition( GzVectorSet(0, 0, oz) );  geom->SetMass( mass );  geom->SetColor( GzColor(1, 0, 0) );    geom = new BoxGeom( this->chassis, this->modelSpaceId, length, width, 0.02 );  geom->SetRelativePosition( GzVectorSet(0, 0, oz + 0.55 * height) );  geom->SetMass( 0 );  geom->SetColor( GzColor(0, 0, 0) );    this->AddBody( this->chassis, true );  // Create the wheels  for (i = 0; i < 4; i++)  {    this->wheels[i] = new Body( this->world );    geom = new WheelGeom( this->wheels[i], this->modelSpaceId, wheelDiam/2, wheelThick/2);    geom->SetRelativePosition( GzVectorSet(0, 0, 0) );    geom->SetMass( 1.0 );    geom->SetColor( GzColor(0.3, 0.3, 0.3) );    this->AddBody( this->wheels[i] );  }  this->wheels[0]->SetPosition(GzVectorSet(0.25*length, +0.5 * wheelSep, oz - 0.1));  this->wheels[0]->SetRotation(GzQuaternFromAxis(1, 0, 0, -M_PI / 2));  this->wheels[1]->SetPosition(GzVectorSet(0.25*length, -0.5 * wheelSep, oz - 0.1));  this->wheels[1]->SetRotation(GzQuaternFromAxis(1, 0, 0, +M_PI / 2));  this->wheels[2]->SetPosition(GzVectorSet(-0.25*length, +0.5 * wheelSep, oz - 0.1));  this->wheels[2]->SetRotation(GzQuaternFromAxis(1, 0, 0, -M_PI / 2));  this->wheels[3]->SetPosition(GzVectorSet(-0.25*length, -0.5 * wheelSep, oz - 0.1));  this->wheels[3]->SetRotation(GzQuaternFromAxis(1, 0, 0, +M_PI / 2));    // Attach the wheels to the chassis  for (i = 0; i < 4; i++)  {    this->wheelJoints[i] = new HingeJoint( this->world );    this->wheelJoints[i]->Attach( this->wheels[i], this->chassis );    GzVector a = wheels[i]->GetPosition();        this->wheelJoints[i]->SetAnchor( a );    this->wheelJoints[i]->SetAxis( GzVectorSet(0, 1, 0) );    this->wheelJoints[i]->SetParam( dParamSuspensionERP, 0.4 );    this->wheelJoints[i]->SetParam( dParamSuspensionCFM, 0.8 );  }  return 0;}//////////////////////////////////////////////////////////////////////////////// Load the sonarint Pioneer2AT::LoadSonar( WorldFile *file, WorldFileNode *node ){  int i;  GzVector a, b, p;    this->sonarMaxRange = 5.0;  // TODO: check dimensions  p.x = +0.24103;  p.y = +0.135;  p.z = +0.25;      pos[0] = GzVectorSet( p.x, +p.y, p.z );  pos[1] = GzVectorSet( p.x, +p.y, p.z );  pos[2] = GzVectorSet( p.x, +p.y - 2 * 0.03429, p.z );  pos[3] = GzVectorSet( p.x, +p.y - 4 * 0.03429, p.z );  pos[4] = GzVectorSet( p.x, -p.y + 4 * 0.03429, p.z );  pos[5] = GzVectorSet( p.x, -p.y + 2 * 0.03429, p.z );  pos[6] = GzVectorSet( p.x, -p.y, p.z );  pos[7] = GzVectorSet( p.x, -p.y, p.z );  p.x = -0.24103;  p.y = +0.135;  p.z = +0.25;    pos[8] = GzVectorSet( p.x, -p.y, p.z );  pos[9] = GzVectorSet( p.x, -p.y, p.z );  pos[10] = GzVectorSet( p.x, -p.y + 2 * 0.03429, p.z );  pos[11] = GzVectorSet( p.x, -p.y + 4 * 0.03429, p.z );  pos[12] = GzVectorSet( p.x, +p.y - 4 * 0.03429, p.z );  pos[13] = GzVectorSet( p.x, +p.y - 2 * 0.03429, p.z );  pos[14] = GzVectorSet( p.x, +p.y, p.z );  pos[15] = GzVectorSet( p.x, +p.y, p.z );    dir[0] = 90;  dir[1] = 50;  dir[2] = 30;  dir[3] = 10;  dir[4] = -10;  dir[5] = -30;  dir[6] = -50;  dir[7] = -90;  dir[8] = -90;  dir[9] = -130;  dir[10] = -150;  dir[11] = -170;  dir[12] = 170;  dir[13] = 150;  dir[14] = 130;  dir[15] = 90;  this->sonarSensor = new RayProximity(this->world, this->chassis, 16);  for (i = 0; i < 16; i++)  {    a = pos[i];    b = GzVectorSet(this->sonarMaxRange * cos(dir[i] * M_PI / 180),                    this->sonarMaxRange * sin(dir[i] * M_PI / 180), 0.0);    b = GzVectorAdd(a, b);     this->sonarSensor->SetRay(i, a, b);  }    return 0;}//////////////////////////////////////////////////////////////////////////////// Initialize the modelint Pioneer2AT::Init( WorldFile *file, WorldFileNode *node ){  // Create position interface  this->position_iface = gz_position_alloc();  assert(this->position_iface);  if (gz_position_create(this->position_iface, this->world->gz_server, this->GetId(),                         "Pioneer2AT", this->GetIntId(), this->GetParentIntId()) != 0)    return -1;  // Create power inteface  this->power_iface = gz_power_alloc();  if (gz_power_create(this->power_iface, this->world->gz_server, this->GetId(),                      "Pioneer2AT", this->GetIntId(), this->GetParentIntId()) != 0)    return -1;  // Create sonar inteface  this->sonar_iface = gz_sonar_alloc();  if (gz_sonar_create(this->sonar_iface, this->world->gz_server, this->GetId(),                       "Pioneer2AT", this->GetIntId(), this->GetParentIntId()) != 0)    return -1;  // Reset odometric pose  this->odomPose[0] = 0.0;  this->odomPose[1] = 0.0;  this->odomPose[2] = 0.0;  return 0;}//////////////////////////////////////////////////////////////////////////////// Finalize the modelint Pioneer2AT::Fini(){  // Close sonar interface  gz_sonar_destroy( this->sonar_iface );  gz_sonar_free( this->sonar_iface );  this->sonar_iface = NULL;  // Close power interface  gz_power_destroy( this->power_iface );  gz_power_free( this->power_iface );  this->power_iface = NULL;  // Close position interface  gz_position_destroy( this->position_iface );  gz_position_free( this->position_iface );  this->position_iface = NULL;  return 0;}//////////////////////////////////////////////////////////////////////////////// Update modelvoid Pioneer2AT::Update( double step ){  // Do nothing if paused  if (step == 0)    return;    // Update the odometry (do this always for better accuracy)  this->UpdateOdometry( step );  // Otherwise, update periodically  if (this->world->GetSimTime() - this->updateTime > this->updatePeriod)  {    this->updateTime = this->world->GetSimTime();    // Get commands from the external interface    this->GetPositionCmd();    this->wheelJoints[0]->SetParam( dParamVel,                                     this->wheelSpeed[1] / this->wheelDiam * 2 );    this->wheelJoints[1]->SetParam( dParamVel,                                     this->wheelSpeed[0] / this->wheelDiam * 2 );    this->wheelJoints[2]->SetParam( dParamVel,                                     this->wheelSpeed[1] / this->wheelDiam * 2 );    this->wheelJoints[3]->SetParam( dParamVel,                                     this->wheelSpeed[0] / this->wheelDiam * 2 );    this->wheelJoints[0]->SetParam( dParamFMax, 10.0 );    this->wheelJoints[1]->SetParam( dParamFMax, 10.0 );    this->wheelJoints[2]->SetParam( dParamFMax, 10.0 );    this->wheelJoints[3]->SetParam( dParamFMax, 10.0 );      // Update the sonar sensor    this->sonarSensor->Update();    // Update the interface    this->PutPositionData();    this->PutPowerData();    this->PutSonarData();  }    return;}//////////////////////////////////////////////////////////////////////////////// Update the odometryvoid Pioneer2AT::UpdateOdometry( double step ){  double wd, ws;  double d1, d2;  double dr, da;  wd = this->wheelDiam;  ws = this->wheelSep;  // Average distance travelled by left and right wheels  d1 = step * wd / 2 *     (wheelJoints[0]->GetAngleRate() + wheelJoints[2]->GetAngleRate()) / 2;  d2 = step * wd / 2 *     (wheelJoints[1]->GetAngleRate() + wheelJoints[3]->GetAngleRate()) / 2;  dr = (d1 + d2) / 2;  da = (d2 - d1) / ws;    // Compute odometric pose  this->odomPose[0] += dr * cos( this->odomPose[2] );  this->odomPose[1] += dr * sin( this->odomPose[2] );  this->odomPose[2] += da;  // Compute odometric instantaneous velocity  this->odomVel[0] = dr / step;  this->odomVel[1] = 0.0;  this->odomVel[2] = da / step;  // Update the power discharge; this is probably completely bogus  this->batteryLevel -= this->batteryCurve[0] * step;  this->batteryLevel -= this->batteryCurve[1] * d1 * d1;  this->batteryLevel -= this->batteryCurve[1] * d2 * d2;  return;}//////////////////////////////////////////////////////////////////////////////// Get commands from the external interfacevoid Pioneer2AT::GetPositionCmd(){  double vr, va;  gz_position_lock(this->position_iface, 1);  vr = this->position_iface->data->cmd_vel_pos[0];  va = this->position_iface->data->cmd_vel_rot[2];  gz_position_unlock(this->position_iface);    this->wheelSpeed[0] = vr + va * this->wheelSep / 2;  this->wheelSpeed[1] = vr - va * this->wheelSep / 2;    return;}//////////////////////////////////////////////////////////////////////////////// Update the data in the erinterfacevoid Pioneer2AT::PutPositionData(){  gz_position_lock(this->position_iface, 1);      // Data timestamp  this->position_iface->data->time = this->world->GetSimTime();  this->position_iface->data->pos[0] = this->odomPose[0];  this->position_iface->data->pos[1] = this->odomPose[1];  this->position_iface->data->rot[2] = this->odomPose[2];  this->position_iface->data->vel_pos[0] = this->odomVel[0];  this->position_iface->data->vel_rot[2] = this->odomVel[2];  gz_position_unlock(this->position_iface);    return;}//////////////////////////////////////////////////////////////////////////////// Update the data in the power interfacevoid Pioneer2AT::PutPowerData(){  gz_power_lock(this->power_iface, 1);      this->power_iface->data->time = this->world->GetSimTime();  this->power_iface->data->levels[0] = this->batteryLevel;  gz_power_unlock(this->power_iface);      return;}//////////////////////////////////////////////////////////////////////////////// Update the data in the sonar interfacevoid Pioneer2AT::PutSonarData(){  int i;  double r;  gz_sonar_lock(this->sonar_iface, 1);      // Data timestamp  this->sonar_iface->data->time = this->world->GetSimTime();  // Sonar count valid  this->sonar_iface->data->sonar_count = 16;    // Sonar's data  for (i = 0; i < 16; i++)  {    r = Min(this->sonarSensor->GetRange(i), this->sonarMaxRange);    this->sonar_iface->data->sonar_pos[i][0] = pos[i].x;    this->sonar_iface->data->sonar_pos[i][1] = pos[i].y;    this->sonar_iface->data->sonar_pos[i][2] = pos[i].z;    this->sonar_iface->data->sonar_rot[i][0] = 0;    this->sonar_iface->data->sonar_rot[i][1] = 0;    this->sonar_iface->data->sonar_rot[i][2] = dir[i] * M_PI / 180;    this->sonar_iface->data->sonar_ranges[i] = r;  }  gz_sonar_unlock(this->sonar_iface);      return;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -