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

📄 amcl_laser.cc

📁 机器人仿真软件
💻 CC
字号:
/* *  Player - One Hell of a Robot Server *  Copyright (C) 2000  Brian Gerkey   &  Kasper Stoy *                      gerkey@usc.edu    kaspers@robotics.usc.edu * *  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: AMCL laser routines// Author: Andrew Howard// Date: 6 Feb 2003// CVS: $Id: amcl_laser.cc,v 1.22.2.2 2006/07/13 17:59:43 gerkey Exp $/////////////////////////////////////////////////////////////////////////////#ifdef HAVE_CONFIG_H#include "config.h"#endif#define PLAYER_ENABLE_MSG 1#include <sys/types.h> // required by Darwin#include <math.h>#include <stdlib.h>#include <unistd.h>#include <libplayercore/playercore.h>#include <libplayercore/error.h>#include "amcl_laser.h"////////////////////////////////////////////////////////////////////////////////// Default constructorAMCLLaser::AMCLLaser(AdaptiveMCL & aAMCL, player_devaddr_t addr) : AMCLSensor(aAMCL){  this->laser_dev = NULL;  this->laser_addr = addr;    return;}////////////////////////////////////////////////////////////////////////////////// Load laser settingsint AMCLLaser::Load(ConfigFile* cf, int section){  // Get the map settings.  Don't error check here; we'll do it later, in  // SetupMap().  cf->ReadDeviceAddr(&(this->map_addr), section, "requires",                     PLAYER_MAP_CODE, -1, "laser");    this->max_beams = cf->ReadInt(section, "laser_max_beams", 6);  this->range_var = cf->ReadLength(section, "laser_range_var", 0.10);  this->range_bad = cf->ReadFloat(section, "laser_range_bad", 0.10);  this->time = 0.0;  return 0;}////////////////////////////////////////////////////////////////////////////////// Unload the modelint AMCLLaser::Unload(void){  //laser_free(this->model);  //this->model = NULL;    return 0;}////////////////////////////////////////////////////////////////////////////////// Set up the laserint AMCLLaser::Setup(void){  if(this->SetupMap() < 0)  {    PLAYER_ERROR("failed to get laser map");    return(-1);  }  // Subscribe to the Laser device  this->laser_dev = deviceTable->GetDevice(this->laser_addr);  if (!this->laser_dev)  {    PLAYER_ERROR("unable to locate suitable laser device");    return -1;  }  if (this->laser_dev->Subscribe(AMCL.InQueue) != 0)  {    PLAYER_ERROR("unable to subscribe to laser device");    return -1;  }  // Ask for the laser's geometry  Message* msg;  if(!(msg = laser_dev->Request(AMCL.InQueue,                                PLAYER_MSGTYPE_REQ,                                PLAYER_LASER_REQ_GET_GEOM,                                NULL, 0, NULL,false)))  {    PLAYER_WARN("failed to get laser geometry");    this->laser_pose.v[0] = 0.0;    this->laser_pose.v[1] = 0.0;    this->laser_pose.v[2] = 0.0;  }  else  {    player_laser_geom_t* geom = (player_laser_geom_t*)msg->GetPayload();    // Set the laser pose relative to the robot    this->laser_pose.v[0] = geom->pose.px;    this->laser_pose.v[1] = geom->pose.py;    this->laser_pose.v[2] = geom->pose.pa;    PLAYER_MSG3(2, "laser geometry: %f,%f,%f",                this->laser_pose.v[0],                this->laser_pose.v[1],                RTOD(this->laser_pose.v[2]));    delete msg;  }  return 0;}// TODO: should Unsubscribe from the map on error returns in the functionintAMCLLaser::SetupMap(void){  Device* mapdev;  // Subscribe to the map device  if(!(mapdev = deviceTable->GetDevice(this->map_addr)))  {    PLAYER_ERROR("unable to locate suitable map device");    return -1;  }  if(mapdev->Subscribe(AMCL.InQueue) != 0)  {    PLAYER_ERROR("unable to subscribe to map device");    return -1;  }  // Create the map  this->map = map_alloc();  PLAYER_MSG1(2, "AMCL loading map from map:%d...", this->map_addr.index);  // Fill in the map structure (I'm doing it here instead of in libmap,   // because libmap is written in C, so it'd be a pain to invoke the internal   // device API from there)  // first, get the map info  Message* msg;  if(!(msg = mapdev->Request(AMCL.InQueue,                             PLAYER_MSGTYPE_REQ,                             PLAYER_MAP_REQ_GET_INFO,                             NULL, 0, NULL, false)))  {    PLAYER_ERROR("failed to get map info");    return(-1);  }  PLAYER_MSG1(2, "AMCL loading map from map:%d...Done", this->map_addr.index);  player_map_info_t* info = (player_map_info_t*)msg->GetPayload();    // copy in the map info  this->map->origin_x = this->map->origin_y = 0.0;  this->map->scale = info->scale;  this->map->size_x = info->width;  this->map->size_y = info->height;  delete msg;  // allocate space for map cells  assert(this->map->cells = (map_cell_t*)malloc(sizeof(map_cell_t) *                                                this->map->size_x *                                                this->map->size_y));  // now, get the map data  player_map_data_t* data_req;  size_t reqlen;  int i,j;  int oi,oj;  int sx,sy;  int si,sj;  reqlen = sizeof(player_map_data_t) - PLAYER_MAP_MAX_TILE_SIZE + 4;  data_req = (player_map_data_t*)calloc(1, reqlen);  assert(data_req);  // Tile size  sy = sx = (int)sqrt(PLAYER_MAP_MAX_TILE_SIZE);  assert(sx * sy < (int)PLAYER_MAP_MAX_TILE_SIZE);  oi=oj=0;  while((oi < this->map->size_x) && (oj < this->map->size_y))  {    si = MIN(sx, this->map->size_x - oi);    sj = MIN(sy, this->map->size_y - oj);    data_req->col = oi;    data_req->row = oj;    data_req->width = si;    data_req->height = sj;    data_req->data_count = 0;    if(!(msg = mapdev->Request(AMCL.InQueue,                               PLAYER_MSGTYPE_REQ,                               PLAYER_MAP_REQ_GET_DATA,                               (void*)data_req,reqlen,NULL,false)))    {      PLAYER_ERROR("failed to get map info");      free(data_req);      free(this->map->cells);      return(-1);    }    player_map_data_t* mapdata = (player_map_data_t*)msg->GetPayload();    // copy the map data    for(j=0;j<sj;j++)    {      for(i=0;i<si;i++)      {        this->map->cells[MAP_INDEX(this->map,oi+i,oj+j)].occ_state =                 mapdata->data[j*si + i];        this->map->cells[MAP_INDEX(this->map,oi+i,oj+j)].occ_dist = 0;      }    }    delete msg;    oi += si;    if(oi >= this->map->size_x)    {      oi = 0;      oj += sj;    }  }  free(data_req);  // we're done with the map device now  if(mapdev->Unsubscribe(AMCL.InQueue) != 0)    PLAYER_WARN("unable to unsubscribe from map device");  PLAYER_MSG0(2, "Done");  return(0);}////////////////////////////////////////////////////////////////////////////////// Shut down the laserint AMCLLaser::Shutdown(void){    this->laser_dev->Unsubscribe(AMCL.InQueue);  this->laser_dev = NULL;  map_free(this->map);  return 0;}////////////////////////////////////////////////////////////////////////////////// Get the current laser reading//AMCLSensorData *AMCLLaser::GetData(void)// Process message for this interfaceint AMCLLaser::ProcessMessage(MessageQueue * resp_queue,                                      player_msghdr * hdr,                                      void * idata){  int i;  double r, b, db;  AMCLLaserData *ndata;  if(!Message::MatchMessage(hdr, PLAYER_MSGTYPE_DATA,                            PLAYER_LASER_DATA_SCAN, this->laser_addr))  	return -1;  this->time = hdr->timestamp;  player_laser_data_t* data = reinterpret_cast<player_laser_data_t*> (idata);    b = data->min_angle;  db = data->resolution;    ndata = new AMCLLaserData;  ndata->sensor = this;  ndata->time = hdr->timestamp;    ndata->range_count = data->ranges_count;  ndata->range_max = data->max_range;  assert((size_t) ndata->range_count < sizeof(ndata->ranges) / sizeof(ndata->ranges[0]));  // Read the range data  for (i = 0; i < ndata->range_count; i++)  {    r = data->ranges[i];    ndata->ranges[i][0] = r;    ndata->ranges[i][1] = b;    b += db;  }  AMCL.Push(ndata);    return 0;}////////////////////////////////////////////////////////////////////////////////// Apply the laser sensor modelbool AMCLLaser::UpdateSensor(pf_t *pf, AMCLSensorData *data){  AMCLLaserData *ndata;    ndata = (AMCLLaserData*) data;  if (this->max_beams < 2)    return false;  // Apply the laser sensor model  pf_update_sensor(pf, (pf_sensor_model_fn_t) SensorModel, data);    return true;}////////////////////////////////////////////////////////////////////////////////// Determine the probability for the given posedouble AMCLLaser::SensorModel(AMCLLaserData *data, pf_sample_set_t* set){  AMCLLaser *self;  int i, j, step;  double z, c, pz;  double p;  double map_range;  double obs_range, obs_bearing;  double total_weight;  pf_sample_t *sample;  pf_vector_t pose;    self = (AMCLLaser*) data->sensor;  total_weight = 0.0;    // Compute the sample weights  for (j = 0; j < set->sample_count; j++)  {    sample = set->samples + j;    pose = sample->pose;    // Take account of the laser pose relative to the robot    pose = pf_vector_coord_add(self->laser_pose, pose);    p = 1.0;    step = (data->range_count - 1) / (self->max_beams - 1);    for (i = 0; i < data->range_count; i += step)    {      obs_range = data->ranges[i][0];      obs_bearing = data->ranges[i][1];      // Compute the range according to the map      map_range = map_calc_range(self->map, pose.v[0], pose.v[1],                                 pose.v[2] + obs_bearing, data->range_max + 1.0);      if (obs_range >= data->range_max && map_range >= data->range_max)      {        pz = 1.0;      }      else      {        // TODO: proper sensor model (using Kolmagorov?)        // Simple gaussian model        c = self->range_var;        z = obs_range - map_range;        pz = self->range_bad + (1 - self->range_bad) * exp(-(z * z) / (2 * c * c));      }      /*         if (obs->range >= 8.0 && map_range >= 8.0)         p *= 1.0;         else if (obs->range >= 8.0 && map_range < 8.0)         p *= self->range_bad;         else if (obs->range < 8.0 && map_range >= 8.0)         p *= self->range_bad;         else         p *= laser_sensor_prob(self, obs->range, map_range);       */      p *= pz;    }    //printf("%e\n", p);    //assert(p >= 0);    sample->weight *= p;    total_weight += sample->weight;  }  return(total_weight);}#ifdef INCLUDE_RTKGUI////////////////////////////////////////////////////////////////////////////////// Setup the GUIvoid AMCLLaser::SetupGUI(rtk_canvas_t *canvas, rtk_fig_t *robot_fig){    this->fig = rtk_fig_create(canvas, robot_fig, 0);  // Draw the laser map  this->map_fig = rtk_fig_create(canvas, NULL, -50);  map_draw_occ(this->map, this->map_fig);    return;}////////////////////////////////////////////////////////////////////////////////// Shutdown the GUIvoid AMCLLaser::ShutdownGUI(rtk_canvas_t *canvas, rtk_fig_t *robot_fig){  rtk_fig_destroy(this->map_fig);  rtk_fig_destroy(this->fig);  this->map_fig = NULL;  this->fig = NULL;  return;}////////////////////////////////////////////////////////////////////////////////// Draw the laser valuesvoid AMCLLaser::UpdateGUI(rtk_canvas_t *canvas, rtk_fig_t *robot_fig, AMCLSensorData *data){  int i, step;  double r, b, ax, ay, bx, by;  AMCLLaserData *ndata;  ndata = (AMCLLaserData*) data;    rtk_fig_clear(this->fig);  // Draw the complete scan  rtk_fig_color_rgb32(this->fig, 0x8080FF);  for (i = 0; i < ndata->range_count; i++)  {    r = ndata->ranges[i][0];    b = ndata->ranges[i][1];    ax = 0;    ay = 0;    bx = ax + r * cos(b);    by = ay + r * sin(b);    rtk_fig_line(this->fig, ax, ay, bx, by);  }  if (this->max_beams < 2)    return;  // Draw the significant part of the scan  step = (ndata->range_count - 1) / (this->max_beams - 1);  for (i = 0; i < ndata->range_count; i += step)  {    r = ndata->ranges[i][0];    b = ndata->ranges[i][1];    //m = map_calc_range(this->map, pose.v[0], pose.v[1], pose.v[2] + b, 8.0);    ax = 0;    ay = 0;    bx = ax + r * cos(b);    by = ay + r * sin(b);    rtk_fig_color_rgb32(this->fig, 0xFF0000);    rtk_fig_line(this->fig, ax, ay, bx, by);  }  return;}#endif

⌨️ 快捷键说明

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