segwayrmp.cc
Go to the documentation of this file.
1 #include <algorithm>
2 #include <iostream>
3 
4 #include <segwayrmp/segwayrmp.h>
7 #if defined(SEGWAYRMP_USE_SERIAL)
9 #endif
10 
11 #if !HAS_CLOCK_GETTIME
12 # include <sys/time.h>
13 #endif
14 
15 inline void
17 {
18  std::cout << "Segway Status:" << std::endl << std::endl
19  << segway_status->str() << std::endl << std::endl;
20 }
21 
22 inline void defaultDebugMsgCallback(const std::string &msg)
23 {
24  std::cerr << "SegwayRMP Debug: " << msg << std::endl;
25 }
26 
27 inline void defaultInfoMsgCallback(const std::string &msg)
28 {
29  std::cerr << "SegwayRMP Info: " << msg << std::endl;
30 }
31 
32 inline void defaultErrorMsgCallback(const std::string &msg)
33 {
34  std::cerr << "SegwayRMP Error: " << msg << std::endl;
35 }
36 
37 // This is from ROS's walltime function
38 // http://www.ros.org/doc/api/rostime/html/time_8cpp_source.html
40 #ifndef WIN32
41 throw(segwayrmp::NoHighPerformanceTimersException)
42 #endif
43 {
45 #ifndef WIN32
46 # if HAS_CLOCK_GETTIME
47  timespec start;
48  clock_gettime(CLOCK_REALTIME, &start);
49  st.sec = start.tv_sec;
50  st.nsec = start.tv_nsec;
51 # else
52  struct timeval timeofday;
53  gettimeofday(&timeofday, NULL);
54  st.sec = timeofday.tv_sec;
55  st.nsec = timeofday.tv_usec * 1000;
56 # endif
57 #else
58  // Win32 implementation
59  // unless I've missed something obvious, the only way to get high-precision
60  // time on Windows is via the QueryPerformanceCounter() call. However,
61  // this is somewhat problematic in Windows XP on some processors,
62  // especially AMD, because the Windows implementation can freak out when
63  // the CPU clocks down to save power. Time can jump or even go backwards.
64  // Microsoft has fixed this bug for most systems now, but it can still
65  // show up if you have not installed the latest CPU drivers (an oxymoron).
66  // They fixed all these problems in Windows Vista, and this API is by far
67  // the most accurate that I know of in Windows, so I'll use it here
68  // despite all these caveats
69  static LARGE_INTEGER cpu_freq, init_cpu_time;
70  uint32_t start_sec = 0;
71  uint32_t start_nsec = 0;
72  if ( ( start_sec == 0 ) && ( start_nsec == 0 ) ) {
73  QueryPerformanceFrequency(&cpu_freq);
74  if (cpu_freq.QuadPart == 0) {
75  throw segwayrmp::NoHighPerformanceTimersException();
76  }
77  QueryPerformanceCounter(&init_cpu_time);
78  // compute an offset from the Epoch using the lower-performance
79  // timer API
80  FILETIME ft;
81  GetSystemTimeAsFileTime(&ft);
82  LARGE_INTEGER start_li;
83  start_li.LowPart = ft.dwLowDateTime;
84  start_li.HighPart = ft.dwHighDateTime;
85  // why did they choose 1601 as the time zero, instead of 1970?
86  // there were no outstanding hard rock bands in 1601.
87 # ifdef _MSC_VER
88  start_li.QuadPart -= 116444736000000000Ui64;
89 # else
90  start_li.QuadPart -= 116444736000000000ULL;
91 # endif
92  // 100-ns units. odd.
93  start_sec = (uint32_t)(start_li.QuadPart / 10000000);
94  start_nsec = (start_li.LowPart % 10000000) * 100;
95  }
96  LARGE_INTEGER cur_time;
97  QueryPerformanceCounter(&cur_time);
98  LARGE_INTEGER delta_cpu_time;
99  delta_cpu_time.QuadPart = cur_time.QuadPart - init_cpu_time.QuadPart;
100  // todo: how to handle cpu clock drift. not sure it's a big deal for us.
101  // also, think about clock wraparound. seems extremely unlikey,
102  // but possible
103  double d_delta_cpu_time =
104  delta_cpu_time.QuadPart / (double) cpu_freq.QuadPart;
105  uint32_t delta_sec = (uint32_t) floor(d_delta_cpu_time);
106  uint32_t delta_nsec =
107  (uint32_t) boost::math::round((d_delta_cpu_time - delta_sec) * 1e9);
108 
109  int64_t sec_sum = (int64_t)start_sec + (int64_t)delta_sec;
110  int64_t nsec_sum = (int64_t)start_nsec + (int64_t)delta_nsec;
111 
112  // Throws an exception if we go out of 32-bit range
113  normalizeSecNSecUnsigned(sec_sum, nsec_sum);
114 
115  st.sec = sec_sum;
116  st.nsec = nsec_sum;
117 #endif
118  return st;
119 }
120 
121 inline void defaultExceptionCallback(const std::exception &error)
122 {
123  std::cerr << "SegwayRMP Unhandled Exception: " << error.what()
124  << std::endl;
125 }
126 
127 inline void printHex(char *data, int length)
128 {
129  for (int i = 0; i < length; ++i) {
130  printf("0x%.2X ", (unsigned)(unsigned char)data[i]);
131  }
132  printf("\n");
133 }
134 
135 inline void printHexFromString(std::string str)
136 {
137  printHex(const_cast<char *>(str.c_str()), str.length());
138 }
139 
140 using namespace segwayrmp;
141 
143  : timestamp(SegwayTime(0, 0)), pitch(0.0f), pitch_rate(0.0f), roll(0.0f),
144  roll_rate(0.0f), left_wheel_speed(0.0f), right_wheel_speed(0.0f),
145  yaw_rate(0.0f), servo_frames(0.0f), integrated_left_wheel_position(0.0f),
146  integrated_right_wheel_position(0.0f), integrated_forward_position(0.0f),
147  integrated_turn_position(0.0f), left_motor_torque(0.0f),
148  right_motor_torque(0.0f), ui_battery_voltage(0.0f),
149  powerbase_battery_voltage(0.0f), commanded_velocity(0.0f),
150  commanded_yaw_rate(0.0f), operational_mode(disabled),
151  controller_gain_schedule(light), motor_status(0), touched(false)
152 {}
153 
154 std::string SegwayStatus::str()
155 {
156  std::stringstream ss;
157  ss << "Time Stamp: "
158  << "\n Seconds: " << timestamp.sec
159  << "\n Nanoseconds: " << timestamp.nsec
160  << "\nPitch: " << pitch << "\nPitch Rate: " << pitch_rate
161  << "\nRoll: " << roll << "\nRoll Rate: " << roll_rate
162  << "\nLeft Wheel Speed: " << left_wheel_speed
163  << "\nRight Wheel Speed: " << right_wheel_speed
164  << "\nYaw Rate: " << yaw_rate
165  << "\nServo Frames: " << servo_frames
166  << "\nIntegrated Left Wheel Position: " << integrated_left_wheel_position
167  << "\nIntegrated Right Wheel Position: "
169  << "\nIntegrated Forward Displacement: " << integrated_forward_position
170  << "\nIntegrated Turn Position: " << integrated_turn_position
171  << "\nLeft Motor Torque: " << left_motor_torque
172  << "\nRight Motor Torque: " << right_motor_torque
173  << "\nUI Battery Voltage: " << ui_battery_voltage
174  << "\nPowerbase Battery Voltage: " << powerbase_battery_voltage
175  << "\nOperational Mode: ";
176  switch (operational_mode) {
177  case disabled:
178  ss << "disabled";
179  break;
180  case tractor:
181  ss << "tractor";
182  break;
183  case balanced:
184  ss << "balanced";
185  break;
186  case power_down:
187  ss << "power down";
188  break;
189  default:
190  ss << "unknown";
191  break;
192  }
193  ss << "\nController Gain Schedule: ";
194  switch (controller_gain_schedule) {
195  case light:
196  ss << "light";
197  break;
198  case tall:
199  ss << "tall";
200  break;
201  case heavy:
202  ss << "heavy";
203  break;
204  default:
205  ss << "unknown";
206  break;
207  }
208  ss << "\nCommanded Velocity: " << commanded_velocity
209  << "\nCommanded Yaw Rate: " << commanded_yaw_rate
210  << "\nMotor Status: ";
211  if (motor_status) {
212  ss << "Motors Enabled";
213  } else {
214  ss << "E-Stopped";
215  }
216  return ss.str();
217 }
218 
220  SegwayRMPType segway_rmp_type)
221 : interface_type_(no_interface), segway_rmp_type_(segway_rmp_type),
222  connected_(false),
223  continuously_reading_(false),
224  status_callback_(defaultSegwayStatusCallback),
225  get_time_(defaultTimestampCallback),
226  debug_(defaultDebugMsgCallback),
227  info_(defaultInfoMsgCallback),
228  error_(defaultErrorMsgCallback),
229  handle_exception_(defaultExceptionCallback)
230 {
232  this->interface_type_ = interface_type;
233  switch (interface_type) {
234  case can:
235  RMP_THROW_MSG(ConfigurationException, "CAN is not supported currently");
236  break;
237  case usb:
238  this->rmp_io_ = new FTD2XXRMPIO();
239  break;
240  case serial:
241 #if defined(SEGWAYRMP_USE_SERIAL)
242  this->rmp_io_ = new SerialRMPIO();
243 #else
244  RMP_THROW_MSG(ConfigurationException, "Library is not built with Serial "
245  "support");
246 #endif
247  break;
248  case ethernet:
249  RMP_THROW_MSG(ConfigurationException, "Ethernet is not currently "
250  "supported");
251  break;
252  case no_interface:
253  // do nothing
254  break;
255  default:
256  RMP_THROW_MSG(ConfigurationException, "Invalid InterfaceType specified");
257  break;
258  }
259 
260  // Set the constants based on the segway type
262 }
263 
265 {
266  if (this->continuously_reading_) {
267  this->StopReadingContinuously_();
268  }
269  if (this->interface_type_ == serial) {
270 #if defined(SEGWAYRMP_USE_SERIAL)
271  SerialRMPIO * ptr = (SerialRMPIO *)(this->rmp_io_);
272  delete ptr;
273 #endif
274  }
275  if (this->interface_type_ == usb) {
276  FTD2XXRMPIO * ptr = (FTD2XXRMPIO *)(this->rmp_io_);
277  delete ptr;
278  }
279 }
280 
281 void SegwayRMP::configureSerial(std::string port, int baudrate)
282 {
283 #if SEGWAYRMP_USE_SERIAL
284  if (this->interface_type_ == serial) {
285  SerialRMPIO *serial_rmp = (SerialRMPIO *)(this->rmp_io_);
286  serial_rmp->configure(port, baudrate);
287  } else {
288  RMP_THROW_MSG(ConfigurationException, "configureSerial: Cannot configure "
289  "serial when the InterfaceType is not serial.");
290  }
291 #else
292  RMP_THROW_MSG(ConfigurationException, "configureSerial: The segwayrmp "
293  "library is not build with serial support, not implemented.");
294 #endif
295 }
296 
297 void SegwayRMP::configureUSBBySerial(std::string serial_number, int baudrate)
298 {
299  if (this->interface_type_ == usb) {
300  FTD2XXRMPIO *ftd2xx_rmp = (FTD2XXRMPIO *)(this->rmp_io_);
301  ftd2xx_rmp->configureUSBBySerial(serial_number, baudrate);
302  } else {
303  RMP_THROW_MSG(ConfigurationException, "configureUSBBySerial: Cannot "
304  "configure ftd2xx usb when the InterfaceType is not usb.");
305  }
306 }
307 
308 void SegwayRMP::configureUSBByDescription(std::string description,
309  int baudrate)
310 {
311  if (this->interface_type_ == usb) {
312  FTD2XXRMPIO *ftd2xx_rmp = (FTD2XXRMPIO *)(this->rmp_io_);
313  ftd2xx_rmp->configureUSBByDescription(description, baudrate);
314  } else {
315  RMP_THROW_MSG(ConfigurationException, "configureUSBByDescription: "
316  "Cannot configure ftd2xx usb when the InterfaceType is not usb.");
317  }
318 }
319 
320 void SegwayRMP::configureUSBByIndex(int device_index, int baudrate)
321 {
322  if (this->interface_type_ == usb) {
323  FTD2XXRMPIO *ftd2xx_rmp = (FTD2XXRMPIO *)(this->rmp_io_);
324  ftd2xx_rmp->configureUSBByIndex(device_index, baudrate);
325  } else {
326  RMP_THROW_MSG(ConfigurationException, "configureUSBByIndex: "
327  "Cannot configure ftd2xx usb when the InterfaceType is not usb.");
328  }
329 }
330 
331 void SegwayRMP::connect(bool reset_integrators)
332 {
333  // Connect to the interface
334  this->rmp_io_->connect();
335 
336  this->connected_ = true;
337 
338  if (reset_integrators) {
339  // Reset all the integrators
340  this->resetAllIntegrators();
341  }
342 
343  // Kick off the read thread
345 
346 }
347 
349 {
350  // Ensure we are connected
351  if (!this->connected_)
352  RMP_THROW_MSG(ConfigurationException, "Cannot send shutdown: "
353  "Not Connected.");
354  try {
355  Packet packet;
356 
357  packet.id = 0x0412;
358 
359  this->rmp_io_->sendPacket(packet);
360  } catch (std::exception &e) {
361  std::stringstream ss;
362  ss << "Cannot send shutdown: " << e.what();
363  RMP_THROW_MSG(ConfigurationException, ss.str().c_str());
364  }
365 }
366 
367 void SegwayRMP::moveCounts(short int linear_counts, short int angular_counts)
368 {
369  // Ensure we are connected
370  if (!this->connected_)
371  RMP_THROW_MSG(MoveFailedException, "Not Connected.");
372  try {
373  short int lc = linear_counts;
374  short int ac = angular_counts;
375  Packet packet;
376 
377  packet.id = 0x0413;
378 
379  packet.data[0] = (unsigned char)((lc & 0xFF00) >> 8);
380  packet.data[1] = (unsigned char)(lc & 0x00FF);
381  packet.data[2] = (unsigned char)((ac & 0xFF00) >> 8);
382  packet.data[3] = (unsigned char)(ac & 0x00FF);
383  packet.data[4] = 0x00;
384  packet.data[5] = 0x00;
385  packet.data[6] = 0x00;
386  packet.data[7] = 0x00;
387 
388  this->rmp_io_->sendPacket(packet);
389  } catch (std::exception &e) {
390  RMP_THROW_MSG(MoveFailedException, e.what());
391  }
392 }
393 
394 void SegwayRMP::move(float linear_velocity, float angular_velocity)
395 {
396  // Ensure we are connected
397  if (!this->connected_)
398  RMP_THROW_MSG(MoveFailedException, "Not Connected.");
399  try {
400  short int lv = (short int)(linear_velocity * this->mps_to_counts_);
401  short int av = (short int)(angular_velocity * this->dps_to_counts_);
402 
403  Packet packet;
404 
405  packet.id = 0x0413;
406 
407  packet.data[0] = (unsigned char)((lv & 0xFF00) >> 8);
408  packet.data[1] = (unsigned char)(lv & 0x00FF);
409  packet.data[2] = (unsigned char)((av & 0xFF00) >> 8);
410  packet.data[3] = (unsigned char)(av & 0x00FF);
411  packet.data[4] = 0x00;
412  packet.data[5] = 0x00;
413  packet.data[6] = 0x00;
414  packet.data[7] = 0x00;
415 
416  this->rmp_io_->sendPacket(packet);
417  } catch (std::exception &e) {
418  RMP_THROW_MSG(MoveFailedException, e.what());
419  }
420 }
421 
423 {
424  // Ensure we are connected
425  if (!this->connected_)
426  RMP_THROW_MSG(ConfigurationException, "Cannot set operational mode: "
427  "Not Connected.");
428  try {
429  Packet packet;
430 
431  packet.id = 0x0413;
432 
433  packet.data[0] = 0x00;
434  packet.data[1] = 0x00;
435  packet.data[2] = 0x00;
436  packet.data[3] = 0x00;
437  packet.data[4] = 0x00;
438  packet.data[5] = 0x10;
439  packet.data[6] = 0x00;
440  packet.data[7] = (unsigned char)operational_mode;
441 
442  this->rmp_io_->sendPacket(packet);
443 
444 // while(this->segway_status_->operational_mode != operational_mode) {
445 // // Check again in 10 ms
446 // boost::this_thread::sleep(boost::posix_time::milliseconds(10));
447 // }
448  } catch (std::exception &e) {
449  std::stringstream ss;
450  ss << "Cannot set operational mode: " << e.what();
451  RMP_THROW_MSG(ConfigurationException, ss.str().c_str());
452  }
453 }
454 
456  ControllerGainSchedule controller_gain_schedule)
457 {
458  // Ensure we are connected
459  if (!this->connected_)
460  RMP_THROW_MSG(ConfigurationException, "Cannot set controller gain "
461  "schedule: Not Connected.");
462  try {
463  Packet packet;
464 
465  packet.id = 0x0413;
466 
467  packet.data[0] = 0x00;
468  packet.data[1] = 0x00;
469  packet.data[2] = 0x00;
470  packet.data[3] = 0x00;
471  packet.data[4] = 0x00;
472  packet.data[5] = 0x0D;
473  packet.data[6] = 0x00;
474  packet.data[7] = (unsigned char)controller_gain_schedule;
475 
476  this->rmp_io_->sendPacket(packet);
477 
478 // while(this->segway_status_->controller_gain_schedule
479 // != controller_gain_schedule)
480 // {
481 // // Check again in 10 ms
482 // boost::this_thread::sleep(boost::posix_time::milliseconds(10));
483 // }
484  } catch (std::exception &e) {
485  std::stringstream ss;
486  ss << "Cannot set controller gain schedule: " << e.what();
487  RMP_THROW_MSG(ConfigurationException, ss.str().c_str());
488  }
489 }
490 
492 {
493  // Ensure we are connected
494  if (!this->connected_)
495  RMP_THROW_MSG(ConfigurationException, "Cannot set balance mode lock: "
496  "Not Connected.");
497  try {
498  Packet packet;
499 
500  packet.id = 0x0413;
501 
502  packet.data[0] = 0x00;
503  packet.data[1] = 0x00;
504  packet.data[2] = 0x00;
505  packet.data[3] = 0x00;
506  packet.data[4] = 0x00;
507  packet.data[5] = 0x0F;
508  packet.data[6] = 0x00;
509  if (state)
510  packet.data[7] = 0x01;
511  else
512  packet.data[7] = 0x00;
513 
514  this->rmp_io_->sendPacket(packet);
515  } catch (std::exception &e) {
516  std::stringstream ss;
517  ss << "Cannot set balance mode lock: " << e.what();
518  RMP_THROW_MSG(ConfigurationException, ss.str().c_str());
519  }
520 }
521 
523 {
524  // Ensure we are connected
525  if (!this->connected_)
526  RMP_THROW_MSG(ConfigurationException, "Cannot reset Integrators: Not "
527  "Connected.");
528  try {
529  Packet packet;
530 
531  packet.id = 0x0413;
532 
533  packet.data[0] = 0x00;
534  packet.data[1] = 0x00;
535  packet.data[2] = 0x00;
536  packet.data[3] = 0x00;
537  packet.data[4] = 0x00;
538  packet.data[5] = 0x32;
539  packet.data[6] = 0x00;
540  packet.data[7] = 0x01;
541 
542  this->rmp_io_->sendPacket(packet);
543 
544  packet.data[7] = 0x02;
545 
546  this->rmp_io_->sendPacket(packet);
547 
548  packet.data[7] = 0x04;
549 
550  this->rmp_io_->sendPacket(packet);
551 
552  packet.data[7] = 0x08;
553 
554  this->rmp_io_->sendPacket(packet);
555 
556  } catch (std::exception &e) {
557  std::stringstream ss;
558  ss << "Cannot reset Integrators: " << e.what();
559  RMP_THROW_MSG(ConfigurationException, ss.str().c_str());
560  }
561 }
562 
564 {
565  // Ensure we are connected
566  if (!this->connected_)
567  RMP_THROW_MSG(ConfigurationException, "Cannot set max velocity scale "
568  "factor: Not Connected.");
569  try {
570  Packet packet;
571 
572  packet.id = 0x0413;
573 
574  packet.data[0] = 0x00;
575  packet.data[1] = 0x00;
576  packet.data[2] = 0x00;
577  packet.data[3] = 0x00;
578  packet.data[4] = 0x00;
579  packet.data[5] = 0x0A;
580  packet.data[6] = 0x00;
581 
582  if (scalar < 0.0)
583  scalar = 0.0;
584  if (scalar > 1.0)
585  scalar = 1.0;
586  scalar *= 16.0;
587  scalar = floor(scalar);
588 
589  short int scalar_int = (short int)scalar;
590 
591  packet.data[7] = (unsigned char)(scalar_int & 0x00FF);
592 
593  this->rmp_io_->sendPacket(packet);
594  } catch (std::exception &e) {
595  std::stringstream ss;
596  ss << "Cannot set max velocity scale factor: " << e.what();
597  RMP_THROW_MSG(ConfigurationException, ss.str().c_str());
598  }
599 }
600 
602 {
603  // Ensure we are connected
604  if (!this->connected_)
605  RMP_THROW_MSG(ConfigurationException, "Cannot set max acceleration scale "
606  "factor: Not Connected.");
607  try {
608  Packet packet;
609 
610  packet.id = 0x0413;
611 
612  packet.data[0] = 0x00;
613  packet.data[1] = 0x00;
614  packet.data[2] = 0x00;
615  packet.data[3] = 0x00;
616  packet.data[4] = 0x00;
617  packet.data[5] = 0x0B;
618  packet.data[6] = 0x00;
619 
620  if (scalar < 0.0)
621  scalar = 0.0;
622  if (scalar > 1.0)
623  scalar = 1.0;
624  scalar *= 16.0;
625  scalar = floor(scalar);
626 
627  short int scalar_int = (short int)scalar;
628 
629  packet.data[7] = (unsigned char)(scalar_int & 0x00FF);
630 
631  this->rmp_io_->sendPacket(packet);
632  } catch (std::exception &e) {
633  std::stringstream ss;
634  ss << "Cannot set max acceleration scale factor: " << e.what();
635  RMP_THROW_MSG(ConfigurationException, ss.str().c_str());
636  }
637 }
638 
640 {
641  // Ensure we are connected
642  if (!this->connected_)
643  RMP_THROW_MSG(ConfigurationException, "Cannot set max turn scale factor: "
644  "Not Connected.");
645  try {
646  Packet packet;
647 
648  packet.id = 0x0413;
649 
650  packet.data[0] = 0x00;
651  packet.data[1] = 0x00;
652  packet.data[2] = 0x00;
653  packet.data[3] = 0x00;
654  packet.data[4] = 0x00;
655  packet.data[5] = 0x0C;
656  packet.data[6] = 0x00;
657 
658  if (scalar < 0.0)
659  scalar = 0.0;
660  if (scalar > 1.0)
661  scalar = 1.0;
662  scalar *= 16.0;
663  scalar = floor(scalar);
664 
665  short int scalar_int = (short int)scalar;
666 
667  packet.data[7] = (unsigned char)(scalar_int & 0x00FF);
668 
669  this->rmp_io_->sendPacket(packet);
670  } catch (std::exception &e) {
671  std::stringstream ss;
672  ss << "Cannot set max turn scale factor: " << e.what();
673  RMP_THROW_MSG(ConfigurationException, ss.str().c_str());
674  }
675 }
676 
678 {
679  // Ensure we are connected
680  if (!this->connected_)
681  RMP_THROW_MSG(ConfigurationException, "Cannot set current limit scale "
682  "factor: Not Connected.");
683  try {
684  Packet packet;
685 
686  packet.id = 0x0413;
687 
688  packet.data[0] = 0x00;
689  packet.data[1] = 0x00;
690  packet.data[2] = 0x00;
691  packet.data[3] = 0x00;
692  packet.data[4] = 0x00;
693  packet.data[5] = 0x0E;
694  packet.data[6] = 0x00;
695 
696  if (scalar < 0.0)
697  scalar = 0.0;
698  if (scalar > 1.0)
699  scalar = 1.0;
700  scalar *= 256.0;
701  scalar = floor(scalar);
702 
703  short int scalar_int = (short int)scalar;
704 
705  packet.data[7] = (unsigned char)(scalar_int & 0x00FF);
706 
707  this->rmp_io_->sendPacket(packet);
708  } catch (std::exception &e) {
709  std::stringstream ss;
710  ss << "Cannot set current limit scale factor: " << e.what();
711  RMP_THROW_MSG(ConfigurationException, ss.str().c_str());
712  }
713 }
714 
716  this->status_callback_ = callback;
717 }
718 
719 void SegwayRMP::setLogMsgCallback(std::string log_level,
720  LogMsgCallback callback)
721 {
722  // Convert to lower case
723  std::transform(log_level.begin(), log_level.end(),
724  log_level.begin(), ::tolower);
725  if (log_level == "debug") {
726  this->debug_ = callback;
727  }
728  if (log_level == "info") {
729  this->info_ = callback;
730  }
731  if (log_level == "error") {
732  this->error_ = callback;
733  }
734 }
735 
737  this->get_time_ = callback;
738 }
739 
741  this->handle_exception_ = exception_callback;
742 }
743 
745  Packet packet;
746  while (this->continuously_reading_) {
747  try {
748  this->rmp_io_->getPacket(packet);
749  this->ProcessPacket_(packet);
750  } catch (PacketRetrievalException &e) {
751  if (e.error_number() == 2) // Failed Checksum
752  this->error_("Checksum mismatch...");
753  else if (e.error_number() == 3) // No packet received
754  this->error_("No data from Segway...");
755  else
756  this->handle_exception_(e);
757  }
758  }
759 }
760 
762  while (this->continuously_reading_) {
763  SegwayStatus::Ptr ss = this->ss_queue_.dequeue();
764  if (this->continuously_reading_) {
765  try {
766  if (ss) {
767  if (this->status_callback_) {
768  this->status_callback_(ss);
769  } // if this->status_callback_
770  } // if ss
771  } catch (std::exception &e) {
772  this->handle_exception_(e);
773  }// try callback
774  }// if continuous
775  }// while continuous
776 }
777 
779  this->continuously_reading_ = true;
780  this->read_thread_ =
781  boost::thread(&SegwayRMP::ReadContinuously_, this);
783  boost::thread(&SegwayRMP::ExecuteCallbacks_, this);
784 }
785 
787 {
788  this->continuously_reading_ = false;
789  this->rmp_io_->cancel();
790  this->read_thread_.join();
791  this->ss_queue_.cancel();
792  this->callback_execution_thread_.join();
793 }
794 
796  if (rmp_type == rmp200 || rmp_type == rmp400) {
797  this->dps_to_counts_ = 7.8;
798  this->mps_to_counts_ = 332.0;
799  this->meters_to_counts_ = 33215.0;
800  this->rev_to_counts_ = 112644.0;
801  this->torque_to_counts_ = 1094.0;
802  } else
803  if (rmp_type == rmp50 || rmp_type == rmp100) {
804  this->dps_to_counts_ = 7.8;
805  this->mps_to_counts_ = 401.0;
806  this->meters_to_counts_ = 40181.0;
807  this->rev_to_counts_ = 117031.0;
808  this->torque_to_counts_ = 1463.0;
809  } else {
810  RMP_THROW_MSG(ConfigurationException, "Invalid Segway RMP Type");
811  }
812 }
813 
814 inline short int getShortInt(unsigned char high, unsigned char low)
815 {
816  return (short int)(((unsigned short int)high << 8)
817  | (unsigned short int)low);
818 }
819 
820 inline int
821 getInt(unsigned char lhigh, unsigned char llow,
822  unsigned char hhigh, unsigned char hlow)
823 {
824  int result = 0;
825  char data[4] = {llow, lhigh, hlow, hhigh};
826  memcpy(&result, data, 4);
827  return result;
828 }
829 
831 {
832  bool status_updated = false;
833  if (packet.channel == 0xBB) // Ignore Channel B messages
834  return status_updated;
835 
836  // This section comes largerly from the Segway example code
837  switch (packet.id) {
838  case 0x0400: // COMMAND REQUEST
839  // This is the first packet of a msg series, timestamp here.
840  ss_ptr->timestamp = this->get_time_();
841  break;
842  case 0x0401:
843  ss_ptr->pitch = getShortInt(packet.data[0], packet.data[1])
844  / this->dps_to_counts_;
845  ss_ptr->pitch_rate = getShortInt(packet.data[2], packet.data[3])
846  / this->dps_to_counts_;
847  ss_ptr->roll = getShortInt(packet.data[4], packet.data[5])
848  / this->dps_to_counts_;
849  ss_ptr->roll_rate = getShortInt(packet.data[6], packet.data[7])
850  / this->dps_to_counts_;
851  ss_ptr->touched = true;
852  break;
853  case 0x0402:
854  ss_ptr->left_wheel_speed = getShortInt(packet.data[0], packet.data[1])
855  / this->mps_to_counts_;
856  ss_ptr->right_wheel_speed = getShortInt(packet.data[2], packet.data[3])
857  / this->mps_to_counts_;
858  ss_ptr->yaw_rate = getShortInt(packet.data[4], packet.data[5])
859  / this->dps_to_counts_;
860  ss_ptr->servo_frames = (
861  (((short unsigned int)packet.data[6]) << 8)
862  | ((short unsigned int)packet.data[7])
863  ) * 0.01;
864  ss_ptr->touched = true;
865  break;
866  case 0x0403:
867  ss_ptr->integrated_left_wheel_position =
868  getInt(packet.data[0], packet.data[1], packet.data[2], packet.data[3])
869  / this->meters_to_counts_;
870  ss_ptr->integrated_right_wheel_position =
871  getInt(packet.data[4], packet.data[5], packet.data[6], packet.data[7])
872  / this->meters_to_counts_;
873  ss_ptr->touched = true;
874  break;
875  case 0x0404:
876  ss_ptr->integrated_forward_position =
877  getInt(packet.data[0], packet.data[1], packet.data[2], packet.data[3])
878  / this->meters_to_counts_;
879  ss_ptr->integrated_turn_position =
880  getInt(packet.data[4], packet.data[5], packet.data[6], packet.data[7])
881  / this->rev_to_counts_;
882  // convert from revolutions to degrees
883  ss_ptr->integrated_turn_position *= 360.0;
884  ss_ptr->touched = true;
885  break;
886  case 0x0405:
887  ss_ptr->left_motor_torque = getShortInt(packet.data[0], packet.data[1])
888  / this->torque_to_counts_;
889  ss_ptr->right_motor_torque = getShortInt(packet.data[2], packet.data[3])
890  / this->torque_to_counts_;
891  ss_ptr->touched = true;
892  break;
893  case 0x0406:
894  ss_ptr->operational_mode =
895  OperationalMode(getShortInt(packet.data[0], packet.data[1]));
896  ss_ptr->controller_gain_schedule =
897  ControllerGainSchedule(getShortInt(packet.data[2], packet.data[3]));
898  ss_ptr->ui_battery_voltage =
899  (
900  (((short unsigned int)packet.data[4]) << 8)
901  | ((short unsigned int)packet.data[5])
902  ) * 0.0125 + 1.4;
903  ss_ptr->powerbase_battery_voltage =
904  (
905  (((short unsigned int)packet.data[6]) << 8)
906  | ((short unsigned int)packet.data[7])
907  ) / 4.0;
908  ss_ptr->touched = true;
909  break;
910  case 0x0407:
911  ss_ptr->commanded_velocity =
912  (float)getShortInt(packet.data[0], packet.data[1])
913  / this->mps_to_counts_;
914  ss_ptr->commanded_yaw_rate =
915  (float)getShortInt(packet.data[2], packet.data[3])
916  / 1024.0;
917  status_updated = true;
918  ss_ptr->touched = true;
919  break;
920  case 0x0680:
921  if (packet.data[3] == 0x80) // Motors Enabled
922  ss_ptr->motor_status = 1;
923  else // E-Stopped
924  ss_ptr->motor_status = 0;
925  ss_ptr->touched = true;
926  break;
927  default: // Unknown/Unhandled Message
928  break;
929  };
930  return status_updated;
931 }
932 
934 {
935  bool status_updated = false;
936 
937  status_updated = this->ParsePacket_(packet, this->segway_status_);
938 
939  // Messages come in order 0x0400, 0x0401, ... 0x0407 so a
940  // complete "cycle" of information has been sent every
941  // time we get an 0x0407
942  if (status_updated) {
943  if (this->ss_queue_.enqueue(this->segway_status_)) {
944  this->error_("Falling behind, SegwayStatus Queue Full, skipping packet "
945  "report...");
946  }
948  }
949 }
950 
int getInt(unsigned char lhigh, unsigned char llow, unsigned char hhigh, unsigned char hlow)
Definition: segwayrmp.cc:821
void configureUSBByDescription(std::string description, int baudrate)
Definition: rmp_ftd2xx.cc:324
SegwayRMPType segway_rmp_type_
Definition: segwayrmp.h:740
LogMsgCallback info_
Definition: segwayrmp.h:757
void configure(std::string port, int baudrate)
Definition: rmp_serial.cc:17
void setControllerGainSchedule(ControllerGainSchedule controller_gain_schedule)
Definition: segwayrmp.cc:455
SegwayRMP(InterfaceType interface_type=serial, SegwayRMPType segway_rmp_type=rmp200)
Definition: segwayrmp.cc:219
short int getShortInt(unsigned char high, unsigned char low)
Definition: segwayrmp.cc:814
void configureUSBByIndex(int device_index, int baudrate=460800)
Definition: segwayrmp.cc:320
LogMsgCallback debug_
Definition: segwayrmp.h:757
boost::function< void(SegwayStatus::Ptr)> SegwayStatusCallback
Definition: segwayrmp.h:328
void setLogMsgCallback(std::string log_level, LogMsgCallback callback)
Definition: segwayrmp.cc:719
boost::shared_ptr< SegwayStatus > Ptr
Definition: segwayrmp.h:325
void setCurrentLimitScaleFactor(double scalar=1.0)
Definition: segwayrmp.cc:677
ExceptionCallback handle_exception_
Definition: segwayrmp.h:758
void SetConstantsBySegwayType_(SegwayRMPType &rmp_type)
Definition: segwayrmp.cc:795
void connect(bool reset_integrators=true)
Definition: segwayrmp.cc:331
void defaultExceptionCallback(const std::exception &error)
Definition: segwayrmp.cc:121
void ProcessPacket_(Packet &packet)
Definition: segwayrmp.cc:933
void defaultSegwayStatusCallback(segwayrmp::SegwayStatus::Ptr &segway_status)
Definition: segwayrmp.cc:16
void StartReadingContinuously_()
Definition: segwayrmp.cc:778
ControllerGainSchedule
Definition: segwayrmp.h:173
GetTimeCallback get_time_
Definition: segwayrmp.h:756
void cancel()
Definition: rmp_io.h:123
virtual void connect()=0
void sendPacket(Packet &packet)
Definition: rmp_io.cc:109
SegwayStatusCallback status_callback_
Definition: segwayrmp.h:755
void defaultDebugMsgCallback(const std::string &msg)
Definition: segwayrmp.cc:22
void setStatusCallback(SegwayStatusCallback callback)
Definition: segwayrmp.cc:715
boost::function< SegwayTime(void)> GetTimeCallback
Definition: segwayrmp.h:329
ControllerGainSchedule controller_gain_schedule
Definition: segwayrmp.h:311
boost::thread read_thread_
Definition: segwayrmp.h:767
void getPacket(Packet &packet)
Definition: rmp_io.cc:18
void printHex(char *data, int length)
Definition: segwayrmp.cc:127
unsigned char channel
Definition: rmp_io.h:57
void setBalanceModeLocking(bool state=true)
Definition: segwayrmp.cc:491
float integrated_left_wheel_position
Definition: segwayrmp.h:288
LogMsgCallback error_
Definition: segwayrmp.h:757
SegwayStatus::Ptr segway_status_
Definition: segwayrmp.h:744
boost::function< void(const std::exception &)> ExceptionCallback
Definition: segwayrmp.h:330
void resetAllIntegrators()
Definition: segwayrmp.cc:522
void configureSerial(std::string port, int baudrate=460800)
Definition: segwayrmp.cc:281
void move(float linear_velocity, float angular_velocity)
Definition: segwayrmp.cc:394
double meters_to_counts_
Definition: segwayrmp.h:750
InterfaceType interface_type_
Definition: segwayrmp.h:739
void setExceptionCallback(ExceptionCallback callback)
Definition: segwayrmp.cc:740
void configureUSBByDescription(std::string description, int baudrate=460800)
Definition: segwayrmp.cc:308
void configureUSBBySerial(std::string serial_number, int baudrate=460800)
Definition: segwayrmp.cc:297
unsigned short id
Definition: rmp_io.h:56
unsigned char data[8]
Definition: rmp_io.h:58
void setMaxVelocityScaleFactor(double scalar=1.0)
Definition: segwayrmp.cc:563
float integrated_right_wheel_position
Definition: segwayrmp.h:290
void setOperationalMode(OperationalMode operational_mode)
Definition: segwayrmp.cc:422
void setMaxAccelerationScaleFactor(double scalar=1.0)
Definition: segwayrmp.cc:601
void moveCounts(short int linear_counts, short int angular_counts)
Definition: segwayrmp.cc:367
void StopReadingContinuously_()
Definition: segwayrmp.cc:786
void setMaxTurnScaleFactor(double scalar=1.0)
Definition: segwayrmp.cc:639
void configureUSBByIndex(unsigned int device_index, int baudrate)
Definition: rmp_ftd2xx.cc:351
OperationalMode operational_mode
Definition: segwayrmp.h:306
bool ParsePacket_(Packet &packet, SegwayStatus::Ptr &ss_ptr)
Definition: segwayrmp.cc:830
float integrated_forward_position
Definition: segwayrmp.h:292
void printHexFromString(std::string str)
Definition: segwayrmp.cc:135
void configureUSBBySerial(std::string serial_number, int baudrate)
Definition: rmp_ftd2xx.cc:296
void defaultInfoMsgCallback(const std::string &msg)
Definition: segwayrmp.cc:27
void setTimestampCallback(GetTimeCallback callback)
Definition: segwayrmp.cc:736
FiniteConcurrentSharedQueue< SegwayStatus > ss_queue_
Definition: segwayrmp.h:759
struct timeval FILETIME
Definition: WinTypes.h:55
segwayrmp::SegwayTime defaultTimestampCallback()
Definition: segwayrmp.cc:39
void defaultErrorMsgCallback(const std::string &msg)
Definition: segwayrmp.cc:32
boost::thread callback_execution_thread_
Definition: segwayrmp.h:768
boost::function< void(const std::string &)> LogMsgCallback
Definition: segwayrmp.h:331
#define RMP_THROW_MSG(ExceptionClass, Message)
Definition: segwayrmp.h:83
double torque_to_counts_
Definition: segwayrmp.h:752


libsegwayrmp
Author(s): William Woodall
autogenerated on Mon Jun 10 2019 13:46:49