SickLIDAR.hh
Go to the documentation of this file.
1 
30 #ifndef SICK_LIDAR
31 #define SICK_LIDAR
32 
33 /* Definition dependencies */
34 #include <new>
35 #include <string>
36 #include <iomanip>
37 #include <iostream>
38 #include <fcntl.h>
39 #include <pthread.h>
40 #include <arpa/inet.h>
41 #include <sys/time.h>
42 #include <unistd.h>
43 #include "SickException.hh"
44 
45 /* Associate the namespace */
46 namespace SickToolbox {
47 
52  template < class SICK_MONITOR_CLASS, class SICK_MSG_CLASS >
53  class SickLIDAR {
54 
55  public:
56 
58  SickLIDAR( );
59 
61  bool IsInitialized() { return _sick_initialized; }
62 
64  virtual ~SickLIDAR( );
65 
66  protected:
67 
69  int _sick_fd;
70 
73 
75  SICK_MONITOR_CLASS *_sick_buffer_monitor;
76 
79 
81  virtual void _setupConnection( ) = 0;
82 
84  virtual void _teardownConnection( ) = 0;
85 
87  void _startListening( ) throw( SickThreadException );
88 
90  void _stopListening( ) throw( SickThreadException );
91 
93  bool _monitorRunning( ) const { return _sick_monitor_running; }
94 
96  void _setBlockingIO( ) const throw ( SickIOException );
97 
99  void _setNonBlockingIO( ) const throw ( SickIOException );
100 
102  void _sendMessage( const SICK_MSG_CLASS &sick_message, const unsigned int byte_interval ) const
103  throw( SickIOException );
104 
106  void _recvMessage( SICK_MSG_CLASS &sick_message, const unsigned int timeout_value ) const throw ( SickTimeoutException );
107 
109  void _recvMessage( SICK_MSG_CLASS &sick_message,
110  const uint8_t * const byte_sequence,
111  const unsigned int byte_sequence_length,
112  const unsigned int timeout_value ) const throw ( SickTimeoutException );
113 
115  double _computeElapsedTime( const struct timeval &beg_time, const struct timeval &end_time ) const { return ((end_time.tv_sec*1e6)+(end_time.tv_usec))-((beg_time.tv_sec*1e6)+beg_time.tv_usec); }
116 
118  virtual void _sendMessageAndGetReply( const SICK_MSG_CLASS &send_message,
119  SICK_MSG_CLASS &recv_message,
120  const uint8_t * const byte_sequence,
121  const unsigned int byte_sequence_length,
122  const unsigned int byte_interval,
123  const unsigned int timeout_value,
124  const unsigned int num_tries ) throw( SickTimeoutException, SickIOException);
125 
126  };
127 
131  template< class SICK_MONITOR_CLASS, class SICK_MSG_CLASS >
134 
135  try {
136  /* Attempt to instantiate a new SickBufferMonitor for the device */
137  _sick_buffer_monitor = new SICK_MONITOR_CLASS;
138  }
139  catch ( std::bad_alloc &allocation_exception ) {
140  std::cerr << "SickLIDAR::SickLIDAR: Allocation error - " << allocation_exception.what() << std::endl;
141  }
142 
143  }
144 
148  template< class SICK_MONITOR_CLASS, class SICK_MSG_CLASS >
150 
151  /* Deallocate the buffer monitor */
152  if (_sick_buffer_monitor) {
153  delete _sick_buffer_monitor;
154  }
155 
156  }
157 
161  template< class SICK_MONITOR_CLASS, class SICK_MSG_CLASS >
163 
164  /* Try to start the monitor */
165  try {
166  _sick_buffer_monitor->StartMonitor(_sick_fd);
167  }
168 
169  /* Handle a thread exception */
170  catch(SickThreadException &sick_thread_exception) {
171  std::cerr << sick_thread_exception.what() << std::endl;
172  throw;
173  }
174 
175  /* Handle a thread exception */
176  catch(...) {
177  std::cerr << "SickLIDAR::_startListening: Unknown exception!!!" << std::endl;
178  throw;
179  }
180 
181  /* Set the flag */
182  _sick_monitor_running = true;
183 
184  }
185 
189  template< class SICK_MONITOR_CLASS, class SICK_MSG_CLASS >
191 
192  /* Try to start the monitor */
193  try {
194  _sick_buffer_monitor->StopMonitor();
195  }
196 
197  /* Handle a thread exception */
198  catch(SickThreadException &sick_thread_exception) {
199  std::cerr << sick_thread_exception.what() << std::endl;
200  throw;
201  }
202 
203  /* Handle a thread exception */
204  catch(...) {
205  std::cerr << "SickLIDAR::_stopListening: Unknown exception!!!" << std::endl;
206  throw;
207  }
208 
209  /* Reset the flag */
210  _sick_monitor_running = false;
211 
212  }
213 
217  template< class SICK_MONITOR_CLASS, class SICK_MSG_CLASS >
219 
220  /* Read the flags */
221  int fd_flags = 0;
222  if((fd_flags = fcntl(_sick_fd,F_GETFL)) < 0) {
223  throw SickIOException("SickLIDAR::_setNonBlocking: fcntl failed!");
224  }
225 
226  /* Set the new flags */
227  if(fcntl(_sick_fd,F_SETFL,fd_flags & (~O_NONBLOCK)) < 0) {
228  throw SickIOException("SickLIDAR::_setNonBlocking: fcntl failed!");
229  }
230 
231  }
232 
236  template< class SICK_MONITOR_CLASS, class SICK_MSG_CLASS >
238 
239  /* Read the flags */
240  int fd_flags = 0;
241  if((fd_flags = fcntl(_sick_fd,F_GETFL)) < 0) {
242  throw SickIOException("SickLIDAR::_setNonBlockingIO: fcntl failed!");
243  }
244 
245  /* Set the new flags */
246  if(fcntl(_sick_fd,F_SETFL,fd_flags | O_NONBLOCK) < 0) {
247  throw SickIOException("SickLIDAR::_setNonBlockingIO: fcntl failed!");
248  }
249 
250  }
251 
257  template< class SICK_MONITOR_CLASS, class SICK_MSG_CLASS >
258  void SickLIDAR< SICK_MONITOR_CLASS, SICK_MSG_CLASS >::_sendMessage( const SICK_MSG_CLASS &sick_message, const unsigned int byte_interval ) const
259  throw( SickIOException ) {
260 
261  uint8_t message_buffer[SICK_MSG_CLASS::MESSAGE_MAX_LENGTH] = {0};
262 
263  /* Copy the given message and get the message length */
264  sick_message.GetMessage(message_buffer);
265  unsigned int message_length = sick_message.GetMessageLength();
266 
267  /* Check whether a transmission delay between bytes is requested */
268  if (byte_interval == 0) {
269 
270  /* Write the message to the stream */
271  if ((unsigned int)write(_sick_fd,message_buffer,message_length) != message_length) {
272  throw SickIOException("SickLIDAR::_sendMessage: write() failed!");
273  }
274 
275  }
276  else {
277 
278  /* Write the message to the unit one byte at a time */
279  for (unsigned int i = 0; i < message_length; i++) {
280 
281  /* Write a single byte to the stream */
282  if (write(_sick_fd,&message_buffer[i],1) != 1) {
283  throw SickIOException("SickLIDAR::_sendMessage: write() failed!");
284  }
285 
286  /* Some time between bytes (Sick LMS 2xx likes this) */
287  usleep(byte_interval);
288  }
289 
290  }
291 
292  }
293 
300  template< class SICK_MONITOR_CLASS, class SICK_MSG_CLASS >
302  const unsigned int timeout_value ) const throw ( SickTimeoutException ) {
303 
304  /* Timeval structs for handling timeouts */
305  struct timeval beg_time, end_time;
306 
307  /* Acquire the elapsed time since epoch */
308  gettimeofday(&beg_time,NULL);
309 
310  /* Check the shared object */
311  while(!_sick_buffer_monitor->GetNextMessageFromMonitor(sick_message)) {
312 
313  /* Sleep a little bit */
314  usleep(1000);
315 
316  /* Check whether the allowed time has expired */
317  gettimeofday(&end_time,NULL);
318  if (_computeElapsedTime(beg_time,end_time) > timeout_value) {
319  throw SickTimeoutException("SickLIDAR::_recvMessage: Timeout occurred!");
320  }
321 
322  }
323 
324  }
325 
336  template< class SICK_MONITOR_CLASS, class SICK_MSG_CLASS >
338  const uint8_t * const byte_sequence,
339  const unsigned int byte_sequence_length,
340  const unsigned int timeout_value ) const throw( SickTimeoutException ) {
341 
342  /* Define a buffer */
343  uint8_t payload_buffer[SICK_MSG_CLASS::MESSAGE_PAYLOAD_MAX_LENGTH];
344 
345  /* Timeval structs for handling timeouts */
346  struct timeval beg_time, end_time;
347 
348  /* A container for the message */
349  SICK_MSG_CLASS curr_message;
350 
351  /* Get the elapsed time since epoch */
352  gettimeofday(&beg_time,NULL);
353 
354  /* Check until it is found or a timeout */
355  for(;;) {
356 
357  /* Attempt to acquire the message */
358  unsigned int i = 0;
359  if (_sick_buffer_monitor->GetNextMessageFromMonitor(curr_message)) {
360 
361  /* Extract the payload subregion */
362  curr_message.GetPayloadSubregion(payload_buffer,0,byte_sequence_length-1);
363 
364  /* Match the byte sequence */
365  for (i=0; (i < byte_sequence_length) && (payload_buffer[i] == byte_sequence[i]); i++);
366 
367  /* Our message was found! */
368  if (i == byte_sequence_length) {
369  sick_message = curr_message;
370  break;
371  }
372 
373  }
374 
375  /* Sleep a little bit */
376  usleep(1000);
377 
378  /* Check whether the allowed time has expired */
379  gettimeofday(&end_time,NULL);
380  if (_computeElapsedTime(beg_time,end_time) > timeout_value) {
381  throw SickTimeoutException();
382  }
383 
384  }
385 
386  }
387 
395  template< class SICK_MONITOR_CLASS, class SICK_MSG_CLASS >
397  SICK_MSG_CLASS &recv_message,
398  const uint8_t * const byte_sequence,
399  const unsigned int byte_sequence_length,
400  const unsigned int byte_interval,
401  const unsigned int timeout_value,
402  const unsigned int num_tries )
404 
405  /* Send the message for at most num_tries number of times */
406  for(unsigned int i = 0; i < num_tries; i++) {
407 
408  try {
409 
410  /* Send the frame to the unit */
411  _sendMessage(send_message,byte_interval);
412 
413  /* Wait for the reply! */
414  _recvMessage(recv_message,byte_sequence,byte_sequence_length,timeout_value);
415 
416  /* message was found! */
417  break;
418 
419  }
420 
421  /* Handle a timeout! */
422  catch (SickTimeoutException &sick_timeout) {
423 
424  /* Check if it was found! */
425  if (i == num_tries - 1) {
426  throw SickTimeoutException("SickLIDAR::_sendMessageAndGetReply: Attempted max number of tries w/o success!");
427  }
428 
429  /* Display the number of tries remaining! */
430  std::cerr << sick_timeout.what() << " " << num_tries - i - 1 << " tries remaining" << std::endl;
431 
432  }
433 
434  /* Handle write buffer exceptions */
435  catch (SickIOException &sick_io_error) {
436  std::cerr << sick_io_error.what() << std::endl;
437  throw;
438  }
439 
440  /* A safety net */
441  catch (...) {
442  std::cerr << "SickLIDAR::_sendMessageAndGetReply: Unknown exception!!!" << std::endl;
443  throw;
444  }
445 
446  }
447 
448  }
449 
450 } /* namespace SickToolbox */
451 
452 #endif /* SICK_LIDAR */
void _recvMessage(SICK_MSG_CLASS &sick_message, const unsigned int timeout_value) const
Attempt to acquire the latest available message from the device.
Definition: SickLIDAR.hh:301
Contains some simple exception classes.
virtual void _setupConnection()=0
virtual const char * what() const
From the standard exception library.
void _stopListening()
Activates the buffer monitor for the driver.
Definition: SickLIDAR.hh:190
virtual ~SickLIDAR()
Destructor tears down buffer monitor.
Definition: SickLIDAR.hh:149
Provides an abstract parent for all Sick LIDAR devices.
Definition: SickLIDAR.hh:53
SICK_MONITOR_CLASS * _sick_buffer_monitor
Definition: SickLIDAR.hh:75
void _startListening()
Activates the buffer monitor for the driver.
Definition: SickLIDAR.hh:162
SickLIDAR()
Initializes the buffer monitor.
Definition: SickLIDAR.hh:132
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
Thrown instance where the driver can&#39;t read,write,drain,flush,... the buffers.
void _setBlockingIO() const
A simple method for setting blocking I/O.
Definition: SickLIDAR.hh:218
double _computeElapsedTime(const struct timeval &beg_time, const struct timeval &end_time) const
Definition: SickLIDAR.hh:115
virtual void _teardownConnection()=0
bool _monitorRunning() const
Definition: SickLIDAR.hh:93
Makes handling timeouts much easier.
void _setNonBlockingIO() const
A simple method for setting non-blocking I/O.
Definition: SickLIDAR.hh:237
void _sendMessage(const SICK_MSG_CLASS &sick_message, const unsigned int byte_interval) const
Sends a message to the Sick device.
Definition: SickLIDAR.hh:258
Thrown when error occurs during thread initialization, and uninitialization.


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