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

📄 laservisualbarcode.cc

📁 机器人仿真平台,和stage配合运行
💻 CC
📖 第 1 页 / 共 2 页
字号:
/* *  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 detecting combined laser/visual barcodes.// Author: Andrew Howard// Date: 17 Aug 2002// CVS: $Id: laservisualbarcode.cc,v 1.1 2002/11/29 17:07:24 gerkey Exp $//// Theory of operation://   Parses a laser scan to find the retro-reflective patches (lines or//   circles), then points the camera at the patch, zooms in, and//   attempts to read the colored barcode.  Will not return sensible//   orientations for circular patches.//// Requires://   Laser, PTZ and blobfinder devices./////////////////////////////////////////////////////////////////////////////#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 detecting laser retro-reflectors.class LaserVisualBarcode : public CDevice{  // Constructor  public: LaserVisualBarcode(char* interface, ConfigFile* cf, int section);  // Setup/shutdown routines.  public: virtual int Setup();  public: virtual int Shutdown();  // Main function for device thread.  private: virtual void Main();  // Process requests.  Returns 1 if the configuration has changed.  private: int HandleRequests();  // Handle geometry requests.  private: void HandleGetGeom(void *client, void *req, int reqlen);  // Process laser data.  // Returns non-zero if the laser data has been updated.  private: int UpdateLaser();  // Info on potential fiducials.  private: struct fiducial_t  {    // Id (-1) if undetermined.    int id;    // Pose of fiducial.    double pose[3];    // Uncertainty in pose.    double upose[3];    // Time at which fiducial was last seen by the laser.    double laser_time;    // Time at which ptz selected this fiducial,    // and the time at which the ptz locked on to this fiducial.    double ptz_select_time;    double ptz_lockon_time;    // Time at which the fiducial was identified.    double id_time;  };  // Info on valid blobs.  private: struct blob_t  {    // Blob channel.    int ch;      // Blob position in image.    int x, y;  };  // Analyze the laser data to find fidicuials (reflectors).  private: void FindLaserFiducials(double time, player_laser_data_t *data);      // Find the line of best fit for the given segment of the laser  // scan.  Fills in the pose of the reflector relative to the laser.  private: void FitLaserFiducial(player_laser_data_t *data, int first, int last, double pose[3]);  // Match a new laser fiducial against the ones we are already  // tracking.  The pose is relative to the laser.  private: void MatchLaserFiducial(double time, double pose[3]);  // Retire fiducials we havent seen for a while.  private: void RetireLaserFiducials(double time, player_laser_data_t *data);  // Update the PTZ to point at one of the laser reflectors.  private: int UpdatePtz();  // Select a target fiducial for the PTZ to inspect.  private: void SelectPtzTarget(double time, player_ptz_data_t *data);  // Servo the PTZ to a target fiducial.  private: void ServoPtz(double time, player_ptz_data_t *data);  // Process any new blobfinder data.  private: int UpdateBlobfinder();  // Find blobs with valid properties.  private: void FindBlobs(double time, player_blobfinder_data_t *data);  // Search the list of valid blobs to locate the visual fiducials.  private: int FindVisualFiducials(double time, player_blobfinder_data_t *data,                                   int depth, blob_t *prevblob);      // Update the device data (the data going back to the client).  private: void UpdateData();    // Fiducial properties.  private: int barcount;  private: double barwidth, barheight;  // Max time to spend looking at a fiducial.  private: double max_ptz_attention;  // Retirement age for fiducials that havent been seen for a while.  private: double retire_time;  // Max distance between fiducials in successive laser scans.  private: double max_dist;  // Laser stuff.  private: int laser_index;  private: CDevice *laser;  private: double laser_time;  // PTZ stuff  private: int ptz_index;  private: CDevice *ptz;  private: double ptz_time;  // Blobfinder stuff.  private: int blobfinder_index;  private: CDevice *blobfinder;  private: double blobfinder_time;  // List of currently tracked fiducials.  private: int fiducial_count;  private: fiducial_t fiducials[256];  // The current selected fiducial for the ptz, the time at which we  // selected it, and the time at which we first locked on to it.  private: fiducial_t *ptz_fiducial;  // Dimensions of the zoomed image for the target fiducial (m).  private: double zoomwidth, zoomheight;  // List of current valid blobs.  private: int blob_count;  private: blob_t blobs[256];    // Local copy of the current fiducial data.  private: player_fiducial_data_t fdata;};// Initialization functionCDevice* LaserVisualBarcode_Init(char* interface, ConfigFile* cf, int section){  if (strcmp(interface, PLAYER_FIDUCIAL_STRING) != 0)  {    PLAYER_ERROR1("driver \"laservisualbarcode\" does not support interface \"%s\"\n",                  interface);    return (NULL);  }  return ((CDevice*) (new LaserVisualBarcode(interface, cf, section)));}// a driver registration functionvoid LaserVisualBarcode_Register(DriverTable* table){  table->AddDriver("laservisualbarcode", PLAYER_READ_MODE, LaserVisualBarcode_Init);}////////////////////////////////////////////////////////////////////////////////// ConstructorLaserVisualBarcode::LaserVisualBarcode(char* interface, ConfigFile* cf, int section)    : CDevice(sizeof(player_fiducial_data_t), 0, 10, 10){  this->laser_index = cf->ReadInt(section, "laser", 0);  this->laser = NULL;  this->laser_time = 0;  this->ptz_index = cf->ReadInt(section, "ptz", 0);  this->ptz = NULL;  this->ptz_time = 0;  this->blobfinder_index = cf->ReadInt(section, "blobfinder", 0);  this->blobfinder = NULL;  this->blobfinder_time = 0;  this->max_ptz_attention = cf->ReadFloat(section, "max_ptz_attention", 2.0);  this->retire_time = cf->ReadFloat(section, "retire_time", 1.0);  this->max_dist = cf->ReadFloat(section, "max_dist", 0.2);    // Default fiducial properties.  this->barcount = cf->ReadInt(section, "bit_count", 3);  this->barwidth = cf->ReadLength(section, "bit_width", 0.08);  this->barheight = cf->ReadLength(section, "bit_height", 0.02);  // Reset fiducial list.  this->fiducial_count = 0;  // Reset PTZ target.  this->ptz_fiducial = NULL;  // Reset blob list.  this->blob_count = 0;  return;}////////////////////////////////////////////////////////////////////////////////// Set up the device (called by server thread).int LaserVisualBarcode::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 = deviceTable->GetDevice(id);  if (!this->laser)  {    PLAYER_ERROR("unable to locate suitable laser device");    return(-1);  }  if (this->laser->Subscribe(this) != 0)  {    PLAYER_ERROR("unable to subscribe to laser device");    return(-1);  }  // Subscribe to the PTZ.  id.code = PLAYER_PTZ_CODE;  id.index = this->ptz_index;  id.port = this->device_id.port;  this->ptz = deviceTable->GetDevice(id);  if (!this->ptz)  {    PLAYER_ERROR("unable to locate suitable PTZ device");    return(-1);  }  if (this->ptz->Subscribe(this) != 0)  {    PLAYER_ERROR("unable to subscribe to PTZ device");    return(-1);  }  // Subscribe to the blobfinder.  id.code = PLAYER_BLOBFINDER_CODE;  id.index = this->blobfinder_index;  id.port = this->device_id.port;  this->blobfinder = deviceTable->GetDevice(id);  if (!this->blobfinder)  {    PLAYER_ERROR("unable to locate suitable blobfinder device");    return(-1);  }  if (this->blobfinder->Subscribe(this) != 0)  {    PLAYER_ERROR("unable to subscribe to blobfinder device");    return(-1);  }  // Reset blob list.  this->blob_count = 0;  // Start the driver thread.  this->StartThread();    return 0;}////////////////////////////////////////////////////////////////////////////////// Shutdown the device (called by server thread).int LaserVisualBarcode::Shutdown(){  // Stop the driver thread.  StopThread();    // Unsubscribe from devices.  this->blobfinder->Unsubscribe(this);  this->ptz->Unsubscribe(this);  this->laser->Unsubscribe(this);  return 0;}////////////////////////////////////////////////////////////////////////////////// Main function for device threadvoid LaserVisualBarcode::Main() {  while (true)  {    // Go to sleep for a while (this is a polling loop).    usleep(10000);    // Test if we are supposed to cancel this thread.    pthread_testcancel();    // Process any pending requests.    HandleRequests();    // Process any new laser data.    if (UpdateLaser())    {      // Update the device data (the data going back to the client).      UpdateData();    }    // Process any new PTZ data.    UpdatePtz();    // Process any new blobfinder data.    UpdateBlobfinder();  }}////////////////////////////////////////////////////////////////////////////////// Process requests.  Returns 1 if the configuration has changed.int LaserVisualBarcode::HandleRequests(){  void *client;  char request[PLAYER_MAX_REQREP_SIZE];  int len;    while ((len = GetConfig(&client, &request, sizeof(request))) > 0)  {    switch (request[0])    {      case PLAYER_FIDUCIAL_GET_GEOM:        HandleGetGeom(client, request, len);        break;      default:        if (PutReply(client, PLAYER_MSGTYPE_RESP_NACK) != 0)          PLAYER_ERROR("PutReply() failed");        break;    }  }  return 0;}////////////////////////////////////////////////////////////////////////////////// Handle geometry requests.void LaserVisualBarcode::HandleGetGeom(void *client, void *request, int len){  unsigned short reptype;  struct timeval ts;  int replen;  player_laser_geom_t lgeom;  player_fiducial_geom_t fgeom;      // Get the geometry from the laser  replen = this->laser->Request(&this->laser->device_id, this, request, len,                                &reptype, &ts, &lgeom, sizeof(lgeom));  if (replen <= 0 || replen != sizeof(lgeom))  {    PLAYER_ERROR("unable to get geometry from laser device");    if (PutReply(client, PLAYER_MSGTYPE_RESP_NACK) != 0)      PLAYER_ERROR("PutReply() failed");  }  fgeom.pose[0] = lgeom.pose[0];  fgeom.pose[1] = lgeom.pose[1];  fgeom.pose[2] = lgeom.pose[2];  fgeom.size[0] = lgeom.size[0];  fgeom.size[1] = lgeom.size[1];  fgeom.fiducial_size[0] = ntohs((int) (this->barwidth * 1000));  fgeom.fiducial_size[1] = ntohs((int) (this->barwidth * 1000));      if (PutReply(client, PLAYER_MSGTYPE_RESP_ACK, &ts, &fgeom, sizeof(fgeom)) != 0)    PLAYER_ERROR("PutReply() failed");  return;}////////////////////////////////////////////////////////////////////////////////// Process laser data.int LaserVisualBarcode::UpdateLaser(){  int i;  player_laser_data_t data;  size_t size;  uint32_t timesec, timeusec;  double time;    // Get the laser data.  size = this->laser->GetData(this,(unsigned char*) &data, sizeof(data), &timesec, &timeusec);  time = (double) timesec + ((double) timeusec) * 1e-6;    // Dont do anything if this is old data.  if (time == this->laser_time)    return 0;  this->laser_time = time;    // Do some byte swapping on the laser data.  data.resolution = ntohs(data.resolution);  data.min_angle = ntohs(data.min_angle);  data.max_angle = ntohs(data.max_angle);  data.range_count = ntohs(data.range_count);  for (i = 0; i < data.range_count; i++)    data.ranges[i] = ntohs(data.ranges[i]);  // Find possible fiducials in this scan.  this->FindLaserFiducials(time, &data);  // Retire fiducials we havent seen for a while.  this->RetireLaserFiducials(time, &data);  return 1;}////////////////////////////////////////////////////////////////////////////////// Analyze the laser data to find fidicuials (reflectors).void LaserVisualBarcode::FindLaserFiducials(double time, player_laser_data_t *data){  int i, h;  int valid;  double r, b;  double db, dr;  double mn, mr, mb, mrr, mbb;  double pose[3];  // Empty the fiducial list.  this->fdata.count = 0;    // Initialise patch statistics.  mn = 0.0;  mr = 0.0;  mb = 0.0;  mrr = 0.0;  mbb = 0.0;      // Look for a candidate patch in scan.  for (i = 0; i < data->range_count; i++)  {    r = (double) (data->ranges[i]) / 1000;    b = (double) (data->min_angle + i * data->resolution) / 100.0 * M_PI / 180;    h = (int) (data->intensity[i]);    // If there is a reflection...    if (h > 0)    {      mn += 1;      mr += r;      mb += b;      mrr += r * r;      mbb += b * b;    }    // If there is no reflection and we have a patch...    else if (mn > 0)    {      // Compute the moments of the patch.      mr /= mn;      mb /= mn;      mrr = mrr / mn - mr * mr;      mbb = mbb / mn - mb * mb;      // Test moments to see if they are valid.      valid = 1;      valid &= (mn >= 1.0);      dr = this->barwidth / 2;      db = atan2(this->barwidth / 2, mr);      valid &= (mrr < (dr * dr));      valid &= (mbb < (db * db));            if (valid)      {        // Do a best fit to determine the pose of the reflector.

⌨️ 快捷键说明

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