amcl_odom.cc

00001 /*
00002  *  Player - One Hell of a Robot Server
00003  *  Copyright (C) 2000  Brian Gerkey   &  Kasper Stoy
00004  *                      gerkey@usc.edu    kaspers@robotics.usc.edu
00005  *
00006  *  This program is free software; you can redistribute it and/or modify
00007  *  it under the terms of the GNU General Public License as published by
00008  *  the Free Software Foundation; either version 2 of the License, or
00009  *  (at your option) any later version.
00010  *
00011  *  This program is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *  GNU General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU General Public License
00017  *  along with this program; if not, write to the Free Software
00018  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  *
00020  */
00022 //
00023 // Desc: AMCL odometry routines
00024 // Author: Andrew Howard
00025 // Date: 6 Feb 2003
00026 // CVS: $Id: amcl_odom.cc 4135 2007-08-23 19:58:48Z gerkey $
00027 //
00029 
00030 #ifdef HAVE_CONFIG_H
00031 #include "config.h"
00032 #endif
00033 
00034 #include <sys/types.h> // required by Darwin
00035 #include <math.h>
00036 
00037 #include <libplayercore/playercore.h>
00038 #include <libplayercore/error.h>
00039 #include "amcl_odom.h"
00040 
00042 // Default constructor
00043 AMCLOdom::AMCLOdom(AdaptiveMCL & aAMCL, player_devaddr_t addr) : AMCLSensor(aAMCL)
00044 {
00045   this->odom_dev = NULL;
00046   this->action_pdf = NULL;
00047   this->odom_addr = addr;
00048   
00049   return;
00050 }
00051 
00052 
00054 // Load settings
00055 int AMCLOdom::Load(ConfigFile* cf, int section)
00056 {
00057   this->time = 0.0;
00058 
00059   this->drift = pf_matrix_zero();
00060 
00061   this->drift.m[0][0] = cf->ReadTupleFloat(section, "odom_drift[0]", 0, 0.20);
00062   this->drift.m[0][1] = cf->ReadTupleFloat(section, "odom_drift[0]", 1, 0.00);
00063   this->drift.m[0][2] = cf->ReadTupleFloat(section, "odom_drift[0]", 2, 0.00); 
00064 
00065   this->drift.m[1][0] = cf->ReadTupleFloat(section, "odom_drift[1]", 0, 0.00);
00066   this->drift.m[1][1] = cf->ReadTupleFloat(section, "odom_drift[1]", 1, 0.20);
00067   this->drift.m[1][2] = cf->ReadTupleFloat(section, "odom_drift[1]", 2, 0.00);
00068 
00069   this->drift.m[2][0] = cf->ReadTupleFloat(section, "odom_drift[2]", 0, 0.20);
00070   this->drift.m[2][1] = cf->ReadTupleFloat(section, "odom_drift[2]", 1, 0.00);
00071   this->drift.m[2][2] = cf->ReadTupleFloat(section, "odom_drift[2]", 2, 0.20);
00072 
00073   return 0;
00074 }
00075 
00076 
00078 // Unload the model
00079 int AMCLOdom::Unload(void)
00080 {  
00081   return 0;
00082 }
00083 
00084 
00086 // Set up the underlying odom driver.
00087 int AMCLOdom::Setup(void)
00088 {
00089   // Subscribe to the odometry driver
00090   this->odom_dev = deviceTable->GetDevice(this->odom_addr);
00091   if (!this->odom_dev)
00092   {
00093     PLAYER_ERROR("unable to locate suitable position driver");
00094     return -1;
00095   }
00096   if (this->odom_dev->Subscribe(AMCL.InQueue) != 0)
00097   {
00098     PLAYER_ERROR("unable to subscribe to position device");
00099     return -1;
00100   }
00101   
00102   return 0;
00103 }
00104 
00105 
00107 // Shutdown the underlying odom device.
00108 int AMCLOdom::Shutdown(void)
00109 {
00110   // Unsubscribe from device
00111   this->odom_dev->Unsubscribe(AMCL.InQueue);
00112   this->odom_dev = NULL;
00113   
00114   return 0;
00115 }
00116 
00117 
00119 // Get the current odometry reading
00120 //AMCLSensorData *AMCLOdom::GetData(void)
00121 // Process message for this interface
00122 int AMCLOdom::ProcessMessage(QueuePointer &resp_queue, 
00123                                      player_msghdr * hdr, 
00124                                      void * idata)
00125 {
00126   pf_vector_t pose;
00127   AMCLOdomData *ndata;
00128 
00129   if(!Message::MatchMessage(hdr, PLAYER_MSGTYPE_DATA,
00130                             PLAYER_POSITION2D_DATA_STATE, this->odom_addr))
00131   {
00132     return -1;
00133   }
00134 
00135   player_position2d_data_t* data = reinterpret_cast<player_position2d_data_t*> (idata);
00136 
00137   // Compute new robot pose
00138   pose.v[0] = data->pos.px;
00139   pose.v[1] = data->pos.py;
00140   pose.v[2] = data->pos.pa;
00141 
00142   //printf("getdata %.3f %.3f %.3f\n", 
00143          //pose.v[0], pose.v[1], pose.v[2]);
00144 
00145   ndata = new AMCLOdomData;
00146 
00147   ndata->sensor = this;
00148   ndata->time = hdr->timestamp;
00149 
00150   ndata->pose = pose;
00151   ndata->delta = pf_vector_zero();
00152 
00153   this->time = hdr->timestamp;
00154 
00155   AMCL.Push(ndata);
00156     
00157   return 0;
00158 }
00159 
00160 
00162 // Apply the action model
00163 bool AMCLOdom::UpdateAction(pf_t *pf, AMCLSensorData *data)
00164 {
00165   AMCLOdomData *ndata;
00166   pf_vector_t x;
00167   pf_matrix_t cx;
00168   double ux, uy, ua;
00169   ndata = (AMCLOdomData*) data;
00170 
00171   /*
00172   printf("odom: %f %f %f : %f %f %f\n",
00173          ndata->pose.v[0], ndata->pose.v[1], ndata->pose.v[2],
00174          ndata->delta.v[0], ndata->delta.v[1], ndata->delta.v[2]);
00175   */
00176          
00177   // See how far the robot has moved
00178   x = ndata->delta;
00179   
00180   // Odometric drift model
00181   // This could probably be improved
00182   ux = this->drift.m[0][0] * x.v[0];
00183   uy = this->drift.m[1][1] * x.v[1];
00184   ua = this->drift.m[2][0] * fabs(x.v[0])
00185     + this->drift.m[2][1] * fabs(x.v[1])
00186     + this->drift.m[2][2] * fabs(x.v[2]);
00187 
00188   cx = pf_matrix_zero();
00189   cx.m[0][0] = ux * ux;
00190   cx.m[1][1] = uy * uy;
00191   cx.m[2][2] = ua * ua;
00192 
00193   //printf("x = %f %f %f\n", x.v[0], x.v[1], x.v[2]);
00194   
00195   // Create a pdf with suitable characterisitics
00196   this->action_pdf = pf_pdf_gaussian_alloc(x, cx); 
00197 
00198   // Update the filter
00199   pf_update_action(pf, (pf_action_model_fn_t) ActionModel, this);  
00200 
00201   // Delete the pdf
00202   pf_pdf_gaussian_free(this->action_pdf);
00203   this->action_pdf = NULL;
00204   
00205   return true;
00206 }
00207 
00208 
00210 // The action model function (static method)
00211 void 
00212 AMCLOdom::ActionModel(AMCLOdom *self, pf_sample_set_t* set)
00213 {
00214   int i;
00215   pf_vector_t z;
00216   pf_sample_t *sample;
00217 
00218   // Compute the new sample poses
00219   for (i = 0; i < set->sample_count; i++)
00220   {
00221     sample = set->samples + i;
00222     z = pf_pdf_gaussian_sample(self->action_pdf);
00223     sample->pose = pf_vector_coord_add(z, sample->pose);
00224     sample->weight = 1.0 / set->sample_count;
00225   }
00226 }
00227 
00228 
00229 #ifdef INCLUDE_RTKGUI
00230 
00232 // Setup the GUI
00233 void AMCLOdom::SetupGUI(rtk_canvas_t *canvas, rtk_fig_t *robot_fig)
00234 {
00235   return;
00236 }
00237 
00238 
00240 // Shutdown the GUI
00241 void AMCLOdom::ShutdownGUI(rtk_canvas_t *canvas, rtk_fig_t *robot_fig)
00242 {
00243   return;
00244 }
00245 
00246 #endif

Last updated 12 September 2005 21:38:45