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
[email protected]
https://lists.sourceforge.net/lists/listinfo/playerstage-commit