PageRenderTime 58ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 1ms

/src/hokuyo_aist/hokuyo_aist.h

https://github.com/naderman/gearbox
C Header | 511 lines | 193 code | 57 blank | 261 comment | 0 complexity | 335fbfd78c20309c1b0dd856bdc2ba4b MD5 | raw file
  1. /*
  2. * GearBox Project: Peer-Reviewed Open-Source Libraries for Robotics
  3. * http://gearbox.sf.net/
  4. * Copyright (c) 2008 Geoffrey Biggs
  5. *
  6. * hokuyo_aist Hokuyo laser scanner driver.
  7. *
  8. * This distribution is licensed to you under the terms described in the LICENSE file included in
  9. * this distribution.
  10. *
  11. * This work is a product of the National Institute of Advanced Industrial Science and Technology,
  12. * Japan. Registration number: H22PRO-1086.
  13. *
  14. * This file is part of hokuyo_aist.
  15. *
  16. * This software is licensed under the Eclipse Public License -v 1.0 (EPL). See
  17. * http://www.opensource.org/licenses/eclipse-1.0.txt
  18. */
  19. #ifndef __HOKUYO_AIST_H
  20. #define __HOKUYO_AIST_H
  21. #include <flexiport/port.h>
  22. #include <string>
  23. #if defined (WIN32)
  24. typedef unsigned char uint8_t;
  25. typedef unsigned int uint32_t;
  26. #if defined (HOKUYO_AIST_STATIC)
  27. #define HOKUYO_AIST_EXPORT
  28. #elif defined (HOKUYO_AIST_EXPORTS)
  29. #define HOKUYO_AIST_EXPORT __declspec (dllexport)
  30. #else
  31. #define HOKUYO_AIST_EXPORT __declspec (dllimport)
  32. #endif
  33. #else
  34. #include <stdint.h>
  35. #define HOKUYO_AIST_EXPORT
  36. #endif
  37. /** @ingroup gbx_library_hokuyo_aist
  38. @{
  39. */
  40. namespace hokuyo_aist
  41. {
  42. /// Hokuyo general error class.
  43. class HOKUYO_AIST_EXPORT HokuyoError : public std::exception
  44. {
  45. public:
  46. /** @brief Hokuyo error constructor.
  47. @param code Error code of the error.
  48. @param desc Description of the error. */
  49. HokuyoError (unsigned int code, std::string desc)
  50. : _errorCode (code), _errorDesc (desc)
  51. {}
  52. virtual ~HokuyoError () throw () {};
  53. virtual unsigned int Code () const throw ()
  54. {
  55. return _errorCode;
  56. }
  57. virtual const char* what () const throw ()
  58. {
  59. return _errorDesc.c_str ();
  60. }
  61. virtual std::string AsString () const throw();
  62. private:
  63. /** Error code. */
  64. unsigned int _errorCode;
  65. /** Error description. */
  66. std::string _errorDesc;
  67. };
  68. #if defined (WIN32)
  69. // Exporting data members on Windows is a bloody pain (they have to be initialised somewhere else),
  70. // so we'll use #define's on Win32 and lose the type safety.
  71. /// Read error while reading from the laser.
  72. #define HOKUYO_ERR_READ 1
  73. /// Write error while writing to the laser.
  74. #define HOKUYO_ERR_WRITE 2
  75. /// Error in the SCIP protocol.
  76. #define HOKUYO_ERR_PROTOCOL 3
  77. /// Error while changing baud rate.
  78. #define HOKUYO_ERR_CHANGEBAUD 4
  79. /// Failed to connect to the laser.
  80. #define HOKUYO_ERR_CONNECT_FAILED 5
  81. /// Failed to close a port.
  82. #define HOKUYO_ERR_CLOSE_FAILED 6
  83. /// No destination buffer provided for range readings.
  84. #define HOKUYO_ERR_NODESTINATION 7
  85. /// Bad firmware version.
  86. #define HOKUYO_ERR_BADFIRMWARE 8
  87. /// Unknown/unsupported SCIP protocol version.
  88. #define HOKUYO_ERR_SCIPVERSION 9
  89. /// Memory allocation error.
  90. #define HOKUYO_ERR_MEMORY 10
  91. /// Unsupported function error.
  92. #define HOKUYO_ERR_UNSUPPORTED 11
  93. /// Argument error
  94. #define HOKUYO_ERR_BADARG 12
  95. /// No data received error
  96. #define HOKUYO_ERR_NODATA 13
  97. /// Not a serial connection error
  98. #define HOKUYO_ERR_NOTSERIAL 14
  99. #else
  100. /// Read error while reading from the laser.
  101. const unsigned int HOKUYO_ERR_READ = 1;
  102. /// Write error while writing to the laser.
  103. const unsigned int HOKUYO_ERR_WRITE = 2;
  104. /// Error in the SCIP protocol.
  105. const unsigned int HOKUYO_ERR_PROTOCOL = 3;
  106. /// Error while changing baud rate.
  107. const unsigned int HOKUYO_ERR_CHANGEBAUD = 4;
  108. /// Failed to connect to the laser.
  109. const unsigned int HOKUYO_ERR_CONNECT_FAILED = 5;
  110. /// Failed to close a port.
  111. const unsigned int HOKUYO_ERR_CLOSE_FAILED = 6;
  112. /// No destination buffer provided for range readings.
  113. const unsigned int HOKUYO_ERR_NODESTINATION = 7;
  114. /// Bad firmware version.
  115. const unsigned int HOKUYO_ERR_BADFIRMWARE = 8;
  116. /// Unknown/unsupported SCIP protocol version.
  117. const unsigned int HOKUYO_ERR_SCIPVERSION = 9;
  118. /// Memory allocation error.
  119. const unsigned int HOKUYO_ERR_MEMORY = 10;
  120. /// Unsupported function error.
  121. const unsigned int HOKUYO_ERR_UNSUPPORTED = 11;
  122. /// Argument error
  123. const unsigned int HOKUYO_ERR_BADARG = 12;
  124. /// No data received error
  125. const unsigned int HOKUYO_ERR_NODATA = 13;
  126. /// Not a serial connection error
  127. const unsigned int HOKUYO_ERR_NOTSERIAL = 14;
  128. #endif // defined (WIN32)
  129. /** @brief Sensor information.
  130. Returned from a call to @GetSensorInfo. Contains various information about the laser scanner such as
  131. firmware version and maximum possible range. */
  132. class HOKUYO_AIST_EXPORT HokuyoSensorInfo
  133. {
  134. public:
  135. friend class HokuyoLaser;
  136. HokuyoSensorInfo ();
  137. HokuyoSensorInfo (const HokuyoSensorInfo &rhs);
  138. /// @brief Assignment operator.
  139. HokuyoSensorInfo& operator= (const HokuyoSensorInfo &rhs);
  140. /// @brief Format the entire object into a string.
  141. std::string AsString ();
  142. // Version details.
  143. /// Vendor name.
  144. std::string vendor;
  145. /// Product name.
  146. std::string product;
  147. /// Firmware version.
  148. std::string firmware;
  149. /// Protocol version in use.
  150. std::string protocol;
  151. /// Serial number of this device.
  152. std::string serial;
  153. // Specification details.
  154. /// Sensor model number.
  155. std::string model;
  156. /// Minimum detectable range (mm).
  157. unsigned int minRange;
  158. /// Maximum detectable range (mm).
  159. unsigned int maxRange;
  160. /// Number of steps in a 360-degree scan.
  161. unsigned int steps;
  162. /// First scanable step of a full scan.
  163. unsigned int firstStep;
  164. /// Last scanable step of a full scan.
  165. unsigned int lastStep;
  166. /// Step number that points forward (typically the centre of a full scan).
  167. unsigned int frontStep;
  168. /// Standard motor speed (rpm).
  169. unsigned int standardSpeed;
  170. // Status details.
  171. /// Operational status - illuminated or not.
  172. bool power;
  173. /// Current motor speed (rpm).
  174. unsigned int speed;
  175. /// Speed level (0 for default)
  176. unsigned short speedLevel;
  177. /// Measurement state.
  178. std::string measureState;
  179. /// Baud rate.
  180. unsigned int baud;
  181. /// Current sensor time (s).
  182. unsigned int time;
  183. /// Diagnostic status string.
  184. std::string sensorDiagnostic;
  185. // Calculated details
  186. /// Minimum possible scan angle (radians). Scans go anti-clockwise with negative angles on
  187. /// the right.
  188. double minAngle;
  189. /// Maximum possible scan angle (radians). Scans go anti-clockwise with negative angles on
  190. /// the right.
  191. double maxAngle;
  192. /// Angle between two scan points (radians).
  193. double resolution;
  194. /// Total number of steps in a full scan (lastStep - firstStep).
  195. unsigned int scanableSteps;
  196. private:
  197. void SetDefaults ();
  198. void CalculateValues ();
  199. };
  200. /** @brief Structure to store data returned from the laser scanner. */
  201. class HOKUYO_AIST_EXPORT HokuyoData
  202. {
  203. public:
  204. friend class HokuyoLaser;
  205. /// This constructor creates an empty HokuyoData with no data currently allocated.
  206. HokuyoData ();
  207. /// This constructor performs a deep copy of existing range data.
  208. HokuyoData (uint32_t *ranges, unsigned int length, bool error, unsigned int time);
  209. /// This constructor performs a deep copy of existing range and intensity data.
  210. HokuyoData (uint32_t *ranges, uint32_t *intensities, unsigned int length,
  211. bool error, unsigned int time);
  212. /// This copy constructor performs a deep copy of present data.
  213. HokuyoData (const HokuyoData &rhs);
  214. ~HokuyoData ();
  215. /** @brief Return a pointer to an array of range readings in millimetres.
  216. Values less than 20mm indicate an error. Check the error value for the data to see a
  217. probable cause for the error. Most of the time, it will just be an out-of-range reading. */
  218. const uint32_t* Ranges () const { return _ranges; }
  219. /// @brief Return a pointer to an array of intensity readings.
  220. const uint32_t* Intensities () const { return _intensities; }
  221. /// @brief Get the number of samples in the data.
  222. unsigned int Length () const { return _length; }
  223. /** @brief Indicates if one or more steps had an error.
  224. A step's value will be less than 20 if it had an error. Use @ref ErrorCodeToString to get
  225. a textual representation of the error. */
  226. bool GetErrorStatus () const { return _error; }
  227. /// @brief Return a string representing the error for the given error code.
  228. std::string ErrorCodeToString (uint32_t errorCode);
  229. /** @brief Get the time stamp of the data in milliseconds (only available using SCIP
  230. version 2). */
  231. unsigned int TimeStamp () const { return _time; }
  232. /// @brief Assignment operator.
  233. HokuyoData& operator= (const HokuyoData &rhs);
  234. /// @brief Subscript operator. Provides direct access to an element of the range data.
  235. uint32_t operator[] (unsigned int index);
  236. /// @brief Format the entire object into a string.
  237. std::string AsString ();
  238. /// @brief Force the data to clean up.
  239. void CleanUp ();
  240. protected:
  241. uint32_t *_ranges;
  242. uint32_t *_intensities;
  243. unsigned int _length;
  244. bool _error;
  245. unsigned int _time;
  246. bool _sensorIsUTM30LX;
  247. void AllocateData (unsigned int length, bool includeIntensities = false);
  248. };
  249. /** @brief Hokuyo laser scanner class.
  250. Provides an interface for interacting with a Hokuyo laser scanner using SCIP protocol version 1
  251. or 2. The FlexiPort library is used to implement the data communications with the scanner. See its
  252. documentation for details on controlling the connection.
  253. To use a serial connection, ensure that you do not also have a USB cable connected, as this will
  254. force the scanner into USB mode, preventing the serial connection from functioning correctly.
  255. All functions may throw instances of @ref HokuyoError or its children. Exceptions from
  256. @ref FlexiPort may also occur. */
  257. class HOKUYO_AIST_EXPORT HokuyoLaser
  258. {
  259. public:
  260. HokuyoLaser ();
  261. ~HokuyoLaser ();
  262. /// @brief Open the laser scanner and begin scanning.
  263. void Open (std::string portOptions);
  264. /** @brief Open the laser scanner and begin scanning, probing the baud rate as necessary.
  265. If the port is a serial connection and communication with the laser fails at the given
  266. baud rate, the alternative baud rates supported by the device are tried (see @ref SetBaud
  267. for these) in order from fastest to slowest.
  268. @return The baud rate at which connection with the laser succeeded, or 0 for non-serial
  269. connections. */
  270. unsigned int OpenWithProbing (std::string portOptions);
  271. /// @brief Close the connection to the laser scanner.
  272. void Close ();
  273. /// @brief Checks if the connection to the laser scanner is open.
  274. bool IsOpen () const;
  275. /// @brief Switch the laser scanner on or off.
  276. void SetPower (bool on);
  277. /** @brief Change the baud rate when using a serial connection.
  278. Valid rates are 19.2Kbps, 38.4Kbps, 57.6Kbps, 115.2Kbps, 250.0Kbps, 500.0Kbps, 750.0Kbps
  279. (dependent on those available in FlexiPort). */
  280. void SetBaud (unsigned int baud);
  281. /** @brief Reset the laser scanner to its default settings.
  282. Not available with the SCIP v1 protocol. */
  283. void Reset ();
  284. /** @brief Set the speed at which the scanner's sensor spins.
  285. Set the speed to 0 to have it reset to the default value, and 99 to reset it to the initial
  286. (startup) value. Values between 1 and 10 specify a ratio of the default speed. The speeds in
  287. revolutions per minute that these correspond to will depend on the scanner model. For
  288. example, for a URG-04LX, they are (from 1 to 10) 594, 588, 576, 570, 564, 558, 552, 546, and
  289. 540 rpm.
  290. Not available with the SCIP v1 protocol. */
  291. void SetMotorSpeed (unsigned int speed);
  292. /// @brief Switch the scanner between normal and high sensitivity modes.
  293. void SetHighSensitivity (bool on);
  294. /** @brief Get various information about the scanner.
  295. Much of the information is not available with the SCIP v1 protocol. */
  296. void GetSensorInfo (HokuyoSensorInfo *info);
  297. /** @brief Get the current value of the scanner's clock in milliseconds.
  298. Not available with the SCIP v1 protocol. */
  299. unsigned int GetTime ();
  300. /** @brief Get the latest scan data from the scanner.
  301. This function requires a pointer to a @ref HokuyoData object. It will allocate space in this
  302. object as necessary for storing range data. If the passed-in @ref HokuyoData object already
  303. has the correct quantity of space to store the range data, it will not be re-allocated. If
  304. it does not have any space, it will be allocated. If it has space, but it is the wrong size,
  305. it will be re-allocated. This means you can repeatedly send the same @ref HokuyoData object
  306. without having to worry about allocating its data, whether it will change or not, while also
  307. avoiding excessive allocations.
  308. @param data Pointer to a @ref HokuyoData object to store the range readings in.
  309. @param clusterCount The number of readings to cluster together into a single reading. The
  310. minimum value from a cluster is returned as the range for that cluster.
  311. @param startStep The first step to get ranges from. Set to -1 for the first scannable step.
  312. @param endStep The last step to get ranges from. Set to -1 for the last scannable step.
  313. @return The number of range readings read into @ref data. */
  314. unsigned int GetRanges (HokuyoData *data, int startStep = -1, int endStep = -1,
  315. unsigned int clusterCount = 1);
  316. /** @brief Get the latest scan data from the scanner.
  317. @param data Pointer to a @ref HokuyoData object to store the range readings in.
  318. @param startAngle The angle to get range readings from. Exclusive; if this falls between two
  319. steps the step inside the angle will be returned, but the step outside won't.
  320. @param endAngle The angle to get range readings to. Exclusive; if this falls between two
  321. steps the step inside the angle will be returned, but the step outside won't.
  322. @param clusterCount The number of readings to cluster together into a single reading. The
  323. minimum value from a cluster is returned as the range for that cluster.
  324. @return The number of range readings read into @ref data. */
  325. unsigned int GetRangesByAngle (HokuyoData *data, double startAngle, double endAngle,
  326. unsigned int clusterCount = 1);
  327. /** @brief Get a new scan from the scanner.
  328. Unlike @ref GetRanges, which returns the most recent scan the scanner took, this function
  329. will request a new scan. This means it will wait while the scanner performs the scan, which
  330. means the rate at which scans can be retrieved using this function is less than with @ref
  331. GetRanges. Otherwise behaves identicallty to @ref GetRanges.
  332. Not available with the SCIP v1 protocol.
  333. @note The command used to retrieve a fresh scan is also used for the continuous scanning
  334. mode (not yet supported by this library). After completing a scan, it will turn the laser
  335. off (in anticipation of another continuous scan command being sent, which will automatically
  336. turn the laser back on again). If you want to mix @ref GetNewRanges and @ref GetRanges, you
  337. will need to turn the laser on after each call to @ref GetNewRanges.
  338. @param data Pointer to a @ref HokuyoData object to store the range readings in.
  339. @param clusterCount The number of readings to cluster together into a single reading. The
  340. minimum value from a cluster is returned as the range for that cluster.
  341. @param startStep The first step to get ranges from. Set to -1 for the first scannable step.
  342. @param endStep The last step to get ranges from. Set to -1 for the last scannable step.
  343. @return The number of range readings read into @ref data. */
  344. unsigned int GetNewRanges (HokuyoData *data, int startStep = -1, int endStep = -1,
  345. unsigned int clusterCount = 1);
  346. /** @brief Get a new scan from the scanner.
  347. Not available with the SCIP v1 protocol.
  348. @param data Pointer to a @ref HokuyoData object to store the range readings in.
  349. @param startAngle The angle to get range readings from. Exclusive; if this falls between two
  350. steps the step inside the angle will be returned, but the step outside won't.
  351. @param endAngle The angle to get range readings to. Exclusive; if this falls between two
  352. steps the step inside the angle will be returned, but the step outside won't.
  353. @param clusterCount The number of readings to cluster together into a single reading. The
  354. minimum value from a cluster is returned as the range for that cluster.
  355. @return The number of range readings read into @ref data. */
  356. unsigned int GetNewRangesByAngle (HokuyoData *data, double startAngle, double endAngle,
  357. unsigned int clusterCount = 1);
  358. /** @brief Get a new scan from the scanner with intensity data.
  359. Unlike @ref GetRanges, which returns the most recent scan the scanner took, this function
  360. will request a new scan. This means it will wait while the scanner performs the scan.
  361. Otherwise behaves identicallty to @ref GetRanges.
  362. Not available with the SCIP v1 protocol.
  363. @note The command used to retrieve a fresh scan is also used for the continuous scanning
  364. mode (not yet supported by this library). After completing a scan, it will turn the laser
  365. off (in anticipation of another continuous scan command being sent, which will automatically
  366. turn the laser back on again). If you want to mix @ref GetNewRanges and @ref GetRanges, you
  367. will need to turn the laser on after each call to @ref GetNewRanges.
  368. @param data Pointer to a @ref HokuyoData object to store the range readings in.
  369. @param clusterCount The number of readings to cluster together into a single reading. The
  370. minimum value from a cluster is returned as the range for that cluster.
  371. @param startStep The first step to get ranges from. Set to -1 for the first scannable step.
  372. @param endStep The last step to get ranges from. Set to -1 for the last scannable step.
  373. @return The number of range readings read into @ref data. */
  374. unsigned int GetNewRangesAndIntensities (HokuyoData *data, int startStep = -1,
  375. int endStep = -1, unsigned int clusterCount = 1);
  376. /** @brief Get a new scan from the scanner with intensity data.
  377. Not available with the SCIP v1 protocol.
  378. @param data Pointer to a @ref HokuyoData object to store the range readings in.
  379. @param startAngle The angle to get range readings from. Exclusive; if this falls between two
  380. steps the step inside the angle will be returned, but the step outside won't.
  381. @param endAngle The angle to get range readings to. Exclusive; if this falls between two
  382. steps the step inside the angle will be returned, but the step outside won't.
  383. @param clusterCount The number of readings to cluster together into a single reading. The
  384. minimum value from a cluster is returned as the range for that cluster.
  385. @return The number of range readings read into @ref data. */
  386. unsigned int GetNewRangesAndIntensitiesByAngle (HokuyoData *data, double startAngle,
  387. double endAngle, unsigned int clusterCount = 1);
  388. /// @brief Return the major version of the SCIP protocol in use.
  389. uint8_t SCIPVersion () const { return _scipVersion; }
  390. /** @brief Turns on and off printing of verbose operating information to stderr. Default is
  391. off. */
  392. void SetVerbose (bool verbose) { _verbose = verbose; }
  393. /** @brief Enables/disables ignoring unknown lines in sensor info messages. Default is
  394. off. */
  395. void IgnoreUnknowns (bool ignore) { _ignoreUnknowns = ignore; }
  396. /// @brief A convenience function to convert a step index to an angle.
  397. double StepToAngle (unsigned int step);
  398. /// @brief A convenience function to convert an angle to a step (rounded towards the front).
  399. unsigned int AngleToStep (double angle);
  400. private:
  401. flexiport::Port *_port;
  402. uint8_t _scipVersion;
  403. bool _verbose, _sensorIsUTM30LX, _enableCheckSumWorkaround, _ignoreUnknowns;
  404. double _minAngle, _maxAngle, _resolution;
  405. int _firstStep, _lastStep, _frontStep;
  406. unsigned int _maxRange;
  407. void ClearReadBuffer ();
  408. int ReadLine (char *buffer, int expectedLength = -1);
  409. int ReadLineWithCheck (char *buffer, int expectedLength = -1, bool hasSemicolon = false);
  410. void SkipLines (int count);
  411. int SendCommand (const char *cmd, const char *param, int paramLength, const char *extraOK);
  412. void GetAndSetSCIPVersion ();
  413. void GetDefaults ();
  414. void ProcessVVLine (const char *buffer, HokuyoSensorInfo *info);
  415. void ProcessPPLine (const char *buffer, HokuyoSensorInfo *info);
  416. void ProcessIILine (const char *buffer, HokuyoSensorInfo *info);
  417. void Read2ByteRangeData (HokuyoData *data, unsigned int numSteps);
  418. void Read3ByteRangeData (HokuyoData *data, unsigned int numSteps);
  419. void Read3ByteRangeAndIntensityData (HokuyoData *data, unsigned int numSteps);
  420. int ConfirmCheckSum (const char *buffer, int length, int expectedSum);
  421. };
  422. } // namespace hokuyo_aist
  423. /** @} */
  424. #endif // __HOKUYO_AIST_H