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

📄 laservisualbw.cc

📁 机器人仿真软件
💻 CC
📖 第 1 页 / 共 2 页
字号:
  int i;  double r, b;  double mn, mr, mb;  mn = 0.0;  mr = 1e6;  mb = 0.0;  for (i = first; i <= last; i++)  {    r = (double) (data->ranges[i]) / 1000;    b = (double) (data->min_angle + i * data->resolution) / 100.0 * M_PI / 180;    if (r < mr)      mr = r;    mn += 1.0;    mb += b;  }  mr += this->barwidth / 2;  mb /= mn;  pose[0] = mr * cos(mb);  pose[1] = mr * sin(mb);  pose[2] = mb;  return;}////////////////////////////////////////////////////////////////////////////////// Match a new laser fiducial against the ones we are already// tracking.  The pose is relative to the laser.void LaserVisualBW::MatchLaserFiducial(double time, double pose[3]){  int i;  double dx, dy, dr;  double mindr;  fiducial_t *fiducial;  fiducial_t *minfiducial;    // Observations must be at least this close to the existing  // fiducial.  mindr = this->max_dist;  minfiducial = NULL;  // Find the existing fiducial which is closest to the new  // observation.  for (i = 0; i < this->fiducial_count; i++)  {    fiducial = this->fiducials + i;    dx = pose[0] - fiducial->pose[0];    dy = pose[1] - fiducial->pose[1];    dr = sqrt(dx * dx + dy * dy);    if (dr < mindr)    {      mindr = dr;      minfiducial = fiducial;    }  }  // If we didnt find a matching fiducial, add a new one.  if (minfiducial == NULL)  {    if (this->fiducial_count < ARRAYSIZE(this->fiducials))    {      minfiducial = this->fiducials + this->fiducial_count++;      minfiducial->id = -1;      minfiducial->pose[0] = pose[0];      minfiducial->pose[1] = pose[1];      minfiducial->pose[2] = pose[2];      minfiducial->laser_time = time;      minfiducial->ptz_select_time = -1;      minfiducial->ptz_lockon_time = -1;      minfiducial->id_time = -1;    }  }  // Otherwise, update the existing fiducial.  else  {    minfiducial->pose[0] = pose[0];    minfiducial->pose[1] = pose[1];    minfiducial->pose[2] = pose[2];    minfiducial->laser_time = time;  }    return;}////////////////////////////////////////////////////////////////////////////////// Retire fiducials we havent seen for a while.void LaserVisualBW::RetireLaserFiducials(double time, player_laser_data_t *data){  int i;  fiducial_t *fiducial;    // Remove any old fiducials.  for (i = 0; i < this->fiducial_count; i++)  {    fiducial = this->fiducials + i;    if (time - fiducial->laser_time > this->retire_time)    {      if (this->ptz_fiducial == fiducial)        this->ptz_fiducial = NULL;      memmove(fiducial, fiducial + 1, (this->fiducial_count - i - 1) * sizeof(fiducial_t));      this->fiducial_count--;      i--;    }  }  return;}////////////////////////////////////////////////////////////////////////////////// Update the PTZ to point at one of the laser reflectors.int LaserVisualBW::UpdatePtz(player_ptz_data_t * data, double timestamp){  this->ptz_time = timestamp;    // Pick a fiducial to look at.  this->SelectPtzTarget(timestamp, data);  // Point the fiducial  this->ServoPtz(timestamp, data);  return 1;}////////////////////////////////////////////////////////////////////////////////// Select a target fiducial for the PTZ to inspect.// This algorithm picks the one that we havent looked at for a long time.void LaserVisualBW::SelectPtzTarget(double time, player_ptz_data_t *data){  int i;  double t, maxt;  fiducial_t *fiducial;  // Consider the currently selected target for a while to  // give the blobfinder time to identify it.  if (this->ptz_fiducial != NULL)  {    if (time - this->ptz_fiducial->ptz_select_time < this->max_ptz_attention)      return;  }  // Find one we havent looked at for while.  this->ptz_fiducial = NULL;  maxt = -1;    for (i = 0; i < this->fiducial_count; i++)  {    fiducial = this->fiducials + i;    t = time - fiducial->ptz_select_time;    if (t > maxt)    {      maxt = t;      this->ptz_fiducial = fiducial;    }  }  if (this->ptz_fiducial)  {    this->ptz_fiducial->ptz_select_time = time;    this->ptz_fiducial->ptz_lockon_time = -1;  }    return;}////////////////////////////////////////////////////////////////////////////////// Servo the PTZ to a target fiducial.void LaserVisualBW::ServoPtz(double time, player_ptz_data_t *data){  double dx, dy, r, pan, tilt, zoom;  fiducial_t *fiducial;  player_ptz_cmd_t cmd;  double maxtilt;  double deadpan, deadzoom;  // Max tilt value.  maxtilt = 5 * M_PI / 180;  // Deadband values.  deadpan = 2;  deadzoom = 2;    fiducial = this->ptz_fiducial;  if (fiducial == NULL)  {    r = 0;    pan = 0;    tilt = 0;    zoom = M_PI;  }  else  {    // Compute range and bearing of fiducial relative to camera.    // TODO: account for camera geometry.    dx = fiducial->pose[0];    dy = fiducial->pose[1];    r = sqrt(dx * dx + dy * dy);    pan = atan2(dy, dx);    zoom = 8 * atan2(this->barwidth / 2, r);    // See if we have locked on yet.    if (fiducial->ptz_lockon_time < 0)      if (fabs(pan * 180 / M_PI - data->pan) < deadpan &&          fabs(zoom * 180 / M_PI - data->zoom) < deadzoom)        fiducial->ptz_lockon_time = time;    // If we havent locked on yet...    if (fiducial->ptz_lockon_time < 0)      tilt = 0;    else      tilt = maxtilt * sin((time - fiducial->ptz_lockon_time) /                           this->max_ptz_attention * 2 * M_PI);  }    // Compose the command packet to send to the PTZ device.  cmd.pan = pan;  cmd.tilt = tilt;  cmd.zoom = zoom;    this->ptz->PutMsg(InQueue, PLAYER_MSGTYPE_CMD, PLAYER_PTZ_CMD_STATE, &cmd, sizeof(cmd), NULL);  // Compute the dimensions of the image at the range of the target fiducial.  this->zoomwidth = 2 * r * tan(data->zoom/2);  this->zoomheight = 3.0 / 4.0 * this->zoomwidth;  return;}////////////////////////////////////////////////////////////////////////////////// Process any new camera data.int LaserVisualBW::UpdateCamera(player_camera_data_t * data, double timestamp){  int id, best_id;  int x;  int symbol_count;  int symbols[480];  this->camera_time = timestamp;    best_id = -1;    // Barcode may not be centered, so look across entire image  for (x = 0; x < this->camera_data.width; x += 16)  {    // Extract raw symbols    symbol_count = this->ExtractSymbols(x, sizeof(symbols) / sizeof(symbols[0]), symbols);    // Identify barcode    id = this->ExtractCode(symbol_count, symbols);    // If we see multiple barcodes, we dont know which is the correct one    if (id >= 0)    {      if (best_id < 0)      {        best_id = id;      }      else if (best_id != id)      {        best_id = -1;        break;      }    }  }  // Assign id to fiducial we are currently looking at.  // TODO: check for possible aliasing (not looking at the correct barcode).  if (best_id >= 0 && this->ptz_fiducial)  {    if (this->ptz_fiducial->ptz_lockon_time >= 0)    {      this->ptz_fiducial->id = best_id;      this->ptz_fiducial->id_time = timestamp;    }  }    return 1;}////////////////////////////////////////////////////////////////////////////////// Extract a bit string from the image.  Takes a vertical column in// the image and thresholds it.int LaserVisualBW::ExtractSymbols(int x, int symbol_max_count, int symbols[]){  int i, j, off, inc, pix;  double fn, fv;  int state, start, symbol_count;  double kernel[] = {+1, +2, 0, -2, -1};  // GREY  if (this->camera_data.bpp == 8)  {    off = x * this->camera_data.bpp / 8;    inc = this->camera_data.width * this->camera_data.bpp / 8;  }  // RGB24, use G channel  else if (this->camera_data.bpp == 24)  {    off = x * this->camera_data.bpp / 8 + 1;    inc = this->camera_data.width * this->camera_data.bpp / 8;  }  // RGB32, use G channel  else if (this->camera_data.bpp == 32)  {    off = x * this->camera_data.bpp / 8 + 1;    inc = this->camera_data.width * this->camera_data.bpp / 8;  }  else  {    PLAYER_ERROR1("no support for image depth %d", this->camera_data.bpp);    return 0;  }  //FILE *file = fopen("edge.out", "a+");  assert(symbol_max_count >= this->camera_data.height);  state = -1;  start = -1;  symbol_count = 0;  for (i = 2, pix = off + 2 * inc; i < this->camera_data.height - 2; i++, pix += inc)  {   // Run an edge detector    fn = fv = 0.0;    for (j = -2; j <= 2; j++)    {      fv += kernel[j + 2] * this->camera_data.image[pix + j * inc];      fn += fabs(kernel[j + 2]);    }    fv /= fn;        // Pick the transitions    if (state == -1)    {      if (fv > +this->edge_thresh)      {        state = 1;        start = i;      }      else if (fv < -this->edge_thresh)      {        state = 0;        start = i;      }    }    else if (state == 0)    {      if (fv > +this->edge_thresh)      {        symbols[symbol_count++] = -(i - start);        state = 1;        start = i;      }    }    else if (state == 1)    {      if (fv < -this->edge_thresh)      {        symbols[symbol_count++] = +(i - start);        state = 0;        start = i;      }    }    //fprintf(file, "%d %f %f %d\n", i, fv, fn, state);  }  if (state == 0)    symbols[symbol_count++] = -(i - start);  else if (state == 1)    symbols[symbol_count++] = +(i - start);  //fprintf(file, "\n\n");  //fclose(file);  return symbol_count;}////////////////////////////////////////////////////////////////////////////////// Extract a code from a symbol string.int LaserVisualBW::ExtractCode(int symbol_count, int symbols[]){  int i, j, k;  double a, b, c;  double mean, min, max, wm, wo;  int best_digit;  double best_err;  double err[10];  // These are UPC the mark-space patterns for digits.  From:  // http://www.ee.washington.edu/conselec/Sp96/projects/ajohnson/proposal/project.htm  double digits[][4] =    {      {-3,+2,-1,+1}, // 0      {-2,+2,-2,+1}, // 1      {-2,+1,-2,+2}, // 2      {-1,+4,-1,+1}, // 3      {-1,+1,-3,+2}, // 4      {-1,+2,-3,+1}, // 5      {-1,+1,-1,+4}, // 6      {-1,+3,-1,+2}, // 7      {-1,+2,-1,+3}, // 8      {-3,+1,-1,+2}, // 9    };  best_digit = -1;    // Note that each code has seven symbols in it, not counting the  // initial space.  for (i = 0; i < symbol_count - 7; i++)  {    /*    for (j = 0; j < 7; j++)      printf("%+d", symbols[i + j]);    printf("\n");    */    a = symbols[i];    b = symbols[i + 1];    c = symbols[i + 2];    // Look for a start guard: +N-N+N    if (a > this->guard_min && b < -this->guard_min && c > this->guard_min)    {      mean = (a - b + c) / 3.0;      min = MIN(a, MIN(-b, c));      max = MAX(a, MAX(-b, c));      assert(mean > 0);      if ((mean - min) / mean > this->guard_tol)        continue;      if ((max - mean) / mean > this->guard_tol)        continue;      //printf("guard %d %.2f\n", i, mean);      best_err = this->err_first;      best_digit = -1;            // Read the code digit (4 symbols) and compare against the known      // digit patterns      for (k = 0; k < (int) (sizeof(digits) / sizeof(digits[0])); k++)      {        err[k] = 0;                for (j = 0; j < 4; j++)        {          wm = digits[k][j];          wo = symbols[i + 3 + j] / mean;          err[k] += fabs(wo - wm);          //printf("digit %d = %.3f %.3f\n", k, wm, wo);        }        //printf("digit %d = %.3f\n", k, err[k]);        if (err[k] < best_err)        {          best_err = err[k];          best_digit = k;        }      }      // Id is good if it fits on and *only* one pattern.  So find the      // second best digit and make sure it has a much higher error.      for (k = 0; k < (int) (sizeof(digits) / sizeof(digits[0])); k++)      {        if (k == best_digit)          continue;        if (err[k] < this->err_second)        {          best_digit = -1;          break;        }      }      // Stop if we found a valid digit      if (best_digit >= 0)        break;    }      }  //if (best_digit >= 0)  //  printf("best = %d\n", best_digit);  return best_digit;}////////////////////////////////////////////////////////////////////////////////// Update the device data (the data going back to the client).void LaserVisualBW::WriteData(){  int i;  double r, b, o;  double timestamp;  fiducial_t *fiducial;  player_fiducial_data_t data;  data.fiducials_count = 0;  for (i = 0; i < this->fiducial_count; i++)  {    fiducial = this->fiducials + i;    // Only report fiducials that where seen in the most recent laser    // scan.    if (fiducial->laser_time != this->laser_time)      continue;        r = sqrt(fiducial->pose[0] * fiducial->pose[0] +             fiducial->pose[1] * fiducial->pose[1]);    b = atan2(fiducial->pose[1], fiducial->pose[0]);    o = fiducial->pose[2];    data.fiducials[data.fiducials_count].id = fiducial->id;    data.fiducials[data.fiducials_count].pose.px = r * cos(b);    data.fiducials[data.fiducials_count].pose.py = r * sin(b);    data.fiducials[data.fiducials_count].pose.pyaw = o;    data.fiducials_count++;  }    // Compute the data timestamp (from laser).  timestamp = this->laser_time;    // Copy data to server.  Publish(device_addr, NULL, PLAYER_MSGTYPE_DATA, PLAYER_FIDUCIAL_DATA_SCAN, (void*) &data, sizeof(data), &timestamp);}

⌨️ 快捷键说明

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