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

📄 lasercspace.cc

📁 机器人仿真平台,和stage配合运行
💻 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: Driver for computing the config space for a laser scan.// Author: Andrew Howard// Date: 1 Sep 2002// CVS: $Id: lasercspace.cc,v 1.1.2.1 2003/02/11 18:46:17 gerkey Exp $//// Theory of operation - Shortens each range reading in the laser scan// such that the new scan delimits the boundary of free configuration// space (for a robot of some known radius).//// Requires - Laser device./////////////////////////////////////////////////////////////////////////////#include "player.h"#include <errno.h>#include <string.h>#include <math.h>#include <stdlib.h>       // for atoi(3)#include <netinet/in.h>   // for htons(3)#include <unistd.h>#include "device.h"#include "devicetable.h"#include "drivertable.h"// Driver for computing the free c-space from a laser scan.class LaserCSpace : public CDevice{  // Constructor  public: LaserCSpace(char* interface, ConfigFile* cf, int section);  // Setup/shutdown routines.  public: virtual int Setup();  public: virtual int Shutdown();  // Client interface (this device has no thread).  public: virtual size_t GetData(void* client, unsigned char *dest,                                  size_t maxsize, uint32_t* timestamp_sec,                                  uint32_t* timestamp_usec);  // Client interface (this device has no thread).  public: virtual int PutConfig(player_device_id_t* device, void *client,                                 void *data, size_t len);  // Process laser data.  Returns non-zero if the laser data has been  // updated.  private: int UpdateLaser();  // Pre-compute a bunch of stuff  private: void Precompute();  // Compute the maximum free-space range for sample n.  private: double FreeRange(int n);  // Process requests.  Returns 1 if the configuration has changed.  private: int HandleRequests();  // Handle geometry requests.  private: void HandleGetGeom(void *client, void *req, int reqlen);  // Laser stuff.  private: int laser_index;  private: CDevice *laser_device;  private: player_laser_data_t laser_data;  private: uint32_t laser_timesec, laser_timeusec;  // Step size for subsampling the scan (saves CPU cycles)  private: int sample_step;  // Robot radius.  private: double radius;  // Lookup table for precomputations  private: double lu[PLAYER_LASER_MAX_SAMPLES][4];  // Fiducila stuff (the data we generate).  private: player_laser_data_t data;  private: uint32_t timesec, timeusec;};// Initialization functionCDevice* LaserCSpace_Init(char* interface, ConfigFile* cf, int section){  if (strcmp(interface, PLAYER_LASER_STRING) != 0)  {    PLAYER_ERROR1("driver \"lasercspace\" does not support interface \"%s\"\n",                  interface);    return (NULL);  }  return ((CDevice*) (new LaserCSpace(interface, cf, section)));}// a driver registration functionvoid LaserCSpace_Register(DriverTable* table){  table->AddDriver("lasercspace", PLAYER_READ_MODE, LaserCSpace_Init);}////////////////////////////////////////////////////////////////////////////////// ConstructorLaserCSpace::LaserCSpace(char* interface, ConfigFile* cf, int section)    : CDevice(0, 0, 0, 1){  // Info for the underlying laser device.  this->laser_index = cf->ReadInt(section, "laser", 0);  this->laser_device = NULL;  this->laser_timesec = 0;  this->laser_timeusec = 0;  // Settings.  this->radius = cf->ReadLength(section, "radius", 0.50);  this->sample_step = cf->ReadInt(section, "step", 1);    // Outgoing data  this->timesec = 0;  this->timeusec = 0;  memset(&this->data, 0, sizeof(this->data));  return;}////////////////////////////////////////////////////////////////////////////////// Set up the device (called by server thread).int LaserCSpace::Setup(){  player_device_id_t id;    // Subscribe to the laser.  id.code = PLAYER_LASER_CODE;  id.index = this->laser_index;  id.port = this->device_id.port;  this->laser_device = deviceTable->GetDevice(id);  if (!this->laser_device)  {    PLAYER_ERROR("unable to locate suitable laser device");    return(-1);  }  if (this->laser_device == this)  {    PLAYER_ERROR("attempt to subscribe to self");    return(-1);  }  if (this->laser_device->Subscribe(this) != 0)  {    PLAYER_ERROR("unable to subscribe to laser device");    return(-1);  }  return 0;}////////////////////////////////////////////////////////////////////////////////// Shutdown the device (called by server thread).int LaserCSpace::Shutdown(){  // Unsubscribe from devices.  this->laser_device->Unsubscribe(this);    return 0;}////////////////////////////////////////////////////////////////////////////////// Get data from buffer (called by server thread)size_t LaserCSpace::GetData(void* client, unsigned char *dest, size_t maxsize,                            uint32_t* timesec, uint32_t* timeusec){  // Get the current laser data.  this->laser_device->GetData(client, (uint8_t*) &this->laser_data, sizeof(this->laser_data),                              &this->laser_timesec, &this->laser_timeusec);    // If there is new laser data, update our data.  Otherwise, we will  // just reuse the existing data.  if (this->laser_timesec != this->timesec || this->laser_timeusec != this->timeusec)    this->UpdateLaser();  // Copy results  assert(maxsize >= sizeof(this->data));  memcpy(dest, &this->data, sizeof(this->data));  // Copy the laser timestamp  this->timesec = this->laser_timesec;  this->timeusec = this->laser_timeusec;  *timesec = this->timesec;  *timeusec = this->timeusec;  return (sizeof(this->data));}////////////////////////////////////////////////////////////////////////////////// Process laser data.int LaserCSpace::UpdateLaser(){  int i;  double r;    // Do some byte swapping on the laser data.  this->laser_data.resolution = ntohs(this->laser_data.resolution);  this->laser_data.min_angle = ntohs(this->laser_data.min_angle);  this->laser_data.max_angle = ntohs(this->laser_data.max_angle);  this->laser_data.range_count = ntohs(this->laser_data.range_count);  for (i = 0; i < this->laser_data.range_count; i++)    this->laser_data.ranges[i] = ntohs(this->laser_data.ranges[i]);  // Construct the outgoing laser packet  this->data.resolution = this->laser_data.resolution;  this->data.min_angle = this->laser_data.min_angle;  this->data.max_angle = this->laser_data.max_angle;  this->data.range_count = this->laser_data.range_count;  // Do some precomputations to save time  this->Precompute();  // Generate the range estimate for each bearing.  for (i = 0; i < this->laser_data.range_count; i++)  {    r = this->FreeRange(i);    this->data.ranges[i] = (int16_t) (r * 1000);  }    // Do some byte swapping on the outgoing data.  this->data.resolution = htons(this->data.resolution);  this->data.min_angle = htons(this->data.min_angle);  this->data.max_angle = htons(this->data.max_angle);  for (i = 0; i < this->data.range_count; i++)    this->data.ranges[i] = htons(this->data.ranges[i]);  this->data.range_count = htons(this->data.range_count);  return 1;}////////////////////////////////////////////////////////////////////////////////// Pre-compute a bunch of stuffvoid LaserCSpace::Precompute(){  int i;  double r, b, x, y;    for (i = 0; i < this->laser_data.range_count; i++)  {    r = (double) (this->laser_data.ranges[i]) / 1000;    b = (double) (this->laser_data.min_angle +                  this->laser_data.resolution * i) / 100.0 * M_PI / 180;    x = r * cos(b);    y = r * sin(b);    this->lu[i][0] = r;    this->lu[i][1] = b;    this->lu[i][2] = x;    this->lu[i][3] = y;  }  return;}  ////////////////////////////////////////////////////////////////////////////////// Compute the maximum free-space range for sample n.double LaserCSpace::FreeRange(int n){  int i, step;  double r, b, x, y;  double r_, b_, x_, y_;  double s, nr, nx, ny, dx, dy;  double d, h;  double max_r;  // Step size for subsampling the scan (saves CPU cycles)  step = this->sample_step;    // Range and bearing of this reading.  r = this->lu[n][0];  b = this->lu[n][1];  x = this->lu[n][2];  y = this->lu[n][3];    max_r = r - this->radius;  // Look for intersections with obstacles.  for (i = 0; i < this->laser_data.range_count; i += step)  {    r_ = this->lu[i][0];    if (r_ - this->radius > max_r)      continue;    b_ = this->lu[i][1];    x_ = this->lu[i][2];    y_ = this->lu[i][3];      // Compute parametric point on ray that is nearest the obstacle.    s = (x * x_ + y * y_) / (x * x + y * y);    if (s < 0 || s > 1)      continue;    // Compute the nearest point.    nr = s * r;    nx = s * x;    ny = s * y;    // Compute distance from nearest point to obstacle.    dx = nx - x_;    dy = ny - y_;    d = sqrt(dx * dx + dy * dy);        if (d > this->radius)      continue;        // Compute the shortened range.    h = nr - sqrt(this->radius * this->radius - d * d);    if (h < max_r)      max_r = h;  }  // Clip negative ranges.  if (max_r < 0)    max_r = 0;  return max_r;}////////////////////////////////////////////////////////////////////////////////// Put configuration in buffer (called in server thread)int LaserCSpace::PutConfig(player_device_id_t* device, void *client, void *data, size_t len) {  uint8_t subtype;  if (len < 1)  {    PLAYER_ERROR("empty requestion; ignoring");    return 0;  }  subtype = ((uint8_t*) data)[0];    switch (subtype)  {    case PLAYER_LASER_GET_GEOM:      HandleGetGeom(client, data, len);      break;    default:      if (PutReply(client, PLAYER_MSGTYPE_RESP_NACK) != 0)        PLAYER_ERROR("PutReply() failed");      break;  }  return 0;}////////////////////////////////////////////////////////////////////////////////// Handle geometry requests.void LaserCSpace::HandleGetGeom(void *client, void *request, int len){  unsigned short reptype;  struct timeval ts;  player_laser_geom_t rep;  int replen;      // Get the geometry from the laser  replen = this->laser_device->Request(&this->laser_device->device_id, this, request, len,                                       &reptype, &ts, &rep, sizeof(rep));  if (replen <= 0 || replen != sizeof(rep))  {    PLAYER_ERROR("unable to get geometry from laser device");    if (PutReply(client, PLAYER_MSGTYPE_RESP_NACK) != 0)      PLAYER_ERROR("PutReply() failed");  }      if (PutReply(client, PLAYER_MSGTYPE_RESP_ACK, &ts, &rep, sizeof(rep)) != 0)    PLAYER_ERROR("PutReply() failed");  return;}

⌨️ 快捷键说明

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