SickLD.cc
Go to the documentation of this file.
1 
16 /* Auto-generated header */
18 
19 /* Implementation dependencies */
20 #include <string>
21 #include <cmath>
22 #include <iostream>
23 #include <iomanip>
24 #include <sstream> // for converting numerical values to strings
25 #include <sys/socket.h> // for socket function definitions
26 #include <arpa/inet.h> // for sockaddr_in, inet_addr, and htons
27 #include <sys/ioctl.h> // for using ioctl functionality for the socket input buffer
28 #include <unistd.h> // for select functionality (e.g. FD_SET, etc...)
29 #include <sys/types.h> // for fd data types
30 #include <sys/time.h> // for select timeout parameter
31 #include <fcntl.h> // for getting file flags
32 #include <pthread.h> // for POSIX threads
33 #include <sstream> // for parsing ip addresses
34 #include <vector> // for returning the results of parsed strings
35 #include <errno.h> // for timing connect()
36 
37 #include <sicktoolbox/SickLD.hh>
42 
43 /* Associate the namespace */
44 namespace SickToolbox {
45 
51  SickLD::SickLD( const std::string sick_ip_address, const uint16_t sick_tcp_port ) :
53  _sick_ip_address(sick_ip_address),
54  _sick_tcp_port(sick_tcp_port),
55  _sick_sensor_mode(SICK_SENSOR_MODE_UNKNOWN),
56  _sick_motor_mode(SICK_MOTOR_MODE_UNKNOWN),
57  _sick_streaming_range_data(false),
58  _sick_streaming_range_and_echo_data(false)
59  {
60  /* Initialize the sick identity */
72 
73  /* Initialize the global configuration structure */
75 
76  /* Initialize the Ethernet configuration structure */
78 
79  /* Initialize the sector configuration structure */
81  }
82 
87 
92 
93  std::cout << "\t*** Attempting to initialize the Sick LD..." << std::endl;
94 
95  try {
96 
97  /* Attempt to connect to the Sick LD */
98  std::cout << "\tAttempting to connect to Sick LD @ " << _sick_ip_address << ":" << _sick_tcp_port << std::endl;
100  std::cout << "\t\tConnected to Sick LD!" << std::endl;
101 
102  /* Start the buffer monitor */
103  std::cout << "\tAttempting to start buffer monitor..." << std::endl;
104  _startListening();
105  std::cout << "\t\tBuffer monitor started!" << std::endl;
106 
107  /* Ok, lets sync the driver with the Sick */
108  std::cout << "\tAttempting to sync driver with Sick LD..." << std::endl;
110 
111  }
112 
113  catch(SickIOException &sick_io_exception) {
114  std::cerr << sick_io_exception.what() << std::endl;
115  throw;
116  }
117 
118  catch(SickThreadException &sick_thread_exception) {
119  std::cerr << sick_thread_exception.what() << std::endl;
120  throw;
121  }
122 
123  catch(SickTimeoutException &sick_timeout_exception) {
124  std::cerr << sick_timeout_exception.what() << std::endl;
125  throw;
126  }
127 
128  catch(...) {
129  std::cerr << "SickLD::Initialize - Unknown exception!" << std::endl;
130  throw;
131  }
132 
133  std::cout << "\t\tSynchronized!" << std::endl;
134 
135  _sick_initialized = true;
137 
138  /* Success */
139  }
140 
146  void SickLD::GetSickStatus( unsigned int &sick_sensor_mode, unsigned int &sick_motor_mode )
148 
149  /* Ensure the device has been initialized */
150  if (!_sick_initialized) {
151  throw SickIOException("SickLD::GetSickStatus: Device NOT Initialized!!!");
152  }
153 
154  /* Acquire the sensor and motor mode from the device */
155  try {
156  _getSickStatus();
157  }
158 
159  catch(SickTimeoutException &sick_timeout_exception) {
160  std::cerr << sick_timeout_exception.what() << std::endl;
161  throw;
162  }
163 
164  catch(SickIOException &sick_io_exception) {
165  std::cerr << sick_io_exception.what() << std::endl;
166  throw;
167  }
168 
169  catch(...) {
170  std::cerr << "SickLD::GetSickStatus - Unknown exception!" << std::endl;
171  throw;
172  }
173 
174  /* Now that the driver is updated, assign the return values */
175  sick_sensor_mode = _sick_sensor_mode;
176  sick_motor_mode = _sick_motor_mode;
177 
178  /* Success */
179  }
180 
190  void SickLD::SetSickTempScanAreas( const double * active_sector_start_angles, const double * active_sector_stop_angles,
191  const unsigned int num_active_sectors )
193 
194  /* Ensure the device has been initialized */
195  if (!_sick_initialized) {
196  throw SickConfigException("SickLD::SetSickTempScanAreas: Device NOT Initialized!!!");
197  }
198 
199  /* Do the standard initialization */
200  try {
201 
202  /* Set the temporary scan configuration */
203  std::cout << "\tAttempting to set desired scan config..." << std::endl;
204  _setSickTemporaryScanAreas(active_sector_start_angles,active_sector_stop_angles,num_active_sectors);
205  std::cout << "\t\tUsing desired scan area(s)!" << std::endl;
206 
207  }
208 
209  catch(SickIOException &sick_io_exception) {
210  std::cerr << sick_io_exception.what() << std::endl;
211  throw;
212  }
213 
214  catch(SickTimeoutException &sick_timeout_exception) {
215  std::cerr << sick_timeout_exception.what() << std::endl;
216  throw;
217  }
218 
219  catch(SickConfigException &sick_config_exception) {
220  std::cerr << sick_config_exception.what() << std::endl;
221  throw;
222  }
223 
224  catch(...) {
225  std::cerr << "SickLD::Initialize - Unknown exception!" << std::endl;
226  throw;
227  }
228 
229  /* Success */
230  }
231 
232 
241  void SickLD::SetSickTimeAbsolute( const uint16_t absolute_clock_time, uint16_t &new_sick_clock_time )
243 
244  /* Ensure the device has been initialized */
245  if (!_sick_initialized) {
246  throw SickConfigException("SickLD::SetSickTimeAbsolute: Device NOT Initialized!!!");
247  }
248 
249  /* Ensure the device is not in MEASURE mode */
251 
252  /* If it is then set it to rotate */
253  try {
255  }
256 
257  /* Handle a timeout! */
258  catch (SickTimeoutException &sick_timeout_exception) {
259  std::cerr << sick_timeout_exception.what() << std::endl;
260  throw;
261  }
262 
263  /* Handle I/O exceptions */
264  catch (SickIOException &sick_io_exception) {
265  std::cerr << sick_io_exception.what() << std::endl;
266  throw;
267  }
268 
269  /* Handle a returned error code */
270  catch (SickErrorException &sick_error_exception) {
271  std::cerr << sick_error_exception.what() << std::endl;
272  throw;
273  }
274 
275  /* A safety net */
276  catch (...) {
277  std::cerr << "SickLMS::SetSickTimeAbsolute: Unknown exception!!!" << std::endl;
278  throw;
279  }
280 
281  }
282 
283  std::cout << "\tSetting Sick LD absolute clock time..." << std::endl;
284 
285  /* Allocate a single buffer for payload contents */
286  uint8_t payload_buffer[SickLDMessage::MESSAGE_PAYLOAD_MAX_LENGTH] = {0};
287 
288  /* Set the service codes */
289  payload_buffer[0] = SICK_CONF_SERV_CODE;
290  payload_buffer[1] = SICK_CONF_SERV_SET_TIME_ABSOLUTE;
291 
292  /* Set the new time value */
293  uint16_t temp_buffer = host_to_sick_ld_byte_order(absolute_clock_time);
294  memcpy(&payload_buffer[2],&temp_buffer,2);
295 
296  /* Create the Sick LD send/receive message objects */
297  SickLDMessage send_message(payload_buffer,4);
298  SickLDMessage recv_message;
299 
300  /* Send the message and check for the reply */
301  try {
302  _sendMessageAndGetReply(send_message,recv_message);
303  }
304 
305  /* Handle a timeout! */
306  catch (SickTimeoutException &sick_timeout_exception) {
307  std::cerr << sick_timeout_exception.what() << std::endl;
308  throw;
309  }
310 
311  /* Handle I/O exceptions */
312  catch (SickIOException &sick_io_exception) {
313  std::cerr << sick_io_exception.what() << std::endl;
314  throw;
315  }
316 
317  /* A safety net */
318  catch (...) {
319  std::cerr << "SickLMS::_setSickSensorMode: Unknown exception!!!" << std::endl;
320  throw;
321  }
322 
323  /* Reset the payload buffer */
324  memset(payload_buffer,0,4);
325 
326  /* Get the message payload */
327  recv_message.GetPayload(payload_buffer);
328 
329  /* Extract the new Sick LD clock time from the response */
330  uint16_t clock_time;
331  memcpy(&clock_time,&payload_buffer[2],2);
332  new_sick_clock_time = sick_ld_to_host_byte_order(clock_time);
333 
334  std::cout << "\t\tClock time set!" << std::endl;
335 
336  /* Success */
337  }
338 
347  void SickLD::SetSickTimeRelative( const int16_t delta_time, uint16_t &new_sick_clock_time )
349 
350  /* Ensure the device has been initialized */
351  if (!_sick_initialized) {
352  throw SickConfigException("SickLD::SetSickTimeRelative: Device NOT Initialized!!!");
353  }
354 
355  /* Ensure the device is not in MEASURE mode */
357 
358  /* If it is then set it to rotate */
359  try {
361  }
362 
363  /* Handle a timeout! */
364  catch (SickTimeoutException &sick_timeout_exception) {
365  std::cerr << sick_timeout_exception.what() << std::endl;
366  throw;
367  }
368 
369  /* Handle I/O exceptions */
370  catch (SickIOException &sick_io_exception) {
371  std::cerr << sick_io_exception.what() << std::endl;
372  throw;
373  }
374 
375  /* Handle a returned error code */
376  catch (SickErrorException &sick_error_exception) {
377  std::cerr << sick_error_exception.what() << std::endl;
378  throw;
379  }
380 
381  /* A safety net */
382  catch (...) {
383  std::cerr << "SickLMS::SetSickTimeRelative: Unknown exception!!!" << std::endl;
384  throw;
385  }
386 
387  }
388 
389  std::cout << "\tSetting Sick LD relative clock time..." << std::endl;
390 
391  /* Allocate a single buffer for payload contents */
392  uint8_t payload_buffer[SickLDMessage::MESSAGE_PAYLOAD_MAX_LENGTH] = {0};
393 
394  /* Set the service codes */
395  payload_buffer[0] = SICK_CONF_SERV_CODE;
396  payload_buffer[1] = SICK_CONF_SERV_SET_TIME_RELATIVE;
397 
398  /* Set the new time value */
399  uint16_t temp_buffer = host_to_sick_ld_byte_order((uint16_t)delta_time);
400  memcpy(&payload_buffer[2],&temp_buffer,2);
401 
402  /* Create the Sick LD send/receive message objects */
403  SickLDMessage send_message(payload_buffer,4);
404  SickLDMessage recv_message;
405 
406  /* Send the message and check for the expected reply */
407  try {
408  _sendMessageAndGetReply(send_message,recv_message);
409  }
410 
411  /* Handle a timeout! */
412  catch (SickTimeoutException &sick_timeout_exception) {
413  std::cerr << sick_timeout_exception.what() << std::endl;
414  throw;
415  }
416 
417  /* Handle I/O exceptions */
418  catch (SickIOException &sick_io_exception) {
419  std::cerr << sick_io_exception.what() << std::endl;
420  throw;
421  }
422 
423  /* A safety net */
424  catch (...) {
425  std::cerr << "SickLMS::_setSickTimeRelative: Unknown exception!!!" << std::endl;
426  throw;
427  }
428 
429  /* Reset the payload buffer */
430  memset(payload_buffer,0,4);
431 
432  /* Get the message payload */
433  recv_message.GetPayload(payload_buffer);
434 
435  /* Extract the new Sick LD clock time from the response */
436  uint16_t clock_time;
437  memcpy(&clock_time,&payload_buffer[2],2);
438  new_sick_clock_time = sick_ld_to_host_byte_order(clock_time);
439 
440  std::cout << "\t\tClock time set!" << std::endl;
441 
442  /* Success */
443  }
444 
453  void SickLD::SetSickSignals( const uint8_t sick_signal_flags )
455 
456  /* Ensure the device has been initialized */
457  if (!_sick_initialized) {
458  throw SickConfigException("SickLD::SetSickSignals: Device NOT Initialized!!!");
459  }
460 
461  /* Attempt to set the signal flags */
462  try {
463  _setSickSignals(sick_signal_flags);
464  }
465 
466  /* Handle a timeout! */
467  catch (SickTimeoutException &sick_timeout_exception) {
468  std::cerr << sick_timeout_exception.what() << std::endl;
469  throw;
470  }
471 
472  /* Handle I/O exceptions */
473  catch (SickIOException &sick_io_exception) {
474  std::cerr << sick_io_exception.what() << std::endl;
475  throw;
476  }
477 
478  /* Handle a returned error code */
479  catch (SickErrorException &sick_error_exception) {
480  std::cerr << sick_error_exception.what() << std::endl;
481  throw;
482  }
483 
484  /* A safety net */
485  catch (...) {
486  std::cerr << "SickLMS::_syncDriverWithSick: Unknown exception!!!" << std::endl;
487  throw;
488  }
489 
490  /* Success! */
491  }
492 
497  void SickLD::GetSickSignals( uint8_t &sick_signal_flags ) throw( SickIOException, SickTimeoutException ) {
498 
499  /* Ensure the device has been initialized */
500  if (!_sick_initialized) {
501  throw SickIOException("SickLD::GetSickSignals: Device NOT Initialized!!!");
502  }
503 
504  /* Initialize the destination buffer */
505  sick_signal_flags = 0;
506 
507  /* Allocate a single buffer for payload contents */
508  uint8_t payload_buffer[SickLDMessage::MESSAGE_PAYLOAD_MAX_LENGTH] = {0};
509 
510  /* Set the service IDs */
511  payload_buffer[0] = SICK_STAT_SERV_CODE; // Requested service type
512  payload_buffer[1] = SICK_STAT_SERV_GET_SIGNAL; // Requested service subtype
513 
514  /* Create the Sick message */
515  SickLDMessage send_message(payload_buffer,2);
516  SickLDMessage recv_message;
517 
518  /* Send the message and get the reply */
519  try {
520  _sendMessageAndGetReply(send_message,recv_message);
521  }
522 
523  /* Handle a timeout! */
524  catch (SickTimeoutException &sick_timeout_exception) {
525  std::cerr << sick_timeout_exception.what() << std::endl;
526  throw;
527  }
528 
529  /* Handle I/O exceptions */
530  catch (SickIOException &sick_io_exception) {
531  std::cerr << sick_io_exception.what() << std::endl;
532  throw;
533  }
534 
535  /* A safety net */
536  catch (...) {
537  std::cerr << "SickLMS::GetSickSignals: Unknown exception!!!" << std::endl;
538  throw;
539  }
540 
541  /* Reset the payload buffer */
542  memset(payload_buffer,0,2);
543 
544  /* Extract the message payload */
545  recv_message.GetPayload(payload_buffer);
546 
547  /* Extract the Signal flags */
548  sick_signal_flags = payload_buffer[3];
549 
550  /* Success */
551  }
552 
557  void SickLD::GetSickTime( uint16_t &sick_time )
559 
560  /* Ensure the device has been initialized */
561  if (!_sick_initialized) {
562  throw SickIOException("SickLD::GetSickTime: Device NOT Initialized!!!");
563  }
564 
565  /* Allocate a single buffer for payload contents */
566  uint8_t payload_buffer[SickLDMessage::MESSAGE_PAYLOAD_MAX_LENGTH] = {0};
567 
568  /* Set the service IDs */
569  payload_buffer[0] = SICK_CONF_SERV_CODE; // Requested service type
570  payload_buffer[1] = SICK_CONF_SERV_GET_SYNC_CLOCK; // Requested service subtype
571 
572  /* Create the Sick messages */
573  SickLDMessage send_message(payload_buffer,2);
574  SickLDMessage recv_message;
575 
576  /* Send the message and check the reply */
577  try {
578  _sendMessageAndGetReply(send_message,recv_message);
579  }
580 
581  /* Handle a timeout! */
582  catch (SickTimeoutException &sick_timeout_exception) {
583  std::cerr << sick_timeout_exception.what() << std::endl;
584  throw;
585  }
586 
587  /* Handle I/O exceptions */
588  catch (SickIOException &sick_io_exception) {
589  std::cerr << sick_io_exception.what() << std::endl;
590  throw;
591  }
592 
593  /* A safety net */
594  catch (...) {
595  std::cerr << "SickLMS::GetSickTime: Unknown exception!!!" << std::endl;
596  throw;
597  }
598 
599  /* Reset the payload buffer */
600  memset(payload_buffer,0,2);
601 
602  /* Acquire the returned payload */
603  recv_message.GetPayload(payload_buffer);
604 
605  /* Extract actual time */
606  uint16_t current_time;
607  memcpy(&current_time,&payload_buffer[2],2);
608  sick_time = sick_ld_to_host_byte_order(current_time);
609 
610  /* Success */
611  }
612 
621 
622  /* Ensure the device has been initialized */
623  if(!_sick_initialized) {
624  throw SickIOException("SickLD::EnableNearfieldSuppression: Device NOT Initialized!!!");
625  }
626 
627  /* Tell the Sick LD to use nearfield suppression! */
628  std::cout << "\tEnabling nearfield suppression..." << std::endl;
629  try {
631  }
632 
633  /* Handle a timeout! */
634  catch (SickTimeoutException &sick_timeout_exception) {
635  std::cerr << sick_timeout_exception.what() << std::endl;
636  throw;
637  }
638 
639  /* Handle I/O exceptions */
640  catch (SickIOException &sick_io_exception) {
641  std::cerr << sick_io_exception.what() << std::endl;
642  throw;
643  }
644 
645  /* Handle a returned error code */
646  catch (SickErrorException &sick_error_exception) {
647  std::cerr << sick_error_exception.what() << std::endl;
648  throw;
649  }
650 
651  /* A safety net */
652  catch (...) {
653  std::cerr << "SickLMS::EnableNearfieldSuppression: Unknown exception!!!" << std::endl;
654  throw;
655  }
656 
657  std::cout << "\t\tSuppression is enabled!" << std::endl;
658 
659  /* Success */
660  }
661 
670 
671  /* Ensure the device has been initialized */
672  if (!_sick_initialized) {
673  throw SickIOException("SickLD::DisableNearfieldSuppression: Device NOT Initialized!!!");
674  }
675 
676  /* Tell the Sick LD to use nearfield suppression! */
677  std::cout << "\tDisabling nearfield suppression..." << std::endl;
678  try {
680  }
681 
682  /* Handle a timeout! */
683  catch (SickTimeoutException &sick_timeout_exception) {
684  std::cerr << sick_timeout_exception.what() << std::endl;
685  throw;
686  }
687 
688  /* Handle I/O exceptions */
689  catch (SickIOException &sick_io_exception) {
690  std::cerr << sick_io_exception.what() << std::endl;
691  throw;
692  }
693 
694  /* Handle a returned error code */
695  catch (SickErrorException &sick_error_exception) {
696  std::cerr << sick_error_exception.what() << std::endl;
697  throw;
698  }
699 
700  /* A safety net */
701  catch (...) {
702  std::cerr << "SickLMS::DisableNearfieldSuppression: Unknown exception!!!" << std::endl;
703  throw;
704  }
705 
706  std::cout << "\t\tSuppression is disabled!" << std::endl;
707 
708  /* Success */
709  }
710 
740  void SickLD::GetSickMeasurements( double * const range_measurements,
741  unsigned int * const echo_measurements,
742  unsigned int * const num_measurements,
743  unsigned int * const sector_ids,
744  unsigned int * const sector_data_offsets,
745  double * const sector_step_angles,
746  double * const sector_start_angles,
747  double * const sector_stop_angles,
748  unsigned int * const sector_start_timestamps,
749  unsigned int * const sector_stop_timestamps )
751 
752  /* Ensure the device has been initialized */
753  if(!_sick_initialized) {
754  throw SickIOException("SickLD::GetSickMeasurements: Device NOT Initialized!!!");
755  }
756 
757  /* The following conditional holds true if the user wants a RANGE+ECHO data
758  * stream but already has an active RANGE-ONLY stream.
759  */
760  if (_sick_streaming_range_data && echo_measurements != NULL) {
761 
762  try {
763 
764  /* Cancel the current RANGE-ONLY data stream */
766 
767  /* Request a RANGE+ECHO data stream */
769 
770  }
771 
772  /* Handle a timeout! */
773  catch (SickTimeoutException &sick_timeout_exception) {
774  std::cerr << sick_timeout_exception.what() << std::endl;
775  throw;
776  }
777 
778  /* Handle I/O exceptions */
779  catch (SickIOException &sick_io_exception) {
780  std::cerr << sick_io_exception.what() << std::endl;
781  throw;
782  }
783 
784  /* Handle a returned error code */
785  catch (SickErrorException &sick_error_exception) {
786  std::cerr << sick_error_exception.what() << std::endl;
787  throw;
788  }
789 
790  /* A safety net */
791  catch (...) {
792  std::cerr << "SickLMS::GetSickMeasurements: Unknown exception!!!" << std::endl;
793  throw;
794  }
795 
796  }
797 
798  /* The following conditional holds true if the user wants a RANGE-ONLY data
799  * stream but already has an active RANGE+ECHO stream.
800  */
801  if (_sick_streaming_range_and_echo_data && echo_measurements == NULL) {
802 
803  try {
804 
805  /* Cancel the current RANGE+ECHO data stream */
807 
808  /* Request a RANGE-ONLY data stream */
810 
811  }
812 
813  /* Handle a timeout! */
814  catch (SickTimeoutException &sick_timeout_exception) {
815  std::cerr << sick_timeout_exception.what() << std::endl;
816  throw;
817  }
818 
819  /* Handle I/O exceptions */
820  catch (SickIOException &sick_io_exception) {
821  std::cerr << sick_io_exception.what() << std::endl;
822  throw;
823  }
824 
825  /* Handle a returned error code */
826  catch (SickErrorException &sick_error_exception) {
827  std::cerr << sick_error_exception.what() << std::endl;
828  throw;
829  }
830 
831  /* A safety net */
832  catch (...) {
833  std::cerr << "SickLMS::GetSickMeasurements: Unknown exception!!!" << std::endl;
834  throw;
835  }
836 
837  }
838 
839  /* If there aren't any active data streams, setup a new one */
841 
842  try {
843 
844  /* Determine the target data stream by checking the value of echo_measurements */
845  if (echo_measurements != NULL) {
846 
847  /* Request a RANGE+ECHO data stream */
849 
850  }
851  else {
852 
853  /* Request a RANGE+ONLY data stream */
855 
856  }
857 
858  }
859 
860  /* Handle a timeout! */
861  catch (SickTimeoutException &sick_timeout_exception) {
862  std::cerr << sick_timeout_exception.what() << std::endl;
863  throw;
864  }
865 
866  /* Handle I/O exceptions */
867  catch (SickIOException &sick_io_exception) {
868  std::cerr << sick_io_exception.what() << std::endl;
869  throw;
870  }
871 
872  /* Handle a returned error code */
873  catch (SickErrorException &sick_error_exception) {
874  std::cerr << sick_error_exception.what() << std::endl;
875  throw;
876  }
877 
878  /* A safety net */
879  catch (...) {
880  std::cerr << "SickLMS::_setSickSensorMode: Unknown exception!!!" << std::endl;
881  throw;
882  }
883 
884  }
885 
886  /* Declare the receive message object */
887  SickLDMessage recv_message;
888 
889  /* Acquire the most recently buffered message */
890  try {
891  _recvMessage(recv_message,(unsigned int)1e6);
892  }
893 
894  catch(SickTimeoutException &sick_timeout_exception) {
895  std::cerr << sick_timeout_exception.what() << std::endl;
896  throw;
897  }
898 
899  catch(...) {
900  std::cerr << "SickLD::GetSickMeasurements - Unknown exception!" << std::endl;
901  throw;
902  }
903 
904  /* A single buffer for payload contents */
905  uint8_t payload_buffer[SickLDMessage::MESSAGE_PAYLOAD_MAX_LENGTH] = {0};
906 
907  /* Get the message payload */
908  recv_message.GetPayload(payload_buffer);
909 
910  /* Define the destination Sick LD scan profile struct */
911  sick_ld_scan_profile_t profile_data;
912 
913  /* Extract the scan profile */
914  _parseScanProfile(&payload_buffer[2],profile_data);
915 
916  /* Update and check the returned sensor status */
917  if ((_sick_sensor_mode = profile_data.sensor_status) != SICK_SENSOR_MODE_MEASURE) {
918  throw SickConfigException("SickLD::GetSickMeasurements: Unexpected sensor mode! " + _sickSensorModeToString(_sick_sensor_mode));
919  }
920 
921  /* Update and check the returned motor status */
922  if ((_sick_motor_mode = profile_data.motor_status) != SICK_MOTOR_MODE_OK) {
923  throw SickConfigException("SickLD::GetSickMeasurements: Unexpected motor mode! (Are you using a valid motor speed!)");
924  }
925 
926  /* Everything is OK, so now populate the relevant return buffers */
927  for (unsigned int i = 0, total_measurements = 0; i < _sick_sector_config.sick_num_active_sectors; i++) {
928 
929  /* Copy over the returned range values */
930  memcpy(&range_measurements[total_measurements],profile_data.sector_data[_sick_sector_config.sick_active_sector_ids[i]].range_values,
932 
933  /* Copy the returned echo values if requested */
934  if (echo_measurements != NULL) {
935  memcpy(&echo_measurements[total_measurements],profile_data.sector_data[_sick_sector_config.sick_active_sector_ids[i]].echo_values,
936  profile_data.sector_data[_sick_sector_config.sick_active_sector_ids[i]].num_data_points*sizeof(unsigned int));
937  }
938 
939  /* Set the number of measurements */
940  if (num_measurements != NULL) {
941  num_measurements[i] = profile_data.sector_data[_sick_sector_config.sick_active_sector_ids[i]].num_data_points;
942  }
943 
944  /* Set the associated sector's id if requested */
945  if (sector_ids != NULL) {
946  sector_ids[i] = profile_data.sector_data[_sick_sector_config.sick_active_sector_ids[i]].sector_num;
947  }
948 
949  /* Set the associated sector's index into the range measurement buffer if requested */
950  if (sector_data_offsets != NULL) {
951  sector_data_offsets[i] = total_measurements;
952  }
953 
954  /* Set the step angle if requested */
955  if (sector_step_angles != NULL) {
956  sector_step_angles[i] = profile_data.sector_data[_sick_sector_config.sick_active_sector_ids[i]].angle_step;
957  }
958 
959  /* Set the sector start angle if requested */
960  if (sector_start_angles != NULL) {
961  sector_start_angles[i] = profile_data.sector_data[_sick_sector_config.sick_active_sector_ids[i]].angle_start;
962  }
963 
964  /* Set the sector stop angle if requested */
965  if (sector_stop_angles != NULL) {
966  sector_stop_angles[i] = profile_data.sector_data[_sick_sector_config.sick_active_sector_ids[i]].angle_stop;
967  }
968 
969  /* Set the sector start timestamp if requested */
970  if (sector_start_timestamps != NULL) {
971  sector_start_timestamps[i] = profile_data.sector_data[_sick_sector_config.sick_active_sector_ids[i]].timestamp_start;
972  }
973 
974  /* Set the sector stop timestamp if requested */
975  if (sector_stop_timestamps != NULL) {
976  sector_stop_timestamps[i] = profile_data.sector_data[_sick_sector_config.sick_active_sector_ids[i]].timestamp_stop;
977  }
978 
979  /* Update the total number of measurements */
980  total_measurements += profile_data.sector_data[_sick_sector_config.sick_active_sector_ids[i]].num_data_points;
981  }
982 
983  /* Success */
984 
985  }
986 
991  void SickLD::SetSickSensorID( const unsigned int sick_sensor_id )
993 
994  /* Ensure the device has been initialized */
995  if (!_sick_initialized) {
996  throw SickConfigException("SickLD::SetSickSensorID: Device NOT Initialized!!!");
997  }
998 
999  /* Check that the given ID is valid */
1000  if (!_validSickSensorID(sick_sensor_id)) {
1001  throw SickConfigException("SickLD::SetSickSensorID: Invalid sensor ID!!!");
1002  }
1003 
1004  /* Attempt to set the new sensor ID in the flash! */
1005  try {
1007  }
1008 
1009  /* Handle a timeout! */
1010  catch (SickTimeoutException &sick_timeout_exception) {
1011  std::cerr << sick_timeout_exception.what() << std::endl;
1012  throw;
1013  }
1014 
1015  /* Handle I/O exceptions */
1016  catch (SickIOException &sick_io_exception) {
1017  std::cerr << sick_io_exception.what() << std::endl;
1018  throw;
1019  }
1020 
1021  /* Handle a returned error code */
1022  catch (SickErrorException &sick_error_exception) {
1023  std::cerr << sick_error_exception.what() << std::endl;
1024  throw;
1025  }
1026 
1027  /* A safety net */
1028  catch (...) {
1029  std::cerr << "SickLMS::SetSickSensorID: Unknown exception!!!" << std::endl;
1030  throw;
1031  }
1032 
1033  /* Success! */
1034  }
1035 
1040  void SickLD::SetSickMotorSpeed( const unsigned int sick_motor_speed )
1042 
1043  /* Ensure the device has been initialized */
1044  if (!_sick_initialized) {
1045  throw SickIOException("SickLD::SetSickMotorSpeed: Device NOT Initialized!!!");
1046  }
1047 
1048  /* Check that the given motor speed is valid */
1049  if (!_validSickMotorSpeed(sick_motor_speed)) {
1050  throw SickConfigException("SickLD::SetSickMotorSpeed: Invalid sick motor speed!!!");
1051  }
1052 
1053  /* Check to ensure a valid pulse frequency for the device */
1054  if (!_validPulseFrequency(sick_motor_speed,GetSickScanResolution())) {
1055  throw SickConfigException("SickLD::SetSickMotorSpeed: Invalid pulse frequency!!!");
1056  }
1057 
1058  /* Attempt to set the new global config in the flash! */
1059  try {
1061  }
1062 
1063  /* Handle a timeout! */
1064  catch (SickTimeoutException &sick_timeout_exception) {
1065  std::cerr << sick_timeout_exception.what() << std::endl;
1066  throw;
1067  }
1068 
1069  /* Handle I/O exceptions */
1070  catch (SickIOException &sick_io_exception) {
1071  std::cerr << sick_io_exception.what() << std::endl;
1072  throw;
1073  }
1074 
1075  /* Handle a returned error code */
1076  catch (SickErrorException &sick_error_exception) {
1077  std::cerr << sick_error_exception.what() << std::endl;
1078  throw;
1079  }
1080 
1081  /* A safety net */
1082  catch (...) {
1083  std::cerr << "SickLMS::SetSickMotorSpeed: Unknown exception!!!" << std::endl;
1084  throw;
1085  }
1086 
1087  /* Success! */
1088  }
1089 
1102  void SickLD::SetSickScanResolution( const double sick_angle_step )
1104 
1105  /* Ensure the device has been initialized */
1106  if (!_sick_initialized) {
1107  throw SickIOException("SickLD::SetSickScanResolution: Device NOT Initialized!!!");
1108  }
1109 
1110  /* Buffers to hold the active sector data */
1111  double active_sector_start_angles[SICK_MAX_NUM_SECTORS] = {0};
1112  double active_sector_stop_angles[SICK_MAX_NUM_SECTORS] = {0};
1113 
1114  /* Extract the start and stop angles for the current active sectors */
1115  for (unsigned int i = 0; i < _sick_sector_config.sick_num_active_sectors; i++) {
1118  }
1119 
1120  /* Set the operating parameters accordingly */
1121  try {
1123  active_sector_start_angles,active_sector_stop_angles,
1125  }
1126 
1127  catch(...) { }
1128 
1129  /* Success! */
1130  }
1131 
1140  void SickLD::SetSickGlobalParamsAndScanAreas( const unsigned int sick_motor_speed,
1141  const double sick_angle_step,
1142  const double * const active_sector_start_angles,
1143  const double * const active_sector_stop_angles,
1144  const unsigned int num_active_sectors )
1146 
1147  /* Ensure the device has been initialized */
1148  if (!_sick_initialized) {
1149  throw SickIOException("SickLD::SetSickGlobalParamsAndScanAreas: Device NOT Initialized!!!");
1150  }
1151 
1152  /* Attempt to write both a new scan resolution and scan area config */
1153  try {
1154  _setSickGlobalParamsAndScanAreas(sick_motor_speed,sick_angle_step,
1155  active_sector_start_angles,active_sector_stop_angles,num_active_sectors);
1156  }
1157 
1158  /* Handle a timeout! */
1159  catch (SickTimeoutException &sick_timeout_exception) {
1160  std::cerr << sick_timeout_exception.what() << std::endl;
1161  throw;
1162  }
1163 
1164  /* Handle I/O exceptions */
1165  catch (SickIOException &sick_io_exception) {
1166  std::cerr << sick_io_exception.what() << std::endl;
1167  throw;
1168  }
1169 
1170  /* Handle config exception */
1171  catch (SickConfigException &sick_config_exception) {
1172  std::cerr << sick_config_exception.what() << std::endl;
1173  throw;
1174  }
1175 
1176  /* Handle a returned error code */
1177  catch (SickErrorException &sick_error_exception) {
1178  std::cerr << sick_error_exception.what() << std::endl;
1179  throw;
1180  }
1181 
1182  /* A safety net */
1183  catch (...) {
1184  std::cerr << "SickLMS::SetSickGlobalParamsAndScanAreas: Unknown exception!!!" << std::endl;
1185  throw;
1186  }
1187 
1188  /* Success! */
1189 
1190  }
1191 
1198  void SickLD::SetSickScanAreas( const double * const active_sector_start_angles,
1199  const double * const active_sector_stop_angles,
1200  const unsigned int num_active_sectors )
1202 
1203  /* Ensure the device has been initialized */
1204  if (!_sick_initialized) {
1205  throw SickIOException("SickLD::SetSickScanAreas: Device NOT Initialized!!!");
1206  }
1207 
1208  /* Attempt to write both a new scan resolution and scan area config */
1209  try {
1211  active_sector_start_angles,active_sector_stop_angles,num_active_sectors);
1212  }
1213 
1214  /* Handle a timeout! */
1215  catch (SickTimeoutException &sick_timeout_exception) {
1216  std::cerr << sick_timeout_exception.what() << std::endl;
1217  throw;
1218  }
1219 
1220  /* Handle I/O exceptions */
1221  catch (SickIOException &sick_io_exception) {
1222  std::cerr << sick_io_exception.what() << std::endl;
1223  throw;
1224  }
1225 
1226  /* Handle config exception */
1227  catch (SickConfigException &sick_config_exception) {
1228  std::cerr << sick_config_exception.what() << std::endl;
1229  throw;
1230  }
1231 
1232  /* Handle a returned error code */
1233  catch (SickErrorException &sick_error_exception) {
1234  std::cerr << sick_error_exception.what() << std::endl;
1235  throw;
1236  }
1237 
1238  /* A safety net */
1239  catch (...) {
1240  std::cerr << "SickLMS::SetSickScanAreas: Unknown exception!!!" << std::endl;
1241  throw;
1242  }
1243 
1244  /* Success! */
1245 
1246  }
1247 
1252  void SickLD::ResetSick( const unsigned int reset_level )
1254 
1255  /* Ensure the device has been initialized */
1256  if (!_sick_initialized) {
1257  throw SickIOException("SickLD::ResetSick: Device NOT Initialized!!!");
1258  }
1259 
1260  /* Ensure a valid reset level was given */
1261  if (reset_level > SICK_WORK_SERV_RESET_HALT_APP) {
1262  throw SickConfigException("SickLD::ResetSick: Invalid given reset level!");
1263  }
1264 
1265  /* Allocate a single buffer for payload contents */
1266  uint8_t payload_buffer[SickLDMessage::MESSAGE_PAYLOAD_MAX_LENGTH] = {0};
1267 
1268  /* Set the service IDs */
1269  payload_buffer[0] = SICK_WORK_SERV_CODE; // Requested service type
1270  payload_buffer[1] = SICK_WORK_SERV_RESET; // Requested service subtype
1271  payload_buffer[3] = (uint8_t)reset_level; // RESETLEVEL
1272 
1273  /* Create the Sick messages */
1274  SickLDMessage send_message(payload_buffer,4);
1275  SickLDMessage recv_message;
1276 
1277  /* Send the message and check the reply */
1278  try {
1279  _sendMessageAndGetReply(send_message,recv_message);
1280  }
1281 
1282  /* Handle a timeout! */
1283  catch (SickTimeoutException &sick_timeout_exception) {
1284  std::cerr << sick_timeout_exception.what() << std::endl;
1285  throw;
1286  }
1287 
1288  /* Handle I/O exceptions */
1289  catch (SickIOException &sick_io_exception) {
1290  std::cerr << sick_io_exception.what() << std::endl;
1291  throw;
1292  }
1293 
1294  /* A safety net */
1295  catch (...) {
1296  std::cerr << "SickLMS::_setSickSensorMode: Unknown exception!!!" << std::endl;
1297  throw;
1298  }
1299 
1300  /* Reset the payload buffer */
1301  memset(payload_buffer,0,4);
1302 
1303  /* Acquire the returned payload */
1304  recv_message.GetPayload(payload_buffer);
1305 
1306  /* Extract the returned reset level */
1307  uint16_t current_reset_level;
1308  memcpy(&current_reset_level,&payload_buffer[2],2);
1309  current_reset_level = sick_ld_to_host_byte_order(current_reset_level);
1310 
1311  /* Verify the returned reset level */
1312  if (current_reset_level != (uint16_t)reset_level) {
1313  throw SickErrorException("SickLD::ResetSick: Unexpected returned reset level!");
1314  }
1315 
1316  /* Success */
1317  }
1318 
1323  unsigned int SickLD::GetSickNumActiveSectors( ) const {
1325  }
1326 
1331  unsigned int SickLD::GetSickSensorID( ) const {
1333  }
1334 
1339  unsigned int SickLD::GetSickMotorSpeed( ) const {
1341  }
1342 
1349  }
1350 
1355  std::string SickLD::GetSickIPAddress( ) const {
1356 
1357  /* Declare the string stream */
1358  std::ostringstream str_stream;
1359 
1360  str_stream << _sick_ethernet_config.sick_ip_address[0] << "."
1364 
1365  /* Return the std string representation */
1366  return str_stream.str();
1367 
1368  }
1369 
1374  std::string SickLD::GetSickSubnetMask( ) const {
1375 
1376  /* Declare the string stream */
1377  std::ostringstream str_stream;
1378 
1379  str_stream << _sick_ethernet_config.sick_subnet_mask[0] << "."
1383 
1384  /* Return the std string representation */
1385  return str_stream.str();
1386 
1387  }
1388 
1393  std::string SickLD::GetSickGatewayIPAddress( ) const {
1394 
1395  /* Declare the string stream */
1396  std::ostringstream str_stream;
1397 
1398  str_stream << _sick_ethernet_config.sick_gateway_ip_address[0] << "."
1402 
1403  /* Return the std string representation */
1404  return str_stream.str();
1405 
1406  }
1407 
1412  std::string SickLD::GetSickPartNumber( ) const {
1414  }
1415 
1420  std::string SickLD::GetSickName( ) const {
1421  return _sick_identity.sick_name;
1422  }
1423 
1428  std::string SickLD::GetSickVersion( ) const {
1430  }
1431 
1436  std::string SickLD::GetSickSerialNumber( ) const {
1438  }
1439 
1444  std::string SickLD::GetSickEDMSerialNumber( ) const {
1446  }
1447 
1452  std::string SickLD::GetSickFirmwarePartNumber( ) const {
1454  }
1455 
1460  std::string SickLD::GetSickFirmwareName( ) const {
1462  }
1463 
1468  std::string SickLD::GetSickFirmwareVersion( ) const {
1470  }
1471 
1478  }
1479 
1484  std::string SickLD::GetSickAppSoftwareName( ) const {
1486  }
1487 
1494  }
1495 
1500  std::string SickLD::GetSickStatusAsString() const {
1501 
1502  std::stringstream str_stream;
1503 
1504  str_stream << "\t============= Sick LD Status =============" << std::endl;
1505  str_stream << "\tSensor Mode: " << _sickSensorModeToString(_sick_sensor_mode) << std::endl;
1506  str_stream << "\tMotor Mode: " << _sickMotorModeToString(_sick_motor_mode) << std::endl;
1507  str_stream << "\t==========================================" << std::endl;
1508 
1509  return str_stream.str();
1510 
1511  }
1512 
1517  std::string SickLD::GetSickIdentityAsString() const {
1518 
1519  std::ostringstream str_stream;
1520 
1521  str_stream << "\t============ Sick LD Identity ============" << std::endl;
1522  str_stream << "\tSensor Part #: " << GetSickPartNumber() << std::endl;
1523  str_stream << "\tSensor Name: " << GetSickName() << std::endl;
1524  str_stream << "\tSensor Version: " << GetSickVersion() << std::endl;
1525  str_stream << "\tSensor Serial #: " << GetSickSerialNumber() << std::endl;
1526  str_stream << "\tSensor EDM Serial #: " << GetSickEDMSerialNumber() << std::endl;
1527  str_stream << "\tFirmware Part #: " << GetSickFirmwarePartNumber() << std::endl;
1528  str_stream << "\tFirmware Version: " << GetSickFirmwareVersion() << std::endl;
1529  str_stream << "\tFirmware Name: " << GetSickFirmwareName() << std::endl;
1530  str_stream << "\tApp. Software Part #: " << GetSickAppSoftwarePartNumber() << std::endl;
1531  str_stream << "\tApp. Software Name: " << GetSickAppSoftwareName() << std::endl;
1532  str_stream << "\tApp. Software Version: " << GetSickAppSoftwareVersionNumber() << std::endl;
1533  str_stream << "\t==========================================" << std::endl;
1534 
1535  return str_stream.str();
1536 
1537  }
1538 
1544 
1545  std::stringstream str_stream;
1546 
1547  str_stream << "\t=========== Sick Global Config ===========" << std::endl;
1548  str_stream << "\tSensor ID: " << GetSickSensorID() << std::endl;
1549  str_stream << "\tMotor Speed (5 to 20Hz): " << GetSickMotorSpeed() << std::endl;
1550  str_stream << "\tAngle Step (deg): " << GetSickScanResolution() << std::endl;
1551  str_stream << "\t==========================================" << std::endl;
1552 
1553  return str_stream.str();
1554 
1555  }
1556 
1562 
1563  std::stringstream str_stream;
1564 
1565  str_stream << "\t========== Sick Ethernet Config ==========" << std::endl;
1566  str_stream << "\tIP Address: " << GetSickIPAddress() << std::endl;
1567  str_stream << "\tSubnet Mask: " << GetSickSubnetMask() << std::endl;
1568  str_stream << "\tGateway IP Address: " << GetSickGatewayIPAddress() << std::endl;
1569  str_stream << "\t==========================================" << std::endl;
1570 
1571  return str_stream.str();
1572 
1573  }
1574 
1580 
1581  std::stringstream str_stream;
1582 
1583  str_stream << "\t=========== Sick Sector Config ===========" << std::endl;
1584  str_stream << "\tNum. Active Sectors: " << (int)_sick_sector_config.sick_num_active_sectors << std::endl;
1585  str_stream << "\tNum. Initialized Sectors: " << (int)_sick_sector_config.sick_num_initialized_sectors << std::endl;
1586 
1587  str_stream << "\tSector Configs.:" << std::endl;
1588  for (unsigned int i = 0; i < _sick_sector_config.sick_num_initialized_sectors; i++) {
1589  str_stream << "\t\t" << i << " ["
1593  }
1594 
1595  str_stream << "\t==========================================" << std::endl;
1596 
1597  return str_stream.str();
1598 
1599  }
1600 
1605  double SickLD::GetSickScanArea( ) const {
1606 
1607  /* Some temp buffers */
1608  double sector_start_angles[SICK_MAX_NUM_SECTORS] = {0};
1609  double sector_stop_angles[SICK_MAX_NUM_SECTORS] = {0};
1610 
1611  /* Sum the active areas over all sectors */
1612  for (unsigned int i = 0; i < _sick_sector_config.sick_num_active_sectors; i++) {
1615  }
1616 
1617  /* Return the computed total scan area */
1618  return _computeScanArea(GetSickScanResolution(),sector_start_angles,sector_stop_angles,_sick_sector_config.sick_num_active_sectors);
1619  }
1620 
1624  void SickLD::PrintSickStatus( ) const {
1625  std::cout << GetSickStatusAsString() << std::flush;
1626  }
1627 
1632  std::cout << GetSickIdentityAsString() << std::flush;
1633  }
1634 
1639  std::cout << GetSickGlobalConfigAsString() << std::flush;
1640  }
1641 
1646  std::cout << GetSickEthernetConfigAsString() << std::flush;
1647  }
1648 
1653  std::cout << GetSickSectorConfigAsString() << std::flush;
1654  }
1655 
1660 
1661  /* Ensure the device has been initialized */
1662  if (!_sick_initialized) {
1663  throw SickIOException("SickLD::Uninitialize: Device NOT Initialized!!!");
1664  }
1665 
1666  std::cout << std::endl << "\t*** Attempting to uninitialize the Sick LD..." << std::endl;
1667 
1668  /* If necessary, tell the Sick LD to stop streaming data */
1669  try {
1670 
1671  std::cout << "\tSetting Sick LD to idle mode..." << std::endl;
1673  std::cout << "\t\tSick LD is now idle!" << std::endl;
1674 
1675  /* Clear any signals that were set */
1676  SetSickSignals();
1677 
1678  /* Attempt to cancel the buffer monitor */
1679  std::cout << "\tAttempting to cancel buffer monitor..." << std::endl;
1680  _stopListening();
1681  std::cout << "\t\tBuffer monitor canceled!" << std::endl;
1682 
1683  /* Attempt to close the tcp connection */
1684  std::cout << "\tClosing connection to Sick LD..." << std::endl;
1686 
1687  }
1688 
1689  /* Handle a timeout! */
1690  catch (SickTimeoutException &sick_timeout_exception) {
1691  std::cerr << sick_timeout_exception.what() << std::endl;
1692  throw;
1693  }
1694 
1695  /* Handle I/O exceptions */
1696  catch (SickIOException &sick_io_exception) {
1697  std::cerr << sick_io_exception.what() << std::endl;
1698  throw;
1699  }
1700 
1701  /* Handle a returned error code */
1702  catch (SickErrorException &sick_error_exception) {
1703  std::cerr << sick_error_exception.what() << std::endl;
1704  throw;
1705  }
1706 
1707  /* Handle a returned error code */
1708  catch (SickThreadException &sick_thread_exception) {
1709  std::cerr << sick_thread_exception.what() << std::endl;
1710  throw;
1711  }
1712 
1713  /* A safety net */
1714  catch (...) {
1715  std::cerr << "SickLMS::_setSickSensorMode: Unknown exception!!!" << std::endl;
1716  throw;
1717  }
1718 
1719  std::cout << "\t\tConnection closed!" << std::endl;
1720 
1721  std::cout << "\t*** Uninit. complete - Sick LD is now offline!" << std::endl;
1722 
1723  /* Mark the device as uninitialized */
1724  _sick_initialized = false;
1725 
1726  /* Success! */
1727  }
1728 
1733 
1734  /* Create the TCP socket */
1735  if ((_sick_fd = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP)) < 0) {
1736  throw SickIOException("SickLD::_setupConnection: socket() failed!");
1737  }
1738 
1739  /* Initialize the buffer */
1740  memset(&_sick_inet_address_info,0,sizeof(struct sockaddr_in));
1741 
1742  /* Setup the Sick LD inet address structure */
1743  _sick_inet_address_info.sin_family = AF_INET; // Internet protocol address family
1744  _sick_inet_address_info.sin_port = htons(_sick_tcp_port); // TCP port number
1745  _sick_inet_address_info.sin_addr.s_addr = inet_addr(_sick_ip_address.c_str()); // Convert ip string to numerical address
1746 
1747  try {
1748 
1749  /* Set to non-blocking so we can time connect */
1751 
1752  /* Try to connect to the Sick LD */
1753  int conn_return;
1754  if ((conn_return = connect(_sick_fd,(struct sockaddr *)&_sick_inet_address_info,sizeof(struct sockaddr_in))) < 0) {
1755 
1756  /* Check whether it is b/c it would block */
1757  if (errno != EINPROGRESS) {
1758  throw SickIOException("SickLD::_setupConnection: connect() failed!");
1759  }
1760 
1761  /* Use select to wait on the socket */
1762  int valid_opt = 0;
1763  int num_active_files = 0;
1764  struct timeval timeout_val; // This structure will be used for setting our timeout values
1765  fd_set file_desc_set; // File descriptor set for monitoring I/O
1766 
1767  /* Initialize and set the file descriptor set for select */
1768  FD_ZERO(&file_desc_set);
1769  FD_SET(_sick_fd,&file_desc_set);
1770 
1771  /* Setup the timeout structure */
1772  memset(&timeout_val,0,sizeof(timeout_val)); // Initialize the buffer
1773  timeout_val.tv_usec = DEFAULT_SICK_CONNECT_TIMEOUT; // Wait for specified time before throwing a timeout
1774 
1775  /* Wait for the OS to tell us that the connection is established! */
1776  num_active_files = select(getdtablesize(),0,&file_desc_set,0,&timeout_val);
1777 
1778  /* Figure out what to do based on the output of select */
1779  if (num_active_files > 0) {
1780 
1781  /* This is just a sanity check */
1782  if (!FD_ISSET(_sick_fd,&file_desc_set)) {
1783  throw SickIOException("SickLD::_setupConnection: Unexpected file descriptor!");
1784  }
1785 
1786  /* Check for any errors on the socket - just to be sure */
1787  socklen_t len = sizeof(int);
1788  if (getsockopt(_sick_fd,SOL_SOCKET,SO_ERROR,(void*)(&valid_opt),&len) < 0) {
1789  throw SickIOException("SickLD::_setupConnection: getsockopt() failed!");
1790  }
1791 
1792  /* Check whether the opt value indicates error */
1793  if (valid_opt) {
1794  throw SickIOException("SickLD::_setupConnection: socket error on connect()!");
1795  }
1796 
1797  }
1798  else if (num_active_files == 0) {
1799 
1800  /* A timeout has occurred! */
1801  throw SickTimeoutException("SickLD::_setupConnection: select() timeout!");
1802 
1803  }
1804  else {
1805 
1806  /* An error has occurred! */
1807  throw SickIOException("SickLD::_setupConnection: select() failed!");
1808 
1809  }
1810 
1811  }
1812 
1813  /* Restore blocking IO */
1814  _setBlockingIO();
1815 
1816  }
1817 
1818  catch(SickIOException &sick_io_exception) {
1819  std::cerr << sick_io_exception.what() << std::endl;
1820  throw;
1821  }
1822 
1823  catch(SickTimeoutException &sick_timeout_exception) {
1824  std::cerr << sick_timeout_exception.what() << std::endl;
1825  throw;
1826  }
1827 
1828  catch(...) {
1829  std::cerr << "SickLD::_setupConnection - Unknown exception occurred!" << std::endl;
1830  throw;
1831  }
1832 
1833  /* Success */
1834  }
1835 
1842 
1843  try {
1844 
1845  /* Acquire current configuration */
1846  _getSickStatus();
1847  _getSickIdentity();
1851 
1852  /* Reset Sick signals */
1853  _setSickSignals();
1854 
1855  }
1856 
1857  /* Handle a timeout! */
1858  catch (SickTimeoutException &sick_timeout_exception) {
1859  std::cerr << sick_timeout_exception.what() << std::endl;
1860  throw;
1861  }
1862 
1863  /* Handle I/O exceptions */
1864  catch (SickIOException &sick_io_exception) {
1865  std::cerr << sick_io_exception.what() << std::endl;
1866  throw;
1867  }
1868 
1869  /* Handle a returned error code */
1870  catch (SickErrorException &sick_error_exception) {
1871  std::cerr << sick_error_exception.what() << std::endl;
1872  throw;
1873  }
1874 
1875  /* A safety net */
1876  catch (...) {
1877  std::cerr << "SickLMS::_syncDriverWithSick: Unknown exception!!!" << std::endl;
1878  throw;
1879  }
1880 
1881  /* Success */
1882  }
1883 
1890  void SickLD::_setSickSectorFunction ( const uint8_t sector_number, const uint8_t sector_function,
1891  const double sector_stop_angle, const bool write_to_flash )
1893 
1894  /* Ensure the device is not measuring */
1896 
1897  /* Set the Sick LD to rotate mode */
1898  try {
1900  }
1901 
1902  /* Handle a timeout! */
1903  catch (SickTimeoutException &sick_timeout_exception) {
1904  std::cerr << sick_timeout_exception.what() << std::endl;
1905  throw;
1906  }
1907 
1908  /* Handle I/O exceptions */
1909  catch (SickIOException &sick_io_exception) {
1910  std::cerr << sick_io_exception.what() << std::endl;
1911  throw;
1912  }
1913 
1914  /* Handle a returned error code */
1915  catch (SickErrorException &sick_error_exception) {
1916  std::cerr << sick_error_exception.what() << std::endl;
1917  throw;
1918  }
1919 
1920  /* A safety net */
1921  catch (...) {
1922  std::cerr << "SickLMS::_setSickSectorFunction: Unknown exception!!!" << std::endl;
1923  throw;
1924  }
1925 
1926  }
1927 
1928  /* Ensure a valid sector number */
1929  if (sector_number >= SICK_MAX_NUM_SECTORS) {
1930  throw SickConfigException("SickLD::_setSickSectorFunction: Invalid sector number!");
1931  }
1932 
1933  /* Check that a valid sector_function was given */
1934  if (sector_function != SICK_CONF_SECTOR_NOT_INITIALIZED &&
1935  sector_function != SICK_CONF_SECTOR_NO_MEASUREMENT &&
1936  sector_function != SICK_CONF_SECTOR_RESERVED &&
1937  sector_function != SICK_CONF_SECTOR_NORMAL_MEASUREMENT &&
1938  sector_function != SICK_CONF_SECTOR_REFERENCE_MEASUREMENT) {
1939 
1940  throw SickConfigException("SickLD::_setSickSectorFunction: Invalid sector function code!");
1941  }
1942 
1943  /* Check that a valid stop angle was given */
1944  if (sector_stop_angle > SICK_MAX_SCAN_AREA) {
1945  throw SickConfigException("SickLD::_setSickSectorFunction: Invalid sector stop angle!");
1946  }
1947 
1948  /* Allocate a single buffer for payload contents */
1949  uint8_t payload_buffer[SickLDMessage::MESSAGE_PAYLOAD_MAX_LENGTH] = {0};
1950 
1951  /* A temporary buffer for byte order conversion */
1952  uint16_t temp_buff = 0;
1953 
1954  /* Set the service IDs */
1955  payload_buffer[0] = SICK_CONF_SERV_CODE; // Requested service type
1956  payload_buffer[1] = SICK_CONF_SERV_SET_FUNCTION; // Requested service subtype
1957 
1958  /* Assign the payload data */
1959  payload_buffer[3] = sector_number; // SECTORNUM
1960  payload_buffer[5] = sector_function; // SECTORFUNC
1961 
1962  /* Set the sector stop value */
1963  temp_buff = host_to_sick_ld_byte_order(_angleToTicks(sector_stop_angle));
1964  memcpy(&payload_buffer[6],&temp_buff,2); // SECTORSTOP
1965 
1966  /* Include the flash flag */
1967  payload_buffer[9] = (uint8_t)write_to_flash; // FLASHFLAG
1968 
1969  /* Create the Sick LD messages */
1970  SickLDMessage send_message(payload_buffer,10);
1971  SickLDMessage recv_message;
1972 
1973  /* Send the message and get the reply */
1974  try {
1975  _sendMessageAndGetReply(send_message,recv_message);
1976  }
1977 
1978  /* Handle a timeout! */
1979  catch (SickTimeoutException &sick_timeout_exception) {
1980  std::cerr << sick_timeout_exception.what() << std::endl;
1981  throw;
1982  }
1983 
1984  /* Handle I/O exceptions */
1985  catch (SickIOException &sick_io_exception) {
1986  std::cerr << sick_io_exception.what() << std::endl;
1987  throw;
1988  }
1989 
1990  /* A safety net */
1991  catch (...) {
1992  std::cerr << "SickLMS::_setSickSectorFunction: Unknown exception!!!" << std::endl;
1993  throw;
1994  }
1995 
1996  /* Reset the payload buffer (not necessary, but it doesn't hurt to be careful) */
1997  memset(payload_buffer,0,10);
1998 
1999  /* Extract the message payload */
2000  recv_message.GetPayload(payload_buffer);
2001 
2002  /* Check the response for an error */
2003  if (payload_buffer[2] == 0xFF && payload_buffer[3] == 0xFF) {
2004  throw SickConfigException("SickLD::_setSickSectorFunction: Invalid request!");
2005  }
2006 
2007  /* Success! */
2008  }
2009 
2016  void SickLD::_getSickSectorFunction( const uint8_t sector_num, uint8_t &sector_function, double &sector_stop_angle )
2018 
2019  /* Ensure the device is not measuring */
2021 
2022  /* Set the Sick LD to rotate mode */
2023  try {
2025  }
2026 
2027  /* Handle a timeout! */
2028  catch (SickTimeoutException &sick_timeout_exception) {
2029  std::cerr << sick_timeout_exception.what() << std::endl;
2030  throw;
2031  }
2032 
2033  /* Handle I/O exceptions */
2034  catch (SickIOException &sick_io_exception) {
2035  std::cerr << sick_io_exception.what() << std::endl;
2036  throw;
2037  }
2038 
2039  /* Handle a returned error code */
2040  catch (SickErrorException &sick_error_exception) {
2041  std::cerr << sick_error_exception.what() << std::endl;
2042  throw;
2043  }
2044 
2045  /* A safety net */
2046  catch (...) {
2047  std::cerr << "SickLMS::_getSickSectorFunction: Unknown exception!!!" << std::endl;
2048  throw;
2049  }
2050 
2051  }
2052 
2053  /* Declare the message payload buffer */
2054  uint8_t payload_buffer[SickLDMessage::MESSAGE_PAYLOAD_MAX_LENGTH] = {0};
2055 
2056  /* Set the service IDs */
2057  payload_buffer[0] = SICK_CONF_SERV_CODE; // Requested service type
2058  payload_buffer[1] = SICK_CONF_SERV_GET_FUNCTION; // Requested service subtype
2059  payload_buffer[3] = sector_num; // Sector number
2060 
2061  /* Declare the send/recv Sick LD message objects */
2062  SickLDMessage send_message(payload_buffer,4);
2063  SickLDMessage recv_message;
2064 
2065  /* Send the message and get a response */
2066  try {
2067  _sendMessageAndGetReply(send_message,recv_message);
2068  }
2069 
2070  /* Handle a timeout! */
2071  catch (SickTimeoutException &sick_timeout_exception) {
2072  std::cerr << sick_timeout_exception.what() << std::endl;
2073  throw;
2074  }
2075 
2076  /* Handle I/O exceptions */
2077  catch (SickIOException &sick_io_exception) {
2078  std::cerr << sick_io_exception.what() << std::endl;
2079  throw;
2080  }
2081 
2082  /* A safety net */
2083  catch (...) {
2084  std::cerr << "SickLMS::_getSickSectorFunction: Unknown exception!!!" << std::endl;
2085  throw;
2086  }
2087 
2088  /* Reset the payload buffer */
2089  memset(payload_buffer,0,4);
2090 
2091  /* Extract the message payload */
2092  recv_message.GetPayload(payload_buffer);
2093 
2094  /* Extract the returned sector number */
2095  uint16_t temp_buffer = 0;
2096  memcpy(&temp_buffer,&payload_buffer[2],2);
2097  temp_buffer = sick_ld_to_host_byte_order(temp_buffer);
2098 
2099  /* Check to make sure the returned sector number matches
2100  * the requested sector number.
2101  */
2102  if (temp_buffer != sector_num) {
2103  throw SickConfigException("SickLD::_getSickSectorFunction: Unexpected sector number returned by Sick LD!");
2104  }
2105 
2106  /* Extract the sector function */
2107  memcpy(&temp_buffer,&payload_buffer[4],2);
2108  sector_function = sick_ld_to_host_byte_order(temp_buffer);
2109 
2110  /* Extract the sector stop angle (in ticks) */
2111  memcpy(&temp_buffer,&payload_buffer[6],2);
2112  sector_stop_angle = _ticksToAngle(sick_ld_to_host_byte_order(temp_buffer));
2113 
2114  /* S'ok */
2115  }
2116 
2122 
2123  /* If necessary adjust the operating mode of the sensor */
2125 
2126  /* Switch the sensor's operating mode to IDLE */
2127  try {
2129  }
2130 
2131  /* Handle a timeout! */
2132  catch (SickTimeoutException &sick_timeout_exception) {
2133  std::cerr << sick_timeout_exception.what() << std::endl;
2134  throw;
2135  }
2136 
2137  /* Handle I/O exceptions */
2138  catch (SickIOException &sick_io_exception) {
2139  std::cerr << sick_io_exception.what() << std::endl;
2140  throw;
2141  }
2142 
2143  /* Handle a returned error code */
2144  catch (SickErrorException &sick_error_exception) {
2145  std::cerr << sick_error_exception.what() << std::endl;
2146  throw;
2147  }
2148 
2149  /* A safety net */
2150  catch (...) {
2151  std::cerr << "SickLMS::_setSickSensorModeToIdle: Unknown exception!!!" << std::endl;
2152  throw;
2153  }
2154 
2155  }
2156 
2157  /* Success */
2158  }
2159 
2165 
2166  /* If necessary adjust the operating mode of the sensor */
2168 
2169  /* Switch the sensor's operating mode to ROTATE */
2170  try {
2172  }
2173 
2174  /* Handle a timeout! */
2175  catch (SickTimeoutException &sick_timeout_exception) {
2176  std::cerr << sick_timeout_exception.what() << std::endl;
2177  throw;
2178  }
2179 
2180  /* Handle I/O exceptions */
2181  catch (SickIOException &sick_io_exception) {
2182  std::cerr << sick_io_exception.what() << std::endl;
2183  throw;
2184  }
2185 
2186  /* Handle a returned error code */
2187  catch (SickErrorException &sick_error_exception) {
2188  std::cerr << sick_error_exception.what() << std::endl;
2189  throw;
2190  }
2191 
2192  /* A safety net */
2193  catch (...) {
2194  std::cerr << "SickLMS::_setSickSensorModeToRotate: Unknown exception!!!" << std::endl;
2195  throw;
2196  }
2197 
2198  }
2199 
2200  /* Success */
2201  }
2202 
2208 
2209  /* If necessary adjust the operating mode of the sensor */
2211 
2212  /* Switch the sensor's operating mode to MEASURE */
2213  try {
2215  }
2216 
2217  /* Handle a timeout! */
2218  catch (SickTimeoutException &sick_timeout_exception) {
2219  std::cerr << sick_timeout_exception.what() << std::endl;
2220  throw;
2221  }
2222 
2223  /* Handle I/O exceptions */
2224  catch (SickIOException &sick_io_exception) {
2225  std::cerr << sick_io_exception.what() << std::endl;
2226  throw;
2227  }
2228 
2229  /* Handle a returned error code */
2230  catch (SickErrorException &sick_error_exception) {
2231  std::cerr << sick_error_exception.what() << std::endl;
2232  throw;
2233  }
2234 
2235  /* A safety net */
2236  catch (...) {
2237  std::cerr << "SickLMS::_setSickSensorModeToMeasure: Unknown exception!!!" << std::endl;
2238  throw;
2239  }
2240 
2241  }
2242 
2243  /* Success */
2244  }
2245 
2250  void SickLD::_setSickSensorMode( const uint8_t new_sick_sensor_mode )
2252 
2253  /* If the new mode matches the current mode then just return */
2254  if (_sick_sensor_mode == new_sick_sensor_mode) {
2255  return;
2256  }
2257 
2258  try {
2259 
2260  /* If the current sensor mode is MEASURE and streaming data */
2263 
2264  /* Cancel the current stream */
2266 
2267  }
2268 
2269  /* The Sick LD must be in rotate mode before: going from IDLE to MEASURE or going from MEASURE to IDLE */
2270  if ((_sick_sensor_mode == SICK_SENSOR_MODE_IDLE && new_sick_sensor_mode == SICK_SENSOR_MODE_MEASURE) ||
2271  (_sick_sensor_mode == SICK_SENSOR_MODE_MEASURE && new_sick_sensor_mode == SICK_SENSOR_MODE_IDLE)) {
2272 
2273  /* Set to rotate mode */
2275 
2276  }
2277 
2278  }
2279 
2280  /* Handle a timeout! */
2281  catch (SickTimeoutException &sick_timeout_exception) {
2282  std::cerr << sick_timeout_exception.what() << std::endl;
2283  throw;
2284  }
2285 
2286  /* Handle I/O exceptions */
2287  catch (SickIOException &sick_io_exception) {
2288  std::cerr << sick_io_exception.what() << std::endl;
2289  throw;
2290  }
2291 
2292  /* Handle a returned error code */
2293  catch (SickErrorException &sick_error_exception) {
2294  std::cerr << sick_error_exception.what() << std::endl;
2295  throw;
2296  }
2297 
2298  /* A safety net */
2299  catch (...) {
2300  std::cerr << "SickLMS::_setSickSensorMode: Unknown exception!!!" << std::endl;
2301  throw;
2302  }
2303 
2304  /* Allocate a single buffer for payload contents */
2305  uint8_t payload_buffer[SickLDMessage::MESSAGE_PAYLOAD_MAX_LENGTH] = {0};
2306 
2307  /* The payload length */
2308  uint32_t payload_length = 2;
2309 
2310  /* Set the service IDs */
2311  payload_buffer[0] = SICK_WORK_SERV_CODE; // Requested service type
2312  payload_buffer[1] = _sickSensorModeToWorkServiceSubcode(new_sick_sensor_mode); // Requested service subtype
2313 
2314  /* If the target sensor mode is rotate then we add two more bytes
2315  * to the payload length. Doing so adds two zero values to the payload
2316  * which tells it to use the angular step and scan freqeuncy values
2317  * stored in its flash.
2318  */
2319  if (new_sick_sensor_mode == SICK_SENSOR_MODE_ROTATE) {
2320  payload_length += 2;
2321  }
2322 
2323  /* Define the send/receive message objects */
2324  SickLDMessage send_message(payload_buffer,payload_length);
2325  SickLDMessage recv_message;
2326 
2327  try {
2328  _sendMessageAndGetReply(send_message,recv_message);
2329  }
2330 
2331  /* Handle a timeout! */
2332  catch (SickTimeoutException &sick_timeout_exception) {
2333  std::cerr << sick_timeout_exception.what() << std::endl;
2334  throw;
2335  }
2336 
2337  /* Handle I/O exceptions */
2338  catch (SickIOException &sick_io_exception) {
2339  std::cerr << sick_io_exception.what() << std::endl;
2340  throw;
2341  }
2342 
2343  /* A safety net */
2344  catch (...) {
2345  std::cerr << "SickLMS::_setSickSensorMode: Unknown exception!!!" << std::endl;
2346  throw;
2347  }
2348 
2349  /* Reset the payload buffer */
2350  memset(payload_buffer,0,payload_length);
2351 
2352  /* Extract the message payload */
2353  recv_message.GetPayload(payload_buffer);
2354 
2355  /* Ensure the returned mode matches the requested mode */
2356  if ((_sick_sensor_mode = (payload_buffer[5] & 0x0F)) != new_sick_sensor_mode) {
2357 
2358  /* Check whether there is an error code we can use */
2359  if (new_sick_sensor_mode == SICK_SENSOR_MODE_MEASURE) {
2360 
2361  uint16_t return_code = 0;
2362  std::string errMsg = "SickLD::_setSickSensorMode: Unexpected sensor mode returned from Sick LD!";
2363  memcpy(&return_code,&payload_buffer[6],2);
2364  return_code = sick_ld_to_host_byte_order(return_code);
2365 
2366  /* Print the error code associated with the TRANS_MEASURE request */
2367  errMsg = errMsg + " (TRANS_MEAS Error Code: " + _sickTransMeasureReturnToString(return_code) + ")";
2368  throw SickErrorException(errMsg.c_str());
2369 
2370  }
2371 
2372  }
2373 
2374  /* Make sure the motor is Ok */
2375  if ((_sick_motor_mode = ((payload_buffer[5] >> 4) & 0x0F)) != SICK_MOTOR_MODE_OK) {
2376  throw SickErrorException("SickLD::_setSickSensorMode: Unexpected motor mode returned from Sick LD!");
2377  }
2378 
2379  /* Success */
2380 
2381  }
2382 
2389  void SickLD::_getSickScanProfiles( const uint16_t profile_format, const uint16_t num_profiles )
2391 
2392  /* Ensure the device is in measurement mode */
2393  try {
2395  }
2396 
2397  /* Handle a timeout! */
2398  catch (SickTimeoutException &sick_timeout_exception) {
2399  std::cerr << sick_timeout_exception.what() << std::endl;
2400  throw;
2401  }
2402 
2403  /* Handle I/O exceptions */
2404  catch (SickIOException &sick_io_exception) {
2405  std::cerr << sick_io_exception.what() << std::endl;
2406  throw;
2407  }
2408 
2409  /* Handle a returned error code */
2410  catch (SickErrorException &sick_error_exception) {
2411  std::cerr << sick_error_exception.what() << std::endl;
2412  throw;
2413  }
2414 
2415  /* A safety net */
2416  catch (...) {
2417  std::cerr << "SickLMS::_setSickSensorMode: Unknown exception!!!" << std::endl;
2418  throw;
2419  }
2420 
2421  /* A quick check to ensure the requested format is supported by the driver */
2422  if (!_supportedScanProfileFormat(profile_format)) {
2423  throw SickConfigException("SickLD::_getSickScanProfiles: Unsupported profile format!");
2424  }
2425 
2426  /* Allocate a single buffer for payload contents */
2427  uint8_t payload_buffer[SickLDMessage::MESSAGE_PAYLOAD_MAX_LENGTH] = {0};
2428 
2429  /* Set the service code and subcode */
2430  payload_buffer[0] = SICK_MEAS_SERV_CODE;
2431  payload_buffer[1] = SICK_MEAS_SERV_GET_PROFILE;
2432 
2433  /* Write the number of profiles to request to the payload buffer */
2434  uint16_t temp_buffer = host_to_sick_ld_byte_order(num_profiles);
2435  memcpy(&payload_buffer[2],&temp_buffer,2);
2436 
2437  /* Set the profile format mask (for now, we request everything from the Sick LD) */
2438  temp_buffer = profile_format;
2439  temp_buffer = host_to_sick_ld_byte_order(temp_buffer);
2440  memcpy(&payload_buffer[4],&temp_buffer,2);
2441 
2442  /* Define the send message object */
2443  SickLDMessage send_message(payload_buffer,6);
2444  SickLDMessage recv_message;
2445 
2446  /* Send the request */
2447  if (num_profiles == 0) {
2448  std::cout << "\tRequesting " << _sickProfileFormatToString(profile_format) << " data stream from Sick LD..." << std::endl;
2449  } else {
2450  std::cout << "\tRequesting " << num_profiles << " " << _sickProfileFormatToString(profile_format) << " profiles from Sick LD..." << std::endl;
2451  }
2452 
2453  /* Request scan profiles from the Sick (empirically it can take the Sick up to a few seconds to respond) */
2454  try {
2455  _sendMessageAndGetReply(send_message,recv_message);
2456  }
2457 
2458  /* Handle a timeout! */
2459  catch (SickTimeoutException &sick_timeout_exception) {
2460  std::cerr << sick_timeout_exception.what() << std::endl;
2461  throw;
2462  }
2463 
2464  /* Handle I/O exceptions */
2465  catch (SickIOException &sick_io_exception) {
2466  std::cerr << sick_io_exception.what() << std::endl;
2467  throw;
2468  }
2469 
2470  /* Handle a returned error code */
2471  catch (SickErrorException &sick_error_exception) {
2472  std::cerr << sick_error_exception.what() << std::endl;
2473  throw;
2474  }
2475 
2476  /* A safety net */
2477  catch (...) {
2478  std::cerr << "SickLMS::_setSickSensorMode: Unknown exception!!!" << std::endl;
2479  throw;
2480  }
2481 
2482  /* Reset the payload buffer */
2483  memset(payload_buffer,0,6);
2484 
2485  /* Acquire the payload of the response */
2486  recv_message.GetPayload(payload_buffer);
2487 
2488  /* Check to make sure the returned format is correct and there were no errors */
2489  memcpy(&temp_buffer,&payload_buffer[2],2);
2490  temp_buffer = sick_ld_to_host_byte_order(temp_buffer);
2491 
2492  /* Another sanity check */
2493  if (temp_buffer != profile_format) {
2494  throw SickErrorException("SickLD::_getSickScanProfiles: Incorrect profile format was returned by the Sick LD!");
2495  }
2496 
2497  /* Check if the data stream flags need to be set */
2498  if (num_profiles == 0 && profile_format == SICK_SCAN_PROFILE_RANGE) {
2500  }
2501  else if (num_profiles == 0 && profile_format == SICK_SCAN_PROFILE_RANGE_AND_ECHO) {
2503  }
2504 
2505  /* Show some output */
2506  if (num_profiles == 0) {
2507  std::cout << "\t\tData stream started!" << std::endl;
2508  } else {
2509  std::cout << "\t\tSick LD sending " << num_profiles << " scan profiles!" << std::endl;
2510  }
2511 
2512  /* Success */
2513  }
2514 
2520  void SickLD::_parseScanProfile( uint8_t * const src_buffer, sick_ld_scan_profile_t &profile_data ) const {
2521 
2522  uint16_t profile_format = 0;
2523  unsigned int data_offset = 0;
2524 
2525  /* Extract the scan profile format from the buffer */
2526  memcpy(&profile_format,&src_buffer[data_offset],2);
2527  profile_format = sick_ld_to_host_byte_order(profile_format);
2528  data_offset += 2;
2529 
2530  /* Extract the number of sectors in the scan area */
2531  profile_data.num_sectors = src_buffer[data_offset+1];
2532  data_offset += 2;
2533 
2534  /* NOTE: For the following field definitions see page 32 of the
2535  * Sick LD telegram listing.
2536  */
2537  uint16_t temp_buffer; // A temporary buffer
2538 
2539  /* Check if PROFILESENT is included */
2540  if (profile_format & 0x0001) {
2541  memcpy(&temp_buffer,&src_buffer[data_offset],2);
2542  profile_data.profile_number = sick_ld_to_host_byte_order(temp_buffer);
2543  data_offset += 2;
2544  }
2545 
2546  /* Check if PROFILECOUNT is included */
2547  if (profile_format & 0x0002) {
2548  memcpy(&temp_buffer,&src_buffer[data_offset],2);
2549  profile_data.profile_counter = sick_ld_to_host_byte_order(temp_buffer);
2550  data_offset += 2;
2551  }
2552 
2553  /* Check if LAYERNUM is included */
2554  if (profile_format & 0x0004) {
2555  memcpy(&temp_buffer,&src_buffer[data_offset],2);
2556  profile_data.layer_num = sick_ld_to_host_byte_order(temp_buffer);
2557  data_offset += 2;
2558  }
2559 
2560  /* The extraneous stuff is out of the way, now extract the data
2561  * for each of the sectors in the scan area...
2562  */
2563  for (unsigned int i=0; i < profile_data.num_sectors; i++) {
2564 
2565  /* Check if SECTORNUM is included */
2566  if (profile_format & 0x0008) {
2567  memcpy(&temp_buffer,&src_buffer[data_offset],2);
2568  profile_data.sector_data[i].sector_num = sick_ld_to_host_byte_order(temp_buffer);
2569  data_offset += 2;
2570  }
2571  else {
2572  profile_data.sector_data[i].sector_num = 0;
2573  }
2574 
2575  /* Check if DIRSTEP is included */
2576  if (profile_format & 0x0010) {
2577  memcpy(&temp_buffer,&src_buffer[data_offset],2);
2578  profile_data.sector_data[i].angle_step = ((double)sick_ld_to_host_byte_order(temp_buffer))/16;
2579  data_offset += 2;
2580  }
2581  else {
2582  profile_data.sector_data[i].angle_step = 0;
2583  }
2584 
2585  /* Check if POINTNUM is included */
2586  if (profile_format & 0x0020) {
2587  memcpy(&temp_buffer,&src_buffer[data_offset],2);
2588  profile_data.sector_data[i].num_data_points = sick_ld_to_host_byte_order(temp_buffer);
2589  data_offset += 2;
2590  }
2591  else {
2592  profile_data.sector_data[i].num_data_points = 0;
2593  }
2594 
2595  /* Check if TSTART is included */
2596  if (profile_format & 0x0040) {
2597  memcpy(&temp_buffer,&src_buffer[data_offset],2);
2598  profile_data.sector_data[i].timestamp_start = sick_ld_to_host_byte_order(temp_buffer);
2599  data_offset += 2;
2600  }
2601  else {
2602  profile_data.sector_data[i].timestamp_start = 0;
2603  }
2604 
2605  /* Check if STARTDIR is included */
2606  if (profile_format & 0x0080) {
2607  memcpy(&temp_buffer,&src_buffer[data_offset],2);
2608  profile_data.sector_data[i].angle_start = ((double)sick_ld_to_host_byte_order(temp_buffer))/16;
2609  data_offset += 2;
2610  }
2611  else {
2612  profile_data.sector_data[i].angle_start = 0;
2613  }
2614 
2615  /* Acquire the range and echo values for the sector */
2616  for (unsigned int j=0; j < profile_data.sector_data[i].num_data_points; j++) {
2617 
2618  /* Check if DISTANCE-n is included */
2619  if (profile_format & 0x0100) {
2620  memcpy(&temp_buffer,&src_buffer[data_offset],2);
2621  profile_data.sector_data[i].range_values[j] = ((double)sick_ld_to_host_byte_order(temp_buffer))/256;
2622  data_offset += 2;
2623  }
2624  else {
2625  profile_data.sector_data[i].range_values[j] = 0;
2626  }
2627 
2628  /* Check if DIRECTION-n is included */
2629  if (profile_format & 0x0200) {
2630  memcpy(&temp_buffer,&src_buffer[data_offset],2);
2631  profile_data.sector_data[i].scan_angles[j] = ((double)sick_ld_to_host_byte_order(temp_buffer))/16;
2632  data_offset += 2;
2633  }
2634  else {
2635  profile_data.sector_data[i].scan_angles[j] = 0;
2636  }
2637 
2638  /* Check if ECHO-n is included */
2639  if (profile_format & 0x0400) {
2640  memcpy(&temp_buffer,&src_buffer[data_offset],2);
2641  profile_data.sector_data[i].echo_values[j] = sick_ld_to_host_byte_order(temp_buffer);
2642  data_offset += 2;
2643  }
2644  else {
2645  profile_data.sector_data[i].echo_values[j] = 0;
2646  }
2647 
2648  }
2649 
2650  /* Check if TEND is included */
2651  if (profile_format & 0x0800) {
2652  memcpy(&temp_buffer,&src_buffer[data_offset],2);
2653  profile_data.sector_data[i].timestamp_stop = sick_ld_to_host_byte_order(temp_buffer);
2654  data_offset += 2;
2655  }
2656  else {
2657  profile_data.sector_data[i].timestamp_stop = 0;
2658  }
2659 
2660  /* Check if ENDDIR is included */
2661  if (profile_format & 0x1000) {
2662  memcpy(&temp_buffer,&src_buffer[data_offset],2);
2663  profile_data.sector_data[i].angle_stop = ((double)sick_ld_to_host_byte_order(temp_buffer))/16;
2664  data_offset += 2;
2665  }
2666  else {
2667  profile_data.sector_data[i].angle_stop = 0;
2668  }
2669 
2670  }
2671 
2672  /* Check if SENSTAT is included */
2673  if (profile_format & 0x2000) {
2674  profile_data.sensor_status = src_buffer[data_offset+3] & 0x0F;
2675  profile_data.motor_status = (src_buffer[data_offset+3] >> 4) & 0x0F;
2676  }
2677  else {
2678  profile_data.sensor_status = SICK_SENSOR_MODE_UNKNOWN;
2679  profile_data.motor_status = SICK_MOTOR_MODE_UNKNOWN;
2680  }
2681 
2682  }
2683 
2689 
2690  /* Ensure the device is in measurement mode */
2691  try {
2693  }
2694 
2695  /* Handle a timeout! */
2696  catch (SickTimeoutException &sick_timeout_exception) {
2697  std::cerr << sick_timeout_exception.what() << std::endl;
2698  throw;
2699  }
2700 
2701  /* Handle I/O exceptions */
2702  catch (SickIOException &sick_io_exception) {
2703  std::cerr << sick_io_exception.what() << std::endl;
2704  throw;
2705  }
2706 
2707  /* Handle a returned error code */
2708  catch (SickErrorException &sick_error_exception) {
2709  std::cerr << sick_error_exception.what() << std::endl;
2710  throw;
2711  }
2712 
2713  /* A safety net */
2714  catch (...) {
2715  std::cerr << "SickLMS::_cancelSickScanProfiles: Unknown exception!!!" << std::endl;
2716  throw;
2717  }
2718 
2719  /* Allocate a single buffer for payload contents */
2720  uint8_t payload_buffer[SickLDMessage::MESSAGE_PAYLOAD_MAX_LENGTH] = {0};
2721 
2722  /* Set the service IDs */
2723  payload_buffer[0] = SICK_MEAS_SERV_CODE; // Requested service type
2724  payload_buffer[1] = SICK_MEAS_SERV_CANCEL_PROFILE; // Requested service subtype
2725 
2726  /* Create the Sick messages */
2727  SickLDMessage send_message(payload_buffer,2);
2728  SickLDMessage recv_message;
2729 
2730  std::cout << "\tStopping the data stream..." << std::endl;
2731 
2732  /* Send the message and check the reply */
2733  try {
2734  _sendMessageAndGetReply(send_message,recv_message);
2735  }
2736 
2737  /* Handle a timeout! */
2738  catch (SickTimeoutException &sick_timeout_exception) {
2739  std::cerr << sick_timeout_exception.what() << std::endl;
2740  throw;
2741  }
2742 
2743  /* Handle I/O exceptions */
2744  catch (SickIOException &sick_io_exception) {
2745  std::cerr << sick_io_exception.what() << std::endl;
2746  throw;
2747  }
2748 
2749  /* A safety net */
2750  catch (...) {
2751  std::cerr << "SickLMS::_getFirmwareName: Unknown exception!!!" << std::endl;
2752  throw;
2753  }
2754 
2755  /* Reset the payload buffer */
2756  memset(payload_buffer,0,2);
2757 
2758  /* Update the status of ths Sick LD */
2759  recv_message.GetPayload(payload_buffer);
2760 
2761  /* Extract and assign the sensor and motor status */
2762  _sick_sensor_mode = payload_buffer[5] & 0x0F;
2763  _sick_motor_mode = (payload_buffer[5] >> 4) & 0x0F;
2764 
2765  /* Since we just updated them, let's make sure everything s'ok */
2767  throw SickErrorException("SickLD::_cancelSickScanProfiles: Sick LD returned sensor mode ERROR!");
2768  }
2769 
2770  /* Check the motor mode */
2772  throw SickErrorException("SickLD::_cancelSickScanProfiles: Sick LD returned motor mode ERROR!");
2773  }
2774 
2775  /* Set the stream flag for the driver */
2778  }
2779  else {
2781  }
2782 
2783  std::cout << "\t\tStream stopped!" << std::endl;
2784  }
2785 
2790  void SickLD::_setSickFilter( const uint8_t suppress_code )
2792 
2793  /* Ensure the device is not measuring */
2795 
2796  /* Set the Sick LD to rotate mode */
2797  try {
2799  }
2800 
2801  /* Handle a timeout! */
2802  catch (SickTimeoutException &sick_timeout_exception) {
2803  std::cerr << sick_timeout_exception.what() << std::endl;
2804  throw;
2805  }
2806 
2807  /* Handle I/O exceptions */
2808  catch (SickIOException &sick_io_exception) {
2809  std::cerr << sick_io_exception.what() << std::endl;
2810  throw;
2811  }
2812 
2813  /* Handle a returned error code */
2814  catch (SickErrorException &sick_error_exception) {
2815  std::cerr << sick_error_exception.what() << std::endl;
2816  throw;
2817  }
2818 
2819  /* A safety net */
2820  catch (...) {
2821  std::cerr << "SickLMS::_setSickFilter: Unknown exception!!!" << std::endl;
2822  throw;
2823  }
2824 
2825  }
2826 
2827  /* Allocate a single buffer for payload contents */
2828  uint8_t payload_buffer[SickLDMessage::MESSAGE_PAYLOAD_MAX_LENGTH] = {0};
2829 
2830  /* Set the service IDs */
2831  payload_buffer[0] = SICK_CONF_SERV_CODE; // Requested service type
2832  payload_buffer[1] = SICK_CONF_SERV_SET_FILTER; // Requested service subtype
2833  payload_buffer[3] = SICK_CONF_SERV_SET_FILTER_NEARFIELD; // Setting nearfield suppression filter
2834  payload_buffer[5] = suppress_code; // Code telling whether to turn it on or off
2835 
2836  /* Create the Sick messages */
2837  SickLDMessage send_message(payload_buffer,6);
2838  SickLDMessage recv_message;
2839 
2840  /* Send the message and check the reply */
2841  try {
2842  _sendMessageAndGetReply(send_message,recv_message);
2843  }
2844 
2845  /* Handle a timeout! */
2846  catch (SickTimeoutException &sick_timeout_exception) {
2847  std::cerr << sick_timeout_exception.what() << std::endl;
2848  throw;
2849  }
2850 
2851  /* Handle I/O exceptions */
2852  catch (SickIOException &sick_io_exception) {
2853  std::cerr << sick_io_exception.what() << std::endl;
2854  throw;
2855  }
2856 
2857  /* A safety net */
2858  catch (...) {
2859  std::cerr << "SickLMS::_setSickFilter: Unknown exception!!!" << std::endl;
2860  throw;
2861  }
2862 
2863  /* Reset the payload buffer */
2864  memset(payload_buffer,0,6);
2865 
2866  /* Acquire the returned payload */
2867  recv_message.GetPayload(payload_buffer);
2868 
2869  /* Extract FILTERITEM */
2870  uint16_t filter_item;
2871  memcpy(&filter_item,&payload_buffer[2],2);
2872  filter_item = sick_ld_to_host_byte_order(filter_item);
2873 
2874  /* Check that the returned filter item matches nearfiled suppression */
2875  if (filter_item != SICK_CONF_SERV_SET_FILTER_NEARFIELD) {
2876  throw SickErrorException("SickLD::_setSickFilter: Unexpected filter item returned from Sick LD!");
2877  }
2878 
2879  /* Success */
2880  }
2881 
2886 
2887  try {
2888 
2890  _getSensorName();
2895  _getFirmwareName();
2900 
2901  }
2902 
2903  /* Handle a timeout! */
2904  catch (SickTimeoutException &sick_timeout_exception) {
2905  std::cerr << sick_timeout_exception.what() << std::endl;
2906  throw;
2907  }
2908 
2909  /* Handle I/O exceptions */
2910  catch (SickIOException &sick_io_exception) {
2911  std::cerr << sick_io_exception.what() << std::endl;
2912  throw;
2913  }
2914 
2915  /* A safety net */
2916  catch (...) {
2917  std::cerr << "SickLMS::_getSickIdentity: Unknown exception!!!" << std::endl;
2918  throw;
2919  }
2920 
2921  /* Success! */
2922  }
2923 
2928 
2929  /* Allocate a single buffer for payload contents */
2930  uint8_t payload_buffer[SickLDMessage::MESSAGE_PAYLOAD_MAX_LENGTH] = {0};
2931 
2932  /* Set the service IDs */
2933  payload_buffer[0] = SICK_STAT_SERV_CODE; // Requested service type
2934  payload_buffer[1] = SICK_STAT_SERV_GET_STATUS; // Requested service subtype
2935 
2936  /* Create the Sick messages */
2937  SickLDMessage send_message(payload_buffer,2);
2938  SickLDMessage recv_message;
2939 
2940  /* Send the message and check the reply */
2941  try {
2942  _sendMessageAndGetReply(send_message,recv_message);
2943  }
2944 
2945  catch(SickTimeoutException &sick_timeout_exception) {
2946  std::cerr << sick_timeout_exception.what() << std::endl;
2947  throw;
2948  }
2949 
2950  catch(SickIOException &sick_io_exception) {
2951  std::cerr << sick_io_exception.what() << std::endl;
2952  throw;
2953  }
2954 
2955  catch(...) {
2956  std::cerr << "SickLD::_getSickStatus - Unknown exception!" << std::endl;
2957  throw;
2958  }
2959 
2960  /* Reset the buffer (not necessary, but its better to do so just in case) */
2961  memset(payload_buffer,0,2);
2962 
2963  /* Extract the message payload */
2964  recv_message.GetPayload(payload_buffer);
2965 
2966  /* Extract the Sick LD's current sensor mode */
2967  _sick_sensor_mode = payload_buffer[5] & 0x0F;
2968 
2969  /* Extract the Sick LD's current motor mode */
2970  _sick_motor_mode = (payload_buffer[5] >> 4) & 0x0F;
2971 
2972  /* Success */
2973  }
2974 
2988  void SickLD::_setSickGlobalConfig( const uint8_t sick_sensor_id, const uint8_t sick_motor_speed, const double sick_angle_step )
2990 
2991  /* Ensure the device is in IDLE mode */
2992  try {
2994  }
2995 
2996  /* Handle a timeout! */
2997  catch (SickTimeoutException &sick_timeout_exception) {
2998  std::cerr << sick_timeout_exception.what() << std::endl;
2999  throw;
3000  }
3001 
3002  /* Handle I/O exceptions */
3003  catch (SickIOException &sick_io_exception) {
3004  std::cerr << sick_io_exception.what() << std::endl;
3005  throw;
3006  }
3007 
3008  /* Handle a returned error code */
3009  catch (SickErrorException &sick_error_exception) {
3010  std::cerr << sick_error_exception.what() << std::endl;
3011  throw;
3012  }
3013 
3014  /* A safety net */
3015  catch (...) {
3016  std::cerr << "SickLMS::_setSickGlobalConfig: Unknown exception!!!" << std::endl;
3017  throw;
3018  }
3019 
3020  /* Allocate a single buffer for payload contents */
3021  uint8_t payload_buffer[SickLDMessage::MESSAGE_PAYLOAD_MAX_LENGTH] = {0};
3022 
3023  /* Set the service IDs */
3024  payload_buffer[0] = SICK_CONF_SERV_CODE; // Requested service type
3025  payload_buffer[1] = SICK_CONF_SERV_SET_CONFIGURATION; // Requested service subtype
3026 
3027  /* Set the configuration key */
3028  payload_buffer[3] = SICK_CONF_KEY_GLOBAL; // Use the global configuration key
3029 
3030  /* Set the message parameters */
3031  payload_buffer[5] = sick_sensor_id; // Include the given sensor ID
3032  payload_buffer[7] = sick_motor_speed; // Include the new Sick Motor speed value
3033 
3034  /* Set the angular step */
3035  uint16_t temp_buffer = _angleToTicks(sick_angle_step);
3036  temp_buffer = host_to_sick_ld_byte_order(temp_buffer);
3037  memcpy(&payload_buffer[8],&temp_buffer,2);
3038 
3039  /* Create the Sick messages */
3040  SickLDMessage send_message(payload_buffer,10);
3041  SickLDMessage recv_message;
3042 
3043  /* Send the message and check the reply */
3044  try {
3045  _sendMessageAndGetReply(send_message,recv_message);
3046  }
3047 
3048  /* Handle a timeout! */
3049  catch (SickTimeoutException &sick_timeout_exception) {
3050  std::cerr << sick_timeout_exception.what() << std::endl;
3051  throw;
3052  }
3053 
3054  /* Handle I/O exceptions */
3055  catch (SickIOException &sick_io_exception) {
3056  std::cerr << sick_io_exception.what() << std::endl;
3057  throw;
3058  }
3059 
3060  /* A safety net */
3061  catch (...) {
3062  std::cerr << "SickLMS::_setSickGlobalConfig: Unknown exception!!!" << std::endl;
3063  throw;
3064  }
3065 
3066  /* Reset the payload buffer */
3067  memset(payload_buffer,0,10);
3068 
3069  /* Extract the response payload */
3070  recv_message.GetPayload(payload_buffer);
3071 
3072  /* Check to make sure there wasn't an error */
3073  if (payload_buffer[2] != 0 || payload_buffer[3] != 0) {
3074  throw SickErrorException("SickLD::_setSickGlobalConfig: Configuration setting was NOT sucessful!");
3075  }
3076 
3077  /* Update the device driver with the new values */
3078  _sick_global_config.sick_sensor_id = sick_sensor_id;
3079  _sick_global_config.sick_motor_speed = sick_motor_speed;
3080  _sick_global_config.sick_angle_step = sick_angle_step;
3081 
3082  /* Success! */
3083  }
3084 
3089 
3090  /* Ensure the device is in IDLE mode */
3091  try {
3093  }
3094 
3095  /* Handle a timeout! */
3096  catch (SickTimeoutException &sick_timeout_exception) {
3097  std::cerr << sick_timeout_exception.what() << std::endl;
3098  throw;
3099  }
3100 
3101  /* Handle I/O exceptions */
3102  catch (SickIOException &sick_io_exception) {
3103  std::cerr << sick_io_exception.what() << std::endl;
3104  throw;
3105  }
3106 
3107  /* Handle a returned error code */
3108  catch (SickErrorException &sick_error_exception) {
3109  std::cerr << sick_error_exception.what() << std::endl;
3110  throw;
3111  }
3112 
3113  /* A safety net */
3114  catch (...) {
3115  std::cerr << "SickLMS::_getSickGlobalConfig: Unknown exception!!!" << std::endl;
3116  throw;
3117  }
3118 
3119  /* Allocate a single buffer for payload contents */
3120  uint8_t payload_buffer[SickLDMessage::MESSAGE_PAYLOAD_MAX_LENGTH] = {0};
3121 
3122  /* Set the service IDs */
3123  payload_buffer[0] = SICK_CONF_SERV_CODE; // Requested service type
3124  payload_buffer[1] = SICK_CONF_SERV_GET_CONFIGURATION; // Requested service subtype
3125  payload_buffer[3] = SICK_CONF_KEY_GLOBAL; // Configuration key
3126 
3127  /* Create the Sick messages */
3128  SickLDMessage send_message(payload_buffer,4);
3129  SickLDMessage recv_message;
3130 
3131  /* Send the message and check the reply */
3132  try {
3133  _sendMessageAndGetReply(send_message,recv_message);
3134  }
3135 
3136  /* Handle a timeout! */
3137  catch (SickTimeoutException &sick_timeout_exception) {
3138  std::cerr << sick_timeout_exception.what() << std::endl;
3139  throw;
3140  }
3141 
3142  /* Handle I/O exceptions */
3143  catch (SickIOException &sick_io_exception) {
3144  std::cerr << sick_io_exception.what() << std::endl;
3145  throw;
3146  }
3147 
3148  /* A safety net */
3149  catch (...) {
3150  std::cerr << "SickLMS::_getSickGlobalConfig: Unknown exception!!!" << std::endl;
3151  throw;
3152  }
3153 
3154  /* Reset the buffer (not necessary, but its better to do so just in case) */
3155  memset(payload_buffer,0,4);
3156 
3157  /* Extract the message payload */
3158  recv_message.GetPayload(payload_buffer);
3159 
3160  /* Extract the configuration key */
3161  uint16_t temp_buffer = 0;
3162  unsigned int data_offset = 2;
3163  memcpy(&temp_buffer,&payload_buffer[data_offset],2);
3164  temp_buffer = sick_ld_to_host_byte_order(temp_buffer);
3165  data_offset += 2;
3166 
3167  /* A quick sanity check */
3168  if (temp_buffer != SICK_CONF_KEY_GLOBAL) {
3169  throw SickErrorException("SickLD::_getSickGlobalConfig: Unexpected message contents!");
3170  }
3171 
3172  /* Extract the global sensor ID */
3173  memcpy(&_sick_global_config.sick_sensor_id,&payload_buffer[data_offset],2);
3175  data_offset += 2;
3176 
3177  /* Extract the nominal motor speed */
3178  memcpy(&_sick_global_config.sick_motor_speed,&payload_buffer[data_offset],2);
3180  data_offset += 2;
3181 
3182  /* Extract the angular step */
3183  memcpy(&temp_buffer,&payload_buffer[data_offset],2);
3185 
3186  /* Success */
3187  }
3188 
3194 
3195  /* Ensure the device is in IDLE mode */
3196  try {
3198  }
3199 
3200  /* Handle a timeout! */
3201  catch (SickTimeoutException &sick_timeout_exception) {
3202  std::cerr << sick_timeout_exception.what() << std::endl;
3203  throw;
3204  }
3205 
3206  /* Handle I/O exceptions */
3207  catch (SickIOException &sick_io_exception) {
3208  std::cerr << sick_io_exception.what() << std::endl;
3209  throw;
3210  }
3211 
3212  /* Handle a returned error code */
3213  catch (SickErrorException &sick_error_exception) {
3214  std::cerr << sick_error_exception.what() << std::endl;
3215  throw;
3216  }
3217 
3218  /* A safety net */
3219  catch (...) {
3220  std::cerr << "SickLMS::_setSickSensorMode: Unknown exception!!!" << std::endl;
3221  throw;
3222  }
3223 
3224  /* Allocate a single buffer for payload contents */
3225  uint8_t payload_buffer[SickLDMessage::MESSAGE_PAYLOAD_MAX_LENGTH] = {0};
3226 
3227  /* Set the service IDs */
3228  payload_buffer[0] = SICK_CONF_SERV_CODE; // Requested service type
3229  payload_buffer[1] = SICK_CONF_SERV_GET_CONFIGURATION; // Requested service subtype
3230  payload_buffer[3] = SICK_CONF_KEY_ETHERNET; // Configuration key
3231 
3232  /* Create the Sick messages */
3233  SickLDMessage send_message(payload_buffer,4);
3234  SickLDMessage recv_message;
3235 
3236  try {
3237  _sendMessageAndGetReply(send_message,recv_message);
3238  }
3239 
3240  /* Handle a timeout! */
3241  catch (SickTimeoutException &sick_timeout_exception) {
3242  std::cerr << sick_timeout_exception.what() << std::endl;
3243  throw;
3244  }
3245 
3246  /* Handle I/O exceptions */
3247  catch (SickIOException &sick_io_exception) {
3248  std::cerr << sick_io_exception.what() << std::endl;
3249  throw;
3250  }
3251 
3252  /* A safety net */
3253  catch (...) {
3254  std::cerr << "SickLMS::_setSickSensorMode: Unknown exception!!!" << std::endl;
3255  throw;
3256  }
3257 
3258  /* Reset the buffer (not necessary, but its better to do so just in case) */
3259  memset(payload_buffer,0,4);
3260 
3261  /* Extract the message payload */
3262  recv_message.GetPayload(payload_buffer);
3263 
3264  /* Extract the configuration key */
3265  uint16_t temp_buffer = 0;
3266  unsigned int data_offset = 2;
3267  memcpy(&temp_buffer,&payload_buffer[data_offset],2);
3268  temp_buffer = sick_ld_to_host_byte_order(temp_buffer);
3269  data_offset += 2;
3270 
3271  /* A quick sanity check */
3272  if (temp_buffer != SICK_CONF_KEY_ETHERNET) {
3273  throw SickErrorException("SickLD::_getSickEthernetConfig: Unexpected message contents!");
3274  }
3275 
3276  /* Extract the IP address of the Sick LD */
3277  for(unsigned int i=0; i < 4; i++,data_offset+=2) {
3278  memcpy(&_sick_ethernet_config.sick_ip_address[i],&payload_buffer[data_offset],2);
3280  }
3281 
3282  /* Extract the associated subnet mask */
3283  for(unsigned int i=0; i < 4; i++,data_offset+=2) {
3284  memcpy(&_sick_ethernet_config.sick_subnet_mask[i],&payload_buffer[data_offset],2);
3286  }
3287 
3288  /* Extract the default gateway */
3289  for(unsigned int i=0; i < 4; i++,data_offset+=2) {
3290  memcpy(&_sick_ethernet_config.sick_gateway_ip_address[i],&payload_buffer[data_offset],2);
3292  }
3293 
3294  /* Extract the sick node ID (NOTE: This value doesn't matter, but we buffer it anyways) */
3295  memcpy(&_sick_ethernet_config.sick_node_id,&payload_buffer[data_offset],2);
3297  data_offset += 2;
3298 
3299  /* Extract the transparent TCP port (NOTE: The significance of this value is unclear as
3300  * it doesn't affect the actual TCP port number that the Sick server is operating at.
3301  * But, we buffer it anyways as it is included in the configuration.)
3302  */
3303  memcpy(&_sick_ethernet_config.sick_transparent_tcp_port,&payload_buffer[data_offset],2);
3305  data_offset += 2;
3306 
3307  /* Success */
3308  }
3309 
3320 
3321  /* Reset the sector config struct */
3322  memset(&_sick_sector_config,0,sizeof(sick_ld_config_sector_t));
3323 
3324  /* Get the configuration for all initialized sectors */
3325  for (unsigned int i = 0; i < SICK_MAX_NUM_SECTORS; i++) {
3326 
3327  /* Query the Sick for the function of the ith sector */
3328  try {
3330  }
3331 
3332  /* Handle a timeout! */
3333  catch (SickTimeoutException &sick_timeout_exception) {
3334  std::cerr << sick_timeout_exception.what() << std::endl;
3335  throw;
3336  }
3337 
3338  /* Handle I/O exceptions */
3339  catch (SickIOException &sick_io_exception) {
3340  std::cerr << sick_io_exception.what() << std::endl;
3341  throw;
3342  }
3343 
3344  /* Handle a returned error code */
3345  catch (SickErrorException &sick_error_exception) {
3346  std::cerr << sick_error_exception.what() << std::endl;
3347  throw;
3348  }
3349 
3350  /* A safety net */
3351  catch (...) {
3352  std::cerr << "SickLMS::_getSickSectorConfig: Unknown exception!!!" << std::endl;
3353  throw;
3354  }
3355 
3356  /* Check if the sector is initialized */
3358 
3359  /* Check whether the sector is active (i.e. measuring) */
3363  }
3364 
3365  /* Update the number of initialized sectors */
3367  }
3368  else {
3369 
3370  /* An uninitialized sector marks the end of the sector configuration */
3371  break;
3372  }
3373 
3374  }
3375 
3376  /* Compute the starting angle for each of the initialized sectors */
3377  for (unsigned int i = 1; i < _sick_sector_config.sick_num_initialized_sectors; i++) {
3379  }
3380 
3381  /* Determine the starting angle for the first sector */
3385  }
3386 
3387  /* Success! */
3388  }
3389 
3395  void SickLD::_getIdentificationString( const uint8_t id_request_code, std::string &id_return_string )
3397 
3398  /* Allocate a single buffer for payload contents */
3399  uint8_t payload_buffer[SickLDMessage::MESSAGE_PAYLOAD_MAX_LENGTH] = {0};
3400 
3401  /* Set the service IDs */
3402  payload_buffer[0] = SICK_STAT_SERV_CODE; // Requested service type
3403  payload_buffer[1] = SICK_STAT_SERV_GET_ID; // Requested service subtype
3404  payload_buffer[3] = id_request_code; // ID information that is being requested
3405 
3406  /* Create the Sick LD messages */
3407  SickLDMessage send_message(payload_buffer,4);
3408  SickLDMessage recv_message;
3409 
3410  /* Send the message and get the reply */
3411  try {
3412  _sendMessageAndGetReply(send_message,recv_message);
3413  }
3414 
3415  /* Handle a timeout! */
3416  catch (SickTimeoutException &sick_timeout_exception) {
3417  std::cerr << sick_timeout_exception.what() << std::endl;
3418  throw;
3419  }
3420 
3421  /* Handle write buffer exceptions */
3422  catch (SickIOException &sick_io_exception) {
3423  std::cerr << sick_io_exception.what() << std::endl;
3424  throw;
3425  }
3426 
3427  /* A safety net */
3428  catch (...) {
3429  std::cerr << "SickLMS::_getIdentificationString: Unknown exception!!!" << std::endl;
3430  throw;
3431  }
3432 
3433  /* Reset the payload buffer (not necessary, but it doesn't hurt to be careful) */
3434  memset(payload_buffer,0,4);
3435 
3436  /* Extract the message payload */
3437  recv_message.GetPayload(payload_buffer);
3438 
3439  /* Assign the string */
3440  id_return_string = (char *) &payload_buffer[2];
3441 
3442  /* Success, woohooo! */
3443  }
3444 
3449 
3450  /* Query the Sick LD */
3451  try {
3453  }
3454 
3455  /* Handle a timeout! */
3456  catch (SickTimeoutException &sick_timeout_exception) {
3457  std::cerr << sick_timeout_exception.what() << std::endl;
3458  throw;
3459  }
3460 
3461  /* Handle I/O exceptions */
3462  catch (SickIOException &sick_io_exception) {
3463  std::cerr << sick_io_exception.what() << std::endl;
3464  throw;
3465  }
3466 
3467  /* A safety net */
3468  catch (...) {
3469  std::cerr << "SickLMS::_getSensorPartNumber: Unknown exception!!!" << std::endl;
3470  throw;
3471  }
3472 
3473  /* Success, woohooo! */
3474  }
3475 
3480 
3481  /* Query the Sick LD */
3482  try {
3484  }
3485 
3486  /* Handle a timeout! */
3487  catch (SickTimeoutException &sick_timeout_exception) {
3488  std::cerr << sick_timeout_exception.what() << std::endl;
3489  throw;
3490  }
3491 
3492  /* Handle I/O exceptions */
3493  catch (SickIOException &sick_io_exception) {
3494  std::cerr << sick_io_exception.what() << std::endl;
3495  throw;
3496  }
3497 
3498  /* A safety net */
3499  catch (...) {
3500  std::cerr << "SickLMS::_getSensorName: Unknown exception!!!" << std::endl;
3501  throw;
3502  }
3503 
3504  /* Ok */
3505  }
3506 
3511 
3512  /* Get the id info */
3513  try {
3515  }
3516 
3517  /* Handle a timeout! */
3518  catch (SickTimeoutException &sick_timeout_exception) {
3519  std::cerr << sick_timeout_exception.what() << std::endl;
3520  throw;
3521  }
3522 
3523  /* Handle I/O exceptions */
3524  catch (SickIOException &sick_io_exception) {
3525  std::cerr << sick_io_exception.what() << std::endl;
3526  throw;
3527  }
3528 
3529  /* A safety net */
3530  catch (...) {
3531  std::cerr << "SickLMS::_getSensorVersion: Unknown exception!!!" << std::endl;
3532  throw;
3533  }
3534 
3535  /* Ok */
3536  }
3537 
3542 
3543  try {
3545  }
3546 
3547  /* Handle a timeout! */
3548  catch (SickTimeoutException &sick_timeout_exception) {
3549  std::cerr << sick_timeout_exception.what() << std::endl;
3550  throw;
3551  }
3552 
3553  /* Handle I/O exceptions */
3554  catch (SickIOException &sick_io_exception) {
3555  std::cerr << sick_io_exception.what() << std::endl;
3556  throw;
3557  }
3558 
3559  /* A safety net */
3560  catch (...) {
3561  std::cerr << "SickLMS::_getSensorSerialNumber: Unknown exception!!!" << std::endl;
3562  throw;
3563  }
3564 
3565  /* Ok */
3566  }
3567 
3572 
3573  try {
3575  }
3576 
3577  /* Handle a timeout! */
3578  catch (SickTimeoutException &sick_timeout_exception) {
3579  std::cerr << sick_timeout_exception.what() << std::endl;
3580  throw;
3581  }
3582 
3583  /* Handle I/O exceptions */
3584  catch (SickIOException &sick_io_exception) {
3585  std::cerr << sick_io_exception.what() << std::endl;
3586  throw;
3587  }
3588 
3589  /* A safety net */
3590  catch (...) {
3591  std::cerr << "SickLMS::_getSensorEDMSerialNumber: Unknown exception!!!" << std::endl;
3592  throw;
3593  }
3594 
3595  /* Ok */
3596  }
3597 
3602 
3603  try {
3605  }
3606 
3607  /* Handle a timeout! */
3608  catch (SickTimeoutException &sick_timeout_exception) {
3609  std::cerr << sick_timeout_exception.what() << std::endl;
3610  throw;
3611  }
3612 
3613  /* Handle I/O exceptions */
3614  catch (SickIOException &sick_io_exception) {
3615  std::cerr << sick_io_exception.what() << std::endl;
3616  throw;
3617  }
3618 
3619  /* A safety net */
3620  catch (...) {
3621  std::cerr << "SickLMS::_getFirmwarePartNumber: Unknown exception!!!" << std::endl;
3622  throw;
3623  }
3624 
3625  /* Ok */
3626  }
3627 
3632 
3633  try {
3635  }
3636 
3637  /* Handle a timeout! */
3638  catch (SickTimeoutException &sick_timeout_exception) {
3639  std::cerr << sick_timeout_exception.what() << std::endl;
3640  throw;
3641  }
3642 
3643  /* Handle I/O exceptions */
3644  catch (SickIOException &sick_io_exception) {
3645  std::cerr << sick_io_exception.what() << std::endl;
3646  throw;
3647  }
3648 
3649  /* A safety net */
3650  catch (...) {
3651  std::cerr << "SickLMS::_getFirmwareName: Unknown exception!!!" << std::endl;
3652  throw;
3653  }
3654 
3655  /* Ok */
3656  }
3657 
3662 
3663  try {
3665  }
3666 
3667  /* Handle a timeout! */
3668  catch (SickTimeoutException &sick_timeout_exception) {
3669  std::cerr << sick_timeout_exception.what() << std::endl;
3670  throw;
3671  }
3672 
3673  /* Handle I/O exceptions */
3674  catch (SickIOException &sick_io_exception) {
3675  std::cerr << sick_io_exception.what() << std::endl;
3676  throw;
3677  }
3678 
3679  /* A safety net */
3680  catch (...) {
3681  std::cerr << "SickLMS::_getFirmwareVersion: Unknown exception!!!" << std::endl;
3682  throw;
3683  }
3684 
3685  /* Ok */
3686  }
3687 
3692 
3693  try {
3695  }
3696 
3697  /* Handle a timeout! */
3698  catch (SickTimeoutException &sick_timeout_exception) {
3699  std::cerr << sick_timeout_exception.what() << std::endl;
3700  throw;
3701  }
3702 
3703  /* Handle I/O exceptions */
3704  catch (SickIOException &sick_io_exception) {
3705  std::cerr << sick_io_exception.what() << std::endl;
3706  throw;
3707  }
3708 
3709  /* A safety net */
3710  catch (...) {
3711  std::cerr << "SickLMS::_getApplicationSoftwarePartNumber: Unknown exception!!!" << std::endl;
3712  throw;
3713  }
3714 
3715  /* Ok */
3716  }
3717 
3722 
3723  try {
3725  }
3726 
3727  /* Handle a timeout! */
3728  catch (SickTimeoutException &sick_timeout_exception) {
3729  std::cerr << sick_timeout_exception.what() << std::endl;
3730  throw;
3731  }
3732 
3733  /* Handle I/O exceptions */
3734  catch (SickIOException &sick_io_exception) {
3735  std::cerr << sick_io_exception.what() << std::endl;
3736  throw;
3737  }
3738 
3739  /* A safety net */
3740  catch (...) {
3741  std::cerr << "SickLMS::_getApplication Software Name: Unknown exception!!!" << std::endl;
3742  throw;
3743  }
3744 
3745  /* Ok */
3746  }
3747 
3752 
3753  try {
3755  }
3756 
3757  /* Handle a timeout! */
3758  catch (SickTimeoutException &sick_timeout_exception) {
3759  std::cerr << sick_timeout_exception.what() << std::endl;
3760  throw;
3761  }
3762 
3763  /* Handle I/O exceptions */
3764  catch (SickIOException &sick_io_exception) {
3765  std::cerr << sick_io_exception.what() << std::endl;
3766  throw;
3767  }
3768 
3769  /* A safety net */
3770  catch (...) {
3771  std::cerr << "SickLMS::_getApplicationSoftwareVersion: Unknown exception!!!" << std::endl;
3772  throw;
3773  }
3774 
3775  /* Ok */
3776  }
3777 
3786  void SickLD::_setSickGlobalParamsAndScanAreas( const unsigned int sick_motor_speed, const double sick_angle_step,
3787  const double * const active_sector_start_angles,
3788  const double * const active_sector_stop_angles,
3789  const unsigned int num_active_sectors )
3791 
3792  /* Define buffers to hold the device-ready configuration */
3793  unsigned int num_sectors = 0;
3794  unsigned int sector_functions[SICK_MAX_NUM_SECTORS] = {0};
3795  double sector_stop_angles[SICK_MAX_NUM_SECTORS] = {0};
3796 
3797  /* A few dummy buffers */
3798  double sorted_active_sector_start_angles[SICK_MAX_NUM_SECTORS] = {0};
3799  double sorted_active_sector_stop_angles[SICK_MAX_NUM_SECTORS] = {0};
3800 
3801  /* Begin by checking the num of active sectors */
3802  if (num_active_sectors > SICK_MAX_NUM_SECTORS/2) {
3803  throw SickConfigException("SickLD::_setSickGlobalParamsAndScanAreas: Invalid number of active scan sectors!");
3804  }
3805 
3806  /* Ensure the given motor speed is valid (within proper bounds, etc...) */
3807  if (!_validSickMotorSpeed(sick_motor_speed)) {
3808  throw SickConfigException("SickLD::_setSickGlobalParamsAndScanAreas: Invalid motor speed!");
3809  }
3810 
3811  /* Ensure the scan resolution is valid (within proper bounds, etc...) */
3812  if (!_validSickScanResolution(sick_angle_step,active_sector_start_angles,active_sector_stop_angles,num_active_sectors)) {
3813  throw SickConfigException("SickLD::_setSickGlobalParamsAndScanAreas: Invalid scan resolution!");
3814  }
3815 
3816  /* Copy the input arguments */
3817  memcpy(sorted_active_sector_start_angles,active_sector_start_angles,sizeof(sorted_active_sector_start_angles));
3818  memcpy(sorted_active_sector_stop_angles,active_sector_stop_angles,sizeof(sorted_active_sector_stop_angles));
3819 
3820  /* Ensure a proper ordering of the given sector angle sets */
3821  _sortScanAreas(sorted_active_sector_start_angles,sorted_active_sector_stop_angles,num_active_sectors);
3822 
3823  /* Check for an invalid configuration */
3824  if (!_validActiveSectors(sorted_active_sector_start_angles,sorted_active_sector_stop_angles,num_active_sectors)) {
3825  throw SickConfigException("SickLD::_setSickGlobalParamsAndScanAreas: Invalid sector configuration!");
3826  }
3827 
3828  /* Ensure the resulting pulse frequency is valid for the device */
3829  if (!_validPulseFrequency(sick_motor_speed,sick_angle_step,sorted_active_sector_start_angles, sorted_active_sector_stop_angles,num_active_sectors)) {
3830  throw SickConfigException("SickLD::_setSickGlobalParamsAndScanAreas: Invalid pulse frequency!");
3831  }
3832 
3833  /* Generate the corresponding device-ready sector config */
3834  _generateSickSectorConfig(sorted_active_sector_start_angles,sorted_active_sector_stop_angles,num_active_sectors,sick_angle_step,
3835  sector_functions,sector_stop_angles,num_sectors);
3836 
3837  try {
3838 
3839  /* Set the new sector configuration */
3840  _setSickSectorConfig(sector_functions,sector_stop_angles,num_sectors,false);
3841 
3842  /* Assign the new configuration in the flash
3843  *
3844  * NOTE: The following function must be called, even if the global parameters (motor speed,
3845  * and angular resolution) are the same, in order to write the sector configuration.
3846  * Why this is the case isn't exactly clear as the manual does not explain.
3847  */
3848  _setSickGlobalConfig(GetSickSensorID(),sick_motor_speed,sick_angle_step);
3849 
3850  }
3851 
3852  /* Handle a timeout! */
3853  catch (SickTimeoutException &sick_timeout_exception) {
3854  std::cerr << sick_timeout_exception.what() << std::endl;
3855  throw;
3856  }
3857 
3858  /* Handle I/O exceptions */
3859  catch (SickIOException &sick_io_exception) {
3860  std::cerr << sick_io_exception.what() << std::endl;
3861  throw;
3862  }
3863 
3864  /* Handle a returned error code */
3865  catch (SickErrorException &sick_error_exception) {
3866  std::cerr << sick_error_exception.what() << std::endl;
3867  throw;
3868  }
3869 
3870  /* A safety net */
3871  catch (...) {
3872  std::cerr << "SickLMS::_setSickGlobalParamsAndScanAreas: Unknown exception!!!" << std::endl;
3873  throw;
3874  }
3875 
3876  /* Success! */
3877  }
3878 
3885  void SickLD::_setSickTemporaryScanAreas( const double * const active_sector_start_angles,
3886  const double * const active_sector_stop_angles,
3887  const unsigned int num_active_sectors ) throw( SickTimeoutException, SickIOException, SickConfigException ) {
3888 
3889  /* Define buffers to hold the device-ready configuration */
3890  unsigned int num_sectors = 0;
3891  unsigned int sector_functions[SICK_MAX_NUM_SECTORS] = {0};
3892  double sector_stop_angles[SICK_MAX_NUM_SECTORS] = {0};
3893 
3894  /* A few dummy buffers */
3895  double sorted_active_sector_start_angles[SICK_MAX_NUM_SECTORS] = {0};
3896  double sorted_active_sector_stop_angles[SICK_MAX_NUM_SECTORS] = {0};
3897 
3898  /* Begin by checking the num of active sectors */
3899  if (num_active_sectors > SICK_MAX_NUM_SECTORS/2)
3900  throw SickConfigException("_setSickTemporaryScanAreas: Invalid number of active scan sectors!");
3901 
3902  /* Copy the input arguments */
3903  memcpy(sorted_active_sector_start_angles,active_sector_start_angles,sizeof(sorted_active_sector_start_angles));
3904  memcpy(sorted_active_sector_stop_angles,active_sector_stop_angles,sizeof(sorted_active_sector_stop_angles));
3905 
3906  /* Ensure a proper ordering of the given sector angle sets */
3907  _sortScanAreas(sorted_active_sector_start_angles,sorted_active_sector_stop_angles,num_active_sectors);
3908 
3909  /* Check for an invalid configuration */
3910  if (!_validActiveSectors(sorted_active_sector_start_angles,sorted_active_sector_stop_angles,num_active_sectors)) {
3911  throw SickConfigException("SickLD::_setSickGlobalParamsAndScanAreas: Invalid sector configuration!");
3912  }
3913 
3914  /* Ensure the resulting pulse frequency is valid for the device */
3915  if (!_validPulseFrequency(GetSickMotorSpeed(),GetSickScanResolution(),sorted_active_sector_start_angles,
3916  sorted_active_sector_stop_angles,num_active_sectors)) {
3917  throw SickConfigException("SickLD::_setSickGlobalParamsAndScanAreas: Invalid pulse frequency!");
3918  }
3919 
3920  /* Generate the corresponding device-ready sector config */
3921  _generateSickSectorConfig(sorted_active_sector_start_angles,sorted_active_sector_stop_angles,num_active_sectors,GetSickScanResolution(),
3922  sector_functions,sector_stop_angles,num_sectors);
3923 
3924  /* Set the new sector configuration */
3925  try {
3926  _setSickSectorConfig(sector_functions,sector_stop_angles,num_sectors);
3927  }
3928 
3929  /* Handle a timeout! */
3930  catch (SickTimeoutException &sick_timeout_exception) {
3931  std::cerr << sick_timeout_exception.what() << std::endl;
3932  throw;
3933  }
3934 
3935  /* Handle I/O exceptions */
3936  catch (SickIOException &sick_io_exception) {
3937  std::cerr << sick_io_exception.what() << std::endl;
3938  throw;
3939  }
3940 
3941  /* Handle a returned error code */
3942  catch (SickErrorException &sick_error_exception) {
3943  std::cerr << sick_error_exception.what() << std::endl;
3944  throw;
3945  }
3946 
3947  /* A safety net */
3948  catch (...) {
3949  std::cerr << "SickLMS::_setSickTemporaryScanAreas: Unknown exception!!!" << std::endl;
3950  throw;
3951  }
3952 
3953  /* Success! */
3954  }
3955 
3963  void SickLD::_setSickSectorConfig( const unsigned int * const sector_functions, const double * const sector_stop_angles,
3964  const unsigned int num_sectors, const bool write_to_flash )
3966 
3967  /* Assign the new sector configuration to the device */
3968  for (unsigned int sector_id = 0; sector_id < num_sectors; sector_id++) {
3969 
3970  try {
3971 
3972  /* Set the corresponding sector function */
3973  _setSickSectorFunction(sector_id,sector_functions[sector_id],sector_stop_angles[sector_id],write_to_flash);
3974 
3975  /* Resync the driver with the new sector configuration */
3977 
3978  }
3979 
3980  /* Handle a timeout! */
3981  catch (SickTimeoutException &sick_timeout_exception) {
3982  std::cerr << sick_timeout_exception.what() << std::endl;
3983  throw;
3984  }
3985 
3986  /* Handle I/O exceptions */
3987  catch (SickIOException &sick_io_exception) {
3988  std::cerr << sick_io_exception.what() << std::endl;
3989  throw;
3990  }
3991 
3992  /* Handle a returned error code */
3993  catch (SickErrorException &sick_error_exception) {
3994  std::cerr << sick_error_exception.what() << std::endl;
3995  throw;
3996  }
3997 
3998  /* Handle a returned error code */
3999  catch (SickConfigException &sick_config_exception) {
4000  std::cerr << sick_config_exception.what() << std::endl;
4001  throw;
4002  }
4003 
4004  /* A safety net */
4005  catch (...) {
4006  std::cerr << "SickLMS::_setSickSectorConfig: Unknown exception!!!" << std::endl;
4007  throw;
4008  }
4009 
4010  }
4011 
4012  /* Success */
4013  }
4014 
4023  void SickLD::_setSickSignals( const uint8_t sick_signal_flags ) throw( SickIOException, SickTimeoutException, SickErrorException ) {
4024 
4025  /* Allocate a single buffer for payload contents */
4026  uint8_t payload_buffer[SickLDMessage::MESSAGE_PAYLOAD_MAX_LENGTH] = {0};
4027 
4028  /* Set the service IDs */
4029  payload_buffer[0] = SICK_STAT_SERV_CODE; // Requested service type
4030  payload_buffer[1] = SICK_STAT_SERV_SET_SIGNAL; // Requested service subtype
4031  payload_buffer[3] = sick_signal_flags; // PORTVAL
4032 
4033  /* Create the Sick message */
4034  SickLDMessage send_message(payload_buffer,4);
4035  SickLDMessage recv_message;
4036 
4037  /* Send the message and get a response */
4038  try {
4039  _sendMessageAndGetReply(send_message,recv_message);
4040  }
4041 
4042  /* Handle a timeout! */
4043  catch (SickTimeoutException &sick_timeout_exception) {
4044  std::cerr << sick_timeout_exception.what() << std::endl;
4045  throw;
4046  }
4047 
4048  /* Handle I/O exceptions */
4049  catch (SickIOException &sick_io_exception) {
4050  std::cerr << sick_io_exception.what() << std::endl;
4051  throw;
4052  }
4053 
4054  /* A safety net */
4055  catch (...) {
4056  std::cerr << "SickLMS::_setSickSensorMode: Unknown exception!!!" << std::endl;
4057  throw;
4058  }
4059 
4060  /* Reset the payload buffer */
4061  memset(payload_buffer,0,4);
4062 
4063  /* Extract the message payload */
4064  recv_message.GetPayload(payload_buffer);
4065 
4066  /* Check to see if there was an error */
4067  if (payload_buffer[2] != 0) {
4068  throw SickErrorException("SickLD::_setSickSignals: Command failed!");
4069  }
4070 
4071  /* Success */
4072  }
4073 
4084  SickLDMessage &recv_message,
4085  const unsigned int timeout_value ) throw( SickIOException, SickTimeoutException ) {
4086 
4087  uint8_t byte_sequence[2] = {0};
4088 
4089  byte_sequence[0] = send_message.GetServiceCode() | 0x80;
4090  byte_sequence[1] = send_message.GetServiceSubcode();
4091 
4092  /* Send message and get reply using parent's method */
4093  try {
4095  }
4096 
4097  /* Handle a timeout! */
4098  catch (SickTimeoutException &sick_timeout_exception) {
4099  std::cerr << sick_timeout_exception.what() << std::endl;
4100  throw;
4101  }
4102 
4103  /* Handle write buffer exceptions */
4104  catch (SickIOException &sick_io_exception) {
4105  std::cerr << sick_io_exception.what() << std::endl;
4106  throw;
4107  }
4108 
4109  /* A safety net */
4110  catch (...) {
4111  std::cerr << "SickLD::_sendMessageAndGetReply: Unknown exception!!!" << std::endl;
4112  throw;
4113  }
4114 
4115  }
4116 
4121 
4122  uint8_t null_byte;
4123  int num_bytes_waiting = 0;
4124 
4125  try {
4126 
4127  /* Acquire access to the data stream */
4129 
4130  /* Acquire the number of the bytes awaiting read */
4131  if (ioctl(_sick_fd,FIONREAD,&num_bytes_waiting)) {
4132  throw SickIOException("SickLD::_flushTCPRecvBuffer: ioctl() failed! (Couldn't get the number of bytes awaiting read!)");
4133  }
4134 
4135  /* Read off the bytes awaiting in the buffer */
4136  for (int i = 0; i < num_bytes_waiting; i++) {
4137  read(_sick_fd,&null_byte,1);
4138  }
4139 
4140  /* Release the stream */
4142 
4143  }
4144 
4145  /* Catch any serious IO exceptions */
4146  catch(SickIOException &sick_io_exception) {
4147  std::cerr << sick_io_exception.what() << std::endl;
4148  throw;
4149  }
4150 
4151  /* Handle thread exceptions */
4152  catch(SickThreadException &sick_thread_exception) {
4153  std::cerr << sick_thread_exception.what() << std::endl;
4154  throw;
4155  }
4156 
4157  /* A sanity check */
4158  catch(...) {
4159  std::cerr << "SickLMS::_flushTerminalBuffer: Unknown exception!" << std::endl;
4160  throw;
4161  }
4162 
4163  }
4164 
4169 
4170  /* Close the socket! */
4171  if (close(_sick_fd) < 0) {
4172  throw SickIOException("SickLD::_teardownConnection: close() failed!");
4173  }
4174 
4175  }
4176 
4187  void SickLD::_generateSickSectorConfig( const double * const active_sector_start_angles,
4188  const double * const active_sector_stop_angles,
4189  const unsigned int num_active_sectors,
4190  const double sick_angle_step,
4191  unsigned int * const sector_functions,
4192  double * const sector_stop_angles,
4193  unsigned int &num_sectors ) const {
4194 
4195  num_sectors = 0;
4196 
4197  /* Generate the sector configuration for multiple sectors */
4198  double final_diff = 0;
4199  if (num_active_sectors > 1) {
4200 
4201  /* Generate the actual sector configuration for the device */
4202  for (unsigned int i = 0; i < num_active_sectors; i++) {
4203 
4204  /* Insert the measurement sector for the active area */
4205  sector_functions[num_sectors] = SICK_CONF_SECTOR_NORMAL_MEASUREMENT;
4206  sector_stop_angles[num_sectors] = active_sector_stop_angles[i];
4207  num_sectors++;
4208 
4209  /* Check whether to insert a non-measurement sector */
4210  if ((i < num_active_sectors - 1) && (active_sector_start_angles[i+1]-active_sector_stop_angles[i] >= 2*sick_angle_step)) {
4211 
4212  /* Set the next sector function as non-measurement */
4213  sector_functions[num_sectors] = SICK_CONF_SECTOR_NO_MEASUREMENT;
4214  sector_stop_angles[num_sectors] = active_sector_start_angles[i+1] - sick_angle_step;
4215  num_sectors++;
4216 
4217  }
4218 
4219  }
4220 
4221  /* Compute the difference between the final stop angle and the first start angle*/
4222  if (active_sector_stop_angles[num_active_sectors-1] < active_sector_start_angles[0]) {
4223  final_diff = active_sector_start_angles[0] - active_sector_stop_angles[num_active_sectors-1];
4224  }
4225  else {
4226  final_diff = active_sector_start_angles[0] + (360 - active_sector_stop_angles[num_active_sectors-1]);
4227  }
4228 
4229  }
4230  else {
4231 
4232  /* Insert the measurement sector for the active area */
4233  sector_functions[num_sectors] = SICK_CONF_SECTOR_NORMAL_MEASUREMENT;
4234  sector_stop_angles[num_sectors] = active_sector_stop_angles[0];
4235  num_sectors++;
4236 
4237  /* Compute the difference between the final stop angle and the first start angle*/
4238  if (active_sector_stop_angles[0] <= active_sector_start_angles[0]) {
4239  final_diff = active_sector_start_angles[0] - active_sector_stop_angles[num_active_sectors-1];
4240  }
4241  else {
4242  final_diff = active_sector_start_angles[0] + (360 - active_sector_stop_angles[num_active_sectors-1]);
4243  }
4244 
4245  }
4246 
4247  /* Check whether to add a final non-measurement sector */
4248  if (final_diff >= 2*sick_angle_step) {
4249 
4250  /* Include the final non-measurement sector */
4251  sector_functions[num_sectors] = SICK_CONF_SECTOR_NO_MEASUREMENT;
4252  sector_stop_angles[num_sectors] = active_sector_start_angles[0]-sick_angle_step +
4253  360*(sick_angle_step > active_sector_start_angles[0]);
4254  num_sectors++;
4255 
4256  }
4257 
4258  /* If necessary insert the non-initialized sector */
4259  if (num_sectors < SICK_MAX_NUM_SECTORS) {
4260 
4261  /* Include the uninitialized sector */
4262  sector_functions[num_sectors] = SICK_CONF_SECTOR_NOT_INITIALIZED;
4263  sector_stop_angles[num_sectors] = 0;
4264  num_sectors++;
4265 
4266  }
4267 
4268  }
4269 
4275  double SickLD::_ticksToAngle( const uint16_t ticks ) const {
4276  return (((double)ticks)/16);
4277  }
4278 
4288  uint16_t SickLD::_angleToTicks( const double angle ) const {
4289  return (uint16_t)(angle*16);
4290  }
4291 
4299  double SickLD::_computeMeanPulseFrequency( const double active_scan_area, const double curr_motor_speed,
4300  const double curr_angular_resolution ) const {
4301  /* Compute the mean pulse frequency */
4302  return _computeMaxPulseFrequency(SICK_MAX_SCAN_AREA,curr_motor_speed,curr_angular_resolution)*(active_scan_area/((double)SICK_MAX_SCAN_AREA));
4303  }
4304 
4312  double SickLD::_computeMaxPulseFrequency( const double total_scan_area, const double curr_motor_speed,
4313  const double curr_angular_resolution ) const {
4314  /* Compute the maximum pulse frequency */
4315  return total_scan_area*curr_motor_speed*(1/curr_angular_resolution);
4316  }
4317 
4322  bool SickLD::_validSickSensorID( const unsigned int sick_sensor_id ) const {
4323 
4324  /* Ensure the sensor ID is valid */
4325  if (sick_sensor_id < SICK_MIN_VALID_SENSOR_ID || sick_sensor_id > SICK_MAX_VALID_SENSOR_ID) {
4326  return false;
4327  }
4328 
4329  /* Success */
4330  return true;
4331  }
4332 
4337  bool SickLD::_validSickMotorSpeed( const unsigned int sick_motor_speed ) const {
4338 
4339  /* Check the validity of the new Sick LD motor speed */
4340  if (sick_motor_speed < SICK_MIN_MOTOR_SPEED || sick_motor_speed > SICK_MAX_MOTOR_SPEED) {
4341  return false;
4342  }
4343 
4344  /* Success */
4345  return true;
4346  }
4347 
4354  bool SickLD::_validSickScanResolution( const double sick_angle_step, const double * const sector_start_angles,
4355  const double * const sector_stop_angles, const unsigned int num_sectors ) const {
4356 
4357  /* Check the validity of the new Sick LD angular step */
4358  if (sick_angle_step < SICK_MAX_SCAN_ANGULAR_RESOLUTION || fmod(sick_angle_step,SICK_MAX_SCAN_ANGULAR_RESOLUTION) != 0) {
4359  std::cerr << "Invalid scan resolution! (should be a positive multiple of " << SICK_MAX_SCAN_ANGULAR_RESOLUTION << ")" << std::endl;
4360  return false;
4361  }
4362 
4363  /* Ensure that the sector boundaries are divisible by the desired step angle */
4364  for(unsigned int i = 0; i < num_sectors; i++) {
4365 
4366  /* Check both the sector start and stop angles */
4367  if (fmod(sector_start_angles[i],sick_angle_step) != 0 || fmod(sector_stop_angles[i],sick_angle_step) != 0) {
4368  std::cerr << "Invalid scan resolution! (sector boundaries must be evenly divisible by the step angle)" << std::endl;
4369  return false;
4370  }
4371 
4372  }
4373 
4374  /* Success */
4375  return true;
4376  }
4377 
4383  bool SickLD::_validPulseFrequency( const unsigned int sick_motor_speed, const double sick_angle_step ) const {
4384 
4385  /* Simply call the other function w/ the current sector config and the given motor and step angle values */
4386  if(!_validPulseFrequency(sick_motor_speed,sick_angle_step,_sick_sector_config.sick_sector_start_angles,
4388  return false;
4389  }
4390 
4391  /* Valid! */
4392  return true;
4393  }
4394 
4403  bool SickLD::_validPulseFrequency( const unsigned int sick_motor_speed, const double sick_angle_step,
4404  const double * const active_sector_start_angles,
4405  const double * const active_sector_stop_angles,
4406  const unsigned int num_active_sectors ) const {
4407 
4408  /* Compute the scan area */
4409  double scan_area = _computeScanArea(sick_angle_step,active_sector_start_angles,active_sector_stop_angles,num_active_sectors);
4410 
4411  /* Check the mean pulse rate of the desired configuration */
4412  if (_computeMeanPulseFrequency(scan_area,sick_motor_speed,sick_angle_step) > SICK_MAX_MEAN_PULSE_FREQUENCY) {
4413  std::cerr << "Max mean pulse frequency exceeded! (try a slower motor speed, a larger step angle and/or a smaller active scan area)" << std::endl;
4414  return false;
4415  }
4416 
4417  /* Check the maximum pulse rate of the desired configuration */
4418  if (_computeMaxPulseFrequency(SICK_MAX_SCAN_AREA,sick_motor_speed,sick_angle_step) > SICK_MAX_PULSE_FREQUENCY) {
4419  std::cerr << "Max pulse frequency exceeded! (try a slower motor speed, a larger step angle and/or a smaller active scan area)" << std::endl;
4420  return false;
4421  }
4422 
4423  /* Valid! */
4424  return true;
4425  }
4426 
4444  double SickLD::_computeScanArea( const double sick_angle_step, const double * const active_sector_start_angles,
4445  const double * const active_sector_stop_angles, const unsigned int num_active_sectors ) const {
4446 
4447  /* Define the current scan area */
4448  double total_scan_area = 0;
4449  double curr_sector_scan_area = 0;
4450 
4451  /* For each sector given sum the absolute scan area for it */
4452  for (unsigned int i = 0; i < num_active_sectors; i++) {
4453 
4454  /* Compute the total scan area for this sector */
4455  curr_sector_scan_area = fabs(active_sector_start_angles[i]-active_sector_stop_angles[i]);
4456 
4457  /* Update the total scan area */
4458  total_scan_area += curr_sector_scan_area + sick_angle_step;
4459  }
4460 
4461  /* Return the computed area */
4462  return total_scan_area;
4463 
4464  }
4465 
4472  void SickLD::_sortScanAreas( double * const sector_start_angles, double * const sector_stop_angles,
4473  const unsigned int num_sectors ) const {
4474 
4475  /* A dummy temp variable */
4476  double temp = 0;
4477 
4478  /* Employ a simple bubblesort (NOTE: Only at most a handful of values will have to be sorted) */
4479  for (unsigned int i = 0; i < num_sectors; i++) {
4480  for (unsigned int j = (num_sectors-1); j > i; j--) {
4481  if (sector_start_angles[j] < sector_start_angles[j-1]) {
4482  SWAP_VALUES(sector_start_angles[j],sector_start_angles[j-1],temp);
4483  SWAP_VALUES(sector_stop_angles[j],sector_stop_angles[j-1],temp);
4484  }
4485  }
4486  }
4487 
4488  }
4489 
4496  bool SickLD::_validActiveSectors( const double * const sector_start_angles, const double * const sector_stop_angles,
4497  const unsigned int num_sectors ) const {
4498 
4499  /* A sanity check to make sure all are in [0,360) */
4500  for (unsigned int i = 0; i < num_sectors; i++) {
4501 
4502  if (sector_start_angles[i] < 0 || sector_stop_angles[i] < 0 ||
4503  sector_start_angles[i] >= 360 || sector_stop_angles[i] >= 360) {
4504 
4505  std::cerr << "Invalid sector config! (all degree values must be in [0,360))" << std::endl;
4506  return false;
4507  }
4508 
4509  }
4510 
4511  /* If multiple sectors are defined */
4512  if (num_sectors > 1) {
4513 
4514  /* Check whether the given sector arrangement is overlapping */
4515  for (unsigned int i = 0; i < (num_sectors - 1); i++) {
4516  if (sector_start_angles[i] > sector_stop_angles[i] || sector_stop_angles[i] >= sector_start_angles[i+1]) {
4517  std::cerr << "Invalid sector definitions! (check sector bounds)" << std::endl;
4518  return false;
4519  }
4520  }
4521 
4522  /* Check the last sector against the first */
4523  if (sector_stop_angles[num_sectors-1] <= sector_start_angles[num_sectors-1] &&
4524  sector_stop_angles[num_sectors-1] >= sector_start_angles[0]) {
4525  std::cerr << "Invalid sector definitions! (check sector bounds)" << std::endl;
4526  return false;
4527  }
4528 
4529  }
4530 
4531  /* Valid! */
4532  return true;
4533  }
4534 
4540  bool SickLD::_supportedScanProfileFormat( const uint16_t profile_format ) const {
4541 
4542  /* Check the supplied scan profile format */
4543  switch(profile_format) {
4545  return true;
4547  return true;
4548  default:
4549  return false;
4550  }
4551  }
4552 
4557  void SickLD::_printSectorProfileData( const sick_ld_sector_data_t &sector_data ) const {
4558 
4559  std::cout << "\t---- Sector Data " << sector_data.sector_num << " ----" << std::endl;
4560  std::cout << "\tSector Num.: " << sector_data.sector_num << std::endl;
4561  std::cout << "\tSector Angle Step (deg): " << sector_data.angle_step<< std::endl;
4562  std::cout << "\tSector Num. Data Points: " << sector_data.num_data_points << std::endl;
4563  std::cout << "\tSector Start Timestamp (ms): " << sector_data.timestamp_start << std::endl;
4564  std::cout << "\tSector Stop Timestamp (ms): " << sector_data.timestamp_stop << std::endl;
4565  std::cout << "\tSector Start Angle (deg): " << sector_data.angle_start << std::endl;
4566  std::cout << "\tSector Stop Angle (deg): " << sector_data.angle_stop << std::endl;
4567  std::cout << std::flush;
4568  }
4569 
4576  void SickLD::_printSickScanProfile( const sick_ld_scan_profile_t profile_data, const bool print_sector_data ) const {
4577 
4578  std::cout << "\t========= Sick Scan Prof. =========" << std::endl;
4579  std::cout << "\tProfile Num.: " << profile_data.profile_number << std::endl;
4580  std::cout << "\tProfile Counter: " << profile_data.profile_counter << std::endl;
4581  std::cout << "\tLayer Num.: " << profile_data.layer_num << std::endl;
4582  std::cout << "\tSensor Status: " << _sickSensorModeToString(profile_data.sensor_status) << std::endl;
4583  std::cout << "\tMotor Status: " << _sickMotorModeToString(profile_data.motor_status) << std::endl;
4584  std::cout << "\tNum. Sectors: " << profile_data.num_sectors << std::endl;
4585 
4586  // Print the corresponding active and non-active sector data
4587  for (unsigned int i=0; i < profile_data.num_sectors && print_sector_data; i++) {
4588  _printSectorProfileData(profile_data.sector_data[i]);
4589  }
4590 
4591  std::cout << "\t====================================" << std::endl;
4592  std::cout << std::flush;
4593  }
4594 
4600  uint8_t SickLD::_sickSensorModeToWorkServiceSubcode( const uint8_t sick_sensor_mode ) const {
4601 
4602  switch(sick_sensor_mode) {
4603  case SICK_SENSOR_MODE_IDLE:
4609  default:
4610  std::cerr << "SickLD::_sickSensorModeToWorkServiceSubcode: Invalid sensor mode! (Returning 0)" << std::endl;
4611  return 0; //Something is seriously wrong if we end up here!
4612  }
4613  }
4614 
4620  std::string SickLD::_sickSensorModeToString( const uint8_t sick_sensor_mode ) const {
4621 
4622  switch(sick_sensor_mode) {
4623  case SICK_SENSOR_MODE_IDLE:
4624  return "IDLE";
4626  return "ROTATE (laser is off)";
4628  return "MEASURE (laser is on)";
4630  return "ERROR";
4632  return "UNKNOWN";
4633  default:
4634  return "UNRECOGNIZED!!!";
4635  }
4636  }
4637 
4643  std::string SickLD::_sickMotorModeToString( const uint8_t sick_motor_mode ) const {
4644 
4645  switch(sick_motor_mode) {
4646  case SICK_MOTOR_MODE_OK:
4647  return "OK";
4649  return "SPIN TOO HIGH";
4651  return "SPIN TOO LOW";
4652  case SICK_MOTOR_MODE_ERROR:
4653  return "ERROR";
4655  return "UNKNOWN";
4656  default:
4657  return "UNRECOGNIZED!!!";
4658  }
4659  }
4660 
4666  std::string SickLD::_sickTransMeasureReturnToString( const uint8_t return_value ) const {
4667 
4668  switch(return_value) {
4670  return "LD-OEM/LD-LRS Measures";
4672  return "Max Pulse Frequency Too High";
4674  return "Mean Pulse Frequency Too High";
4676  return "Sector Borders Not Configured Correctly";
4678  return "Sector Borders Not Multiple of Angle Step";
4679  default:
4680  return "UNRECOGNIZED!!!";
4681  }
4682 
4683  }
4684 
4690  std::string SickLD::_sickResetLevelToString( const uint16_t reset_level ) const {
4691 
4692  switch(reset_level) {
4694  return "RESET (CPU Reinitialized)";
4696  return "RESET (CPU Not Reinitialized)";
4698  return "RESET (Halt App. and Enter IDLE)";
4699  default:
4700  return "UNRECOGNIZED!!!";
4701  }
4702 
4703  }
4704 
4710  std::string SickLD::_sickSectorFunctionToString( const uint16_t sick_sector_function ) const {
4711 
4712  switch(sick_sector_function) {
4714  return "NOT INITIALIZED";
4716  return "NOT MEASURING";
4718  return "RESERVED";
4720  return "MEASURING";
4722  return "REFERENCE";
4723  default:
4724  return "UNRECOGNIZED!!!";
4725  }
4726 
4727  }
4728 
4734  std::string SickLD::_sickProfileFormatToString( const uint16_t profile_format ) const {
4735 
4736  switch(profile_format) {
4738  return "RANGE ONLY";
4740  return "RANGE + ECHO";
4741  default:
4742  return "UNRECOGNIZED!!!";
4743  }
4744 
4745  }
4746 
4751 
4752  std::cout << "\t*** Init. complete: Sick LD is online and ready!" << std::endl;
4753  std::cout << "\tNum. Active Sectors: " << (int)_sick_sector_config.sick_num_active_sectors << std::endl;
4754  std::cout << "\tMotor Speed: " << _sick_global_config.sick_motor_speed << " (Hz)" << std::endl;
4755  std::cout << "\tScan Resolution: " << _sick_global_config.sick_angle_step << " (deg)" << std::endl;
4756  std::cout << std::endl;
4757 
4758  }
4759 
4760 } //namespace SickToolbox
double _computeMaxPulseFrequency(const double total_scan_area, const double curr_motor_speed, const double curr_angular_resolution) const
Compute the mean pulse frequency (see page 22 of the operator&#39;s manual)
Definition: SickLD.cc:4312
std::string GetSickAppSoftwareName() const
Acquire the Sick LD&#39;s application software name.
Definition: SickLD.cc:1484
uint16_t _sick_tcp_port
Definition: SickLD.hh:551
void _teardownConnection()
Teardown TCP connection to Sick LD.
Definition: SickLD.cc:4168
void _recvMessage(SickLDMessage &sick_message, const unsigned int timeout_value) const
static const uint8_t SICK_CONF_SECTOR_NO_MEASUREMENT
Sector has no measurements.
Definition: SickLD.hh:182
double sick_sector_stop_angles[SICK_MAX_NUM_SECTORS]
Stop angles for each sector (deg)
Definition: SickLD.hh:300
bool _sick_streaming_range_data
Definition: SickLD.hh:566
double angle_stop
The angle at which the last measurement in the sector was acquired.
Definition: SickLD.hh:343
std::string GetSickIdentityAsString() const
Acquire the Sick LD&#39;s identity as a printable string.
Definition: SickLD.cc:1517
unsigned int timestamp_stop
The timestamp (in ms) corresponding to the time the last measurement in the sector was taken...
Definition: SickLD.hh:339
static const uint8_t SICK_WORK_SERV_TRANS_ROTATE
Sick LD enters ROTATE mode (motor starts and rotates with a specified speed in Hz, laser is off)
Definition: SickLD.hh:142
static const uint8_t SICK_WORK_SERV_RESET
Sick LD enters a reset sequence.
Definition: SickLD.hh:140
void SetSickScanResolution(const double sick_step_angle)
Attempts to set a new scan resolution for the device (in flash) while retaining the previously define...
Definition: SickLD.cc:1102
void AcquireDataStream()
Acquires a lock on the data stream.
static const uint8_t SICK_CONF_SERV_CODE
Configuration service code.
Definition: SickLD.hh:91
static const uint8_t SICK_CONF_SECTOR_RESERVED
Sector is reserved by Sick LD.
Definition: SickLD.hh:183
A structure to aggregate the fields that collectively define the profile of a single scan acquired fr...
Definition: SickLD.hh:358
void _getSickScanProfiles(const uint16_t profile_format, const uint16_t num_profiles=DEFAULT_SICK_NUM_SCAN_PROFILES)
Request n scan profiles from the Sick LD unit.
Definition: SickLD.cc:2389
void _getApplicationSoftwarePartNumber()
Get application software part number.
Definition: SickLD.cc:3691
static const uint8_t SICK_STAT_SERV_GET_ID_SENSOR_EDM_SERIAL_NUM
Request the edm??? serial number.
Definition: SickLD.hh:110
static const uint16_t SICK_MAX_PULSE_FREQUENCY
Max pulse frequency of the device (in Hz) (see page 22 of the operator&#39;s manual)
Definition: SickLD.hh:70
static const uint8_t SICK_STAT_SERV_GET_ID_SENSOR_VERSION
Request the sensor&#39;s version.
Definition: SickLD.hh:108
static const uint8_t SICK_CONF_SERV_SET_FILTER_NEARFIELD_OFF
Used to set nearfield suppression off.
Definition: SickLD.hh:132
bool _sick_streaming_range_and_echo_data
Definition: SickLD.hh:569
std::string _sickSensorModeToString(const uint8_t sick_sensor_mode) const
Converts the Sick LD numerical sensor mode to a representative string.
Definition: SickLD.cc:4620
void _sortScanAreas(double *const sector_start_angles, double *const sector_stop_angles, const unsigned int num_sectors) const
Sort the scan areas based on the given angles to place them in device "scan" order.
Definition: SickLD.cc:4472
unsigned int num_data_points
The number of data points in the scan area.
Definition: SickLD.hh:337
uint16_t sick_node_id
Single word address of the Sick LD.
Definition: SickLD.hh:281
void _getApplicationSoftwareVersion()
Get application software part number.
Definition: SickLD.cc:3751
static const uint8_t SICK_CONF_SERV_GET_SYNC_CLOCK
Read the internal time of the LD-OEM/LD-LRS.
Definition: SickLD.hh:123
static const uint8_t SICK_WORK_SERV_TRANS_IDLE
Sick LD enters IDLE mode (motor stops and laser is turned off)
Definition: SickLD.hh:141
uint8_t _sickSensorModeToWorkServiceSubcode(const uint8_t sick_sensor_mode) const
Map Sick LD sensor modes to their equivalent service subcode representations.
Definition: SickLD.cc:4600
uint16_t sick_ip_address[4]
IP address in numerical form w/ leftmost part at sick_ip_address[0].
Definition: SickLD.hh:278
void PrintSickGlobalConfig() const
Print the Sick LD&#39;s global configuration.
Definition: SickLD.cc:1638
void _setSickFilter(const uint8_t suppress_code)
Enables/disables nearfield suppression on the Sick LD.
Definition: SickLD.cc:2790
static const uint8_t SICK_STAT_SERV_GET_ID_SENSOR_PART_NUM
Request the sensor&#39;s part number.
Definition: SickLD.hh:106
static const uint8_t SICK_CONF_SERV_SET_FILTER
Set the filter configuration.
Definition: SickLD.hh:124
A class for monitoring the receive buffer when interfacing with a Sick LD LIDAR.
Thrown when Sick returns an error code or an unexpected response.
A structure to aggregate the data used to configure the Sick LD global parameter values.
Definition: SickLD.hh:260
Contains some simple exception classes.
static const uint8_t SICK_STAT_SERV_GET_ID_FIRMWARE_PART_NUM
Requess the firmware&#39;s part number.
Definition: SickLD.hh:111
void _generateSickSectorConfig(const double *const active_sector_start_angles, const double *const active_sector_stop_angles, const unsigned int num_active_sectors, const double sick_step_angle, unsigned int *const sector_functions, double *const sector_stop_angles, unsigned int &num_sectors) const
Generates a device-ready sector set given only an active sector spec.
Definition: SickLD.cc:4187
double GetSickScanArea() const
Computes the active area over all measuring sectors.
Definition: SickLD.cc:1605
std::string sick_application_software_part_number
The Sick LD&#39;s app. software part number.
Definition: SickLD.hh:321
unsigned int timestamp_start
The timestamp (in ms) corresponding to the time the first measurement in the sector was taken...
Definition: SickLD.hh:338
static const uint8_t SICK_CONF_SERV_GET_FUNCTION
Returns the configuration of the given sector.
Definition: SickLD.hh:126
void _getSensorVersion()
Get the Sick LD&#39;s sensor version.
Definition: SickLD.cc:3510
std::string _sickResetLevelToString(const uint16_t reset_level) const
Converts the Sick LD numerical reset level to a representative string.
Definition: SickLD.cc:4690
void SetSickScanAreas(const double *const active_sector_start_angles, const double *const active_sector_stop_angles, const unsigned int num_active_sectors)
Attempts to set the active scan areas for the device (in flash)
Definition: SickLD.cc:1198
void SetSickTimeRelative(const int16_t time_delta, uint16_t &new_sick_clock_time)
Set the relative time of the Sick LD unit.
Definition: SickLD.cc:347
uint8_t _sick_sensor_mode
Definition: SickLD.hh:560
std::string sick_serial_number
The Sick LD&#39;s serial number.
Definition: SickLD.hh:316
double _computeMeanPulseFrequency(const double active_scan_area, const double curr_motor_speed, const double curr_angular_resolution) const
Compute the mean pulse frequency (see page 22 of the operator&#39;s manual)
Definition: SickLD.cc:4299
std::string sick_edm_serial_number
The Sick LD&#39;s edm??? serial number.
Definition: SickLD.hh:317
std::string sick_name
The name assigned to the Sick.
Definition: SickLD.hh:314
void PrintSickSectorConfig() const
Print the Sick LD&#39;s sector configuration.
Definition: SickLD.cc:1652
void GetSickSignals(uint8_t &sick_signal_flags)
Gets the Sick LD signal LED&#39;s and switching outputs.
Definition: SickLD.cc:497
void _setSickSignals(const uint8_t sick_signal_flags=DEFAULT_SICK_SIGNAL_SET)
Sets the Sick LEDs and switching outputs.
Definition: SickLD.cc:4023
static const uint8_t SICK_STAT_SERV_CODE
Status service code.
Definition: SickLD.hh:90
unsigned int GetSickSensorID() const
Acquire the Sick LD&#39;s sensor ID.
Definition: SickLD.cc:1331
unsigned int sensor_status
The status of the Sick LD sensor.
Definition: SickLD.hh:362
uint8_t sick_num_active_sectors
Number of active sectors (sectors that are actually being scanned)
Definition: SickLD.hh:295
uint8_t sick_num_initialized_sectors
Number of sectors configured w/ a function other than "not initialized".
Definition: SickLD.hh:296
void _getSensorEDMSerialNumber()
Get sensor EDM serial number.
Definition: SickLD.cc:3571
void DisableNearfieldSuppression()
Disables nearfield suppressive filtering.
Definition: SickLD.cc:668
std::string sick_firmware_version
The Sick LD&#39;s firmware version.
Definition: SickLD.hh:320
uint16_t sick_sensor_id
The single word sensor ID for the Sick unit.
Definition: SickLD.hh:261
static const uint8_t SICK_CONF_SERV_SET_FILTER_NEARFIELD_ON
Used to set nearfield suppression on.
Definition: SickLD.hh:133
static const uint8_t SICK_WORK_SERV_TRANS_MEASURE
Sick LD enters MEASURE mode (laser starts with next revolution)
Definition: SickLD.hh:143
void _getSickSectorFunction(const uint8_t sector_num, uint8_t &sector_function, double &sector_stop_angle)
Acquires the function of the given sector.
Definition: SickLD.cc:2016
void _setSickGlobalConfig(const uint8_t sick_sensor_id, const uint8_t sick_motor_speed, const double sick_angle_step)
Sets the Sick LD&#39;s global parameters (sensor id, motor speed, and angular step) in flash...
Definition: SickLD.cc:2988
uint16_t sick_subnet_mask[4]
Subnet mask for the network to which the Sick LD is assigned.
Definition: SickLD.hh:279
static const uint8_t SICK_STAT_SERV_GET_ID_APP_PART_NUM
Request the application part number.
Definition: SickLD.hh:114
void EnableNearfieldSuppression()
Enables nearfield suppressive filtering.
Definition: SickLD.cc:619
SickLD(const std::string sick_ip_address=DEFAULT_SICK_IP_ADDRESS, const uint16_t sick_tcp_port=DEFAULT_SICK_TCP_PORT)
A standard constructor.
Definition: SickLD.cc:51
void ReleaseDataStream()
Releases a lock on the data stream.
double scan_angles[SICK_MAX_NUM_MEASUREMENTS]
The scan angles corresponding to the respective measurements.
Definition: SickLD.hh:345
static const uint8_t SICK_MEAS_SERV_GET_PROFILE
Requests n profiles of a defined format.
Definition: SickLD.hh:136
void _setSickSensorModeToRotate()
Sets the Sick LD sensor mode to ROTATE.
Definition: SickLD.cc:2163
static const uint8_t SICK_STAT_SERV_SET_SIGNAL
Sets the switches and LEDs.
Definition: SickLD.hh:102
unsigned int echo_values[SICK_MAX_NUM_MEASUREMENTS]
The corresponding echo/reflectivity values.
Definition: SickLD.hh:340
void _printSickScanProfile(const sick_ld_scan_profile_t profile_data, const bool print_sector_data=true) const
Prints data fields of the given scan profile.
Definition: SickLD.cc:4576
bool _validPulseFrequency(const unsigned int sick_motor_speed, const double sick_step_angle) const
Checks whether the given configuration yields a valid mean and max pulse frequency (uses current sect...
Definition: SickLD.cc:4383
void _setSickGlobalParamsAndScanAreas(const unsigned int sick_motor_speed, const double sick_step_angle, const double *const active_sector_start_angles, const double *const active_sector_stop_angles, const unsigned int num_active_sectors)
Attempts to set the "permanent" (by writing flash) operating values for the device.
Definition: SickLD.cc:3786
void _sendMessageAndGetReply(const SickLDMessage &send_message, SickLDMessage &recv_message, const unsigned int timeout_value=DEFAULT_SICK_MESSAGE_TIMEOUT)
Send a message to the Sick LD and get its reply.
Definition: SickLD.cc:4083
static const uint8_t SICK_MOTOR_MODE_ERROR
Motor stops or coder error.
Definition: SickLD.hh:86
bool _validSickSensorID(const unsigned int sick_sensor_id) const
Checks whether the given senor id is valid for the device.
Definition: SickLD.cc:4322
static const uint8_t SICK_WORK_SERV_CODE
Working service code.
Definition: SickLD.hh:93
std::string GetSickEDMSerialNumber() const
Acquire the Sick LD&#39;s EDM serial number.
Definition: SickLD.cc:1444
static const uint8_t SICK_CONF_SERV_SET_FILTER_NEARFIELD
Code for identifying filter type: nearfield suppression.
Definition: SickLD.hh:129
static const uint8_t SICK_STAT_SERV_GET_ID_SENSOR_SERIAL_NUM
Request the sensor&#39;s serial number.
Definition: SickLD.hh:109
unsigned int sector_num
The sector number in the scan area.
Definition: SickLD.hh:336
void _getFirmwareName()
Get firmware name.
Definition: SickLD.cc:3631
#define DEFAULT_SICK_CONNECT_TIMEOUT
The max time to wait before considering a connection attempt as failed (usecs)
Definition: SickLD.hh:24
A class to represent all messages sent to and from the Sick LD unit.
std::string GetSickSectorConfigAsString() const
Acquire the Sick LD&#39;s sector config as a printable string.
Definition: SickLD.cc:1579
bool _validActiveSectors(const double *const sector_start_angles, const double *const sector_stop_angles, const unsigned int num_active_sectors) const
Determines wheter a given set of sector bounds are valid.
Definition: SickLD.cc:4496
virtual const char * what() const
From the standard exception library.
sick_ld_config_global_t _sick_global_config
Definition: SickLD.hh:575
std::string sick_application_software_name
The Sick LD&#39;s app. software name.
Definition: SickLD.hh:322
static const uint8_t SICK_MOTOR_MODE_UNKNOWN
Motor is in an unknown state.
Definition: SickLD.hh:87
uint16_t _angleToTicks(const double angle) const
Converts encoder ticks to equivalent angle representation.
Definition: SickLD.cc:4288
uint8_t _sick_motor_mode
Definition: SickLD.hh:563
std::string GetSickGatewayIPAddress() const
Acquire the IP address of the Sick gateway.
Definition: SickLD.cc:1393
static const uint16_t SICK_MAX_MOTOR_SPEED
Maximum motor speed in Hz.
Definition: SickLD.hh:66
void _printSectorProfileData(const sick_ld_sector_data_t &sector_data) const
Print data corresponding to the referenced sector data structure.
Definition: SickLD.cc:4557
void _getFirmwarePartNumber()
Get firmware part number.
Definition: SickLD.cc:3601
void _getIdentificationString(const uint8_t id_request_code, std::string &id_return_string)
Query the Sick LD for a particular ID string.
Definition: SickLD.cc:3395
static const uint16_t SICK_MAX_VALID_SENSOR_ID
The largest value the Sick will accept as a Sensor ID.
Definition: SickLD.hh:68
void _setSickSectorConfig(const unsigned int *const sector_functions, const double *const sector_stop_angles, const unsigned int num_sectors, const bool write_to_flash=false)
Sets the sector configuration for the device.
Definition: SickLD.cc:3963
static const uint8_t SICK_SENSOR_MODE_UNKNOWN
The Sick LD is in an unknown state.
Definition: SickLD.hh:80
static const uint8_t SICK_STAT_SERV_GET_ID_FIRMWARE_NAME
Request the firmware&#39;s name.
Definition: SickLD.hh:112
void _flushTCPRecvBuffer()
Flushes TCP receive buffer contents.
Definition: SickLD.cc:4120
static const uint8_t SICK_WORK_SERV_TRANS_MEASURE_RET_ERR_MAX_PULSE
Sick LD reports config yields a max laser pulse frequency that is too high.
Definition: SickLD.hh:152
void _parseScanProfile(uint8_t *const src_buffer, sick_ld_scan_profile_t &profile_data) const
Parses a well-formed sequence of bytes into a corresponding scan profile.
Definition: SickLD.cc:2520
static const uint8_t SICK_WORK_SERV_TRANS_MEASURE_RET_OK
Sick LD is ready to stream/obtain scan profiles.
Definition: SickLD.hh:151
void SetSickMotorSpeed(const unsigned int sick_motor_speed)
Attempts to set a new motor speed for the device (in flash)
Definition: SickLD.cc:1040
double _ticksToAngle(const uint16_t ticks) const
Converts encoder ticks to equivalent angle representation.
Definition: SickLD.cc:4275
std::string GetSickFirmwareVersion() const
Acquire the Sick LD&#39;s firmware version.
Definition: SickLD.cc:1468
static const uint8_t SICK_STAT_SERV_GET_SIGNAL
Reads the value of the switch and LED port.
Definition: SickLD.hh:101
std::string GetSickSubnetMask() const
Acquire the subnet mask for the Sick.
Definition: SickLD.cc:1374
uint16_t sick_ld_to_host_byte_order(uint16_t value)
Converts Sick LD byte order (big-endian) to host byte order (little-endian)
A structure to aggregate the fields that collectively define a sector in the scan area of the Sick LD...
Definition: SickLD.hh:335
static const uint8_t SICK_CONF_SECTOR_NORMAL_MEASUREMENT
Sector is returning measurements.
Definition: SickLD.hh:184
static const uint8_t SICK_MEAS_SERV_CANCEL_PROFILE
Stops profile output.
Definition: SickLD.hh:137
sick_ld_sector_data_t sector_data[SICK_MAX_NUM_SECTORS]
The sectors associated with the scan profile.
Definition: SickLD.hh:365
static const uint8_t SICK_CONF_KEY_ETHERNET
Key for configuring Ethernet.
Definition: SickLD.hh:177
bool _validSickScanResolution(const double sick_step_angle, const double *const active_sector_start_angles, const double *const active_sector_stop_angles, const unsigned int num_active_sectors) const
Checks whether the given scan resolution is valid.
Definition: SickLD.cc:4354
double sick_angle_step
Difference between two laser pulse positions in 1/16th deg. (NOTE: this value must be a divisor of 57...
Definition: SickLD.hh:263
std::string GetSickName() const
Acquire the Sick LD&#39;s name.
Definition: SickLD.cc:1420
std::string sick_part_number
The Sick LD&#39;s part number.
Definition: SickLD.hh:313
struct sockaddr_in _sick_inet_address_info
Definition: SickLD.hh:557
void GetPayload(uint8_t *const payload_buffer) const
Get the payload contents as a sequence of well-formed bytes.
Definition: SickMessage.hh:156
std::string _sick_ip_address
Definition: SickLD.hh:548
static const uint8_t SICK_CONF_SECTOR_REFERENCE_MEASUREMENT
Sector can be used as reference measurement.
Definition: SickLD.hh:185
uint8_t sick_active_sector_ids[SICK_MAX_NUM_SECTORS]
IDs of all active sectors.
Definition: SickLD.hh:297
uint16_t sick_motor_speed
Nominal motor speed value: 0x0005 to 0x0014 (5 to 20)
Definition: SickLD.hh:262
std::string GetSickFirmwareName() const
Acquire the Sick LD&#39;s firmware number.
Definition: SickLD.cc:1460
void _getSickIdentity()
Get the parameters that define the Sick LD&#39;s identity.
Definition: SickLD.cc:2885
void _printInitFooter() const
Prints the initialization footer.
Definition: SickLD.cc:4750
static const uint8_t SICK_MEAS_SERV_CODE
Measurement service code.
Definition: SickLD.hh:92
double sick_sector_start_angles[SICK_MAX_NUM_SECTORS]
Start angles for each initialized sector (deg)
Definition: SickLD.hh:299
static const uint8_t SICK_MOTOR_MODE_SPIN_TOO_LOW
Motor spin too high (i.e. rotational velocity too fast)
Definition: SickLD.hh:85
static const uint8_t SICK_STAT_SERV_GET_ID
Request the Sick LD ID.
Definition: SickLD.hh:99
void SetSickGlobalParamsAndScanAreas(const unsigned int sick_motor_speed, const double sick_step_angle, const double *const active_sector_start_angles, const double *const active_sector_stop_angles, const unsigned int num_active_sectors)
Attempts to set the scan resolution and active sectors/scan areas for the device (in flash) ...
Definition: SickLD.cc:1140
void _getSickGlobalConfig()
Get the global configuration of the Sick LD.
Definition: SickLD.cc:3088
static const uint8_t SICK_SENSOR_MODE_MEASURE
The Sick LD prism is rotating, and the laser is on.
Definition: SickLD.hh:78
Provides an abstract parent for all Sick LIDAR devices.
Definition: SickLIDAR.hh:53
static const uint8_t SICK_SENSOR_MODE_ROTATE
The Sick LD prism is rotating, but laser is off.
Definition: SickLD.hh:77
std::string sick_firmware_name
The Sick LD&#39;s firmware name.
Definition: SickLD.hh:319
void ResetSick(const unsigned int reset_level=SICK_WORK_SERV_RESET_INIT_CPU)
Resets the device according to the given reset level.
Definition: SickLD.cc:1252
std::string GetSickEthernetConfigAsString() const
Acquire the Sick LD&#39;s global config as a printable string.
Definition: SickLD.cc:1561
void GetSickTime(uint16_t &sick_time)
Gets the internal clock time of the Sick LD unit.
Definition: SickLD.cc:557
uint8_t sick_sector_functions[SICK_MAX_NUM_SECTORS]
Function values associated w/ each of the Sick LD&#39;s sectors.
Definition: SickLD.hh:298
void _setSickSectorFunction(const uint8_t sector_number, const uint8_t sector_function, const double sector_angle_stop, const bool write_to_flash=false)
Sets the function for a particular scan sector.
Definition: SickLD.cc:1890
sick_ld_config_ethernet_t _sick_ethernet_config
Definition: SickLD.hh:578
static const uint8_t SICK_MOTOR_MODE_OK
Motor is functioning properly.
Definition: SickLD.hh:83
static const uint8_t SICK_WORK_SERV_RESET_INIT_CPU
Sick LD does a complete reset (Reinitializes the CPU)
Definition: SickLD.hh:146
std::string sick_version
The Sick LD&#39;s version number.
Definition: SickLD.hh:315
std::string GetSickAppSoftwareVersionNumber() const
Acquire the Sick LD&#39;s application software version number.
Definition: SickLD.cc:1492
double _computeScanArea(const double sick_step_angle, const double *const sector_start_angles, const double *const sector_stop_angles, const unsigned int num_sectors) const
Computes the active scan area for the Sick given the current sector configuration.
Definition: SickLD.cc:4444
void _setSickSensorModeToIdle()
Sets the Sick LD sensor mode to IDLE.
Definition: SickLD.cc:2120
void _cancelSickScanProfiles()
Kills the current data stream.
Definition: SickLD.cc:2687
unsigned int motor_status
The status of the Sick LD motor.
Definition: SickLD.hh:363
unsigned int profile_number
The number of profiles sent to the host (i.e. the current profile number)
Definition: SickLD.hh:359
static const uint8_t SICK_WORK_SERV_TRANS_MEASURE_RET_ERR_MEAN_PULSE
Sick LD reports config yields a max mean pulse frequency that is too high.
Definition: SickLD.hh:153
void PrintSickStatus() const
Print the status of the Sick LD.
Definition: SickLD.cc:1624
void _getSensorSerialNumber()
Get the Sick LD&#39;s serial number.
Definition: SickLD.cc:3541
static const uint8_t SICK_STAT_SERV_GET_ID_FIRMWARE_VERSION
Request the firmware&#39;s version.
Definition: SickLD.hh:113
std::string GetSickPartNumber() const
Acquire the Sick LD&#39;s part number.
Definition: SickLD.cc:1412
std::string _sickProfileFormatToString(const uint16_t profile_format) const
Converts the Sick LD numerical motor mode to a representative string.
Definition: SickLD.cc:4734
void Initialize()
Initializes the driver and syncs it with Sick LD unit. Uses sector config given in flash...
Definition: SickLD.cc:91
void _setSickTemporaryScanAreas(const double *const active_sector_start_angles, const double *const active_sector_stop_angles, const unsigned int num_active_sectors)
Attempts to set the "temporary" (until a device reset) scan area config for the device.
Definition: SickLD.cc:3885
void SetSickSensorID(const unsigned int sick_sensor_id)
Attempts to set a new sensor ID for the device (in flash)
Definition: SickLD.cc:991
void GetSickMeasurements(double *const range_measurements, unsigned int *const echo_measurements=NULL, unsigned int *const num_measurements=NULL, unsigned int *const sector_ids=NULL, unsigned int *const sector_data_offsets=NULL, double *const sector_step_angles=NULL, double *const sector_start_angles=NULL, double *const sector_stop_angles=NULL, unsigned int *const sector_start_timestamps=NULL, unsigned int *const sector_stop_timestamps=NULL)
Acquires measurements and corresponding sector data from the Sick LD.
Definition: SickLD.cc:740
static const uint8_t SICK_STAT_SERV_GET_ID_APP_VERSION
Request the application version.
Definition: SickLD.hh:116
static const uint8_t SICK_SENSOR_MODE_ERROR
The Sick LD is in error mode.
Definition: SickLD.hh:79
static constexpr double SICK_MAX_SCAN_ANGULAR_RESOLUTION
Minimum valid separation between laser pulses in active scan ares (deg)
Definition: SickLD.hh:72
static const uint8_t SICK_CONF_SERV_SET_CONFIGURATION
Set the Sick LD configuration.
Definition: SickLD.hh:119
static const uint16_t SICK_MAX_NUM_SECTORS
Maximum number of scan sectors (NOTE: This value must be even)
Definition: SickLD.hh:62
static const uint8_t SICK_WORK_SERV_TRANS_MEASURE_RET_ERR_SECT_BORDER_MULT
Sick LD reports sector borders are not a multiple of the step angle.
Definition: SickLD.hh:155
Defines a class for monitoring the receive buffer when interfacing w/ a Sick LMS LIDAR.
static const uint16_t SICK_MAX_MEAN_PULSE_FREQUENCY
Max mean pulse frequence of the current device configuration (in Hz) (see page 22 of the operator&#39;s m...
Definition: SickLD.hh:69
A structure to aggregate the data used to configure the Sick LD unit for Ethernet.
Definition: SickLD.hh:277
void PrintSickEthernetConfig() const
Print the Sick LD&#39;s Ethernet configuration.
Definition: SickLD.cc:1645
static const uint8_t SICK_SENSOR_MODE_IDLE
The Sick LD is powered but idle.
Definition: SickLD.hh:76
void SetSickSignals(const uint8_t sick_signal_flags=DEFAULT_SICK_SIGNAL_SET)
Sets the Sick LD signal LED&#39;s and switching outputs.
Definition: SickLD.cc:453
unsigned int GetSickMotorSpeed() const
Acquire the Sick LD&#39;s current motor speed in Hz.
Definition: SickLD.cc:1339
void _getSickSectorConfig()
Query the Sick for its current sector configuration.
Definition: SickLD.cc:3318
Defines the SickLD class for working with the Sick LD-OEM/LD-LRS long range LIDARs.
virtual void _sendMessageAndGetReply(const SICK_MSG_CLASS &send_message, SICK_MSG_CLASS &recv_message, const uint8_t *const byte_sequence, const unsigned int byte_sequence_length, const unsigned int byte_interval, const unsigned int timeout_value, const unsigned int num_tries)
Definition: SickLIDAR.hh:396
Encapsulates the Sick LIDAR Matlab/C++ toolbox.
Definition: SickLD.cc:44
static const uint16_t SICK_SCAN_PROFILE_RANGE_AND_ECHO
Request sector scan data w/ echo data.
Definition: SickLD.hh:212
unsigned int GetSickNumActiveSectors() const
Acquire the number of sectors that are measuring.
Definition: SickLD.cc:1323
std::string GetSickIPAddress() const
Acquire the current IP address of the Sick.
Definition: SickLD.cc:1355
void _getSensorPartNumber()
Get the Sick LD&#39;s part number.
Definition: SickLD.cc:3448
static const uint8_t SICK_STAT_SERV_GET_ID_SENSOR_NAME
Request the sensor&#39;s name.
Definition: SickLD.hh:107
unsigned int profile_counter
The number of profiles gathered by the Sick LD.
Definition: SickLD.hh:360
Defines simple utility functions for working with the Sick LD.
void _setSickSensorModeToMeasure()
Sets the Sick LD sensor mode to ROTATE.
Definition: SickLD.cc:2206
std::string _sickMotorModeToString(const uint8_t sick_motor_mode) const
Converts the Sick LD numerical motor mode to a representative string.
Definition: SickLD.cc:4643
Defines the class SickLDMessage.
void _setSickSensorMode(const uint8_t new_sick_sensor_mode)
Sets the Sick LD to the requested sensor mode.
Definition: SickLD.cc:2250
#define SWAP_VALUES(x, y, t)
A simple macro for swapping two values.
Definition: SickLD.hh:32
static const uint8_t SICK_WORK_SERV_RESET_HALT_APP
Sick LD does a minimal reset (Application is halted and device enters IDLE state) ...
Definition: SickLD.hh:148
uint16_t host_to_sick_ld_byte_order(uint16_t value)
Converts host byte order (little-endian) to Sick LD byte order (big-endian)
static const uint8_t SICK_CONF_SERV_GET_CONFIGURATION
Read the Sick LD configuration information.
Definition: SickLD.hh:120
uint16_t sick_transparent_tcp_port
The TCP/IP transparent port associated with the Sick LD.
Definition: SickLD.hh:282
double range_values[SICK_MAX_NUM_MEASUREMENTS]
The corresponding range values (NOTE: The size of this array is intended to be large enough to accomo...
Definition: SickLD.hh:344
uint16_t sick_gateway_ip_address[4]
The address of the local gateway.
Definition: SickLD.hh:280
static const uint16_t SICK_SCAN_PROFILE_RANGE
Request sector scan data w/o any echo data.
Definition: SickLD.hh:188
Thrown instance where the driver can&#39;t read,write,drain,flush,... the buffers.
void PrintSickIdentity() const
Print the parameters comprising the Sick LD&#39;s identity.
Definition: SickLD.cc:1631
void Uninitialize()
Tear down the connection between the host and the Sick LD.
Definition: SickLD.cc:1659
sick_ld_config_sector_t _sick_sector_config
Definition: SickLD.hh:581
double angle_step
The angle step used for the given sector (this should be the same for all sectors) ...
Definition: SickLD.hh:341
std::string GetSickSerialNumber() const
Acquire the Sick LD&#39;s serial number.
Definition: SickLD.cc:1436
bool _validSickMotorSpeed(const unsigned int sick_motor_speed) const
Checks whether the given sick motor speed is valid for the device.
Definition: SickLD.cc:4337
std::string GetSickVersion() const
Acquire the Sick LD&#39;s version number.
Definition: SickLD.cc:1428
void _getFirmwareVersion()
Get firmware version number.
Definition: SickLD.cc:3661
unsigned int num_sectors
The number of sectors returned in the profile.
Definition: SickLD.hh:364
std::string GetSickFirmwarePartNumber() const
Acquire the Sick LD&#39;s firmware part number.
Definition: SickLD.cc:1452
void _getApplicationSoftwareName()
Get application software name.
Definition: SickLD.cc:3721
std::string GetSickAppSoftwarePartNumber() const
Acquire the Sick LD&#39;s application software part number.
Definition: SickLD.cc:1476
std::string _sickSectorFunctionToString(const uint16_t sick_sector_function) const
Converts the Sick LD numerical sector config to a representative string.
Definition: SickLD.cc:4710
double angle_start
The angle at which the first measurement in the sector was acquired.
Definition: SickLD.hh:342
std::string sick_application_software_version
The Sick LD&#39;s app. software version.
Definition: SickLD.hh:323
static const uint8_t SICK_CONF_SECTOR_NOT_INITIALIZED
Sector is uninitialized.
Definition: SickLD.hh:181
void SetSickTimeAbsolute(const uint16_t absolute_clock_time, uint16_t &new_sick_clock_time)
Set the absolute time of the Sick LD unit.
Definition: SickLD.cc:241
void _syncDriverWithSick()
Synchronizes buffer driver parameters with those of the Sick LD.
Definition: SickLD.cc:1841
static const uint8_t SICK_WORK_SERV_RESET_KEEP_CPU
Sick LD does a partial reset (CPU is not reinitialized)
Definition: SickLD.hh:147
#define DEFAULT_SICK_MESSAGE_TIMEOUT
The max time to wait for a message reply (usecs)
Definition: SickLD.hh:23
static const uint8_t SICK_WORK_SERV_TRANS_MEASURE_RET_ERR_SECT_BORDER
Sick LD reports sector borders are not configured correctly.
Definition: SickLD.hh:154
void _getSickStatus()
Get the status of the Sick LD.
Definition: SickLD.cc:2927
Thrown when the driver detects (or the Sick reports) an invalid config.
static const uint8_t SICK_MOTOR_MODE_SPIN_TOO_HIGH
Motor spin too low (i.e. rotational velocity too low)
Definition: SickLD.hh:84
static const uint8_t SICK_CONF_SERV_SET_TIME_RELATIVE
Correct the internal clock by some value.
Definition: SickLD.hh:122
void _setupConnection()
Establish a TCP connection to the unit.
Definition: SickLD.cc:1732
static const uint8_t SICK_STAT_SERV_GET_ID_APP_NAME
Request the application name.
Definition: SickLD.hh:115
static const uint16_t SICK_MAX_SCAN_AREA
Maximum area that can be covered in a single scan (deg)
Definition: SickLD.hh:64
Makes handling timeouts much easier.
unsigned int layer_num
The layer number associated with a scan (this will always be 0)
Definition: SickLD.hh:361
void _getSensorName()
Get the Sick LD&#39;s assigned sensor name.
Definition: SickLD.cc:3479
A structure to aggregate data used to define the Sick LD&#39;s sector configuration.
Definition: SickLD.hh:294
sick_ld_identity_t _sick_identity
Definition: SickLD.hh:572
std::string sick_firmware_part_number
The Sick LD&#39;s firmware part number.
Definition: SickLD.hh:318
void SetSickTempScanAreas(const double *active_sector_start_angles, const double *const active_sector_stop_angles, const unsigned int num_active_sectors)
Set the temporary scan areas for the Sick LD.
Definition: SickLD.cc:190
static const uint8_t SICK_CONF_KEY_GLOBAL
Key for global configuration.
Definition: SickLD.hh:178
double GetSickScanResolution() const
Acquire the Sick LD&#39;s current scan resolution.
Definition: SickLD.cc:1347
std::string GetSickGlobalConfigAsString() const
Acquire the Sick LD&#39;s global config as a printable string.
Definition: SickLD.cc:1543
std::string _sickTransMeasureReturnToString(const uint8_t return_value) const
Converts return value from TRANS_MEASURE to a representative string.
Definition: SickLD.cc:4666
Thrown when error occurs during thread initialization, and uninitialization.
std::string GetSickStatusAsString() const
Acquire the Sick LD&#39;s status as a printable string.
Definition: SickLD.cc:1500
void GetSickStatus(unsigned int &sick_sensor_mode, unsigned int &sick_motor_mode)
Acquires the status of the Sick from the device.
Definition: SickLD.cc:146
static const uint8_t SICK_CONF_SERV_SET_TIME_ABSOLUTE
Set the internal clock to a timestamp value.
Definition: SickLD.hh:121
bool _supportedScanProfileFormat(const uint16_t profile_format) const
Check that the given profile format is supported by the current driver version.
Definition: SickLD.cc:4540
void _getSickEthernetConfig()
Get the Sick LD&#39;s Ethernet configuration.
Definition: SickLD.cc:3192
static const uint8_t SICK_STAT_SERV_GET_STATUS
Request status information.
Definition: SickLD.hh:100
static const uint8_t SICK_CONF_SERV_SET_FUNCTION
Assigns a measurement function to an angle range.
Definition: SickLD.hh:125


sicktoolbox
Author(s): Jason Derenick , Thomas Miller
autogenerated on Tue Sep 10 2019 03:37:34