Revision: 7259
          http://playerstage.svn.sourceforge.net/playerstage/?rev=7259&view=rev
Author:   thjc
Date:     2009-01-09 21:14:24 +0000 (Fri, 09 Jan 2009)

Log Message:
-----------
Applied patch 2101864:
New driver for the sick LD MRS (Ibeo LUX)
Modified to work with threaded driver

Modified Paths:
--------------
    code/player/trunk/client_libs/libplayerc/dev_laser.c
    code/player/trunk/libplayercore/interfaces/006_laser.def
    code/player/trunk/server/drivers/laser/CMakeLists.txt
    code/player/trunk/server/drivers/shell/readlog.cc
    code/player/trunk/server/drivers/shell/writelog.cc

Added Paths:
-----------
    code/player/trunk/server/drivers/laser/sickLDMRS.cc

Modified: code/player/trunk/client_libs/libplayerc/dev_laser.c
===================================================================
--- code/player/trunk/client_libs/libplayerc/dev_laser.c        2009-01-09 
21:03:45 UTC (rev 7258)
+++ code/player/trunk/client_libs/libplayerc/dev_laser.c        2009-01-09 
21:14:24 UTC (rev 7259)
@@ -193,6 +193,40 @@
     device->robot_pose[1] = scan_data->pose.py;
     device->robot_pose[2] = scan_data->pose.pa;
   }
+  else if((header->type == PLAYER_MSGTYPE_DATA) &&
+          (header->subtype == PLAYER_LASER_DATA_SCANANGLE))
+  {
+         player_laser_data_scanangle_t* scan_data = 
(player_laser_data_scanangle_t*)data;
+         
+         device->max_range = scan_data->max_range;
+         device->min_left = device->max_range;
+         device->min_right = device->max_range;          
+         
+         device->scan_count = scan_data->ranges_count;
+         playerc_laser_reallocate_scans(device);
+         
+         for (i = 0; i < scan_data->ranges_count; i++)
+         {
+                 r = scan_data->ranges[i];
+                 assert(r >= 0);
+                 b = scan_data->angles[i];
+                 device->ranges[i] = r;
+                 device->scan[i][0] = r;
+                 device->scan[i][1] = b;
+                 device->point[i].px = r * cos(b);
+                 device->point[i].py = r * sin(b);
+                 
+                 if((i <= scan_data->ranges_count/2) && (r < 
device->min_right))
+                         device->min_right = r;
+                 else if((i > scan_data->ranges_count/2) && (r < 
device->min_left))
+                         device->min_left = r;
+         }
+         for (i = 0; i < scan_data->intensity_count; i++)
+                 device->intensity[i] = scan_data->intensity[i];
+         
+         device->scan_id = scan_data->id;
+  }
+       
   else
     PLAYERC_WARN2("skipping laser message with unknown type/subtype: %s/%d\n",
                  msgtype_to_str(header->type), header->subtype);

Modified: code/player/trunk/libplayercore/interfaces/006_laser.def
===================================================================
--- code/player/trunk/libplayercore/interfaces/006_laser.def    2009-01-09 
21:03:45 UTC (rev 7258)
+++ code/player/trunk/libplayercore/interfaces/006_laser.def    2009-01-09 
21:14:24 UTC (rev 7259)
@@ -21,6 +21,8 @@
 message { DATA, SCAN, 1, player_laser_data_t };
 /** Data subtype: pose-stamped scan */
 message { DATA, SCANPOSE, 2, player_laser_data_scanpose_t };
+/** Data subtype: angle-stamped scan */
+message { DATA, SCANANGLE, 3, player_laser_data_scanangle_t };
 
 /** Request/reply subtype: get geometry */
 message { REQ, GET_GEOM, 1, player_laser_geom_t };
@@ -79,6 +81,30 @@
   player_pose2d_t pose;
 } player_laser_data_scanpose_t;
 
+/** @brief Data: scan (@ref PLAYER_LASER_DATA_SCANANGLE)
+
+The basic laser angle stamped data packet.  */
+typedef struct player_laser_data_scanangle
+{
+  /** Maximum range [m]. */
+  float max_range;
+  /** Number of range readings.  */
+  uint32_t ranges_count;
+  /** Range readings [m]. */
+  float *ranges;
+  /** Number of agle readings. */
+  uint32_t angles_count;
+  /** Angle readings [m]. */
+  float *angles;
+  /** Number of intensity readings */
+  uint32_t intensity_count;
+  /** Intensity readings. */
+  uint8_t *intensity;
+  /** A unique, increasing, ID for the scan */
+  uint32_t id;
+} player_laser_data_scanangle_t;
+
+
 /** @brief Request/reply: Get geometry.
 
 The laser geometry (position and size) can be queried by sending a

Modified: code/player/trunk/server/drivers/laser/CMakeLists.txt
===================================================================
--- code/player/trunk/server/drivers/laser/CMakeLists.txt       2009-01-09 
21:03:45 UTC (rev 7258)
+++ code/player/trunk/server/drivers/laser/CMakeLists.txt       2009-01-09 
21:14:24 UTC (rev 7259)
@@ -43,3 +43,7 @@
 
 PLAYERDRIVER_OPTION (rs4leuze build_rs4leuze ON)
 PLAYERDRIVER_ADD_DRIVER (rs4leuze build_rs4leuze SOURCES 
RS4LeuzeLaserDriver.cc RS4Leuze_laser.cc)
+
+PLAYERDRIVER_OPTION (sickLDMRS build_sickLDMRS ON)
+PLAYERDRIVER_ADD_DRIVER (sickLDMRS build_sickLDMRS SOURCES sickLDMRS.cc)
+

Added: code/player/trunk/server/drivers/laser/sickLDMRS.cc
===================================================================
--- code/player/trunk/server/drivers/laser/sickLDMRS.cc                         
(rev 0)
+++ code/player/trunk/server/drivers/laser/sickLDMRS.cc 2009-01-09 21:14:24 UTC 
(rev 7259)
@@ -0,0 +1,539 @@
+/** @ingroup drivers Drivers */
+/** @{ */
+/** @defgroup driver_sickLDMRS sickLDMRS
+ * @brief SICK LD MRS / Multi plae and multi return laser scanner
+
+This driver is for communicting with the Ibeo LUX laser scanner over ethernet 
using the tcpstream driver
+
+...@par Provides
+
+- laser
+
+...@par Requires
+
+ - opaque
+
+...@par Supported commands
+
+- none
+
+...@par Supported configuration requests
+
+ - none
+
+...@par Configuration file options
+
+ - buffer_size (int)
+       - default: 100000
+       - The size of the buffer in the lux driver
+ - layer (int)
+       - -1(default) = all layers
+       - 0,1,2,3 = only publish layer x of the data (3 = highest)
+ - echo (int)
+       - -1(default) = all echos
+       - 0,1,2,3 = only publish laser returns which are echo x
+ - intensity (0,1,2,3)
+       - 1(default) - publishes the echo width (in cm) as the intensity 
variable (cut at 255cm should never be exceeded?)
+    - 2 - publishes the echo number as the intensity value (0,1,2,3)
+       - 3 - publishes the scan layer as the intensity value (0,1,2,3)
+       - 0 - No intensity data
+
+...@par Example:
+
+...@verbatim
+driver
+(
+  name "sickLDMRS"
+  provides ["laser:0"]
+  requires ["opaque:0"]
+  buffer_size 20480
+  layer 3
+)
+
+driver
+(
+  name "tcpstream"
+  provides ["opaque:0"]
+  port 12002
+  ip "10.99.0.1"
+  buffer_size 10000
+)
+...@endverbatim
+
+...@author Chris Chambers
+
+
+*/
+/** @} */
+
+#define DEG2RAD(x) (((double)(x))*0.01745329251994)
+//#define RAD2DEG(x) (((double)(x))*57.29577951308232)
+
+#include <unistd.h>
+#include <string.h>
+#include <iostream>
+#include <arpa/inet.h>
+//#include <stdint.h>
+//#include <sys/time.h>
+//#include <time.h>
+//#include <assert.h>
+//#include <math.h>
+
+#include <libplayercore/playercore.h>
+
+#define LUX_DEFAULT_RX_BUFFER_SIZE 100000U
+#define LUX_DEFAULT_LAYER -1
+#define LUX_DEFAULT_ECHO -1
+#define LUX_DEFAULT_INTENSITY 1
+
+#define HEADER_LEN 24U
+#define SCAN_HEADER_LEN 46U
+#define SCAN_DATA_LEN 24U
+
+#define MESSAGE_LEN 38U
+
+using namespace std;
+
+//extern PlayerTime *GlobalTime;
+
+///////////////////////////////////////////////////////////////////////////////
+// The class for the driver
+class sickLDMRS : public ThreadedDriver
+{
+  public:
+    // Constructor; need that
+    sickLDMRS(ConfigFile* cf, int section);
+       ~sickLDMRS();
+
+    // Must implement the following methods.
+    virtual int MainSetup();
+    virtual void MainQuit();
+
+    // This method will be invoked on each incoming message
+    virtual int ProcessMessage(QueuePointer & resp_queue,
+                               player_msghdr* hdr,
+                               void* data);
+
+  private:
+
+       //Makes a filter command
+       void makeStartStopCommand(uint8_t* buffer, bool start = true);
+
+       bool ProcessLaserData();
+
+    // Main function for device thread.
+    virtual void Main();
+
+       // Opaque Driver info
+    Device *opaque;
+    player_devaddr_t opaque_id;
+
+       player_laser_data_scanangle_t data_packet;
+
+       struct timeval debug_time;
+
+       int layer, echo, intensity;
+
+       // rx buffer
+    uint8_t * rx_buffer;
+    unsigned int rx_buffer_size;
+    unsigned int rx_count;
+
+};
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Now the driver
+
+// A factory creation function, declared outside of the class so that it
+// can be invoked without any object context (alternatively, you can
+// declare it static in the class).  In this function, we create and return
+// (as a generic Driver*) a pointer to a new instance of this driver.
+Driver*
+sickLDMRS_Init(ConfigFile* cf, int section)
+{
+       // Create and return a new instance of this driver
+       return ((Driver*)(new sickLDMRS(cf, section)));
+
+}
+
+// A driver registration function, again declared outside of the class so
+// that it can be invoked without object context.  In this function, we add
+// the driver into the given driver table, indicating which interface the
+// driver can support and how to create a driver instance.
+void sickLDMRS_Register(DriverTable* table)
+{
+       table->AddDriver("sickLDMRS", sickLDMRS_Init);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Constructor.  Retrieve options from the configuration file and do any
+// pre-Setup() setup.
+sickLDMRS::sickLDMRS(ConfigFile* cf, int section)
+    : ThreadedDriver(cf, section, false, PLAYER_MSGQUEUE_DEFAULT_MAXLEN, 
PLAYER_LASER_CODE)
+{
+       this->opaque = NULL;
+       // Must have an opaque device
+       if (cf->ReadDeviceAddr(&this->opaque_id, section, "requires",
+                       PLAYER_OPAQUE_CODE, -1, NULL) != 0)
+       {
+               puts ("No Opaque driver specified");
+               this->SetError(-1);
+               return;
+       }
+
+       // Read options from the configuration file
+
+       rx_count = 0;
+       rx_buffer_size = cf->ReadInt(section, "buffer_size", 
LUX_DEFAULT_RX_BUFFER_SIZE);
+       rx_buffer = new uint8_t[rx_buffer_size];
+       assert(rx_buffer);
+
+       layer = cf->ReadInt(section, "layer", LUX_DEFAULT_LAYER);
+       echo = cf->ReadInt(section, "echo", LUX_DEFAULT_ECHO);
+       intensity = cf->ReadInt(section, "intensity", LUX_DEFAULT_INTENSITY);
+
+       //this->RegisterProperty ("mirror", &this->mirror, cf, section);
+
+       return;
+}
+
+sickLDMRS::~sickLDMRS()
+{
+       delete [] rx_buffer;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Set up the device.  Return 0 if things go well, and -1 otherwise.
+int sickLDMRS::MainSetup()
+{
+       puts("Setting up sickLDMRS driver");
+
+       if(Device::MatchDeviceAddress(this->opaque_id, this->device_addr))
+       {
+               PLAYER_ERROR("attempt to subscribe to self");
+               return(-1);
+       }
+
+       if(!(this->opaque = deviceTable->GetDevice(this->opaque_id)))
+       {
+               PLAYER_ERROR("unable to locate suitable opaque device");
+               return(-1);
+       }
+
+       if(this->opaque->Subscribe(this->InQueue) != 0)
+       {
+               PLAYER_ERROR("unable to subscribe to opaque device");
+               return(-1);
+       }
+
+       uint8_t* buffer = new uint8_t[MESSAGE_LEN];
+       assert(buffer);
+       makeStartStopCommand(buffer, true);
+       player_opaque_data_t mData;
+       mData.data_count = MESSAGE_LEN;
+       mData.data = buffer;
+
+       opaque->PutMsg(this->InQueue, PLAYER_MSGTYPE_CMD, 
PLAYER_OPAQUE_CMD_DATA, reinterpret_cast<void*>(&mData),0,NULL);
+
+       delete [] buffer;
+       buffer = NULL;
+
+       puts("sickLDMRS driver ready");
+
+       return(0);
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Shutdown the device
+void sickLDMRS::MainQuit()
+{
+       uint8_t* buffer = new uint8_t[MESSAGE_LEN];
+       assert(buffer);
+       makeStartStopCommand(buffer, false);
+       player_opaque_data_t mData;
+       mData.data_count = MESSAGE_LEN;
+       mData.data = buffer;
+
+       opaque->PutMsg(this->InQueue, PLAYER_MSGTYPE_CMD, 
PLAYER_OPAQUE_CMD_DATA, reinterpret_cast<void*>(&mData),0,NULL);
+
+       delete [] buffer;
+
+       puts("sickLDMRS driver shutting down");
+
+       opaque->Unsubscribe(InQueue);
+
+       puts("sickLDMRS driver has been shutdown");
+}
+
+
+
+// Process an incoming message
+int sickLDMRS::ProcessMessage(QueuePointer & resp_queue,
+                                 player_msghdr* hdr,
+                                 void* data)
+{
+       assert(hdr);
+       //assert(data);
+
+       if (Message::MatchMessage(hdr, PLAYER_MSGTYPE_DATA, 
PLAYER_OPAQUE_DATA_STATE, opaque_id))
+       {
+               //GlobalTime->GetTime(&(this->debug_time));
+               //PLAYER_MSG2(1,"LUX driver received data packet at %d:%d", 
this->debug_time.tv_sec, this->debug_time.tv_usec);
+               //puts("Received tcp data");
+               player_opaque_data_t * recv = 
reinterpret_cast<player_opaque_data_t * > (data);
+               unsigned int messageOffset = rx_count;
+               rx_count += recv->data_count;
+               if (rx_count > rx_buffer_size)
+               {
+                       PLAYER_WARN("sickLDMRS driver Buffer Full");
+                       rx_count = 0;
+               }
+               else
+               {
+                       memcpy(&rx_buffer[messageOffset], recv->data, 
recv->data_count);
+               }
+               return 0;
+       }
+       return -1;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Main function for device thread
+void sickLDMRS::Main()
+{
+
+       // The main loop; interact with the device here
+       for(;;)
+       {
+               // Process incoming messages
+               ProcessMessages();
+
+               // Ask for the current position and publish it
+               ProcessLaserData();
+
+               if (!this->Wait(1))
+               {
+                       PLAYER_WARN("No TCP data received within 1s, possible 
loss of connection");
+               }
+       }
+       return;
+}
+
+// Currently this alternates between reading the pedal position and reading 
the steering position
+bool sickLDMRS::ProcessLaserData()
+{
+       //TODO: Implement a timeout here so that if it gets no data back in a 
time frame it either errors or sends a reset and stuff
+       while(rx_count > HEADER_LEN)
+       {
+               //puts("Got enough data");
+               // find our continuous data header
+               unsigned int ii;
+               bool found = false;
+               for (ii = 0; ii < rx_count - HEADER_LEN; ++ii)
+               {
+                       if (memcmp(&rx_buffer[ii],"\xaf\xfe\xc0\xc2",4) == 0)
+                       {
+                               //PLAYER_MSG0(3,"Header string found");
+                               memmove(rx_buffer, &rx_buffer[ii], rx_count-ii);
+                               rx_count -= ii;
+                               found = true;
+                               break;
+                       }
+               }
+               if (!found)
+               {
+                       memmove(rx_buffer, &rx_buffer[ii], rx_count-ii);
+                       rx_count -= ii;
+                       return 0;
+               }
+
+               // get relevant bits of the header
+               // size includes all data in the data block
+               // through to the end of the packet including the checksum
+               uint32_t size = htonl(*reinterpret_cast<uint32_t*> 
(&rx_buffer[8])); // Should this be htons????
+               if (size > rx_buffer_size - HEADER_LEN)
+               {
+                       PLAYER_WARN("sickLDMRS: Requested Size of data is 
larger than the buffer size");
+                       memmove(rx_buffer, &rx_buffer[1], --rx_count);
+                       return 0;
+               }
+
+               // check if we have enough data yet
+               if (size > rx_count - HEADER_LEN)
+               {
+                       return 0;
+               }
+               //PLAYER_MSG0(5, "GOT ENOUGH 
DATATATATATATATATATATATATATATATATATATATATAT");
+
+               uint8_t * data = &rx_buffer[HEADER_LEN];
+               if (memcmp(&rx_buffer[14], "\x22\x01", 2) == 0)
+               {
+                       //PLAYER_MSG0(1, "Got scan data packet");
+                       if (size < SCAN_HEADER_LEN)
+                       {
+                               PLAYER_WARN1("sickLDMRS- bad data count 
(%d)\n", size);
+                               memmove(rx_buffer, &rx_buffer[1], --rx_count);
+                               continue;
+                       }
+                       if (size == SCAN_HEADER_LEN)
+                       {
+                               PLAYER_MSG0(1, "LUX - no scans returned");
+                               continue;
+                       }
+                       //PLAYER_MSG0(1, "Not bad count");
+                       //PLAYER_MSG2(1, "Size hex %x %x", 
rx_buffer[34+HEADER_LEN], rx_buffer[35+HEADER_LEN]);
+
+                       uint16_t scan_count = 
htons(*reinterpret_cast<uint16_t*> (&data[34]));
+                       //uint16_t scan_count = 
htons(*reinterpret_cast<uint16_t*> (&rx_buffer[34+HEADER_LEN]));
+                       //PLAYER_MSG1(4,"Scan count %d", scan_count);
+                       if (size != (SCAN_HEADER_LEN + 
SCAN_DATA_LEN*scan_count))
+                       {
+                               PLAYER_WARN2("sickLDMRS - data size mismatch, 
size = %d, number of scans = %d\n", size, scan_count);
+                               memmove(rx_buffer, &rx_buffer[1], --rx_count);
+                               continue;
+                       }
+
+                       if (intensity)
+                               data_packet.intensity = new uint8_t 
[scan_count];
+                       data_packet.ranges = new float [scan_count];
+                       data_packet.angles = new float [scan_count];
+                       data_packet.max_range = 300;
+                       // This is needed as the true count will be less than 
the scan count if you are only interesed in a single layer
+                       // or a single echo thingy
+                       int true_count = 0;
+                       data_packet.id = htons(*reinterpret_cast<uint16_t 
*>(&data[6]));
+                       for (int ii = 0; ii < scan_count; ++ii)
+                       {
+                               if (!(layer == -1 || layer == 
data[SCAN_HEADER_LEN+SCAN_DATA_LEN*ii+2]))
+                                       continue;
+                               if (!(echo == -1 || echo == 
data[SCAN_HEADER_LEN+SCAN_DATA_LEN*ii+3]))
+                                       continue;
+                               uint16_t Distance_CM = 
htons(*reinterpret_cast<uint16_t *> 
(&data[SCAN_HEADER_LEN+SCAN_DATA_LEN*ii+6]));
+                               assert(SCAN_HEADER_LEN + 
SCAN_DATA_LEN*ii+6+HEADER_LEN <= rx_count);
+                               double distance_m = 
static_cast<double>(Distance_CM)/100.0;
+                               data_packet.ranges[true_count] = distance_m;
+                               int16_t angle_i = 
htons(*reinterpret_cast<uint16_t *> 
(&data[SCAN_HEADER_LEN+SCAN_DATA_LEN*ii+4]));
+                               if (angle_i > 180*32)
+                               {
+                                       angle_i -= 360*32;
+                               }
+                               double angle_d = DEG2RAD(angle_i)/32.0;
+                               data_packet.angles[true_count] = angle_d;
+                               if (intensity == 1)
+                               {
+                                       // echo width in cm
+                                       uint16_t tmp = 
htons(*reinterpret_cast<uint16_t *> 
(&data[SCAN_HEADER_LEN+SCAN_DATA_LEN*ii+8]));
+                                       if (tmp > 255)
+                                               tmp = 255;
+                                       data_packet.intensity[true_count] = tmp;
+                               }
+                               else if (intensity == 2)
+                                       data_packet.intensity[true_count] = 
data[SCAN_HEADER_LEN+SCAN_DATA_LEN*ii+3];
+                               else if (intensity == 3)
+                                       data_packet.intensity[true_count] = 
data[SCAN_HEADER_LEN+SCAN_DATA_LEN*ii+2];
+                               true_count++;
+
+                       }
+                       assert(true_count <= scan_count);
+                       data_packet.ranges_count = true_count;
+                       data_packet.angles_count = true_count;
+                       if (intensity)
+                               data_packet.intensity_count = true_count;
+                       else
+                               data_packet.intensity_count = 0;
+                       // About to publish stuff
+                       //GlobalTime->GetTime(&(this->debug_time));
+                       //PLAYER_MSG2(1,"LUX driver publishing data at time 
%d:%d", this->debug_time.tv_sec, this->debug_time.tv_usec);
+                       //PLAYER_MSG0(1, "Publishing data");
+                       //PLAYER_MSG2(1, "Scan number = %x %x", data[6], 
data[7]);
+                       //PLAYER_MSG2(1, "Rx_count %d size %d", rx_count, size);
+                       this->Publish (this->device_addr, PLAYER_MSGTYPE_DATA,
+                                        PLAYER_LASER_DATA_SCANANGLE, 
(void*)&data_packet);
+                       delete [] data_packet.ranges;
+                       delete [] data_packet.angles;
+                       delete [] data_packet.intensity;
+
+
+               }
+               else if (memcmp(&rx_buffer[14], "\x20\x20", 2) == 0)
+               {
+                       if (size != 2)
+                       {
+                               PLAYER_ERROR("Ibeo LUX: Only set mode ack 
returns are currently supported");
+                       }
+                       // Got a command message reply
+                       if (data[1] & 0x80)
+                               PLAYER_ERROR("Ibeo LUX: The laser returned a 
failed flag for the command message sent");
+
+               }
+               else
+                       PLAYER_WARN("Ibeo LUX got a unrecognised responce 
type");
+               memmove(rx_buffer, &rx_buffer[size+HEADER_LEN], rx_count - 
(size+HEADER_LEN));
+               rx_count -= (size + HEADER_LEN);
+               continue;
+       }
+       return 1;
+}
+
+void sickLDMRS::makeStartStopCommand(uint8_t* buffer, bool start /*= true*/ )
+{
+
+       buffer[0] = 0xAF; // magic word
+       buffer[1] = 0xFE;
+       buffer[2] = 0xC0;
+       buffer[3] = 0xC2;
+       buffer[4] = 0x00; // Size of previous message, here just left to nullL
+       buffer[5] = 0x00;
+       buffer[6] = 0x00;
+       buffer[7] = 0x00;
+       buffer[8] = 0x00; // Size of data block
+       buffer[9] = 0x00;
+       buffer[10] = 0x00;
+       buffer[11] = 0x0e;
+       buffer[12] = 0x00;      // Reserved + source Id
+       buffer[13] = 0x00;
+       buffer[14] = 0x20;      // Data Type - 2010 = command
+       buffer[15] = 0x10;
+       buffer[16] = 0x00;      // 4* ntpp time (s) + 4* fractions of a second
+       buffer[17] = 0x00;
+       buffer[18] = 0x00;
+       buffer[19] = 0x00;
+       buffer[20] = 0x00;
+       buffer[21] = 0x00;
+       buffer[22] = 0x00;
+       buffer[23] = 0x00;
+       // Data Block - all little endian
+       buffer[24] = 0x02;      // Command Type - 0002 = set mode
+       buffer[25] = 0x00;
+       buffer[26] = 0x00; // Version
+       buffer[27] = 0x00;
+       // Start of set mode stuff - all little endian
+       buffer[28] = 0xc0; // start angle /32
+       buffer[29] = 0x26;
+       buffer[30] = 0x40; // end angle /32
+       buffer[31] = 0x06;
+       buffer[32] = 0x80; // frequency /256, must be 12.5 Hz
+       buffer[33] = 0x0c;
+       if (start)
+       {
+               buffer[34] = 0x03;
+               buffer[35] = 0x03;
+       }
+       else
+       {
+               buffer[34] = 0x00;
+               buffer[35] = 0x00;
+       }
+       buffer[36] = 0x00; // reserved
+       buffer[37] = 0x00;
+
+
+}
+
+
+
+
+

Modified: code/player/trunk/server/drivers/shell/readlog.cc
===================================================================
--- code/player/trunk/server/drivers/shell/readlog.cc   2009-01-09 21:03:45 UTC 
(rev 7258)
+++ code/player/trunk/server/drivers/shell/readlog.cc   2009-01-09 21:14:24 UTC 
(rev 7259)
@@ -1559,6 +1559,55 @@
             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 = 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] = atof(tokens[i + 0]);
+                                 data.angles[count] = 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, type, 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);

Modified: code/player/trunk/server/drivers/shell/writelog.cc
===================================================================
--- code/player/trunk/server/drivers/shell/writelog.cc  2009-01-09 21:03:45 UTC 
(rev 7258)
+++ code/player/trunk/server/drivers/shell/writelog.cc  2009-01-09 21:14:24 UTC 
(rev 7259)
@@ -983,6 +983,7 @@
   player_laser_data_t* scan;
   player_laser_data_scanpose_t* scanpose;
   player_laser_geom_t* geom;
+  player_laser_data_scanangle_t* scanangle;
 
   // Check the type
   switch(hdr->type)
@@ -1032,6 +1033,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);
+                                 
         default:
           return(-1);
       }


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 is the best place to buy or sell services for
just about anything Open Source.
http://p.sf.net/sfu/Xq1LFB
_______________________________________________
Playerstage-commit mailing list
Playerstage-commit@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/playerstage-commit

Reply via email to