sip.cpp
Go to the documentation of this file.
1 /*
2  * P2OS for ROS
3  * Copyright (C) 2009 David Feil-Seifer, Brian Gerkey, Kasper Stoy,
4  * Richard Vaughan, & Andrew Howard
5  * Copyright (C) 2018 Hunter L. Allen
6  *
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21  */
22 
23 
24 #include <stdio.h>
25 #include <limits.h>
26 #include <math.h> /* rint(3) */
27 #include <sys/types.h>
28 #include <stdlib.h> /* for abs() */
29 #include <unistd.h>
30 
31 #include <p2os_driver/sip.hpp>
32 #include <tf/tf.h>
33 #include <tf/transform_datatypes.h>
34 #include <sstream>
35 
37 {
39  // odometry
40 
41  double px, py, pa;
42 
43  // initialize position to current offset
44  px = this->x_offset / 1e3;
45  py = this->y_offset / 1e3;
46  // now transform current position by rotation if there is one
47  // and add to offset
48  if (this->angle_offset != 0) {
49  double rot = DTOR(this->angle_offset); // convert rotation to radians
50  px += ((this->xpos / 1e3) * cos(rot) -
51  (this->ypos / 1e3) * sin(rot));
52  py += ((this->xpos / 1e3) * sin(rot) +
53  (this->ypos / 1e3) * cos(rot));
54  pa = DTOR(this->angle_offset + angle);
55  } else {
56  px += this->xpos / 1e3;
57  py += this->ypos / 1e3;
58  pa = DTOR(this->angle);
59  }
60 
61  // timestamps get set in the p2os::StandardSIPPutData fcn
62  data->position.header.frame_id = odom_frame_id;
63  data->position.child_frame_id = base_link_frame_id;
64 
65  data->position.pose.pose.position.x = px;
66  data->position.pose.pose.position.y = py;
67  data->position.pose.pose.position.z = 0.0;
68  data->position.pose.pose.orientation = tf::createQuaternionMsgFromYaw(pa);
69 
70  // add rates
71  data->position.twist.twist.linear.x = ((lvel + rvel) / 2) / 1e3;
72  data->position.twist.twist.linear.y = 0.0;
73  data->position.twist.twist.angular.z =
74  static_cast<double>((rvel - lvel) / (2.0 / PlayerRobotParams[param_idx].DiffConvFactor));
75 
76 
77  data->position.pose.covariance = {
78  1e-3, 0, 0, 0, 0, 0, 0, 1e-3, 0, 0, 0, 0, 0, 0, 1e6, 0, 0, 0, 0, 0, 0, 1e6, 0, 0, 0, 0, 0, 0,
79  1e6, 0, 0, 0, 0, 0, 0, 1e3
80  };
81 
82  data->position.twist.covariance = {
83  1e-3, 0, 0, 0, 0, 0, 0, 1e-3, 0, 0, 0, 0, 0, 0, 1e6, 0, 0, 0, 0, 0, 0, 1e6, 0, 0, 0, 0, 0, 0,
84  1e6, 0, 0, 0, 0, 0, 0, 1e3
85  };
86 
87 
88  // publish transform
89  data->odom_trans.header = data->position.header;
90  data->odom_trans.child_frame_id = data->position.child_frame_id;
91  data->odom_trans.transform.translation.x = px;
92  data->odom_trans.transform.translation.y = py;
93  data->odom_trans.transform.translation.z = 0;
94  data->odom_trans.transform.rotation = tf::createQuaternionMsgFromYaw(pa);
95 
96  // battery
97  data->batt.voltage = battery / 10.0;
98 
99  // motor state
100  // The below will tell us if the motors are currently moving or not, it does
101  // not tell us whether they have been enabled
102  // data->motors.state = (status & 0x01);
103  data->motors.state = motors_enabled & 0x01;
104  /*
106  // compass
107  memset(&(data->compass),0,sizeof(data->compass));
108  data->compass.pos.pa = DTOR(this->compass);
109  */
110 
112  // sonar
113  data->sonar.ranges_count = static_cast<int>(sonarreadings);
114  data->sonar.ranges.clear();
115  for (int i = 0; i < data->sonar.ranges_count; i++) {
116  data->sonar.ranges.emplace_back(sonars[i] / 1e3);
117  }
118 
120  // gripper
121  unsigned char gripState = timer;
122  if ((gripState & 0x01) && (gripState & 0x02) && !(gripState & 0x04)) {
123  data->gripper.grip.state = PLAYER_GRIPPER_STATE_ERROR;
124  data->gripper.grip.dir = 0;
125  } else if (gripState & 0x04) {
126  data->gripper.grip.state = PLAYER_GRIPPER_STATE_MOVING;
127  if (gripState & 0x01) {
128  data->gripper.grip.dir = 1;
129  }
130  if (gripState & 0x02) {
131  data->gripper.grip.dir = -1;
132  }
133  } else if (gripState & 0x01) {
134  data->gripper.grip.state = PLAYER_GRIPPER_STATE_OPEN;
135  data->gripper.grip.dir = 0;
136  } else if (gripState & 0x02) {
137  data->gripper.grip.state = PLAYER_GRIPPER_STATE_CLOSED;
138  data->gripper.grip.dir = 0;
139  }
140 
141  // Reset data to false
142  data->gripper.grip.inner_beam = false;
143  data->gripper.grip.outer_beam = false;
144  data->gripper.grip.left_contact = false;
145  data->gripper.grip.right_contact = false;
146 
147  if (digin & 0x08) {
148  data->gripper.grip.inner_beam = true;
149  }
150  if (digin & 0x04) {
151  data->gripper.grip.outer_beam = true;
152  }
153  if (!(digin & 0x10)) {
154  data->gripper.grip.left_contact = true;
155  }
156  if (!(digin & 0x20)) {
157  data->gripper.grip.right_contact = true;
158  }
159 
160  // lift
161  data->gripper.lift.dir = 0;
162 
163  if ((gripState & 0x10) && (gripState & 0x20) && !(gripState & 0x40)) {
164  // In this case, the lift is somewhere in between, so
165  // must be at an intermediate carry position. Use last commanded position
166  data->gripper.lift.state = PLAYER_ACTARRAY_ACTSTATE_IDLE;
167  data->gripper.lift.position = lastLiftPos;
168  } else if (gripState & 0x40) { // Moving
169  data->gripper.lift.state = PLAYER_ACTARRAY_ACTSTATE_MOVING;
170  // There is no way to know where it is for sure, so use last commanded
171  // position.
172  data->gripper.lift.position = lastLiftPos;
173  if (gripState & 0x10) {
174  data->gripper.lift.dir = 1;
175  } else if (gripState & 0x20) {
176  data->gripper.lift.dir = -1;
177  }
178  } else if (gripState & 0x10) { // Up
179  data->gripper.lift.state = PLAYER_ACTARRAY_ACTSTATE_IDLE;
180  data->gripper.lift.position = 1.0f;
181  data->gripper.lift.dir = 0;
182  } else if (gripState & 0x20) { // Down
183  data->gripper.lift.state = PLAYER_ACTARRAY_ACTSTATE_IDLE;
184  data->gripper.lift.position = 0.0f;
185  data->gripper.lift.dir = 0;
186  } else { // Assume stalled
187  data->gripper.lift.state = PLAYER_ACTARRAY_ACTSTATE_STALLED;
188  }
189  // Store the last lift position
190  lastLiftPos = data->gripper.lift.position;
191 
192  /*
194  // bumper
195  unsigned int bump_count = PlayerRobotParams[param_idx].NumFrontBumpers + PlayerRobotParams[param_idx].NumRearBumpers;
196  if (data->bumper.bumpers_count != bump_count)
197  {
198  data->bumper.bumpers_count = bump_count;
199  delete [] data->bumper.bumpers;
200  data->bumper.bumpers = new uint8_t[bump_count];
201  }
202  int j = 0;
203  for(int i=PlayerRobotParams[param_idx].NumFrontBumpers-1;i>=0;i--)
204  data->bumper.bumpers[j++] =
205  (unsigned char)((this->frontbumpers >> i) & 0x01);
206  for(int i=PlayerRobotParams[param_idx].NumRearBumpers-1;i>=0;i--)
207  data->bumper.bumpers[j++] =
208  (unsigned char)((this->rearbumpers >> i) & 0x01);
209  */
210 
212  // digital I/O
213  data->dio.count = 8;
214  data->dio.bits = static_cast<unsigned int>(this->digin);
215 
217  // analog I/O
218  // TODO(allenh1): should do this smarter, based on which analog input is selected
219  data->aio.voltages_count = static_cast<unsigned char>(1);
220  // if (!data->aio.voltages)
221  // data->aio.voltages = new float[1];
222  // data->aio.voltages[0] = (this->analog / 255.0) * 5.0;
223  data->aio.voltages.clear();
224  data->aio.voltages.push_back((this->analog / 255.0) * 5.0);
225 }
226 
227 int SIP::PositionChange(uint16_t from, uint16_t to)
228 {
229  int diff1, diff2;
230 
231  /* find difference in two directions and pick int16_test */
232  if (to > from) {
233  diff1 = to - from;
234  diff2 = -(from + 4096 - to);
235  } else {
236  diff1 = to - from;
237  diff2 = 4096 - from + to;
238  }
239  return abs(diff1) < abs(diff2) ? diff1 : diff2;
240 }
241 
243 {
244  int i;
245 
246  ROS_DEBUG("lwstall:%d rwstall:%d\n", lwstall, rwstall);
247 
248  std::stringstream front_bumper_info;
249  for (int i = 0; i < 5; i++) {
250  front_bumper_info << " " <<
251  static_cast<int>((frontbumpers >> i) & 0x01 );
252  }
253  ROS_DEBUG("Front bumpers:%s", front_bumper_info.str().c_str());
254  std::stringstream rear_bumper_info;
255  for (int i = 0; i < 5; i++) {
256  rear_bumper_info << " " <<
257  static_cast<int>((rearbumpers >> i) & 0x01 );
258  }
259  ROS_DEBUG("Rear bumpers:%s", rear_bumper_info.str().c_str());
260 
261  ROS_DEBUG("status: 0x%x analog: %d param_id: %d ", status, analog, param_idx);
262  std::stringstream status_info;
263  for (i = 0; i < 11; i++) {
264  status_info << " " <<
265  static_cast<int>((status >> (7 - i) ) & 0x01);
266  }
267  ROS_DEBUG("status:%s", status_info.str().c_str());
268  std::stringstream digin_info;
269  for (i = 0; i < 8; i++) {
270  digin_info << " " <<
271  static_cast<int>((digin >> (7 - i) ) & 0x01);
272  }
273  ROS_DEBUG("digin:%s", digin_info.str().c_str());
274  std::stringstream digout_info;
275  for (i = 0; i < 8; i++) {
276  digout_info << " " <<
277  static_cast<int>((digout >> (7 - i) ) & 0x01);
278  }
279  ROS_DEBUG("digout:%s", digout_info.str().c_str());
280  ROS_DEBUG("battery: %d compass: %d sonarreadings: %d\n", battery,
282  ROS_DEBUG("xpos: %d ypos:%d ptu:%hu timer:%hu\n", xpos, ypos, ptu, timer);
283  ROS_DEBUG("angle: %d lvel: %d rvel: %d control: %d\n", angle, lvel,
284  rvel, control);
285 
286  PrintSonars();
287  PrintArmInfo();
288  PrintArm();
289 }
290 
292 {
293  if (sonarreadings <= 0) {
294  return;
295  }
296  std::stringstream sonar_info;
297  for (int i = 0; i < sonarreadings; i++) {
298  sonar_info << " " << static_cast<int>(sonars[i]);
299  }
300  ROS_DEBUG("Sonars: %s", sonar_info.str().c_str());
301 }
302 
304 {
305  ROS_DEBUG("Arm power is %s\tArm is %sconnected\n", (armPowerOn ? "on" : "off"),
306  (armConnected ? "" : "not "));
307  ROS_DEBUG("Arm joint status:\n");
308  for (int ii = 0; ii < 6; ii++) {
309  ROS_DEBUG("Joint %d %s %d\n", ii + 1, (armJointMoving[ii] ? "Moving " : "Stopped"),
310  armJointPos[ii]);
311  }
312 }
313 
315 {
316  ROS_DEBUG("Arm version:\t%s\n", armVersionString);
317  ROS_DEBUG("Arm has %d joints:\n", armNumJoints);
318  ROS_DEBUG(" |\tSpeed\tHome\tMin\tCentre\tMax\tTicks/90\n");
319  for (int ii = 0; ii < armNumJoints; ii++) {
320  ROS_DEBUG("%d |\t%d\t%d\t%d\t%d\t%d\t%d\n", ii, armJoints[ii].speed, armJoints[ii].home,
321  armJoints[ii].min, armJoints[ii].centre, armJoints[ii].max, armJoints[ii].ticksPer90);
322  }
323 }
324 
325 void SIP::ParseStandard(unsigned char * buffer)
326 {
327  int cnt = 0, change;
328  uint16_t newxpos, newypos;
329 
330  status = buffer[cnt];
331  cnt += sizeof(unsigned char);
332  /*
333  * Remember P2OS uses little endian:
334  * for a 2 byte int16_t (called integer on P2OS)
335  * byte0 is low byte, byte1 is high byte
336  * The following code is host-machine endian independant
337  * Also we must or (|) bytes together instead of casting to a
338  * int16_t * since on ARM architectures int16_t * must be even byte aligned!
339  * You can get away with this on a i386 since int16_ts * can be
340  * odd byte aligned. But on ARM, the last bit of the pointer will be ignored!
341  * The or'ing will work on either arch.
342  */
343  newxpos = ((buffer[cnt] | (buffer[cnt + 1] << 8)) &
344  0xEFFF) % 4096; /* 15 ls-bits */
345 
346  if (xpos != INT_MAX) {
347  change = static_cast<int>(rint(PositionChange(rawxpos, newxpos) *
348  PlayerRobotParams[param_idx].DistConvFactor));
349  if (abs(change) > 100) {
350  ROS_DEBUG("invalid odometry change [%d]; odometry values are tainted", change);
351  } else {
352  xpos += change;
353  }
354  } else {
355  xpos = 0;
356  }
357  rawxpos = newxpos;
358  cnt += sizeof(int16_t);
359 
360  newypos = ((buffer[cnt] | (buffer[cnt + 1] << 8)) &
361  0xEFFF) % 4096; /* 15 ls-bits */
362 
363  if (ypos != INT_MAX) {
364  change = static_cast<int>(rint(PositionChange(rawypos, newypos) *
365  PlayerRobotParams[param_idx].DistConvFactor));
366  if (abs(change) > 100) {
367  ROS_DEBUG("invalid odometry change [%d]; odometry values are tainted", change);
368  } else {
369  ypos += change;
370  }
371  } else {
372  ypos = 0;
373  }
374  rawypos = newypos;
375  cnt += sizeof(int16_t);
376 
377  angle = (int16_t)
378  rint(((int16_t)(buffer[cnt] | (buffer[cnt + 1] << 8))) *
379  PlayerRobotParams[param_idx].AngleConvFactor * 180.0 / M_PI);
380  cnt += sizeof(int16_t);
381 
382  lvel = (int16_t)
383  rint(((int16_t)(buffer[cnt] | (buffer[cnt + 1] << 8))) *
384  PlayerRobotParams[param_idx].VelConvFactor);
385  cnt += sizeof(int16_t);
386 
387  rvel = (int16_t)
388  rint(((int16_t)(buffer[cnt] | (buffer[cnt + 1] << 8))) *
389  PlayerRobotParams[param_idx].VelConvFactor);
390  cnt += sizeof(int16_t);
391 
392  battery = buffer[cnt];
393  cnt += sizeof(unsigned char);
394  ROS_DEBUG("battery value: %d", battery);
395 
396  lwstall = buffer[cnt] & 0x01;
397  rearbumpers = buffer[cnt] >> 1;
398  cnt += sizeof(unsigned char);
399 
400  rwstall = buffer[cnt] & 0x01;
401  frontbumpers = buffer[cnt] >> 1;
402  cnt += sizeof(unsigned char);
403 
404  control = (int16_t)
405  rint(((int16_t)(buffer[cnt] | (buffer[cnt + 1] << 8))) *
406  PlayerRobotParams[param_idx].AngleConvFactor);
407  cnt += sizeof(int16_t);
408 
409  ptu = (buffer[cnt] | (buffer[cnt + 1] << 8));
410  motors_enabled = buffer[cnt];
411  sonar_flag = buffer[cnt + 1];
412  cnt += sizeof(int16_t);
413 
414  // compass = buffer[cnt]*2;
415  if (buffer[cnt] != 255 && buffer[cnt] != 0 && buffer[cnt] != 181) {
416  compass = (buffer[cnt] - 1) * 2;
417  }
418  cnt += sizeof(unsigned char);
419 
420  unsigned char numSonars = buffer[cnt];
421  cnt += sizeof(unsigned char);
422 
423  if (numSonars > 0) {
424  // find the largest sonar index supplied
425  unsigned char maxSonars = sonarreadings;
426  for (unsigned char i = 0; i < numSonars; i++) {
427  unsigned char sonarIndex = buffer[cnt + i * (sizeof(unsigned char) + sizeof(uint16_t))];
428  if ((sonarIndex + 1) > maxSonars) {maxSonars = sonarIndex + 1;}
429  }
430 
431  // if necessary make more space in the array and preserve existing readings
432  if (maxSonars > sonarreadings) {
433  uint16_t * newSonars = new uint16_t[maxSonars];
434  for (unsigned char i = 0; i < sonarreadings; i++) {
435  newSonars[i] = sonars[i];
436  }
437  if (sonars != NULL) {delete[] sonars;}
438  sonars = newSonars;
439  sonarreadings = maxSonars;
440  }
441 
442  // update the sonar readings array with the new readings
443  for (unsigned char i = 0; i < numSonars; i++) {
444  sonars[buffer[cnt]] = static_cast<uint16_t>(
445  rint((buffer[cnt + 1] | (buffer[cnt + 2] << 8)) *
446  PlayerRobotParams[param_idx].RangeConvFactor));
447  cnt += sizeof(unsigned char) + sizeof(uint16_t);
448  }
449  }
450 
451  timer = (buffer[cnt] | (buffer[cnt + 1] << 8));
452  cnt += sizeof(int16_t);
453 
454  analog = buffer[cnt];
455  cnt += sizeof(unsigned char);
456 
457  digin = buffer[cnt];
458  cnt += sizeof(unsigned char);
459 
460  digout = buffer[cnt];
461  cnt += sizeof(unsigned char);
462  // for debugging:
463  Print();
464  // PrintSonars();
465 }
466 
476 void SIP::ParseSERAUX(unsigned char * buffer)
477 {
478  unsigned char type = buffer[1];
479  if (type != SERAUX && type != SERAUX2) {
480  // Really should never get here...
481  ROS_ERROR("Attempt to parse non SERAUX packet as serial data.\n");
482  return;
483  }
484 
485  int len = static_cast<int>(buffer[0]) - 3; // Get the string length
486 
487  /* First thing is to find the beginning of last full packet (if possible).
488  ** If there are less than CMUCAM_MESSAGE_LEN*2-1 bytes (19), we're not
489  ** guaranteed to have a full packet. If less than CMUCAM_MESSAGE_LEN
490  ** bytes, it is impossible to have a full packet.
491  ** To find the beginning of the last full packet, search between bytes
492  ** len-17 and len-8 (inclusive) for the start flag (255).
493  */
494  int ix;
495  for (ix = (len > 18 ? len - 17 : 2); ix <= len - 8; ix++) {
496  if (buffer[ix] == 255) {
497  break; // Got it!
498  }
499  }
500  if (len < 10 || ix > len - 8) {
501  ROS_ERROR("Failed to get a full blob tracking packet.\n");
502  return;
503  }
504 
505  // There is a special 'S' message containing the tracking color info
506  if (buffer[ix + 1] == 'S') {
507  // Color information (track color)
508  ROS_DEBUG("Tracking color (RGB): %d %d %d\n"
509  " with variance: %d %d %d\n",
510  buffer[ix + 2], buffer[ix + 3], buffer[ix + 4],
511  buffer[ix + 5], buffer[ix + 6], buffer[ix + 7]);
512  blobcolor = buffer[ix + 2] << 16 | buffer[ix + 3] << 8 | buffer[ix + 4];
513  return;
514  }
515 
516  // Tracking packets with centroid info are designated with a 'M'
517  if (buffer[ix + 1] == 'M') {
518  // Now it's easy. Just parse the packet.
519  blobmx = buffer[ix + 2];
520  blobmy = buffer[ix + 3];
521  blobx1 = buffer[ix + 4];
522  bloby1 = buffer[ix + 5];
523  blobx2 = buffer[ix + 6];
524  bloby2 = buffer[ix + 7];
525  blobconf = buffer[ix + 9];
526  // Xiaoquan Fu's calculation for blob area (max 11297).
527  blobarea = (bloby2 - bloby1 + 1) * (blobx2 - blobx1 + 1) * blobconf / 255;
528  return;
529  }
530 
531  ROS_ERROR("Unknown blob tracker packet type: %c\n", buffer[ix + 1]);
532 }
533 
534 // Parse a set of gyro measurements. The buffer is formatted thusly:
535 // length (2 bytes), type (1 byte), count (1 byte)
536 // followed by <count> pairs of the form:
537 // rate (2 bytes), temp (1 byte)
538 // <rate> falls in [0,1023]; less than 512 is CCW rotation and greater
539 // than 512 is CW
540 void
541 SIP::ParseGyro(unsigned char * buffer)
542 {
543  // Get the message length (account for the type byte and the 2-byte
544  // checksum)
545  int len = static_cast<int>(buffer[0] - 3);
546 
547  unsigned char type = buffer[1];
548  if (type != GYROPAC) {
549  // Really should never get here...
550  ROS_ERROR("Attempt to parse non GYRO packet as gyro data.\n");
551  return;
552  }
553 
554  if (len < 1) {
555  ROS_DEBUG("Couldn't get gyro measurement count");
556  return;
557  }
558 
559  // get count
560  int count = static_cast<int>(buffer[2]);
561 
562  // sanity check
563  if ((len - 1) != (count * 3)) {
564  ROS_DEBUG("Mismatch between gyro measurement count and packet length");
565  return;
566  }
567 
568  // Actually handle the rate values. Any number of things could (and
569  // probably should) be done here, like filtering, calibration, conversion
570  // from the gyro's arbitrary units to something meaningful, etc.
571  //
572  // As a first cut, we'll just average all the rate measurements in this
573  // set, and ignore the temperatures.
574  float ratesum = 0;
575  int bufferpos = 3;
576  uint16_t rate;
577  for (int i = 0; i < count; i++) {
578  rate = (uint16_t)(buffer[bufferpos++]);
579  rate |= buffer[bufferpos++] << 8;
580 
581  ratesum += rate;
582  }
583 
584  int32_t average_rate = static_cast<int32_t>(rint(ratesum / static_cast<float>(count)));
585 
586  // store the result for sending
587  gyro_rate = average_rate;
588 }
589 
590 void SIP::ParseArm(unsigned char * buffer)
591 {
592  int length = static_cast<int>(buffer[0]) - 2;
593 
594  if (buffer[1] != ARMPAC) {
595  ROS_ERROR("Attempt to parse a non ARM packet as arm data.\n");
596  return;
597  }
598 
599  if (length < 1 || length != 9) {
600  ROS_DEBUG("ARMpac length incorrect size");
601  return;
602  }
603 
604  unsigned char status = buffer[2];
605  armPowerOn = status & 0x01;
606  armConnected = status & 0x02;
607  unsigned char motionStatus = buffer[3];
608  if (motionStatus & 0x01) {
609  armJointMoving[0] = true;
610  }
611  if (motionStatus & 0x02) {
612  armJointMoving[1] = true;
613  }
614  if (motionStatus & 0x04) {
615  armJointMoving[2] = true;
616  }
617  if (motionStatus & 0x08) {
618  armJointMoving[3] = true;
619  }
620  if (motionStatus & 0x10) {
621  armJointMoving[4] = true;
622  }
623  if (motionStatus & 0x20) {
624  armJointMoving[5] = true;
625  }
626 
627  ::memcpy(armJointPos, &buffer[4], 6);
628  ::memset(armJointPosRads, 0, 6 * sizeof(double));
629 }
630 
631 void SIP::ParseArmInfo(unsigned char * buffer)
632 {
633  int length = static_cast<int>(buffer[0]) - 2;
634  if (buffer[1] != ARMINFOPAC) {
635  ROS_ERROR("Attempt to parse a non ARMINFO packet as arm info.\n");
636  return;
637  }
638 
639  if (length < 1) {
640  ROS_DEBUG("ARMINFOpac length bad size");
641  return;
642  }
643 
644  // Copy the version string
645  if (armVersionString) {
646  free(armVersionString);
647  }
648  // strndup() isn't available everywhere (e.g., Darwin)
649  // armVersionString = strndup ((char*) &buffer[2], length); // Can't be any bigger than length
650  armVersionString = reinterpret_cast<char *>(calloc(length + 1, sizeof(char)));
651  assert(armVersionString);
652  strncpy(armVersionString, reinterpret_cast<char *>(&buffer[2]), length);
653  int dataOffset = strlen(armVersionString) + 3; // 1 for packet size byte, 1 ID, 1 for '\0'
654  armNumJoints = buffer[dataOffset];
655  if (armJoints) {
656  delete[] armJoints;
657  }
658  if (armNumJoints <= 0) {
659  return;
660  }
662  dataOffset += 1;
663  for (int ii = 0; ii < armNumJoints; ii++) {
664  armJoints[ii].speed = buffer[dataOffset + (ii * 6)];
665  armJoints[ii].home = buffer[dataOffset + (ii * 6) + 1];
666  armJoints[ii].min = buffer[dataOffset + (ii * 6) + 2];
667  armJoints[ii].centre = buffer[dataOffset + (ii * 6) + 3];
668  armJoints[ii].max = buffer[dataOffset + (ii * 6) + 4];
669  armJoints[ii].ticksPer90 = buffer[dataOffset + (ii * 6) + 5];
670  }
671 }
unsigned char armJointPos[6]
Definition: sip.hpp:88
Container struct.
Definition: p2os.hpp:53
bool rwstall
Definition: sip.hpp:63
int16_t lvel
Definition: sip.hpp:68
int16_t control
Definition: sip.hpp:68
#define GYROPAC
unsigned char centre
Definition: sip.hpp:35
p2os_msgs::SonarArray sonar
Container for sonar data.
Definition: p2os.hpp:64
int xpos
Definition: sip.hpp:70
char * armVersionString
Definition: sip.hpp:91
double lastLiftPos
Definition: sip.hpp:97
unsigned char status
Definition: sip.hpp:65
std::string odom_frame_id
Definition: sip.hpp:72
void ParseGyro(unsigned char *buffer)
Definition: sip.cpp:541
void ParseArmInfo(unsigned char *buffer)
Definition: sip.cpp:631
unsigned char sonar_flag
Definition: sip.hpp:64
unsigned char home
Definition: sip.hpp:33
uint16_t compass
Definition: sip.hpp:66
unsigned char digout
Definition: sip.hpp:65
void Print()
Definition: sip.cpp:242
uint16_t rawypos
Definition: sip.hpp:67
p2os_msgs::AIO aio
Analog In/Out.
Definition: p2os.hpp:68
#define DTOR(a)
unsigned char motors_enabled
Definition: sip.hpp:64
ArmJoint * armJoints
Definition: sip.hpp:93
int16_t angle
Definition: sip.hpp:68
uint16_t blobarea
Definition: sip.hpp:79
p2os_msgs::GripperState gripper
Provides the state of the gripper.
Definition: p2os.hpp:62
geometry_msgs::TransformStamped odom_trans
Transformed odometry frame.
Definition: p2os.hpp:70
void ParseSERAUX(unsigned char *buffer)
Definition: sip.cpp:476
int PositionChange(uint16_t, uint16_t)
Definition: sip.cpp:227
uint16_t * sonars
Definition: sip.hpp:69
unsigned char analog
Definition: sip.hpp:65
void ParseStandard(unsigned char *buffer)
Definition: sip.cpp:325
void PrintArm()
Definition: sip.cpp:303
unsigned char sonarreadings
Definition: sip.hpp:65
uint16_t blobconf
Definition: sip.hpp:79
#define SERAUX2
int ypos
Definition: sip.hpp:70
uint16_t blobmy
Definition: sip.hpp:77
char speed
Definition: sip.hpp:32
int param_idx
Definition: sip.hpp:59
uint16_t bloby1
Definition: sip.hpp:78
int32_t gyro_rate
Definition: sip.hpp:83
uint16_t ptu
Definition: sip.hpp:66
uint16_t bloby2
Definition: sip.hpp:78
uint16_t rawxpos
Definition: sip.hpp:66
RobotParams_t PlayerRobotParams[]
double min(double a, double b)
unsigned char max
Definition: sip.hpp:36
int y_offset
Definition: sip.hpp:71
unsigned char ticksPer90
Definition: sip.hpp:37
p2os_msgs::BatteryState batt
Provides the battery voltage.
Definition: p2os.hpp:58
void FillStandard(ros_p2os_data_t *data)
Definition: sip.cpp:36
uint16_t blobx1
Definition: sip.hpp:78
static geometry_msgs::Quaternion createQuaternionMsgFromYaw(double yaw)
INLINE Rall1d< T, V, S > abs(const Rall1d< T, V, S > &x)
unsigned char min
Definition: sip.hpp:34
uint16_t timer
Definition: sip.hpp:66
#define ARMINFOPAC
void PrintSonars()
Definition: sip.cpp:291
unsigned char battery
Definition: sip.hpp:65
#define SERAUX
bool lwstall
Definition: sip.hpp:63
Definition: sip.hpp:30
unsigned char armNumJoints
Definition: sip.hpp:92
int16_t rvel
Definition: sip.hpp:68
bool armConnected
Definition: sip.hpp:86
TFSIMD_FORCE_INLINE tfScalar length(const Quaternion &q)
bool armPowerOn
Definition: sip.hpp:86
INLINE Rall1d< T, V, S > cos(const Rall1d< T, V, S > &arg)
bool armJointMoving[6]
Definition: sip.hpp:87
int x_offset
Definition: sip.hpp:71
int angle_offset
Definition: sip.hpp:71
unsigned int blobcolor
Definition: sip.hpp:80
double max(double a, double b)
void ParseArm(unsigned char *buffer)
Definition: sip.cpp:590
p2os_msgs::MotorState motors
Provides the state of the motors (enabled or disabled)
Definition: p2os.hpp:60
#define ROS_ERROR(...)
INLINE Rall1d< T, V, S > sin(const Rall1d< T, V, S > &arg)
void PrintArmInfo()
Definition: sip.cpp:314
uint16_t rearbumpers
Definition: sip.hpp:67
nav_msgs::Odometry position
Provides the position of the robot.
Definition: p2os.hpp:56
uint16_t blobmx
Definition: sip.hpp:77
unsigned char digin
Definition: sip.hpp:65
uint16_t frontbumpers
Definition: sip.hpp:67
#define ARMPAC
std::string base_link_frame_id
Definition: sip.hpp:73
p2os_msgs::DIO dio
Digital In/Out.
Definition: p2os.hpp:66
uint16_t blobx2
Definition: sip.hpp:78
#define ROS_DEBUG(...)
double armJointPosRads[6]
Definition: sip.hpp:89


p2os_driver
Author(s): Hunter L. Allen , David Feil-Seifer , Aris Synodinos , Brian Gerkey, Kasper Stoy, Richard Vaughan, Andrew Howard, Tucker Hermans, ActivMedia Robotics LLC, MobileRobots Inc.
autogenerated on Sat Jun 20 2020 03:29:42