Revision: 8228
http://playerstage.svn.sourceforge.net/playerstage/?rev=8228&view=rev
Author: gbiggs
Date: 2009-08-26 08:23:52 +0000 (Wed, 26 Aug 2009)
Log Message:
-----------
Applied patch #2843865: added ranger to writelog/readlog
Modified Paths:
--------------
code/player/trunk/server/drivers/shell/readlog.cc
code/player/trunk/server/drivers/shell/writelog.cc
Modified: code/player/trunk/server/drivers/shell/readlog.cc
===================================================================
--- code/player/trunk/server/drivers/shell/readlog.cc 2009-08-26 08:19:56 UTC
(rev 8227)
+++ code/player/trunk/server/drivers/shell/readlog.cc 2009-08-26 08:23:52 UTC
(rev 8228)
@@ -57,6 +57,7 @@
The readlog driver can provide the following device interfaces.
- @ref interface_laser
+- @ref interface_ranger
- @ref interface_position2d
- @ref interface_sonar
- @ref interface_wifi
@@ -158,6 +159,7 @@
#define strdup _strdup
#endif
+
#if 0
// we use this pointer to reset timestamps in the client objects when the
// log gets rewound
@@ -206,6 +208,11 @@
player_msghdr_t * hdr,
void * data);
+ // Process ranger interface configuration requests
+ private: int ProcessRangerConfig(QueuePointer & resp_queue,
+ player_msghdr_t * hdr,
+ void * data);
+
// Process sonar interface configuration requests
private: int ProcessSonarConfig(QueuePointer & resp_queue,
player_msghdr_t * hdr,
@@ -269,6 +276,12 @@
int linenum,
int token_count, char **tokens, double time);
+ // Parse ranger data
+ private: int ParseRanger(player_devaddr_t id,
+ unsigned short type, unsigned short subtype,
+ int linenum,
+ int token_count, char **tokens, double time);
+
// Parse localize data
private: int ParseLocalize(player_devaddr_t id, unsigned short type,
unsigned short subtype,
@@ -395,6 +408,12 @@
// Should we auto-rewind? This is set in the log devie in the .cfg
// file, and defaults to false
public: bool autorewind;
+
+ private: typedef struct {
+ player_ranger_geom_t* geom;
+ player_ranger_config_t* config;
+ } ranger_meta_t;
+
};
@@ -1024,6 +1043,76 @@
}
int
+ReadLog::ProcessRangerConfig(QueuePointer & resp_queue,
+ player_msghdr_t * hdr,
+ void * data)
+{
+ switch(hdr->subtype)
+ {
+ case PLAYER_RANGER_REQ_GET_GEOM:
+ {
+ // Find the right place from which to retrieve it
+ int j;
+ for(j=0;j<this->provide_count;j++)
+ {
+ if(Device::MatchDeviceAddress(this->provide_ids[j], hdr->addr))
+ break;
+ }
+ if(j>=this->provide_count)
+ {
+ puts("no matching device");
+ return(-1);
+ }
+
+ if(!this->provide_metadata[j])
+ {
+ puts("no metadata");
+ return(-1);
+ }
+
+ this->Publish(this->provide_ids[j], resp_queue,
+ PLAYER_MSGTYPE_RESP_ACK, hdr->subtype,
+ ((ranger_meta_t*)this->provide_metadata[j])->geom,
+ sizeof(player_ranger_geom_t),
+ NULL);
+ return(0);
+ }
+
+ case PLAYER_RANGER_REQ_GET_CONFIG:
+ {
+ // Find the right place from which to retrieve it
+ int j;
+ for(j=0;j<this->provide_count;j++)
+ {
+ if(Device::MatchDeviceAddress(this->provide_ids[j], hdr->addr))
+ break;
+ }
+ if(j>=this->provide_count)
+ {
+ puts("no matching device");
+ return(-1);
+ }
+
+ if(!this->provide_metadata[j])
+ {
+ puts("no metadata");
+ return(-1);
+ }
+
+ this->Publish(this->provide_ids[j], resp_queue,
+ PLAYER_MSGTYPE_RESP_ACK, hdr->subtype,
+ ((ranger_meta_t*)this->provide_metadata[j])->config,
+ sizeof(player_ranger_config_t),
+ NULL);
+ return(0);
+ }
+
+ default:
+ return(-1);
+ }
+}
+
+int
ReadLog::ProcessSonarConfig(QueuePointer & resp_queue,
player_msghdr_t * hdr,
void * data)
@@ -1147,6 +1236,11 @@
return(this->ProcessLaserConfig(resp_queue, hdr, data));
}
else if((hdr->type == PLAYER_MSGTYPE_REQ) &&
+ (hdr->addr.interf == PLAYER_RANGER_CODE))
+ {
+ return(this->ProcessRangerConfig(resp_queue, hdr, data));
+ }
+ else if((hdr->type == PLAYER_MSGTYPE_REQ) &&
(hdr->addr.interf == PLAYER_SONAR_CODE))
{
return(this->ProcessSonarConfig(resp_queue, hdr, data));
@@ -1258,6 +1352,9 @@
if (id.interf == PLAYER_LASER_CODE)
return this->ParseLaser(id, type, subtype, linenum,
token_count, tokens, time);
+ if (id.interf == PLAYER_RANGER_CODE)
+ return this->ParseRanger(id, type, subtype, linenum,
+ token_count, tokens, time);
else if (id.interf == PLAYER_FIDUCIAL_CODE)
return this->ParseFiducial(id, type, subtype, linenum,
token_count, tokens, time);
@@ -1681,55 +1778,7 @@
return ret;
}
- case PLAYER_LASER_DATA_SCANANGLE:
- {
- player_laser_data_scanangle_t data;
- if (token_count < 13)
- {
- PLAYER_ERROR2("incomplete line at %s:%d",
- this->filename,
linenum);
- return -1;
- }
-
- data.id = atoi(tokens[7]);
- data.max_range = static_cast<float> (atof(tokens[8]));
- data.ranges_count = atoi(tokens[9]);
- data.intensity_count = data.ranges_count;
- data.angles_count = data.ranges_count;
-
- data.ranges = new float[ data.ranges_count ];
- data.intensity = new uint8_t[ data.ranges_count ];
- data.angles = new float[ data.ranges_count ];
-
- count = 0;
- for (i = 10; i < token_count; i += 3)
- {
- data.ranges[count] = static_cast<float>
(atof(tokens[i + 0]));
- data.angles[count] = static_cast<float>
(atof(tokens[i + 1]));
- data.intensity[count] = atoi(tokens[i + 2]);
- count += 1;
- }
-
- if (count != (int)data.ranges_count)
- {
- PLAYER_ERROR2("range count mismatch at %s:%d",
- this->filename,
linenum);
- ret = -1;
- }
- else
- {
- this->Publish(id, static_cast<uint8_t>
(type), static_cast<uint8_t> (subtype),
- (void*)&data,
sizeof(data), &time);
- }
- delete [] data.ranges;
- delete [] data.intensity;
- delete [] data.angles;
-
- return ret;
- }
-
-
default:
PLAYER_ERROR1("unknown laser data subtype %d\n", subtype);
return(-1);
@@ -1790,7 +1839,631 @@
}
+////////////////////////////////////////////////////////////////////////////
+// Parse ranger data
+int ReadLog::ParseRanger(player_devaddr_t id,
+ unsigned short type, unsigned short subtype,
+ int linenum,
+ int token_count, char **tokens, double time)
+{
+ int i, count, ret;
+ ret = 0;
+ switch(type)
+ {
+ case PLAYER_MSGTYPE_DATA:
+ switch(subtype)
+ {
+ case PLAYER_RANGER_DATA_RANGE:
+ {
+ player_ranger_data_range_t data;
+ if (token_count < 8)
+ {
+ PLAYER_ERROR2("incomplete line at %s:%d",
+ this->filename, linenum);
+ return -1;
+ }
+
+ data.ranges_count = atoi(tokens[7]);
+
+ data.ranges = new double[ data.ranges_count ];
+
+ count = 0;
+ for (i = 8; i < token_count; i++)
+ {
+ data.ranges[count] = static_cast<double> (atof(tokens[i + 0]));
+ count++;
+ }
+
+ if (count != (int)data.ranges_count)
+ {
+ PLAYER_ERROR2("range count mismatch at %s:%d",
+ this->filename, linenum);
+ ret = -1;
+ }
+ else
+ {
+ this->Publish(id, static_cast<uint8_t> (type),
static_cast<uint8_t> (subtype),
+ (void*)&data, sizeof(data), &time);
+ }
+ delete [] data.ranges;
+
+ return ret;
+ }
+
+ case PLAYER_RANGER_DATA_RANGESTAMPED:
+ {
+ player_ranger_data_rangestamped_t data;
+
+ if (token_count < 10)
+ {
+ PLAYER_ERROR2("incomplete line at %s:%d",
+ this->filename, linenum);
+ return -1;
+ }
+
+ int total_count=7;
+ data.data.ranges_count = atoi(tokens[total_count]);
+ total_count++;
+
+ data.data.ranges = new double[ data.data.ranges_count ];
+
+ count = 0;
+ int loop_size=fmin(token_count, total_count+data.data.ranges_count);
+ for (i = total_count; i < loop_size; i += 2)
+ {
+ data.data.ranges[count] = static_cast<double> (atof(tokens[i]));
+ count++;
+ total_count++;
+ }
+
+ if (count != (int)data.data.ranges_count)
+ {
+ PLAYER_ERROR2("range count mismatch at %s:%d",
+ this->filename, linenum);
+ delete [] data.data.ranges;
+ return -1;
+ }
+
+ data.have_geom = atoi(tokens[total_count]);
+ total_count++;
+
+ if (data.have_geom)
+ {
+ if (token_count < total_count+11)
+ {
+ PLAYER_ERROR2("incomplete line at %s:%d",
+ this->filename, linenum);
+ delete [] data.data.ranges;
+ return -1;
+ }
+
+ data.geom.pose.px = static_cast<double>
(atof(tokens[total_count]));
+ total_count++;
+ data.geom.pose.py = static_cast<double>
(atof(tokens[total_count]));
+ total_count++;
+ data.geom.pose.pz = static_cast<double>
(atof(tokens[total_count]));
+ total_count++;
+ data.geom.pose.proll = static_cast<double>
(atof(tokens[total_count]));
+ total_count++;
+ data.geom.pose.ppitch = static_cast<double>
(atof(tokens[total_count]));
+ total_count++;
+ data.geom.pose.pyaw = static_cast<double>
(atof(tokens[total_count]));
+
+ total_count++;
+ data.geom.size.sw = static_cast<double>
(atof(tokens[total_count]));
+ total_count++;
+ data.geom.size.sl = static_cast<double>
(atof(tokens[total_count]));
+ total_count++;
+ data.geom.size.sh = static_cast<double>
(atof(tokens[total_count]));
+ total_count++;
+
+ data.geom.element_poses_count = atoi(tokens[total_count]);
+ total_count++;
+
+ data.geom.element_poses = new player_pose3d_t [
data.geom.element_poses_count ];
+
+ count = 0;
+ loop_size=fmin(token_count,
total_count+data.geom.element_poses_count*6);
+ for (i = total_count; i < loop_size; i += 6)
+ {
+ data.geom.element_poses[count].px = static_cast<double>
(atof(tokens[i]));
+ total_count++;
+ data.geom.element_poses[count].py = static_cast<double>
(atof(tokens[i+1]));
+ total_count++;
+ data.geom.element_poses[count].pz = static_cast<double>
(atof(tokens[i+2]));
+ total_count++;
+ data.geom.element_poses[count].proll = static_cast<double>
(atof(tokens[i+3]));
+ total_count++;
+ data.geom.element_poses[count].ppitch = static_cast<double>
(atof(tokens[i+4]));
+ total_count++;
+ data.geom.element_poses[count].pyaw = static_cast<double>
(atof(tokens[i+5]));
+ total_count++;
+ count++;
+ }
+
+ if (count != (int)data.geom.element_poses_count || total_count
> token_count)
+ {
+ PLAYER_ERROR2("poses count mismatch at %s:%d",
+ this->filename, linenum);
+ delete [] data.data.ranges;
+ delete [] data.geom.element_poses;
+ return -1;
+ }
+
+
+ data.geom.element_sizes_count = atoi(tokens[total_count]);
+ total_count++;
+
+ data.geom.element_sizes = new player_bbox3d_t [
data.geom.element_sizes_count ];
+
+ count = 0;
+ loop_size=fmin(token_count,
total_count+data.geom.element_sizes_count*3);
+ for (i = total_count; i < loop_size; i += 3)
+ {
+ data.geom.element_sizes[count].sw = static_cast<double>
(atof(tokens[i]));
+ total_count++;
+ data.geom.element_sizes[count].sl = static_cast<double>
(atof(tokens[i+1]));
+ total_count++;
+ data.geom.element_sizes[count].sh = static_cast<double>
(atof(tokens[i+2]));
+ total_count++;
+ count++;
+ }
+
+ if (count != (int)data.geom.element_sizes_count || total_count
> token_count)
+ {
+ PLAYER_ERROR2("sizes count mismatch at %s:%d",
+ this->filename, linenum);
+ delete [] data.data.ranges;
+ delete [] data.geom.element_poses;
+ delete [] data.geom.element_sizes;
+ return -1;
+ }
+ }
+
+ data.have_config = atoi(tokens[total_count]);
+
+ if (data.have_config)
+ {
+
+ if (token_count < total_count+7)
+ {
+ PLAYER_ERROR2("incomplete line at %s:%d",
+ this->filename, linenum);
+ delete [] data.data.ranges;
+ if (data.have_geom)
+ {
+ delete [] data.geom.element_poses;
+ delete [] data.geom.element_sizes;
+ }
+ return -1;
+ }
+
+ data.config.min_angle = static_cast<double>
(atof(tokens[total_count]));
+ total_count++;
+ data.config.max_angle = static_cast<double>
(atof(tokens[total_count]));
+ total_count++;
+ data.config.angular_res = static_cast<double>
(atof(tokens[total_count]));
+ total_count++;
+ data.config.min_range = static_cast<double>
(atof(tokens[total_count]));
+ total_count++;
+ data.config.max_range = static_cast<double>
(atof(tokens[total_count]));
+ total_count++;
+ data.config.range_res = static_cast<double>
(atof(tokens[total_count]));
+ total_count++;
+ data.config.frequency = static_cast<double>
(atof(tokens[total_count]));
+ total_count++;
+ }
+
+ if (total_count != token_count)
+ {
+ PLAYER_ERROR2("invalid line at %s:%d: number of tokens does not
"
+ "match count", filename, linenum);
+ delete [] data.data.ranges;
+ if (data.have_geom)
+ {
+ delete [] data.geom.element_poses;
+ delete [] data.geom.element_sizes;
+ }
+ return -1;
+ }
+
+ this->Publish(id, static_cast<uint8_t> (type), static_cast<uint8_t>
(subtype),
+ (void*)&data, sizeof(data), &time);
+ delete [] data.data.ranges;
+ if (data.have_geom)
+ {
+ delete [] data.geom.element_poses;
+ delete [] data.geom.element_sizes;
+ }
+
+ return ret;
+ }
+
+ case PLAYER_RANGER_DATA_INTNS:
+ {
+ player_ranger_data_intns_t data;
+
+ if (token_count < 8)
+ {
+ PLAYER_ERROR2("incomplete line at %s:%d",
+ this->filename, linenum);
+ return -1;
+ }
+
+ data.intensities_count = atoi(tokens[7]);
+ data.intensities = new double[ data.intensities_count ];
+
+ count = 0;
+ for (i = 8; i < token_count; i++)
+ {
+ data.intensities[count] = static_cast<double> (atof(tokens[i +
0]));
+ count++;
+ }
+
+ if (count != (int)data.intensities_count)
+ {
+ PLAYER_ERROR2("range count mismatch at %s:%d",
+ this->filename, linenum);
+ ret = -1;
+ }
+ else
+ {
+ this->Publish(id, static_cast<uint8_t> (type),
static_cast<uint8_t> (subtype),
+ (void*)&data, sizeof(data), &time);
+ }
+ delete [] data.intensities;
+
+ return ret;
+ }
+
+ case PLAYER_RANGER_DATA_INTNSSTAMPED:
+ {
+ player_ranger_data_intnsstamped_t data;
+
+ if (token_count < 10)
+ {
+ PLAYER_ERROR2("incomplete line at %s:%d",
+ this->filename, linenum);
+ return -1;
+ }
+
+ int total_count=7;
+ data.data.intensities_count = atoi(tokens[total_count]);
+ total_count++;
+
+ data.data.intensities = new double[ data.data.intensities_count ];
+
+ count = 0;
+ int loop_size=fmin(token_count,
total_count+data.data.intensities_count);
+ for (i = total_count; i < loop_size; i += 2)
+ {
+ data.data.intensities[count] = static_cast<double>
(atof(tokens[i]));
+ count++;
+ total_count++;
+ }
+
+ if (count != (int)data.data.intensities_count)
+ {
+ PLAYER_ERROR2("range count mismatch at %s:%d",
+ this->filename, linenum);
+ delete [] data.data.intensities;
+ return -1;
+ }
+
+ data.have_geom = atoi(tokens[total_count]);
+ total_count++;
+
+ if (data.have_geom)
+ {
+ if (token_count < total_count+11)
+ {
+ PLAYER_ERROR2("incomplete line at %s:%d",
+ this->filename, linenum);
+ delete [] data.data.intensities;
+ return -1;
+ }
+
+ data.geom.pose.px = static_cast<double>
(atof(tokens[total_count]));
+ total_count++;
+ data.geom.pose.py = static_cast<double>
(atof(tokens[total_count]));
+ total_count++;
+ data.geom.pose.pz = static_cast<double>
(atof(tokens[total_count]));
+ total_count++;
+ data.geom.pose.proll = static_cast<double>
(atof(tokens[total_count]));
+ total_count++;
+ data.geom.pose.ppitch = static_cast<double>
(atof(tokens[total_count]));
+ total_count++;
+ data.geom.pose.pyaw = static_cast<double>
(atof(tokens[total_count]));
+
+ total_count++;
+ data.geom.size.sw = static_cast<double>
(atof(tokens[total_count]));
+ total_count++;
+ data.geom.size.sl = static_cast<double>
(atof(tokens[total_count]));
+ total_count++;
+ data.geom.size.sh = static_cast<double>
(atof(tokens[total_count]));
+ total_count++;
+
+ data.geom.element_poses_count = atoi(tokens[total_count]);
+ total_count++;
+
+ data.geom.element_poses = new player_pose3d_t [
data.geom.element_poses_count ];
+
+ count = 0;
+ loop_size=fmin(token_count,
total_count+data.geom.element_poses_count*6);
+ for (i = total_count; i < loop_size; i += 6)
+ {
+ data.geom.element_poses[count].px = static_cast<double>
(atof(tokens[i]));
+ total_count++;
+ data.geom.element_poses[count].py = static_cast<double>
(atof(tokens[i+1]));
+ total_count++;
+ data.geom.element_poses[count].pz = static_cast<double>
(atof(tokens[i+2]));
+ total_count++;
+ data.geom.element_poses[count].proll = static_cast<double>
(atof(tokens[i+3]));
+ total_count++;
+ data.geom.element_poses[count].ppitch = static_cast<double>
(atof(tokens[i+4]));
+ total_count++;
+ data.geom.element_poses[count].pyaw = static_cast<double>
(atof(tokens[i+5]));
+ total_count++;
+ count++;
+ }
+
+ if (count != (int)data.geom.element_poses_count || total_count
> token_count)
+ {
+ PLAYER_ERROR2("poses count mismatch at %s:%d",
+ this->filename, linenum);
+ delete [] data.data.intensities;
+ delete [] data.geom.element_poses;
+ return -1;
+ }
+
+
+ data.geom.element_sizes_count = atoi(tokens[total_count]);
+ total_count++;
+
+ data.geom.element_sizes = new player_bbox3d_t [
data.geom.element_sizes_count ];
+
+ count = 0;
+ loop_size=fmin(token_count,
total_count+data.geom.element_sizes_count*3);
+ for (i = total_count; i < loop_size; i += 3)
+ {
+ data.geom.element_sizes[count].sw = static_cast<double>
(atof(tokens[i]));
+ total_count++;
+ data.geom.element_sizes[count].sl = static_cast<double>
(atof(tokens[i+1]));
+ total_count++;
+ data.geom.element_sizes[count].sh = static_cast<double>
(atof(tokens[i+2]));
+ total_count++;
+ count++;
+ }
+
+ if (count != (int)data.geom.element_sizes_count || total_count
> token_count)
+ {
+ PLAYER_ERROR2("sizes count mismatch at %s:%d",
+ this->filename, linenum);
+ delete [] data.data.intensities;
+ delete [] data.geom.element_poses;
+ delete [] data.geom.element_sizes;
+ return -1;
+ }
+ }
+
+ data.have_config = atoi(tokens[total_count]);
+
+ if (data.have_config)
+ {
+
+ if (token_count < total_count+7)
+ {
+ PLAYER_ERROR2("incomplete line at %s:%d",
+ this->filename, linenum);
+ delete [] data.data.intensities;
+ if (data.have_geom)
+ {
+ delete [] data.geom.element_poses;
+ delete [] data.geom.element_sizes;
+ }
+ return -1;
+ }
+
+ data.config.min_angle = static_cast<double>
(atof(tokens[total_count]));
+ total_count++;
+ data.config.max_angle = static_cast<double>
(atof(tokens[total_count]));
+ total_count++;
+ data.config.angular_res = static_cast<double>
(atof(tokens[total_count]));
+ total_count++;
+ data.config.min_range = static_cast<double>
(atof(tokens[total_count]));
+ total_count++;
+ data.config.max_range = static_cast<double>
(atof(tokens[total_count]));
+ total_count++;
+ data.config.range_res = static_cast<double>
(atof(tokens[total_count]));
+ total_count++;
+ data.config.frequency = static_cast<double>
(atof(tokens[total_count]));
+ total_count++;
+ }
+
+ if (total_count != token_count)
+ {
+ PLAYER_ERROR2("invalid line at %s:%d: number of tokens does not
"
+ "match count", filename, linenum);
+ delete [] data.data.intensities;
+ if (data.have_geom)
+ {
+ delete [] data.geom.element_poses;
+ delete [] data.geom.element_sizes;
+ }
+ return -1;
+ }
+
+ this->Publish(id, static_cast<uint8_t> (type), static_cast<uint8_t>
(subtype),
+ (void*)&data, sizeof(data), &time);
+ delete [] data.data.intensities;
+ if (data.have_geom)
+ {
+ delete [] data.geom.element_poses;
+ delete [] data.geom.element_sizes;
+ }
+ return ret;
+ }
+
+ default:
+ PLAYER_ERROR1("unknown ranger data subtype %d\n", subtype);
+ return(-1);
+ }
+ break;
+
+ case PLAYER_MSGTYPE_RESP_ACK:
+ switch(subtype)
+ {
+ case PLAYER_RANGER_REQ_GET_GEOM:
+ {
+ if(token_count < 18)
+ {
+ PLAYER_ERROR2("incomplete line at %s:%d",
+ this->filename, linenum);
+ return -1;
+ }
+
+ int num_poses=atoi(tokens[16]);
+
+ if(token_count < 18+num_poses*6)
+ {
+ PLAYER_ERROR2("incomplete line at %s:%d",
+ this->filename, linenum);
+ return -1;
+ }
+
+ int num_sizes=atoi(tokens[17+num_poses*6]);
+
+ if(token_count < 18+num_poses*6+num_sizes*3)
+ {
+ PLAYER_ERROR2("incomplete line at %s:%d",
+ this->filename, linenum);
+ return -1;
+ }
+
+
+ // cache it
+ player_ranger_geom_t* geom =
+
(player_ranger_geom_t*)calloc(1,sizeof(player_ranger_geom_t)+sizeof(player_pose3d_t)*num_poses+sizeof(player_bbox3d_t)*num_sizes);
+ assert(geom);
+
+ geom->pose.px = atof(tokens[7]);
+ geom->pose.py = atof(tokens[8]);
+ geom->pose.pz = atof(tokens[9]);
+ geom->pose.proll = atof(tokens[10]);
+ geom->pose.ppitch = atof(tokens[11]);
+ geom->pose.pyaw = atof(tokens[12]);
+ geom->size.sw = atof(tokens[13]);
+ geom->size.sl = atof(tokens[14]);
+ geom->size.sh = atof(tokens[15]);
+ geom->element_poses_count = num_poses;
+ geom->element_poses = new player_pose3d_t [ num_poses ];
+ geom->element_sizes_count = num_sizes;
+ geom->element_sizes = new player_bbox3d_t [ num_sizes ];
+
+ for (int i=0; i < num_poses; i++)
+ {
+ geom->element_poses[i].px=atof(tokens[17+i*6]);
+ geom->element_poses[i].py=atof(tokens[17+i*6+1]);
+ geom->element_poses[i].pz=atof(tokens[17+i*6+2]);
+ geom->element_poses[i].proll=atof(tokens[17+i*6+3]);
+ geom->element_poses[i].ppitch=atof(tokens[17+i*6+4]);
+ geom->element_poses[i].pyaw=atof(tokens[17+i*6+5]);
+ }
+
+ for (int i=0; i < num_sizes; i++)
+ {
+ geom->element_sizes[i].sw=atof(tokens[17+num_poses*6+1+i*3]);
+ geom->element_sizes[i].sl=atof(tokens[17+num_poses*6+1+i*3+1]);
+ geom->element_sizes[i].sh=atof(tokens[17+num_poses*6+1+i*3+2]);
+ }
+
+
+ // Find the right place to put it
+ int j;
+ for(j=0;j<this->provide_count;j++)
+ {
+ if(Device::MatchDeviceAddress(this->provide_ids[j], id))
+ break;
+ }
+ assert(j<this->provide_count);
+
+ // if something is already here, use it
+ if(this->provide_metadata[j])
+ ((ranger_meta_t*)this->provide_metadata[j])->geom = geom;
+ else
+ {
+ ranger_meta_t* meta =
+ (ranger_meta_t*)calloc(1,sizeof(ranger_meta_t));
+ meta->geom=geom;
+ this->provide_metadata[j] = (void*)meta;
+ }
+
+ // nothing to publish
+ return(0);
+ }
+
+ case PLAYER_RANGER_REQ_GET_CONFIG:
+ {
+ if(token_count < 14)
+ {
+ PLAYER_ERROR2("incomplete line at %s:%d",
+ this->filename, linenum);
+ return -1;
+ }
+
+ // cache it
+ player_ranger_config_t* config =
+ (player_ranger_config_t*)calloc(1,sizeof(player_ranger_config_t));
+ assert(config);
+
+ config->min_angle = atof(tokens[7]);
+ config->max_angle = atof(tokens[8]);
+ config->angular_res = atof(tokens[9]);
+ config->min_range = atof(tokens[10]);
+ config->max_range = atof(tokens[11]);
+ config->range_res = atof(tokens[12]);
+ config->frequency = atof(tokens[13]);
+
+ // Find the right place to put it
+ int j;
+ for(j=0;j<this->provide_count;j++)
+ {
+ if(Device::MatchDeviceAddress(this->provide_ids[j], id))
+ break;
+ }
+ assert(j<this->provide_count);
+
+ // if something is already here, use it
+ if(this->provide_metadata[j]) {
+ ((ranger_meta_t*)this->provide_metadata[j])->config = config;
+ }
+ else
+ {
+ ranger_meta_t* meta =
+ (ranger_meta_t*)calloc(1,sizeof(ranger_meta_t));
+ meta->config=config;
+ this->provide_metadata[j] = (void*)meta;
+ }
+
+ // nothing to publish
+ return(0);
+ }
+
+ default:
+ PLAYER_ERROR1("unknown ranger reply subtype %d\n", subtype);
+ return(-1);
+ }
+ break;
+
+ default:
+ PLAYER_ERROR1("unknown ranger msg type %d\n", type);
+ return(-1);
+ }
+}
+
+
+
////////////////////////////////////////////////////////////////////////////
// Parse localize data
int ReadLog::ParseLocalize(player_devaddr_t id,
Modified: code/player/trunk/server/drivers/shell/writelog.cc
===================================================================
--- code/player/trunk/server/drivers/shell/writelog.cc 2009-08-26 08:19:56 UTC
(rev 8227)
+++ code/player/trunk/server/drivers/shell/writelog.cc 2009-08-26 08:23:52 UTC
(rev 8228)
@@ -70,6 +70,7 @@
The writelog driver can will log data from the following interfaces:
- @ref interface_laser
+- @ref interface_ranger
- @ref interface_sonar
- @ref interface_position2d
- @ref interface_ptz
@@ -225,6 +226,9 @@
// Write laser data to file
private: int WriteLaser(player_msghdr_t* hdr, void *data);
+ // Write ranger data to file
+ private: int WriteRanger(player_msghdr_t* hdr, void *data);
+
// Write localize data to file
private: int WriteLocalize(player_msghdr_t* hdr, void *data);
@@ -585,9 +589,42 @@
delete msg;
}
}
+ else if (device->addr.interf == PLAYER_RANGER_CODE)
+ {
+ // Get the ranger geometry
+ Message* msg;
+ if(!(msg = device->device->Request(this->InQueue,
+ PLAYER_MSGTYPE_REQ,
+ PLAYER_RANGER_REQ_GET_GEOM,
+ NULL, 0, NULL, true)))
+ {
+ // oh well.
+ PLAYER_WARN("unable to get ranger geometry");
+ }
+ else
+ {
+ // log it
+ this->Write(device, msg->GetHeader(), msg->GetPayload());
+ delete msg;
+ }
+ if(!(msg = device->device->Request(this->InQueue,
+ PLAYER_MSGTYPE_REQ,
+ PLAYER_RANGER_REQ_GET_CONFIG,
+ NULL, 0, NULL, true)))
+ {
+ // oh well.
+ PLAYER_WARN("unable to get ranger config");
+ }
+ else
+ {
+ // log it
+ this->Write(device, msg->GetHeader(), msg->GetPayload());
+ delete msg;
+ }
+ }
else if (device->addr.interf == PLAYER_POSITION2D_CODE)
{
- // Get the laser geometry
+ // Get the position geometry
Message* msg;
if(!(msg = device->device->Request(this->InQueue,
PLAYER_MSGTYPE_REQ,
@@ -607,7 +644,7 @@
/* HHAA 15-02-2007 */
else if (device->addr.interf == PLAYER_BUMPER_CODE)
{
- // Get the laser geometry
+ // Get the bumper geometry
Message* msg;
if(!(msg = device->device->Request(this->InQueue,
PLAYER_MSGTYPE_REQ,
@@ -627,7 +664,7 @@
/* HHAA 15-02-2007 */
else if (device->addr.interf == PLAYER_IR_CODE)
{
- // Get the laser geometry
+ // Get the IR geometry
Message* msg;
if(!(msg = device->device->Request(this->InQueue,
PLAYER_MSGTYPE_REQ,
@@ -827,6 +864,9 @@
case PLAYER_LASER_CODE:
retval = this->WriteLaser(hdr, data);
break;
+ case PLAYER_RANGER_CODE:
+ retval = this->WriteRanger(hdr, data);
+ break;
case PLAYER_LOCALIZE_CODE:
retval = this->WriteLocalize(hdr, data);
break;
@@ -1039,22 +1079,22 @@
}
return(0);
- case PLAYER_LASER_DATA_SCANANGLE:
- scanangle = (player_laser_data_scanangle_t*)data;
- fprintf(this->file, "%04d %+07.4f %04d ",
- scanangle->id, scanangle->max_range,
scanangle->ranges_count);
-
- for (i = 0; i < scanangle->ranges_count; i++)
- {
- fprintf(this->file, "%.3f ",
scanangle->ranges[i]);
- fprintf(this->file, "%.3f ",
scanangle->angles[i]);
- if(i < scanangle->intensity_count)
- fprintf(this->file, "%2d ",
scanangle->intensity[i]);
- else
- fprintf(this->file, "%2d ", 0);
- }
- return(0);
-
+ case PLAYER_LASER_DATA_SCANANGLE:
+ scanangle = (player_laser_data_scanangle_t*)data;
+ fprintf(this->file, "%04d %+07.4f %04d ",
+ scanangle->id, scanangle->max_range, scanangle->ranges_count);
+
+ for (i = 0; i < scanangle->ranges_count; i++)
+ {
+ fprintf(this->file, "%.3f ", scanangle->ranges[i]);
+ fprintf(this->file, "%.3f ", scanangle->angles[i]);
+ if(i < scanangle->intensity_count)
+ fprintf(this->file, "%2d ", scanangle->intensity[i]);
+ else
+ fprintf(this->file, "%2d ", 0);
+ }
+ return(0);
+
default:
return(-1);
}
@@ -1078,12 +1118,334 @@
}
}
+
/** @ingroup tutorial_datalog
+ * @defgroup player_driver_writelog_ranger ranger format
+
+...@brief ranger log format
+
+The following type:subtype ranger messages can be logged:
+- 1:1 (PLAYER_RANGER_DATA_RANGE) - A range scan. The format is:
+ - ranges_count (uint): number of ranges
+ - list of ranges_count ranges:
+ - range (double): distance
+
+- 1:2 (PLAYER_RANGER_DATA_RANGEPOSE) - A range scan optionally with
+the (possibly estimated) geometry of the device when the scan was
+acquired and optional sensor configuration. The format is:
+ - ranges_count (uint): number of ranges
+ - list of ranges_count ranges:
+ - range (double): distance
+ - have_geom (uint8): If non-zero, the geometry data has been filled
+ - geometry of device at the time of range data:
+ - pose of device:
+ - px (float): X coordinate of the pose, in meters
+ - py (float): Y coordinate of the pose, in meters
+ - pz (float): Z coordinate of the pose, in meters
+ - proll (float): roll coordinate of the pose, in radians
+ - ppitch (float): pitch coordinate of the pose, in radians
+ - pyaw (float): yaw coordinate of the pose, in radians
+ - size of device:
+ - sw (float): width of the device, in meters
+ - sl (float): length of the device, in meters
+ - sh (float): height of the device, in meters
+ - element_poses_count (uint): pose of each individual range sensor that
makes up the device
+ - list of element_poses_count poses:
+ - px (float): X coordinate of the pose, in meters
+ - py (float): Y coordinate of the pose, in meters
+ - pz (float): Z coordinate of the pose, in meters
+ - proll (float): roll coordinate of the pose, in radians
+ - ppitch (float): pitch coordinate of the pose, in radians
+ - pyaw (float): yaw coordinate of the pose, in radians
+ - element_sizes_count (uint): size of each individual range sensor that
makes up the device
+ - list of element_sizes_count sizes:
+ - sw (float): width of the device, in meters
+ - sl (float): length of the device, in meters
+ - sh (float): height of the device, in meters
+ - have_config(uint8): If non-zero, the config data has been filled
+ - config of device:
+ - min_angle (float): start angle of scans, in radians
+ - max_angle (float): end angle of scans, in radians
+ - angular_res (float): scan resolution, in radians
+ - min_range (float): minimum range, in meters
+ - max_range (float): maximum range, in meters
+ - range_res (float): range resolution, in meters
+ - frequency (float): scanning frequency, in Hz
+
+- 1:3 (PLAYER_RANGER_DATA_INTNS) - An intensity scan. The format is:
+ - intensities_count (uint): number of intensities
+ - list of intensities_count intensities:
+ - intensity (double)
+
+- 1:4 (PLAYER_RANGER_DATA_ITNSPOSE) - An intensity scan with an attached pose
(estimated from the time of the scan). The format is:
+ - intensities_count (uint): number of intensities
+ - list of intensities_count intensities:
+ - intensity (double)
+ - have_geom (uint8): If non-zero, the geometry data has been filled
+ - geometry of device at the time of intensity data:
+ - pose of device:
+ - px (float): X coordinate of the pose, in meters
+ - py (float): Y coordinate of the pose, in meters
+ - pz (float): Z coordinate of the pose, in meters
+ - proll (float): roll coordinate of the pose, in radians
+ - ppitch (float): pitch coordinate of the pose, in radians
+ - pyaw (float): yaw coordinate of the pose, in radians
+ - size of device:
+ - sw (float): width of the device, in meters
+ - sl (float): length of the device, in meters
+ - sh (float): height of the device, in meters
+ - element_poses_count (uint): pose of each individual range sensor that
makes up the device
+ - list of element_poses_count poses:
+ - px (float): X coordinate of the pose, in meters
+ - py (float): Y coordinate of the pose, in meters
+ - pz (float): Z coordinate of the pose, in meters
+ - proll (float): roll coordinate of the pose, in radians
+ - ppitch (float): pitch coordinate of the pose, in radians
+ - pyaw (float): yaw coordinate of the pose, in radians
+ - element_sizes_count (uint): size of each individual range sensor that
makes up the device
+ - list of element_sizes_count sizes:
+ - sw (float): width of the device, in meters
+ - sl (float): length of the device, in meters
+ - sh (float): height of the device, in meters
+ - have_config(uint8): If non-zero, the config data has been filled
+ - config of device:
+
+- 4:1 (PLAYER_RANGER_REQ_GET_GEOM) - Ranger pose information. The format is:
+ - pose of device:
+ - px (float): X coordinate of the pose, in meters
+ - py (float): Y coordinate of the pose, in meters
+ - pz (float): Z coordinate of the pose, in meters
+ - proll (float): roll coordinate of the pose, in radians
+ - ppitch (float): pitch coordinate of the pose, in radians
+ - pyaw (float): yaw coordinate of the pose, in radians
+ - size of device:
+ - sw (float): width of the device, in meters
+ - sl (float): length of the device, in meters
+ - sh (float): height of the device, in meters
+ - element_poses_count (uint): pose of each individual range sensor that
makes up the device
+ - list of element_poses_count poses:
+ - px (float): X coordinate of the pose, in meters
+ - py (float): Y coordinate of the pose, in meters
+ - pz (float): Z coordinate of the pose, in meters
+ - proll (float): roll coordinate of the pose, in radians
+ - ppitch (float): pitch coordinate of the pose, in radians
+ - pyaw (float): yaw coordinate of the pose, in radians
+ - element_sizes_count (uint): size of each individual range sensor that
makes up the device
+ - list of element_sizes_count sizes:
+ - sw (float): width of the device, in meters
+ - sl (float): length of the device, in meters
+ - sh (float): height of the device, in meters
+*/
+int
+WriteLog::WriteRanger(player_msghdr_t* hdr, void *data)
+{
+ size_t i;
+ player_ranger_data_range_t* rscan;
+ player_ranger_data_rangestamped_t* rscanpose;
+ player_ranger_data_intns_t* iscan;
+ player_ranger_data_intnsstamped_t* iscanpose;
+ player_ranger_geom_t* geom;
+ player_ranger_config_t* config;
+
+ // Check the type
+ switch(hdr->type)
+ {
+ case PLAYER_MSGTYPE_DATA:
+ // Check the subtype
+ switch(hdr->subtype)
+ {
+ case PLAYER_RANGER_DATA_RANGE:
+ rscan = (player_ranger_data_range_t*)data;
+ // Note that, in this format, we need a lot of precision in the
+ // resolution field.
+
+ fprintf(this->file, "%04d ", rscan->ranges_count);
+
+ for (i = 0; i < rscan->ranges_count; i++)
+ {
+ fprintf(this->file, "%.3f ", rscan->ranges[i]);
+ }
+ return(0);
+
+ case PLAYER_RANGER_DATA_RANGESTAMPED:
+ rscanpose = (player_ranger_data_rangestamped_t*)data;
+ // Note that, in this format, we need a lot of precision in the
+ // resolution field.
+
+ fprintf(this->file, "%04d ", rscanpose->data.ranges_count);
+
+ for (i = 0; i < rscanpose->data.ranges_count; i++)
+ {
+ fprintf(this->file, "%.3f ", rscanpose->data.ranges[i]);
+ }
+
+ fprintf(this->file, "%d ", rscanpose->have_geom);
+
+ if (rscanpose->have_geom)
+ {
+ fprintf(this->file, "%+07.3f %+07.3f %+07.3f %+07.3f %+07.3f
%+07.3f %+07.3f %+07.3f %+07.3f ",
+ rscanpose->geom.pose.px, rscanpose->geom.pose.py,
rscanpose->geom.pose.pz,
+ rscanpose->geom.pose.proll, rscanpose->geom.pose.ppitch,
rscanpose->geom.pose.pyaw,
+ rscanpose->geom.size.sw, rscanpose->geom.size.sl,
rscanpose->geom.size.sh);
+
+ fprintf(this->file, "%04d ", rscanpose->geom.element_poses_count);
+
+ for (i = 0; i < rscanpose->geom.element_poses_count; i++)
+ {
+ fprintf(this->file, "%+07.3f %+07.3f %+07.3f %+07.3f %+07.3f
%+07.3f ",
+ rscanpose->geom.element_poses[i].px,
rscanpose->geom.element_poses[i].py, rscanpose->geom.element_poses[i].pz,
+ rscanpose->geom.element_poses[i].proll,
rscanpose->geom.element_poses[i].ppitch, rscanpose->geom.element_poses[i].pyaw);
+ }
+
+ fprintf(this->file, "%04d ", rscanpose->geom.element_sizes_count);
+
+ for (i = 0; i < rscanpose->geom.element_sizes_count; i++)
+ {
+ fprintf(this->file, "%+07.3f %+07.3f %+07.3f ",
+ rscanpose->geom.element_sizes[i].sw,
rscanpose->geom.element_sizes[i].sl, rscanpose->geom.element_sizes[i].sh);
+ }
+ }
+
+ if (rscanpose->have_config)
+ {
+ fprintf(this->file, "%.4f %.4f %.4f %.4f %.4f %.4f %.4f ",
+ rscanpose->config.min_angle, rscanpose->config.max_angle,
+ rscanpose->config.angular_res,
rscanpose->config.min_range,
+ rscanpose->config.max_range, rscanpose->config.range_res,
+ rscanpose->config.frequency);
+ }
+
+ return(0);
+
+
+ case PLAYER_RANGER_DATA_INTNS:
+ iscan = (player_ranger_data_intns_t*)data;
+ // Note that, in this format, we need a lot of precision in the
+ // resolution field.
+
+ fprintf(this->file, "%04d ", iscan->intensities_count);
+
+ for (i = 0; i < iscan->intensities_count; i++)
+ {
+ fprintf(this->file, "%.3f ", iscan->intensities[i]);
+ }
+ return(0);
+
+
+ case PLAYER_RANGER_DATA_INTNSSTAMPED:
+ iscanpose = (player_ranger_data_intnsstamped_t*)data;
+ // Note that, in this format, we need a lot of precision in the
+ // resolution field.
+
+ fprintf(this->file, "%04d ", iscanpose->data.intensities_count);
+
+ for (i = 0; i < iscanpose->data.intensities_count; i++)
+ {
+ fprintf(this->file, "%.3f ", iscanpose->data.intensities[i]);
+ }
+
+ fprintf(this->file, "%d ", iscanpose->have_geom);
+
+ if (iscanpose->have_geom)
+ {
+ fprintf(this->file, "%+07.3f %+07.3f %+07.3f %+07.3f %+07.3f
%+07.3f %+07.3f %+07.3f %+07.3f ",
+ iscanpose->geom.pose.px, iscanpose->geom.pose.py,
iscanpose->geom.pose.pz,
+ iscanpose->geom.pose.proll, iscanpose->geom.pose.ppitch,
iscanpose->geom.pose.pyaw,
+ iscanpose->geom.size.sw, iscanpose->geom.size.sl,
iscanpose->geom.size.sh);
+
+ fprintf(this->file, "%04d ", iscanpose->geom.element_poses_count);
+
+ for (i = 0; i < iscanpose->geom.element_poses_count; i++)
+ {
+ fprintf(this->file, "%+07.3f %+07.3f %+07.3f %+07.3f %+07.3f
%+07.3f ",
+ iscanpose->geom.element_poses[i].px,
iscanpose->geom.element_poses[i].py, iscanpose->geom.element_poses[i].pz,
+ iscanpose->geom.element_poses[i].proll,
iscanpose->geom.element_poses[i].ppitch, iscanpose->geom.element_poses[i].pyaw);
+ }
+
+ fprintf(this->file, "%04d ", iscanpose->geom.element_sizes_count);
+
+ for (i = 0; i < iscanpose->geom.element_sizes_count; i++)
+ {
+ fprintf(this->file, "%+07.3f %+07.3f %+07.3f ",
+ iscanpose->geom.element_sizes[i].sw,
iscanpose->geom.element_sizes[i].sl, iscanpose->geom.element_sizes[i].sh);
+ }
+ }
+
+ if (iscanpose->have_config)
+ {
+ fprintf(this->file, "%.4f %.4f %.4f %.4f %.4f %.4f %.4f ",
+ iscanpose->config.min_angle, iscanpose->config.max_angle,
+ iscanpose->config.angular_res,
iscanpose->config.min_range,
+ iscanpose->config.max_range, iscanpose->config.range_res,
+ iscanpose->config.frequency);
+ }
+
+ return(0);
+
+ default:
+ return(-1);
+ }
+ case PLAYER_MSGTYPE_RESP_ACK:
+ switch(hdr->subtype)
+ {
+ case PLAYER_RANGER_REQ_GET_GEOM:
+ geom = (player_ranger_geom_t*)data;
+ fprintf(this->file, "%+07.3f %+07.3f %+07.3f %+07.3f %+07.3f %+07.3f
%+07.3f %+07.3f %+07.3f ",
+ geom->pose.px,
+ geom->pose.py,
+ geom->pose.pz,
+ geom->pose.proll,
+ geom->pose.ppitch,
+ geom->pose.pyaw,
+ geom->size.sw,
+ geom->size.sl,
+ geom->size.sh);
+
+ fprintf(this->file, "%04d ", geom->element_poses_count);
+
+ for (i = 0; i < geom->element_poses_count; i++)
+ {
+ fprintf(this->file, "%+07.3f %+07.3f %+07.3f %+07.3f %+07.3f
%+07.3f ",
+ geom->element_poses[i].px, geom->element_poses[i].py,
geom->element_poses[i].pz,
+ geom->element_poses[i].proll,
geom->element_poses[i].ppitch, geom->element_poses[i].pyaw);
+ }
+
+ fprintf(this->file, "%04d ", geom->element_sizes_count);
+
+ for (i = 0; i < geom->element_sizes_count; i++)
+ {
+ fprintf(this->file, "%+07.3f %+07.3f %+07.3f ",
+ geom->element_sizes[i].sw, geom->element_sizes[i].sl,
geom->element_sizes[i].sh);
+ }
+
+ return(0);
+
+ case PLAYER_RANGER_REQ_GET_CONFIG:
+ config = (player_ranger_config_t*)data;
+
+ fprintf(this->file, "%lf %lf %lf %lf %lf %lf %lf ",
+ config->min_angle, config->max_angle,
+ config->angular_res, config->min_range,
+ config->max_range, config->range_res,
+ config->frequency);
+
+ return(0);
+
+ default:
+ return(-1);
+ }
+ default:
+ return(-1);
+ }
+}
+
+
+/** @ingroup tutorial_datalog
* @defgroup player_driver_writelog_localize localize format
-...@brief laser log format
+...@brief localize log format
-The following type:subtype laser messages can be logged:
+The following type:subtype localize messages can be logged:
- 1:1 (PLAYER_LOCALIZE_DATA_HYPOTHS) - A set of pose hypotheses. The format
is:
- pending_count (int): number of pending (unprocessed observations)
- pending time (float): time stamp of the last observation processed
This was sent by the SourceForge.net collaborative development platform, the
world's largest Open Source development site.
------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day
trial. Simplify your report design, integration and deployment - and focus on
what you do best, core application coding. Discover what's new with
Crystal Reports now. http://p.sf.net/sfu/bobj-july
_______________________________________________
Playerstage-commit mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/playerstage-commit