Revision: 6544
http://playerstage.svn.sourceforge.net/playerstage/?rev=6544&view=rev
Author: thjc
Date: 2008-06-11 13:54:18 -0700 (Wed, 11 Jun 2008)
Log Message:
-----------
cleaned up position mode entry code
added reflector radius as property
added optional odometry input and 'PM' mdoe recovery from stall
changed logging code to not log time deltas in reverse
changed commands to not overwrite
fixed return for propset
Modified Paths:
--------------
code/player/branches/release-2-1-patches/server/drivers/position/nav200/sicknav200.cc
Modified:
code/player/branches/release-2-1-patches/server/drivers/position/nav200/sicknav200.cc
===================================================================
---
code/player/branches/release-2-1-patches/server/drivers/position/nav200/sicknav200.cc
2008-06-11 20:49:48 UTC (rev 6543)
+++
code/player/branches/release-2-1-patches/server/drivers/position/nav200/sicknav200.cc
2008-06-11 20:54:18 UTC (rev 6544)
@@ -20,7 +20,7 @@
*
*/
/*
- Desc: Driver for the SICK S3000 laser
+ Desc: Driver for the SICK NAV200 laser localisation system
Author: Toby Collett (based on lms200 by Andrew Howard)
Date: 7 Nov 2000
CVS: $Id$
@@ -143,8 +143,10 @@
int Initialise();
bool Initialised;
-
-
+
+ // set device to positioning mode and set positioning mode parameters
+ int EnterPositioning();
+
// Get device to map reflectors.
void UpdateMap();
// Get the reflector positions from the device.
@@ -177,6 +179,7 @@
uint8_t* wkbData;
uint32_t wkbSize;
player_pose2d_t speed;
+ player_pose2d_t odo_pos;
double navAngle;
// If mode is set to mapping the reflector positions will be mapped,
@@ -199,7 +202,10 @@
// number of values for slifing mean
IntProperty SmoothingInput;
-
+
+ // radius of the reflectors in meters
+ DoubleProperty ReflectorRadius;
+
// storage for outgoing data
player_position2d_data_t data_packet;
@@ -207,16 +213,20 @@
Nav200 Laser;
int min_radius, max_radius;
- // Reflector Map Driver info
+ // Reflector Map Device info
// Provides reflector positions if not mapped by nav200
Device *reflector_map;
player_devaddr_t reflector_map_id;
- // Velocity Driver info
+ // Velocity Device info
Device *velocity;
player_devaddr_t velocity_id;
- // Opaque Driver info
+ // Odometry Device info
+ Device *odometry;
+ player_devaddr_t odometry_addr;
+
+ // Opaque Device info
Device *opaque;
player_devaddr_t opaque_id;
@@ -257,7 +267,7 @@
////////////////////////////////////////////////////////////////////////////////
// Constructor
SickNAV200::SickNAV200(ConfigFile* cf, int section) :
- Driver(cf, section, true, PLAYER_MSGQUEUE_DEFAULT_MAXLEN),
+ Driver(cf, section, false),
Initialised(false),
mode("mode", DEFAULT_SICKNAV200_MODE, false, this, cf, section),
Nearest("nearest", 0, false, this, cf, section),
@@ -266,6 +276,7 @@
Quality("quality", 0,true, this, cf, section),
QualityThreshold("quality_threshold", 0,true, this, cf, section),
SmoothingInput("smoothing_input", 4, false, this, cf, section),
+ ReflectorRadius("relector_radius",0.45,false,this,cf,section),
NavUpdateRequestDelay("update_request_delay",DEFAULT_NAV_REQUEST_DELAY_USECS,false,this,cf,section),
TimingLogFilename("timing_log","",true,this,cf,section),
TimingLogFile(NULL)
@@ -334,14 +345,23 @@
this->velocity = NULL;
memset(&this->velocity_id, 0, sizeof(this->velocity_id));
cf->ReadDeviceAddr(&this->velocity_id, section, "requires",
- PLAYER_POSITION2D_CODE, -1, NULL);
+ PLAYER_POSITION2D_CODE, -1, "velocity");
+ PLAYER_MSG0(2, "reading odometry addr now");
+ this->odometry = NULL;
+ memset(&this->odometry_addr, 0, sizeof(this->odometry_addr));
+ cf->ReadDeviceAddr(&this->odometry_addr, section, "requires",
+ PLAYER_POSITION2D_CODE, -1, "odometry");
+
+
PLAYER_MSG0(2, "reading reflector map id now");
this->reflector_map = NULL;
memset(&this->reflector_map_id, 0, sizeof(this->reflector_map_id));
cf->ReadDeviceAddr(&this->reflector_map_id, section, "requires",
PLAYER_VECTORMAP_CODE, -1, NULL);
+
+
return;
}
@@ -372,6 +392,7 @@
return (-1);
}
+ // subscribe to velocity if it was provided, but we wait for the
odometry otherwise we create a recursive subscription list
if (this->velocity_id.interf == PLAYER_POSITION2D_CODE) // Velocity is
provided.
{
if (!(this->velocity =
deviceTable->GetDevice(this->velocity_id))) {
@@ -384,7 +405,7 @@
return (-1);
}
}
-
+
if (this->reflector_map_id.interf == PLAYER_VECTORMAP_CODE) //
Reflector positions are provided.
{
if (!(this->reflector_map
@@ -457,6 +478,15 @@
return 0;
}
+ if (Message::MatchMessage(hdr, PLAYER_MSGTYPE_DATA,
+ PLAYER_POSITION2D_DATA_STATE, odometry_addr)) {
+ player_position2d_data_t * recv =
+ reinterpret_cast<player_position2d_data_t * >
(data);
+ odo_pos = recv->pos;
+ return 0;
+ }
+
+
if (Message::MatchMessage(hdr, PLAYER_MSGTYPE_REQ,
PLAYER_POSITION2D_REQ_GET_GEOM, this->position_addr)) {
player_position2d_geom_t geom= { { 0 } };
@@ -593,6 +623,7 @@
this->Publish(hdr->addr, resp_queue, PLAYER_MSGTYPE_RESP_ACK,
PLAYER_SET_INTPROP_REQ);
+ return 0;
}
// Don't know how to handle this message.
@@ -632,22 +663,12 @@
PLAYER_ERROR("unable to enter standby mode\n");
return -1;
}
- if (!Laser.SetReflectorRadius(0, 45)) {
+ if (!Laser.SetReflectorRadius(0, static_cast<int>
(ReflectorRadius*100))) {
PLAYER_ERROR("unable to set reflector radius\n");
return -1;
}
- if (!Laser.EnterPositioningInput(SmoothingInput)) {
- PLAYER_ERROR("unable to enter position mode\n");
+ if (EnterPositioning() <0)
return -1;
- }
- if (!Laser.SelectNearest(Nearest)) {
- PLAYER_ERROR("unable to set nearest reflector count\n");
- return -1;
- }
- if (!Laser.SetActionRadii(min_radius, max_radius)) {
- PLAYER_ERROR("failed to set action radii\n");
- return -1;
- }
BuildWKB(); // Build an empty WKB.
@@ -667,10 +688,46 @@
}
+// set device to positioning mode and set positioning mode parameters
+int SickNAV200::EnterPositioning()
+{
+ if (!Laser.EnterPositioningInput(SmoothingInput)) {
+ PLAYER_ERROR("unable to enter position mode\n");
+ return -1;
+ }
+
+ if (!Laser.SelectNearest(Nearest)) {
+ PLAYER_ERROR("unable to set nearest reflector count\n");
+ return -1;
+ }
+ if (!Laser.SetActionRadii(min_radius, max_radius)) {
+ PLAYER_ERROR("failed to set action radii\n");
+ return -1;
+ }
+ return 0;
+}
+
+
////////////////////////////////////////////////////////////////////////////////
// Main function for device thread
void SickNAV200::Main() {
-
+ // The first thing we need to do is subscribe to the odometry
+ // this was delayed to now so we dont create dependency loops
+ // This does mean that we cannot fail as gracefully if we dont get the
subscription
+ // so instead we just continue without odometry if we dont get the
subscription
+ if (this->odometry_addr.interf == PLAYER_POSITION2D_CODE) // Velocity
is provided.
+ {
+ if (!(this->odometry =
deviceTable->GetDevice(this->odometry_addr))) {
+ PLAYER_ERROR("unable to locate suitable position2d
device for odometry");
+ }
+ else
+ {
+ if (this->odometry->Subscribe(this->InQueue) != 0) {
+ PLAYER_ERROR("unable to subscribe to position2d
device for odometry");
+ }
+ }
+ }
+
LaserPos Reading;
for (;;) {
// test if we are supposed to cancel
@@ -705,10 +762,11 @@
usleep(1000);
continue;
}
-
- if (velocity)
+
+ player_pose2d_t nav_vel_WCF = {0,0,0};
+ if (velocity)
{
- player_pose2d_t nav_vel_WCF = GetNavVelocityInWRF();
+ nav_vel_WCF = GetNavVelocityInWRF();
short pa_in_bdeg = static_cast<short> (nav_vel_WCF.pa *
32768.0 / M_PI);
//fprintf(stderr,"WCF: %f %f %f %04x\n",
nav_vel_WCF.px, nav_vel_WCF.py, nav_vel_WCF.pa, pa_in_bdeg);
gettimeofday(&last_nav_request_time,NULL);
@@ -742,25 +800,27 @@
data_packet.vel.py = speed.py;
// update our last request timestamp
- struct timeval previous_update = last_nav_position_time;
- gettimeofday(&last_nav_position_time,NULL);
+ struct timeval now;
+ gettimeofday(&now,NULL);
if (TimingLogFile)
{
// Log the following data:
- // TIMESTAMP, UPDATE_PERIOD, REQUEST_DELTA,
POSE, NAV_POSE, QUALITY, VELOCITY_DELTA, VELOCITY
- fprintf(TimingLogFile, "%f %f %f %f %f %f %d %d
%d %d %f %f %f %f\n",
-
time_double(last_nav_position_time),
- -static_cast<double>
(usec_diff(last_nav_position_time, previous_update))/1e6,
- -static_cast<double>
(usec_diff(last_nav_position_time, last_nav_request_time))/1e6,
+ // TIMESTAMP, UPDATE_PERIOD, REQUEST_DELTA,
POSE, NAV_POSE, QUALITY,NUM_REFLECTORS, VELOCITY_DELTA, VELOCITY,
VELOCITY_NAV_WRF
+ fprintf(TimingLogFile, "%f %f %f %f %f %f %d %d
%d %d %d %f %f %f %f %f %f %f\n",
+ time_double(now),
+ -static_cast<double>
(usec_diff(now, last_nav_position_time))/1e6,
+ static_cast<double>
(usec_diff(last_nav_position_time, last_nav_request_time))/1e6,
data_packet.pos.px,data_packet.pos.py,data_packet.pos.pa,
-
Reading.pos.x,Reading.pos.y,Reading.orientation,Reading.quality,
- -static_cast<double>
(usec_diff(last_nav_position_time, last_velocity_update_time))/1e6,
- speed.px,speed.py,speed.pa
+
Reading.pos.x,Reading.pos.y,Reading.orientation,Reading.quality,Reading.number,
+ static_cast<double>
(usec_diff(last_nav_position_time, last_velocity_update_time))/1e6,
+ speed.px,speed.py,speed.pa,
+
nav_vel_WCF.px,nav_vel_WCF.py,nav_vel_WCF.pa
);
fflush(TimingLogFile);
}
-
-
+ last_nav_position_time = now;
+
+
//printf("Got reading: quality %d\n", Reading.quality);
if (Reading.quality==0xFF || Reading.quality==0xFE
|| Reading.quality<=QualityThreshold) {
@@ -775,14 +835,21 @@
if (AutoFullMapCount != 0 && StallCount >
AutoFullMapCount)
{
PLAYER_WARN1("Stalled for %d readings,
performing full update\n", StallCount);
- if
(!Laser.EnterPositioningInput(SmoothingInput)) {
+ if (!EnterPositioning()) {
PLAYER_ERROR("NAV200: ERROR on attempt
to enter position mode, setting intialised false\n");
Initialised = false;
data_packet.stall =1;
continue;
}
}
-
+ else if (StallCount > 0)
+ {
+ short pa_in_bdeg = static_cast<short>
(odo_pos.pa * 32768.0 / M_PI);
+ // TODO: set layer to relevant ID once layer
support is added
+ PLAYER_MSG0(4,"NAV200 using odometry to try
recover position\n");
+ Laser.ChangeLayerDefPosition(0,static_cast<int>
(odo_pos.px*1000),static_cast<int> (odo_pos.py*1000),pa_in_bdeg);
+ }
+
} else {
PLAYER_WARN("Failed to get reading from laser
scanner\n");
Initialised = false;
@@ -843,7 +910,7 @@
BuildWKB(); // Update wkb to show new reflectors.
- if (!Laser.EnterPositioningInput(SmoothingInput)) {
+ if (!EnterPositioning()) {
PLAYER_ERROR("Unable to return to positioning mode after
mapping.\n");
return;
}
@@ -886,7 +953,7 @@
PLAYER_ERROR("Unable to return to standby mode after getting
reflectors.\n");
}
- if (!Laser.EnterPositioningInput(SmoothingInput)) {
+ if (!EnterPositioning()) {
PLAYER_ERROR("Unable to return to positioning mode after
getting reflectors.\n");
return;
}
@@ -977,7 +1044,7 @@
if (!Laser.EnterStandby())
PLAYER_ERROR("Unable to return to standby mode after getting
reflectors.\n");
- if (!Laser.EnterPositioningInput(SmoothingInput))
+ if (!EnterPositioning())
PLAYER_ERROR("Unable to return to positioning mode after
getting reflectors.\n");
}
This was sent by the SourceForge.net collaborative development platform, the
world's largest Open Source development site.
-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://sourceforge.net/services/buy/index.php
_______________________________________________
Playerstage-commit mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/playerstage-commit