Main MRPT website > C++ reference for MRPT 1.9.9
CSickLaserUSB.cpp
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | http://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2017, Individual contributors, see AUTHORS file |
6  | See: http://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See details in http://www.mrpt.org/License |
8  +------------------------------------------------------------------------+ */
9 
10 #include "hwdrivers-precomp.h" // Precompiled headers
11 
12 #include <mrpt/utils/CStream.h>
13 #include <mrpt/utils/utils_defs.h>
14 #include <mrpt/system/os.h>
15 #include <mrpt/utils/crc.h>
17 
18 #ifdef MRPT_OS_WINDOWS
19 #include <windows.h>
20 #endif
21 
23 
24 using namespace std;
25 using namespace mrpt;
26 using namespace mrpt::utils;
27 using namespace mrpt::comms;
28 using namespace mrpt::obs;
29 using namespace mrpt::hwdrivers;
30 using namespace mrpt::poses;
31 
32 /*-------------------------------------------------------------
33  CSickLaserUSB
34 -------------------------------------------------------------*/
35 CSickLaserUSB::CSickLaserUSB()
36  : m_usbConnection(nullptr), m_serialNumber("LASER001"), m_timeStartUI(0)
37 {
39  m_sensorLabel = "SICKLMS";
41  MRPT_END
42 }
43 
44 /*-------------------------------------------------------------
45  ~CSickLaserUSB
46 -------------------------------------------------------------*/
48 {
49  delete m_usbConnection;
50  m_usbConnection = nullptr;
51 }
52 
53 /*-------------------------------------------------------------
54  doProcessSimple
55 -------------------------------------------------------------*/
57  bool& outThereIsObservation,
58  mrpt::obs::CObservation2DRangeScan& outObservation, bool& hardwareError)
59 {
60  outThereIsObservation = false;
61  hardwareError = false;
62 
64  {
65  hardwareError = true;
66  return;
67  }
68 
69  vector<float> ranges;
70  unsigned char LMS_stat;
71  uint32_t board_timestamp;
72  bool is_mm_mode;
73 
75 
76  // Wait for a scan:
78  ranges, LMS_stat, board_timestamp, is_mm_mode))
79  return;
80 
81  // Yes, we have a new scan:
82 
83  // -----------------------------------------------
84  // Extract the observation:
85  // -----------------------------------------------
86  uint32_t AtUI = 0;
87  if (m_timeStartUI == 0)
88  {
89  m_timeStartUI = board_timestamp;
91  }
92  else
93  AtUI = board_timestamp - m_timeStartUI;
94 
96  mrpt::system::secondsToTimestamp(AtUI * 1e-3 /* Board time is ms */);
97  outObservation.timestamp =
98  m_timeStartTT + AtDO -
100  0.05); // 50 ms delay for scan sending from the scanner
101 
102  outObservation.sensorLabel = m_sensorLabel; // Set label
103 
104  // Extract the timestamp of the sensor:
105 
106  // And the scan ranges:
107  outObservation.rightToLeft = true;
108  outObservation.aperture = M_PIf;
109  outObservation.maxRange = is_mm_mode ? 32.7 : 81.0;
110  outObservation.stdError = 0.003f;
111  outObservation.sensorPose = m_sensorPose;
112 
113  outObservation.resizeScan(ranges.size());
114 
115  for (size_t i = 0; i < ranges.size(); i++)
116  {
117  outObservation.setScanRange(i, ranges[i]);
118  outObservation.setScanRangeValidity(
119  i, (ranges[i] <= outObservation.maxRange));
120  }
121 
122  // Do filter:
125  // Do show preview:
127 
128  outThereIsObservation = true;
129 }
130 
131 /*-------------------------------------------------------------
132  loadConfig_sensorSpecific
133 -------------------------------------------------------------*/
135  const mrpt::utils::CConfigFileBase& configSource,
136  const std::string& iniSection)
137 {
138  m_serialNumber = configSource.read_string(
139  iniSection, "SICKUSB_serialNumber", m_serialNumber);
141  configSource.read_float(iniSection, "pose_x", 0),
142  configSource.read_float(iniSection, "pose_y", 0),
143  configSource.read_float(iniSection, "pose_z", 0),
144  DEG2RAD(configSource.read_float(iniSection, "pose_yaw", 0)),
145  DEG2RAD(configSource.read_float(iniSection, "pose_pitch", 0)),
146  DEG2RAD(configSource.read_float(iniSection, "pose_roll", 0)));
147  // Parent options:
148  C2DRangeFinderAbstract::loadCommonParams(configSource, iniSection);
149 }
150 
151 /*-------------------------------------------------------------
152  turnOn
153 -------------------------------------------------------------*/
154 bool CSickLaserUSB::turnOn() { return true; }
155 /*-------------------------------------------------------------
156  turnOff
157 -------------------------------------------------------------*/
158 bool CSickLaserUSB::turnOff() { return true; }
159 /*-------------------------------------------------------------
160  checkControllerIsConnected
161 -------------------------------------------------------------*/
163 {
164  // If device is already open, thats ok:
165  if (m_usbConnection->isOpen()) return true;
166 
167  // If it isn't, try to open it now:
168  try
169  {
172  std::this_thread::sleep_for(10ms);
173  m_usbConnection->SetTimeouts(10, 20); // read, write, in milliseconds
174  std::this_thread::sleep_for(10ms);
175  m_usbConnection->SetLatencyTimer(1); // 1ms, the minimum
176  std::this_thread::sleep_for(10ms);
177 
179  "[CSickLaserUSB] USB DEVICE S/N:'%s' OPEN SUCCESSFULLY!!!\n",
180  m_serialNumber.c_str());
181  return true;
182  }
183  catch (std::exception& e)
184  {
186  "[CSickLaserUSB] ERROR TRYING TO OPEN USB DEVICE S/N:'%s'\n%s",
187  m_serialNumber.c_str(), e.what());
188  return false;
189  }
190 }
191 
192 /*-------------------------------------------------------------
193  waitContinuousSampleFrame
194 -------------------------------------------------------------*/
196  vector<float>& out_ranges_meters, unsigned char& LMS_status,
197  uint32_t& out_board_timestamp, bool& is_mm_mode)
198 {
199  size_t nRead, nBytesToRead;
200  size_t nFrameBytes = 0;
201  size_t lenghtField;
202  unsigned char buf[2000];
203  buf[2] = buf[3] = 0;
204 
205  while (nFrameBytes < (lenghtField = (6 + (buf[2] | (buf[3] << 8)))) +
206  5 /* for 32bit timestamp + end-flag */)
207  {
208  if (lenghtField > 800)
209  {
210  cout << "#";
211  nFrameBytes = 0; // No es cabecera de trama correcta
212  buf[2] = buf[3] = 0;
213  }
214 
215  if (nFrameBytes < 4)
216  nBytesToRead = 1;
217  else
218  nBytesToRead =
219  (5 /* for 32bit timestamp + end-flag */ + lenghtField) -
220  nFrameBytes;
221 
222  try
223  {
224  nRead = m_usbConnection->ReadSync(buf + nFrameBytes, nBytesToRead);
225  }
226  catch (std::exception& e)
227  {
228  // Disconnected?
230  "[CSickLaserUSB::waitContinuousSampleFrame] Disconnecting due "
231  "to comms error: %s\n",
232  e.what());
234  m_timeStartUI = 0;
235  return false;
236  }
237 
238  if (nRead == 0 && nFrameBytes == 0) return false;
239 
240  if (nRead > 0)
241  {
242  // Lectura OK:
243  // Era la primera?
244  if (nFrameBytes > 1 || (!nFrameBytes && buf[0] == 0x02) ||
245  (nFrameBytes == 1 && buf[1] == 0x80))
246  nFrameBytes += nRead;
247  else
248  {
249  nFrameBytes = 0; // No es cabecera de trama correcta
250  buf[2] = buf[3] = 0;
251  }
252  }
253  }
254 
255  // Frame received
256  // --------------------------------------------------------------------------
257  // | STX | ADDR | L1 | L2 | COM | INF1 | INF2 | DATA | STA | CRC1 | CRC2
258  // |
259  // --------------------------------------------------------------------------
260 
261  // Trama completa:
262  // Checkear que el byte de comando es 0xB0:
263  if (buf[4] != 0xB0) return false;
264 
265  // GET FRAME INFO
266  int info = buf[5] | (buf[6] << 8); // Little Endian
267  int n_points = info & 0x01FF;
268  is_mm_mode = 0 != ((info & 0xC000) >> 14); // 0x00: cm 0x01: mm
269 
270  out_ranges_meters.resize(n_points);
271 
272  // Copiar rangos:
273  short mask = is_mm_mode ? 0x7FFF : 0x1FFF;
274  float meters_scale = is_mm_mode ? 0.001f : 0.01f;
275 
276  for (int i = 0; i < n_points; i++)
277  out_ranges_meters[i] =
278  ((buf[7 + i * 2] | (buf[8 + i * 2] << 8)) & mask) * meters_scale;
279 
280  // Status
281  LMS_status = buf[lenghtField - 3];
282 
283  // End frame:
284  if (buf[nFrameBytes - 1] != 0x55)
285  {
286 // cerr << format("[CSickLaserUSB::waitContinuousSampleFrame] bad end flag") <<
287 // endl;
288 #ifdef MRPT_OS_WINDOWS
289  OutputDebugStringA(
290  "[CSickLaserUSB::waitContinuousSampleFrame] bad end flag\n");
291 #endif
292  return false; // Bad CRC
293  }
294 
295  // CRC:
296  const uint16_t CRC = mrpt::utils::compute_CRC16(buf, lenghtField - 2);
297  const uint16_t CRC_packet =
298  buf[lenghtField - 2] | (buf[lenghtField - 1] << 8);
299  if (CRC_packet != CRC)
300  {
301  const string s = format(
302  "[CSickLaserUSB::waitContinuousSampleFrame] bad CRC len=%u "
303  "nptns=%u: %i != %i\n",
304  unsigned(lenghtField), unsigned(n_points), CRC_packet, CRC);
305  cerr << s;
306 #ifdef MRPT_OS_WINDOWS
307  OutputDebugStringA(s.c_str());
308 #endif
309  return false; // Bad CRC
310  }
311 
312  // Get USB board timestamp:
313  out_board_timestamp = (uint32_t(buf[nFrameBytes - 5]) << 24) |
314  (uint32_t(buf[nFrameBytes - 4]) << 16) |
315  (uint32_t(buf[nFrameBytes - 3]) << 8) |
316  uint32_t(buf[nFrameBytes - 2]);
317 
318  // All OK
319  return true;
320 }
uint64_t TTimeStamp
A system independent time type, it holds the the number of 100-nanosecond intervals since January 1...
Definition: datetime.h:32
void doProcessSimple(bool &outThereIsObservation, mrpt::obs::CObservation2DRangeScan &outObservation, bool &hardwareError)
Specific laser scanner "software drivers" must process here new data from the I/O stream...
virtual ~CSickLaserUSB()
Destructor.
bool isOpen()
Checks whether the chip has been successfully open.
GLenum GLint GLuint mask
Definition: glext.h:4050
uint32_t m_timeStartUI
Time of the first data packet, for synchronization purposes.
Definition: CSickLaserUSB.h:74
Classes for serialization, sockets, ini-file manipulation, streams, list of properties-values, timewatch, extensions to STL.
unsigned __int16 uint16_t
Definition: rptypes.h:44
void ResetDevice()
Reset the USB device.
float read_float(const std::string &section, const std::string &name, float defaultValue, bool failIfNotFound=false) const
void setScanRange(const size_t i, const float val)
std::string m_sensorLabel
See CGenericSensor.
This "software driver" implements the communication protocol for interfacing a SICK LMS2XX laser scan...
Definition: CSickLaserUSB.h:65
void OpenBySerialNumber(const std::string &serialNumber)
Open by device serial number.
mrpt::system::TTimeStamp now()
A shortcut for system::getCurrentTime.
Definition: datetime.h:76
Contains classes for various device interfaces.
std::string read_string(const std::string &section, const std::string &name, const std::string &defaultValue, bool failIfNotFound=false) const
STL namespace.
void filterByExclusionAreas(mrpt::obs::CObservation2DRangeScan &obs) const
Mark as invalid those points which (x,y) coordinates fall within the exclusion polygons.
float stdError
The "sigma" error of the device in meters, used while inserting the scan in an occupancy grid...
#define MRPT_LOG_ERROR_FMT(_FMT_STRING,...)
GLdouble s
Definition: glext.h:3676
bool turnOn()
Enables the scanning mode (in this class this has no effect).
void filterByExclusionAngles(mrpt::obs::CObservation2DRangeScan &obs) const
Mark as invalid those ranges in a set of forbiden angle ranges.
This class allows loading and storing values and vectors of different types from a configuration text...
float maxRange
The maximum range allowed by the device, in meters (e.g.
size_t ReadSync(void *Buffer, size_t Count)
Tries to read, raising no exception if not all the bytes are available, but raising one if there is s...
void Close()
Close the USB device.
void SetTimeouts(unsigned long dwReadTimeout_ms, unsigned long dwWriteTimeout_ms)
Change read & write timeouts, in milliseconds.
#define M_PIf
#define MRPT_END
mrpt::comms::CInterfaceFTDI * m_usbConnection
Definition: CSickLaserUSB.h:70
This namespace contains representation of robot actions and observations.
std::string format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
Definition: format.cpp:19
uint16_t compute_CRC16(const std::vector< uint8_t > &data, const uint16_t gen_pol=0x8005)
Computes the CRC16 checksum of a block of data.
Definition: crc.cpp:20
#define DEG2RAD
void loadCommonParams(const mrpt::utils::CConfigFileBase &configSource, const std::string &iniSection)
Should be call by derived classes at "loadConfig" (loads exclusion areas AND exclusion angles)...
GLsizei const GLchar ** string
Definition: glext.h:4101
#define IMPLEMENTS_GENERIC_SENSOR(class_name, NameSpace)
This must be inserted in all CGenericSensor classes implementation files:
Classes for 2D/3D geometry representation, both of single values and probability density distribution...
Definition: CPoint.h:17
#define MRPT_START
std::string sensorLabel
An arbitrary label that can be used to identify the sensor.
Definition: CObservation.h:60
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
mrpt::system::TTimeStamp timestamp
The associated UTC time-stamp.
Definition: CObservation.h:58
A "CObservation"-derived class that represents a 2D range scan measurement (typically from a laser sc...
A definition of a CStream actually representing a USB connection to a FTDI chip.
A class used to store a 3D pose (a 3D translation + a rotation in 3D).
Definition: CPose3D.h:88
void resizeScan(const size_t len)
Resizes all data vectors to allocate a given number of scan rays.
void processPreview(const mrpt::obs::CObservation2DRangeScan &obs)
Must be called inside the capture method to allow optional GUI preview of scans.
bool turnOff()
Disables the scanning mode (in this class this has no effect).
#define MRPT_LOG_INFO_FMT(_FMT_STRING,...)
float aperture
The "aperture" or field-of-view of the range finder, in radians (typically M_PI = 180 degrees)...
poses::CPose3D m_sensorPose
The sensor 6D pose:
Definition: CSickLaserUSB.h:79
mrpt::system::TTimeStamp secondsToTimestamp(const double nSeconds)
Transform a time interval (in seconds) into TTimeStamp (e.g.
Definition: datetime.cpp:223
Serial and networking devices and utilities.
void loadConfig_sensorSpecific(const mrpt::utils::CConfigFileBase &configSource, const std::string &iniSection)
See the class documentation at the top for expected parameters.
bool waitContinuousSampleFrame(std::vector< float > &ranges, unsigned char &LMS_status, uint32_t &out_board_timestamp, bool &is_mm_mode)
unsigned __int32 uint32_t
Definition: rptypes.h:47
void SetLatencyTimer(unsigned char latency_ms)
Change the latency timer (in milliseconds) implemented on the FTDI chip: for a few ms...
mrpt::poses::CPose3D sensorPose
The 6D pose of the sensor on the robot at the moment of starting the scan.
bool rightToLeft
The scanning direction: true=counterclockwise; false=clockwise.
mrpt::system::TTimeStamp m_timeStartTT
Definition: CSickLaserUSB.h:75
void setScanRangeValidity(const size_t i, const bool val)



Page generated by Doxygen 1.8.14 for MRPT 1.9.9 Git: ae4571287 Thu Nov 23 00:06:53 2017 +0100 at dom oct 27 23:51:55 CET 2019