Revision: 8137 http://playerstage.svn.sourceforge.net/playerstage/?rev=8137&view=rev Author: gbiggs Date: 2009-07-27 06:31:32 +0000 (Mon, 27 Jul 2009)
Log Message: ----------- Backported hokuyo_aist driver Modified Paths: -------------- code/player/branches/release-2-1-patches/server/drivers/ranger/hokuyo_aist.cc Modified: code/player/branches/release-2-1-patches/server/drivers/ranger/hokuyo_aist.cc =================================================================== --- code/player/branches/release-2-1-patches/server/drivers/ranger/hokuyo_aist.cc 2009-07-26 20:48:48 UTC (rev 8136) +++ code/player/branches/release-2-1-patches/server/drivers/ranger/hokuyo_aist.cc 2009-07-27 06:31:32 UTC (rev 8137) @@ -6,7 +6,7 @@ * * This program is free software: you can redistribute it and/or modify it under the terms of the * GNU Lesser General Public License as published by the Free Software Foundation, either version - * 3 of the License, or (at your option) any later version. + * 2 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU @@ -43,19 +43,26 @@ @par Configuration requests + - PLAYER_RANGER_REQ_INTNS + - PLAYER_RANGER_REQ_POWER - PLAYER_RANGER_REQ_GET_GEOM - PLAYER_RANGER_REQ_GET_CONFIG - PLAYER_RANGER_REQ_SET_CONFIG - - PLAYER_RANGER_REQ_POWER - - Note: Only the min_angle, max_angle and frequency values can be configured using this request. - In addition, the frequency value must be equivalent to a suitable RPM value (see the hokuyo_aist - library documentation for suitable values). + - Note: Only the min_angle and max_angle values can be configured using this request. To change + the scanning frequency, use the speed_level property. @par Configuration file options + - get_intensities (boolean) + - Default: false + - Set to non-zero to get intensity data with each range scan on models that support it. This can + also be enabled/disabled using the PLAYER_RANGER_REQ_INTNS message. Note that the data + retrieval mode used to get intensity data requires that the scan is performed *after* the + command is received, so this will introduce a slight delay before the data is delivered. - portopts (string) - Default: "type=serial,device=/dev/ttyACM0,timeout=1" - - Options to create the Flexiport port with. + - Options to create the Flexiport port with. Note that any baud rate specified in this line + should be the scanner's startup baud rate. - pose (float 6-tuple: (m, m, m, rad, rad, rad)) - Default: [0.0 0.0 0.0 0.0 0.0 0.0] - Pose (x, y, z, roll, pitch, yaw) of the laser relative to its parent object (e.g. the robot). @@ -63,30 +70,41 @@ - Default: [0.0 0.0 0.0] - Size of the laser in metres. - min_angle (float, radians) - - Default: -2.08 rad (-119.0 degrees) + - Default: -4.0 rad (Will use laser default) - Minimum scan angle to return. Will be adjusted if outside the laser's scannable range. - max_angle (float, radians) - - Default: 2.08 rad (119.0 degrees) + - Default: 4.0 rad (Will use laser default) - Maximum scan angle to return. Will be adjusted if outside the laser's scannable range. - - frequency (float, Hz) - - Default: 10Hz - - The frequency at which the laser operates. This must be equivalent to a suitable RPM value. See - - the hokuyo_aist library documentation for suitable values. - power (boolean) - Default: true - If true, the sensor power will be switched on upon driver activation (i.e. when the first - client connects). Otherwise a power request must be made to turn it on before data will be - received. + client connects). Otherwise a power request must be made to turn it on before data will be + received. - verbose (boolean) - Default: false - Enable verbose debugging information in the underlying library. + - ignoreunknowns (boolean) + - Default: false + - Ignore unknown lines sent by the laser in response to sensor info request commands. @par Properties - - baudrate (integer) + - baud_rate (integer) - Default: 19200bps - Change the baud rate of the connection to the laser. See hokuyo_aist documentation for valid - values. + values. This is separate from the scanner's power-on default baud rate, which should be + specified in portopts. + - speed_level (integer, 0 to 10 or 99) + - Default: 0 + - The speed at which the laser operates, as a level down from maximum speed. See the hokuyo_aist + library documentation for suitable values. + - high_sensitivity (integer) + - Default: 0 + - Set to non-zero to enable high sensitivity mode on models that support it. + - min_dist (float, metres) + - Default: 0m + - Minimum possible distance. Below that means there is an error (a scratch on the laser for + instance). The reading is then adjusted to the average of the neighboring valid beams. @par Example @@ -110,7 +128,10 @@ #include <libplayercore/playercore.h> const int DEFAULT_BAUDRATE = 19200; -const int DEFAULT_SPEED = 600; +const int DEFAULT_SPEED_LEVEL = 0; +const int DEFAULT_SENSITIVITY = 0; +const int DEFAULT_GET_INTENSITIES = 0; +const double DEFAULT_MIN_DIST = 0.0; //////////////////////////////////////////////////////////////////////////////////////////////////// // Driver object @@ -132,10 +153,10 @@ bool AllocateDataSpace (void); // Configuration parameters - bool _verbose, _powerOnStartup; - int _frequency; + bool _verbose, _powerOnStartup, _getIntensities, _ignoreUnknowns; double _minAngle, _maxAngle; - IntProperty _baudRate; + IntProperty _baudRate, _speedLevel, _highSensitivity; + DoubleProperty _minDist; std::string _portOpts; // Geometry player_ranger_geom_t _geom; @@ -146,6 +167,8 @@ // Data storage hokuyo_aist::HokuyoData _data; double *_ranges; + double *_intensities; + int _numRanges; }; //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -154,17 +177,25 @@ HokuyoDriver::HokuyoDriver (ConfigFile* cf, int section) : Driver (cf, section, false, PLAYER_MSGQUEUE_DEFAULT_MAXLEN, PLAYER_RANGER_CODE), - _baudRate ("baudrate", DEFAULT_BAUDRATE, false), _ranges (NULL) + _baudRate ("baud_rate", DEFAULT_BAUDRATE, false), + _speedLevel ("speed_level", DEFAULT_SPEED_LEVEL, false), + _highSensitivity ("high_sensitivity", DEFAULT_SENSITIVITY, false), + _minDist ("min_dist", DEFAULT_MIN_DIST, false), + _ranges (NULL), _intensities (NULL) { - // Get the baudrate and motor speed - RegisterProperty ("baudrate", &_baudRate, cf, section); + // Get the baudrate, speed and sensitivity + RegisterProperty ("baud_rate", &_baudRate, cf, section); + RegisterProperty ("speed_level", &_speedLevel, cf, section); + RegisterProperty ("high_sensitivity", &_highSensitivity, cf, section); + RegisterProperty ("min_dist", &_minDist, cf, section); // Get config - _minAngle = cf->ReadFloat (section, "min_angle", -2.08); - _maxAngle = cf->ReadFloat (section, "max_angle", 2.08); - _frequency = cf->ReadInt (section, "frequency", 10); + _getIntensities = cf->ReadBool (section, "get_intensities", false); + _minAngle = cf->ReadFloat (section, "min_angle", -4.0); + _maxAngle = cf->ReadFloat (section, "max_angle", 4.0); _portOpts = cf->ReadString (section, "portopts", "type=serial,device=/dev/ttyACM0,timeout=1"); _verbose = cf->ReadBool (section, "verbose", false); + _ignoreUnknowns = cf->ReadBool (section, "ignoreunknowns", false); _powerOnStartup = cf->ReadBool (section, "power", true); // Set up geometry information @@ -192,6 +223,8 @@ { if (_ranges != NULL) delete[] _ranges; + if (_intensities != NULL) + delete[] _intensities; } //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -203,13 +236,23 @@ if (_ranges != NULL) delete _ranges; - int numRanges = _device.AngleToStep (_maxAngle) - _device.AngleToStep (_minAngle) + 1; - if ((_ranges = new double[numRanges]) == NULL) + _numRanges = _device.AngleToStep (_maxAngle) - _device.AngleToStep (_minAngle) + 1; + if ((_ranges = new double[_numRanges]) == NULL) { - PLAYER_ERROR1 ("hokuyo_aist: Failed to allocate space for %d range readings.", numRanges); + PLAYER_ERROR1 ("hokuyo_aist: Failed to allocate space for %d range readings.", _numRanges); return false; } + if (_getIntensities) + { + if ((_intensities = new double[_numRanges]) == NULL) + { + PLAYER_ERROR1 ("hokuyo_aist: Failed to allocate space for %d intensity readings.", + _numRanges); + return false; + } + } + return true; } @@ -238,13 +281,15 @@ PLAYER_MSGTYPE_REQ, PLAYER_RANGER_REQ_SET_CONFIG); HANDLE_CAPABILITY_REQUEST (device_addr, resp_queue, hdr, data, PLAYER_MSGTYPE_REQ, PLAYER_RANGER_REQ_POWER); + HANDLE_CAPABILITY_REQUEST (device_addr, resp_queue, hdr, data, + PLAYER_MSGTYPE_REQ, PLAYER_RANGER_REQ_INTNS); // Property handlers that need to be done manually due to calling into the hokuyo_aist library. if (Message::MatchMessage (hdr, PLAYER_MSGTYPE_REQ, PLAYER_SET_INTPROP_REQ, this->device_addr)) { player_intprop_req_t *req = reinterpret_cast<player_intprop_req_t*> (data); // Change in the baud rate - if (strncmp (req->key, "baudrate", 8) == 0) + if (strncmp (req->key, "baud_rate", 9) == 0) { try { @@ -274,6 +319,46 @@ 0, NULL); return 0; } + else if (strncmp (req->key, "speed_level", 11) == 0) + { + try + { + _device.SetMotorSpeed (req->value); + } + catch (hokuyo_aist::HokuyoError &e) + { + PLAYER_ERROR2 ("hokuyo_aist: Error while changing motor speed: (%d) %s", + e.Code (), e.what ()); + SetError (e.Code ()); + Publish (device_addr, resp_queue, PLAYER_MSGTYPE_RESP_NACK, PLAYER_SET_INTPROP_REQ, + NULL, 0, NULL); + return 0; + } + _speedLevel.SetValueFromMessage (data); + Publish (device_addr, resp_queue, PLAYER_MSGTYPE_RESP_ACK, PLAYER_SET_INTPROP_REQ, NULL, + 0, NULL); + return 0; + } + else if (strncmp (req->key, "high_sensitivity", 16) == 0) + { + try + { + _device.SetHighSensitivity (req->value != 0); + } + catch (hokuyo_aist::HokuyoError &e) + { + PLAYER_ERROR2 ("hokuyo_aist: Error while changing sensitivity: (%d) %s", + e.Code (), e.what ()); + SetError (e.Code ()); + Publish (device_addr, resp_queue, PLAYER_MSGTYPE_RESP_NACK, PLAYER_SET_INTPROP_REQ, + NULL, 0, NULL); + return 0; + } + _highSensitivity.SetValueFromMessage (data); + Publish (device_addr, resp_queue, PLAYER_MSGTYPE_RESP_ACK, PLAYER_SET_INTPROP_REQ, NULL, + 0, NULL); + return 0; + } } // Standard ranger messages @@ -300,6 +385,32 @@ 0, NULL); return 0; } + else if (Message::MatchMessage (hdr, PLAYER_MSGTYPE_REQ, PLAYER_RANGER_REQ_INTNS, device_addr)) + { + bool newValue = (reinterpret_cast<player_ranger_intns_config_t*> (data)->state != 0); + if (newValue && !_getIntensities) + { + // State change, allocate space for intensity data + if ((_intensities = new double[_numRanges]) == NULL) + { + PLAYER_ERROR1 ("hokuyo_aist: Failed to allocate space for %d intensity readings.", + _numRanges); + Publish (device_addr, resp_queue, PLAYER_MSGTYPE_RESP_NACK, PLAYER_RANGER_REQ_INTNS, + NULL, 0, NULL); + return 0; + } + } + else if (!newValue && _getIntensities) + { + // State change, remove allocated space + delete[] _intensities; + _intensities = NULL; + } + _getIntensities = newValue; + Publish (device_addr, resp_queue, PLAYER_MSGTYPE_RESP_ACK, PLAYER_RANGER_REQ_INTNS, NULL, + 0, NULL); + return 0; + } else if (Message::MatchMessage (hdr, PLAYER_MSGTYPE_REQ, PLAYER_RANGER_REQ_GET_GEOM, device_addr)) { @@ -339,7 +450,6 @@ return 0; } - _frequency = static_cast<int> (newParams->frequency); try { hokuyo_aist::HokuyoSensorInfo info; @@ -354,7 +464,6 @@ _maxAngle = info.maxAngle; PLAYER_WARN1 ("hokuyo_aist: Adjusted max_angle to %lf", _maxAngle); } - _device.SetMotorSpeed (_frequency * 60); } catch (hokuyo_aist::HokuyoError &e) { @@ -376,26 +485,79 @@ bool HokuyoDriver::ReadLaser (void) { - player_ranger_data_range_t rangeData; + if (_getIntensities) + { + player_ranger_data_range_t rangeData; + player_ranger_data_intns_t intensityData; - try - { - _device.GetRanges (&_data, _minAngle, _maxAngle); + try + { + _device.GetNewRangesAndIntensitiesByAngle (&_data, _minAngle, _maxAngle); + } + catch (hokuyo_aist::HokuyoError &e) + { + PLAYER_ERROR2 ("hokuyo_aist: Failed to read scan: (%d) %s", e.Code (), e.what ()); + SetError (e.Code ()); + return false; + } + + double lastValidValue = _minDist; + for (unsigned int ii = 0; ii < _data.Length (); ii++) + { + _ranges[ii] = _data[ii] / 1000.0f; + _intensities[ii] = _data.Intensities ()[ii]; + if (_minDist > 0) + { + if (_ranges[ii] < _minDist) + _ranges[ii] = lastValidValue; + else + lastValidValue = _ranges[ii]; + } + } + + rangeData.ranges = _ranges; + rangeData.ranges_count = _data.Length (); + Publish (device_addr, PLAYER_MSGTYPE_DATA, PLAYER_RANGER_DATA_RANGE, + reinterpret_cast<void*> (&rangeData), sizeof (rangeData), NULL); + + intensityData.intensities = _intensities; + intensityData.intensities_count = _data.Length (); + Publish (device_addr, PLAYER_MSGTYPE_DATA, PLAYER_RANGER_DATA_INTNS, + reinterpret_cast<void*> (&intensityData), sizeof (intensityData), NULL); } - catch (hokuyo_aist::HokuyoError &e) + else { - PLAYER_ERROR2 ("hokuyo_aist: Failed to read scan: (%d) %s", e.Code (), e.what ()); - SetError (e.Code ()); - return false; + player_ranger_data_range_t rangeData; + + try + { + _device.GetRangesByAngle (&_data, _minAngle, _maxAngle); + } + catch (hokuyo_aist::HokuyoError &e) + { + PLAYER_ERROR2 ("hokuyo_aist: Failed to read scan: (%d) %s", e.Code (), e.what ()); + SetError (e.Code ()); + return false; + } + + double lastValidValue = _minDist; + for (unsigned int ii = 0; ii < _data.Length (); ii++) + { + _ranges[ii] = _data[ii] / 1000.0f; + if (_minDist > 0) + { + if (_ranges[ii] < _minDist) + _ranges[ii] = lastValidValue; + else + lastValidValue = _ranges[ii]; + } + } + rangeData.ranges = _ranges; + rangeData.ranges_count = _data.Length (); + Publish (device_addr, PLAYER_MSGTYPE_DATA, PLAYER_RANGER_DATA_RANGE, + reinterpret_cast<void*> (&rangeData), sizeof (rangeData), NULL); } - for (unsigned int ii = 0; ii < _data.Length (); ii++) - _ranges[ii] = _data[ii] / 1000.0f; - rangeData.ranges = _ranges; - rangeData.ranges_count = _data.Length (); - Publish (device_addr, PLAYER_MSGTYPE_DATA, PLAYER_RANGER_DATA_RANGE, - reinterpret_cast<void*> (&rangeData), sizeof (rangeData), NULL); - return true; } @@ -403,8 +565,9 @@ { try { + _device.IgnoreUnknowns (_ignoreUnknowns); // Open the laser - _device.Open (_portOpts); + _device.OpenWithProbing (_portOpts); // Get the sensor information and check _minAngle and _maxAngle are OK hokuyo_aist::HokuyoSensorInfo info; _device.GetSensorInfo (&info); @@ -430,10 +593,29 @@ } catch (hokuyo_aist::HokuyoError &e) { - if (e.Code () != hokuyo_aist::HOKUYO_ERR_NOTSERIAL) - throw; - PLAYER_WARN ("hokuyo_aist: Cannot change the baud rate of a non-serial connection."); + if (e.Code () == hokuyo_aist::HOKUYO_ERR_NOTSERIAL) + PLAYER_WARN ("hokuyo_aist: Cannot change the baud rate of a non-serial connection."); + else + PLAYER_WARN2 ("hokuyo_aist: Error changing baud rate: (%d) %s", e.Code (), e.what ()); } + try + { + // Catch any errors here as this is an optional setting not supported by all models + _device.SetMotorSpeed (_speedLevel.GetValue ()); + } + catch (hokuyo_aist::HokuyoError &e) + { + PLAYER_WARN2 ("hokuyo_aist: Unable to set motor speed: (%d) %s", e.Code (), e.what ()); + } + try + { + // Optional setting + _device.SetHighSensitivity (_highSensitivity.GetValue () != 0); + } + catch (hokuyo_aist::HokuyoError &e) + { + PLAYER_WARN2 ("hokuyo_aist: Unable to set sensitivity: (%d) %s", e.Code (), e.what ()); + } } catch (hokuyo_aist::HokuyoError &e) { @@ -453,7 +635,10 @@ _device.Close (); _data.CleanUp (); if (_ranges != NULL) + { delete[] _ranges; + _ranges = NULL; + } return 0; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. ------------------------------------------------------------------------------ _______________________________________________ Playerstage-commit mailing list Playerstage-commit@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/playerstage-commit