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 }
#define IMPLEMENTS_GENERIC_SENSOR(class_name, NameSpace)
This must be inserted in all CGenericSensor classes implementation files:
#define MRPT_LOG_INFO_FMT(_FMT_STRING,...)
#define MRPT_LOG_ERROR_FMT(_FMT_STRING,...)
#define DEG2RAD
Definition: bits.h:112
A definition of a CStream actually representing a USB connection to a FTDI chip.
void ResetDevice()
Reset the USB device.
bool isOpen()
Checks whether the chip has been successfully open.
void SetTimeouts(unsigned long dwReadTimeout_ms, unsigned long dwWriteTimeout_ms)
Change read & write timeouts, in milliseconds.
void Close()
Close the USB device.
void SetLatencyTimer(unsigned char latency_ms)
Change the latency timer (in milliseconds) implemented on the FTDI chip: for a few ms,...
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 OpenBySerialNumber(const std::string &serialNumber)
Open by device serial number.
void processPreview(const mrpt::obs::CObservation2DRangeScan &obs)
Must be called inside the capture method to allow optional GUI preview of scans.
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).
void filterByExclusionAngles(mrpt::obs::CObservation2DRangeScan &obs) const
Mark as invalid those ranges in a set of forbiden angle ranges.
void filterByExclusionAreas(mrpt::obs::CObservation2DRangeScan &obs) const
Mark as invalid those points which (x,y) coordinates fall within the exclusion polygons.
std::string m_sensorLabel
See CGenericSensor.
This "software driver" implements the communication protocol for interfacing a SICK LMS2XX laser scan...
Definition: CSickLaserUSB.h:66
bool turnOff()
Disables the scanning mode (in this class this has no effect).
poses::CPose3D m_sensorPose
The sensor 6D pose:
Definition: CSickLaserUSB.h:79
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,...
bool turnOn()
Enables the scanning mode (in this class this has no effect).
bool waitContinuousSampleFrame(std::vector< float > &ranges, unsigned char &LMS_status, uint32_t &out_board_timestamp, bool &is_mm_mode)
mrpt::comms::CInterfaceFTDI * m_usbConnection
Definition: CSickLaserUSB.h:70
virtual ~CSickLaserUSB()
Destructor.
uint32_t m_timeStartUI
Time of the first data packet, for synchronization purposes.
Definition: CSickLaserUSB.h:74
mrpt::system::TTimeStamp m_timeStartTT
Definition: CSickLaserUSB.h:75
void loadConfig_sensorSpecific(const mrpt::utils::CConfigFileBase &configSource, const std::string &iniSection)
See the class documentation at the top for expected parameters.
A "CObservation"-derived class that represents a 2D range scan measurement (typically from a laser sc...
float maxRange
The maximum range allowed by the device, in meters (e.g.
float aperture
The "aperture" or field-of-view of the range finder, in radians (typically M_PI = 180 degrees).
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.
void resizeScan(const size_t len)
Resizes all data vectors to allocate a given number of scan rays.
void setScanRangeValidity(const size_t i, const bool val)
float stdError
The "sigma" error of the device in meters, used while inserting the scan in an occupancy grid.
void setScanRange(const size_t i, const float val)
std::string sensorLabel
An arbitrary label that can be used to identify the sensor.
Definition: CObservation.h:60
mrpt::system::TTimeStamp timestamp
The associated UTC time-stamp.
Definition: CObservation.h:58
A class used to store a 3D pose (a 3D translation + a rotation in 3D).
Definition: CPose3D.h:89
This class allows loading and storing values and vectors of different types from a configuration text...
std::string read_string(const std::string &section, const std::string &name, const std::string &defaultValue, bool failIfNotFound=false) const
float read_float(const std::string &section, const std::string &name, float defaultValue, bool failIfNotFound=false) const
GLenum GLint GLuint mask
Definition: glext.h:4050
GLdouble s
Definition: glext.h:3676
GLsizei const GLchar ** string
Definition: glext.h:4101
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
mrpt::system::TTimeStamp secondsToTimestamp(const double nSeconds)
Transform a time interval (in seconds) into TTimeStamp (e.g.
Definition: datetime.cpp:223
uint64_t TTimeStamp
A system independent time type, it holds the the number of 100-nanosecond intervals since January 1,...
Definition: datetime.h:32
mrpt::system::TTimeStamp now()
A shortcut for system::getCurrentTime.
Definition: datetime.h:76
#define MRPT_START
Definition: mrpt_macros.h:425
#define MRPT_END
Definition: mrpt_macros.h:429
#define M_PIf
Definition: mrpt_macros.h:440
Serial and networking devices and utilities.
Contains classes for various device interfaces.
This namespace contains representation of robot actions and observations.
Classes for 2D/3D geometry representation, both of single values and probability density distribution...
Definition: CPoint.h:18
Classes for serialization, sockets, ini-file manipulation, streams, list of properties-values,...
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
std::string format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
Definition: format.cpp:19
unsigned __int16 uint16_t
Definition: rptypes.h:44
unsigned __int32 uint32_t
Definition: rptypes.h:47



Page generated by Doxygen 1.9.1 for MRPT 1.9.9 Git: 63ea9d1f1 Thu Nov 23 00:06:53 2017 +0100 at mar 26 may 2026 12:19:29 CEST