Update of /cvsroot/playerstage/code/player/server/drivers/ranger
In directory 
sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv22655/server/drivers/ranger

Added Files:
        Makefile.am lasertoranger.cc sonartoranger.cc toranger.cc 
        toranger.h 
Log Message:
added geoffs ranger interface


--- NEW FILE: sonartoranger.cc ---
/*
 *  Player - One Hell of a Robot Server
 *  Copyright (C) 2000  Brian Gerkey   &  Kasper Stoy
 *                      [EMAIL PROTECTED]    [EMAIL PROTECTED]
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either 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 General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */
///////////////////////////////////////////////////////////////////////////
//
// Desc: Driver for converting sonar-interface devices to ranger-interface
//       devices
// Author: Geoffrey Biggs
// Date: 06/05/2007
//
// Requires - sonar device.
//
///////////////////////////////////////////////////////////////////////////

/** @ingroup drivers */
/** @{ */
/** @defgroup driver_sonartoranger sonartoranger
 * @brief Sonar-to-Ranger converter

This driver translates data provided via the @ref interface_sonar interface into
the @ref interface_ranger interface.

@par Compile-time dependencies

- None

@par Provides

- @ref interface_ranger : Output ranger interface

@par Requires

- @ref interface_sonar : Sonar interface to translate

@par Configuration requests

- PLAYER_RANGER_REQ_GET_GEOM
- PLAYER_RANGER_REQ_POWER

@par Configuration file options

 - None

@par Example

@verbatim
driver
(
  name "p2os"
  provides ["sonar:0"]
)
driver
(
  name "sonartoranger"
  requires ["sonar:0"] # read from sonar:0
  provides ["ranger:0"] # output results on ranger:0
)
@endverbatim

@author Geoffrey Biggs

*/
/** @} */

#include <errno.h>
#include <string.h>

#include <libplayercore/playercore.h>

#include "toranger.h"

// Driver for computing the free c-space from a sonar scan.
class SonarToRanger : public ToRanger
{
        public:
                SonarToRanger (ConfigFile *cf, int section);

                int Setup (void);
                int Shutdown (void);

        protected:
                // Child message handler, for handling messages from the input 
device
                int ProcessMessage (MessageQueue *respQueue, player_msghdr 
*hdr, void *data);
                // Function called when a property has been changed so it can 
be passed on to the input driver
                bool PropertyChanged (void);
                // Set power state
                int SetPower (MessageQueue *respQueue, player_msghdr *hdr, 
uint8_t state);
                // Convert sonar geometry to ranger geometry
                int ConvertGeom (player_sonar_geom_t *geom);
                // Convert sonar data to ranger data
                int ConvertData (player_sonar_data_t *data);
};

// Initialisation function
Driver* SonarToRanger_Init (ConfigFile* cf, int section)
{
        return reinterpret_cast<Driver*> (new SonarToRanger (cf, section));
}

// Register function
void SonarToRanger_Register (DriverTable* table)
{
        table->AddDriver ("sonartoranger", SonarToRanger_Init);
}

////////////////////////////////////////////////////////////////////////////////
// Driver management
////////////////////////////////////////////////////////////////////////////////

// Constructor
// Sets up the input sonar interface
SonarToRanger::SonarToRanger( ConfigFile* cf, int section)
        : ToRanger (cf, section)
{
        // Need a sonar device as input
        if (cf->ReadDeviceAddr(&inputDeviceAddr, section, "requires", 
PLAYER_SONAR_CODE, -1, NULL) != 0)
        {
                SetError (-1);
                return;
        }
}

// Setup function
int SonarToRanger::Setup (void)
{
        // First call the base setup
        if (ToRanger::Setup () != 0)
                return -1;

        // Subscribe to the sonar.
        if ((inputDevice = deviceTable->GetDevice (inputDeviceAddr)) == NULL)
        {
                PLAYER_ERROR ("Could not find input sonar device");
                return -1;
        }

        if (inputDevice->Subscribe (InQueue) != 0)
        {
                PLAYER_ERROR ("Could not subscribe to input sonar device");
                return -1;
        }

        // Request the sonar geometry
        inputDevice->PutMsg (InQueue, PLAYER_MSGTYPE_REQ, 
PLAYER_SONAR_REQ_GET_GEOM, NULL, 0, NULL);

        return 0;
}

// Shutdown function
int SonarToRanger::Shutdown (void)
{
        // Unsubscribe from the sonar device
        inputDevice->Unsubscribe (InQueue);

        // Call the base shutdown function
        return ToRanger::Shutdown ();
}

////////////////////////////////////////////////////////////////////////////////
//  Message handling
////////////////////////////////////////////////////////////////////////////////

bool SonarToRanger::PropertyChanged (void)
{
        // No properties for sonar
        return true;
}

int SonarToRanger::ConvertGeom (player_sonar_geom_t *geom)
{
        double minX = 0.0f, maxX = 0.0f, minY = 0.0f, maxY = 0.0f;

        // Prepare some space for storing geometry data - the parent class will 
clean this up when necessary
        if (deviceGeom.sensor_poses != NULL)
                delete deviceGeom.sensor_poses;
        if (deviceGeom.sensor_sizes != NULL)
                delete deviceGeom.sensor_sizes;
        memset (&deviceGeom, 0, sizeof (player_ranger_geom_t));
        if ((deviceGeom.sensor_poses = new player_pose3d_t[geom->poses_count]) 
== NULL)
        {
                PLAYER_ERROR ("Failed to allocate memory for sensor poses");
                deviceGeom.sensor_poses = NULL;
                return 0;
        }
        memset (deviceGeom.sensor_poses, 0, sizeof (player_pose3d_t) * 
geom->poses_count);
        if ((deviceGeom.sensor_sizes = new player_bbox3d_t[geom->poses_count]) 
== NULL)
        {
                PLAYER_ERROR ("Failed to allocate memory for sensor sizes");
                delete deviceGeom.sensor_sizes;
                deviceGeom.sensor_sizes = NULL;
                return 0;
        }
        memset (deviceGeom.sensor_sizes, 0, sizeof (player_bbox3d_t) * 
geom->poses_count);

        // Copy across the poses, making a note of the bounding box for all 
poses
        deviceGeom.sensor_poses_count = geom->poses_count;
        for (uint32_t ii = 0; ii < geom->poses_count; ii++)
        {
                minX = (geom->poses[ii].px < minX) ? geom->poses[ii].px : minX;
                maxX = (geom->poses[ii].px > maxX) ? geom->poses[ii].px : maxX;
                deviceGeom.sensor_poses[ii].px = geom->poses[ii].px;
                minY = (geom->poses[ii].py < minY) ? geom->poses[ii].py : minY;
                maxY = (geom->poses[ii].py > maxY) ? geom->poses[ii].py : maxY;
                deviceGeom.sensor_poses[ii].py = geom->poses[ii].py;
                deviceGeom.sensor_poses[ii].pyaw = geom->poses[ii].pa;
        }
        // Even though the sensor sizes are all zero, they're still there
        deviceGeom.sensor_sizes_count = geom->poses_count;
        // Set the device size
        deviceGeom.size.sw = maxX - minX;
        deviceGeom.size.sl = maxY - minY;

        return 0;
}

int SonarToRanger::ConvertData (player_sonar_data_t *data)
{
        player_ranger_data_range_t rangeData;

        memset (&rangeData, 0, sizeof (rangeData));
        if ((rangeData.ranges = new double[data->ranges_count]) == NULL)
        {
                PLAYER_ERROR ("Failed to allocate memory for range data");
                return 0;
        }

        // Copy the data out
        rangeData.ranges_count = data->ranges_count;
        for (uint32_t ii = 0; ii < data->ranges_count; ii++)
                rangeData.ranges[ii] = data->ranges[ii];

        // Publish the data
        Publish (device_addr, NULL, PLAYER_MSGTYPE_DATA, 
PLAYER_RANGER_DATA_RANGE, reinterpret_cast<void*> (&rangeData), sizeof 
(rangeData), NULL);

        // Clean up
        delete[] rangeData.ranges;

        return 0;
}

int SonarToRanger::ProcessMessage (MessageQueue *respQueue, player_msghdr *hdr, 
void *data)
{
        // Check the parent message handler
        if (ToRanger::ProcessMessage (respQueue, hdr, data) == 0)
                return 0;

        // Check capabilities requests
        HANDLE_CAPABILITY_REQUEST (device_addr, respQueue, hdr, data, 
PLAYER_MSGTYPE_REQ, PLAYER_RANGER_REQ_POWER);
        HANDLE_CAPABILITY_REQUEST (device_addr, respQueue, hdr, data, 
PLAYER_MSGTYPE_REQ, PLAYER_RANGER_REQ_GET_GEOM);

        // Messages from the ranger interface
        // Power config request
        if (Message::MatchMessage (hdr, PLAYER_MSGTYPE_REQ, 
PLAYER_RANGER_REQ_POWER, device_addr))
        {
                // Tell the sonar device to switch the power state
                player_sonar_power_config_t req;
                req.state = reinterpret_cast<player_ranger_power_config_t*> 
(data)->state;
                inputDevice->PutMsg (InQueue, PLAYER_MSGTYPE_REQ, 
PLAYER_SONAR_REQ_POWER, &req, sizeof (req), 0);
                // Store the return queue
                ret_queue = respQueue;
                return 0;
        }
        // Geometry request
        else if (Message::MatchMessage (hdr, PLAYER_MSGTYPE_REQ, 
PLAYER_RANGER_REQ_GET_GEOM, device_addr))
        {
                // Get geometry from the sonar device
                inputDevice->PutMsg (InQueue, PLAYER_MSGTYPE_REQ, 
PLAYER_SONAR_REQ_GET_GEOM, NULL, 0, NULL);
                ret_queue = respQueue;
                return 0;
        }


        // Messages from the sonar interface
        // Reqest ACKs
        else if (Message::MatchMessage (hdr, PLAYER_MSGTYPE_RESP_ACK, 
PLAYER_SONAR_REQ_POWER, inputDeviceAddr))
        {
                // Power request
                Publish (device_addr, ret_queue, PLAYER_MSGTYPE_RESP_ACK, 
PLAYER_RANGER_REQ_POWER, NULL, 0, NULL);
                return 0;
        }
        else if (Message::MatchMessage (hdr, PLAYER_MSGTYPE_RESP_ACK, 
PLAYER_SONAR_REQ_GET_GEOM, inputDeviceAddr))
        {
                // Geometry request - need to manage the info we just got
                if (ConvertGeom (reinterpret_cast<player_sonar_geom_t*> (data)) 
== 0)
                {
                        Publish (device_addr, NULL, PLAYER_MSGTYPE_RESP_ACK, 
PLAYER_RANGER_REQ_GET_GEOM, reinterpret_cast<void*> (&deviceGeom), sizeof 
(deviceGeom), NULL);
                        return 0;
                }
                else
                {
                        Publish (device_addr, ret_queue, 
PLAYER_MSGTYPE_RESP_NACK, PLAYER_RANGER_REQ_GET_GEOM, NULL, 0, NULL);
                        return 0;
                }
        }

        // Request NACKs
        else if (Message::MatchMessage (hdr, PLAYER_MSGTYPE_RESP_NACK, 
PLAYER_SONAR_REQ_POWER, inputDeviceAddr))
        {
                // Power request
                Publish (device_addr, ret_queue, PLAYER_MSGTYPE_RESP_NACK, 
PLAYER_RANGER_REQ_POWER, NULL, 0, NULL);
                return 0;
        }
        else if (Message::MatchMessage (hdr, PLAYER_MSGTYPE_RESP_NACK, 
PLAYER_SONAR_REQ_GET_GEOM, inputDeviceAddr))
        {
                // Geometry request
                Publish (device_addr, ret_queue, PLAYER_MSGTYPE_RESP_NACK, 
PLAYER_RANGER_REQ_GET_GEOM, NULL, 0, NULL);
                return 0;
        }

        // Data
        else if (Message::MatchMessage (hdr, PLAYER_MSGTYPE_DATA, 
PLAYER_SONAR_DATA_RANGES, inputDeviceAddr))
        {
                return ConvertData (reinterpret_cast<player_sonar_data_t*> 
(data));
        }
        else if (Message::MatchMessage (hdr, PLAYER_MSGTYPE_DATA, 
PLAYER_SONAR_DATA_GEOM, inputDeviceAddr))
        {
                if (ConvertGeom (reinterpret_cast<player_sonar_geom_t*> (data)) 
== 0)
                {
                        Publish (device_addr, NULL, PLAYER_MSGTYPE_DATA, 
PLAYER_RANGER_DATA_GEOM, reinterpret_cast<void*> (&deviceGeom), sizeof 
(deviceGeom), NULL);
                        return 0;
                }
        }

        return -1;
        }

--- NEW FILE: toranger.h ---
/*
 *  Player - One Hell of a Robot Server
 *  Copyright (C) 2000  Brian Gerkey   &  Kasper Stoy
 *                      [EMAIL PROTECTED]    [EMAIL PROTECTED]
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either 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 General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

///////////////////////////////////////////////////////////////////////////
//
// Desc: Base class for ->ranger interface converter drivers.
// Author: Geoffrey Biggs
// Date: 06/05/2007
//
///////////////////////////////////////////////////////////////////////////

#include <libplayercore/playercore.h>
#include <libplayercore/error.h>

// Driver for computing the free c-space from a laser scan.
class ToRanger : public Driver
{
        public:
                ToRanger (ConfigFile* cf, int section);
                ~ToRanger (void);

                // Message processor - must be called first by child classes if 
overridden
                virtual int ProcessMessage (MessageQueue *resp_queue, 
player_msghdr *hdr, void *data);

                virtual int Setup (void);
                virtual int Shutdown (void);

        protected:
                // Function called when a property has been changed so it can 
be passed on to the input driver
                virtual bool PropertyChanged (void) = 0;

                // Property request processor
                int ProcessProperty (MessageQueue *respQueue, player_msghdr 
*hdr, void *data);

                // Ranger interface stuff - should be filled by ProcessMessage()
                player_ranger_geom_t deviceGeom;                        // 
Geometry of the device

                // Properties - should be set by GetDataFromSource()
                double minAngle;                                                
        // Minimum scan angle
                double maxAngle;                                                
        // Maximum scan angle
                double resolution;                                              
        // Scan resolution
                double maxRange;                                                
        // Scan range (m)
                double rangeRes;                                                
        // Range resolution (m)
                double frequency;                                               
        // Scanning frequency

                // Input device
                Device *inputDevice;                                            
// Input device interface
                player_devaddr_t inputDeviceAddr;                       // 
Input device address
};

--- NEW FILE: Makefile.am ---
noinst_LTLIBRARIES =

if INCLUDE_LASERTORANGER
noinst_LTLIBRARIES += liblasertoranger.la
endif

if INCLUDE_SONARTORANGER
noinst_LTLIBRARIES += libsonartoranger.la
endif


AM_CPPFLAGS = -Wall -I$(top_srcdir)

liblasertoranger_la_SOURCES = toranger.cc lasertoranger.cc

libsonartoranger_la_SOURCES = toranger.cc sonartoranger.cc
--- NEW FILE: lasertoranger.cc ---
/*
 *  Player - One Hell of a Robot Server
 *  Copyright (C) 2000  Brian Gerkey   &  Kasper Stoy
 *                      [EMAIL PROTECTED]    [EMAIL PROTECTED]
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either 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 General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */
///////////////////////////////////////////////////////////////////////////
//
// Desc: Driver for converting laser-interface devices to ranger-interface
//       devices
// Author: Geoffrey Biggs
// Date: 06/05/2007
//
// Requires - Laser device.
//
///////////////////////////////////////////////////////////////////////////

/** @ingroup drivers */
/** @{ */
/** @defgroup driver_lasertoranger lasertoranger
 * @brief Laser-to-Ranger converter

This driver translates data provided via the @ref interface_laser interface into
the @ref interface_ranger interface.

@par Compile-time dependencies

- None

@par Provides

- @ref interface_ranger : Output ranger interface

@par Requires

- @ref interface_laser : Laser interface to translate

@par Configuration requests

- PLAYER_RANGER_REQ_GET_GEOM
- PLAYER_RANGER_REQ_POWER
- PLAYER_RANGER_REQ_INTNS

@par Configuration file options

 - None

@par Example

@verbatim
driver
(
  name "sicklms200"
  provides ["laser:0"]
  port "/dev/ttyS0"
)
driver
(
  name "lasertoranger"
  requires ["laser:0"] # read from laser:0
  provides ["ranger:0"] # output results on ranger:0
)
@endverbatim

@author Geoffrey Biggs

*/
/** @} */

#include <errno.h>
#include <string.h>

#include <libplayercore/playercore.h>

#include "toranger.h"

// Driver for computing the free c-space from a laser scan.
class LaserToRanger : public ToRanger
{
        public:
                LaserToRanger (ConfigFile *cf, int section);

                int Setup (void);
                int Shutdown (void);

        protected:
                // Child message handler, for handling messages from the input 
device
                int ProcessMessage (MessageQueue *respQueue, player_msghdr 
*hdr, void *data);
                // Function called when a property has been changed so it can 
be passed on to the input driver
                bool PropertyChanged (void);
                // Set power state
                int SetPower (MessageQueue *respQueue, player_msghdr *hdr, 
uint8_t state);
                // Set intensity data state
                int SetIntensity (MessageQueue *respQueue, player_msghdr *hdr, 
uint8_t state);
                // Convert laser data to ranger data
                int ConvertData (player_msghdr *hdr, void *data);
                // Convert geometry data
                bool HandleGeomRequest (player_laser_geom_t *geom);

                uint8_t intensityState;                         // Intensity 
data state
                bool lastReqWasPropSet;                         // True if the 
last request sent to the laser was to set a property
};

// Initialisation function
Driver* LaserToRanger_Init (ConfigFile* cf, int section)
{
        return reinterpret_cast<Driver*> (new LaserToRanger (cf, section));
}

// Register function
void LaserToRanger_Register (DriverTable* table)
{
        table->AddDriver ("lasertoranger", LaserToRanger_Init);
}

////////////////////////////////////////////////////////////////////////////////
// Driver management
////////////////////////////////////////////////////////////////////////////////

// Constructor
// Sets up the input laser interface
LaserToRanger::LaserToRanger( ConfigFile* cf, int section)
        : ToRanger (cf, section)
{
        // Need a laser device as input
        if (cf->ReadDeviceAddr(&inputDeviceAddr, section, "requires", 
PLAYER_LASER_CODE, -1, NULL) != 0)
        {
                SetError (-1);
                return;
        }
}

// Setup function
int LaserToRanger::Setup (void)
{
        // First call the base setup
        if (ToRanger::Setup () != 0)
                return -1;

        // Subscribe to the laser.
        if ((inputDevice = deviceTable->GetDevice (inputDeviceAddr)) == NULL)
        {
                PLAYER_ERROR ("Could not find input laser device");
                return -1;
        }

        if (inputDevice->Subscribe (InQueue) != 0)
        {
                PLAYER_ERROR ("Could not subscribe to input laser device");
                return -1;
        }

        // Request the config from the laser to fill in the properties
        inputDevice->PutMsg (InQueue, PLAYER_MSGTYPE_REQ, 
PLAYER_LASER_REQ_GET_CONFIG, NULL, 0, NULL);

        // Prepare some space for storing geometry data - the parent class will 
clean this up when necessary
        deviceGeom.sensor_poses_count = 1;
        if ((deviceGeom.sensor_poses = new player_pose3d_t) == NULL)
        {
                PLAYER_ERROR ("Failed to allocate memory for sensor poses");
                return -1;
        }
        deviceGeom.sensor_sizes_count = 1;
        if ((deviceGeom.sensor_sizes = new player_bbox3d_t) == NULL)
        {
                PLAYER_ERROR ("Failed to allocate memory for sensor sizes");
                delete deviceGeom.sensor_sizes;
                deviceGeom.sensor_sizes = NULL;
                return -1;
        }

        return 0;
}

// Shutdown function
int LaserToRanger::Shutdown (void)
{
        // Unsubscribe from the laser device
        inputDevice->Unsubscribe (InQueue);

        // Call the base shutdown function
        return ToRanger::Shutdown ();
}

////////////////////////////////////////////////////////////////////////////////
//      Message handling
////////////////////////////////////////////////////////////////////////////////

bool LaserToRanger::PropertyChanged (void)
{
        // Make a config request to the laser with the properties
        player_laser_config_t req;

        req.min_angle = minAngle;
        req.max_angle = maxAngle;
        req.resolution = resolution;
        req.max_range = maxRange;
        req.range_res = rangeRes;
        req.intensity = intensityState;
        req.scanning_frequency = frequency;

        inputDevice->PutMsg (InQueue, PLAYER_MSGTYPE_REQ, 
PLAYER_LASER_REQ_SET_CONFIG, &req, sizeof (req), 0);

        return true;
}

int LaserToRanger::ConvertData (player_msghdr *hdr, void *data)
{
        player_laser_data_t *scanData = NULL;
        player_pose_t *pose = NULL;
        player_ranger_data_rangepose_t rangeData;
        player_ranger_data_intnspose_t intensityData;

        memset (&rangeData, 0, sizeof (rangeData));
        memset (&intensityData, 0, sizeof (intensityData));

        // Copy the data out
        if (hdr->subtype == PLAYER_LASER_DATA_SCAN)
                scanData = reinterpret_cast<player_laser_data_t*> (data);
        else if (hdr->subtype == PLAYER_LASER_DATA_SCANPOSE)
        {
                scanData = &(reinterpret_cast<player_laser_data_scanpose_t*> 
(data)->scan);
                pose = &(reinterpret_cast<player_laser_data_scanpose_t*> 
(data)->pose);
        }
        else
                return -1;

        // If we found a pose, handle that first (we will need to publish it)
        if (pose != NULL)
        {
                deviceGeom.pose.px = pose->px;
                deviceGeom.pose.py = pose->py;
                deviceGeom.pose.pz = 0.0f;
                deviceGeom.pose.proll = 0.0f;
                deviceGeom.pose.ppitch = 0.0f;
                deviceGeom.pose.pyaw = pose->pa;
                *(deviceGeom.sensor_poses) = deviceGeom.pose;
        }
        // Handle any data we got data
        if (data != NULL)
        {
                // Update the properties from the data
                minAngle = scanData->min_angle;
                maxAngle = scanData->max_angle;
                resolution = scanData->resolution;
                maxRange = scanData->max_range;

                // Copy out the range data
                if (scanData->ranges_count > 0)
                {
                        rangeData.data.ranges_count = scanData->ranges_count;
                        if ((rangeData.data.ranges = new 
double[scanData->ranges_count]) == NULL)
                        {
                                PLAYER_ERROR ("Failed to allocate memory for 
range data");
                                return 0;
                        }
                        for (uint32_t ii = 0; ii < scanData->ranges_count; ii++)
                                rangeData.data.ranges[ii] = 
scanData->ranges[ii];
                        // Send off this chunk of data, with pose if necessary
                        if (pose == NULL)
                                Publish (device_addr, NULL, 
PLAYER_MSGTYPE_DATA, PLAYER_RANGER_DATA_RANGE, reinterpret_cast<void*> 
(&rangeData.data), sizeof (rangeData.data), NULL);
                        else
                        {
                                rangeData.geom = deviceGeom;
                                Publish (device_addr, NULL, 
PLAYER_MSGTYPE_DATA, PLAYER_RANGER_DATA_RANGEPOSE, reinterpret_cast<void*> 
(&rangeData), sizeof (rangeData), NULL);
                        }
                        // Delete the space we allocated for the data
                        delete[] rangeData.data.ranges;
                }

                // Do the same for intensity data, if there is any
                if (scanData->intensity_count > 0)
                {
                        intensityData.data.intensities_count = 
scanData->intensity_count;
                        if ((intensityData.data.intensities = new 
double[scanData->intensity_count]) == NULL)
                        {
                                PLAYER_ERROR ("Failed to allocate memory for 
range data");
                                return 0;
                        }
                        for (uint32_t ii = 0; ii < scanData->intensity_count; 
ii++)
                                intensityData.data.intensities[ii] = 
scanData->intensity[ii];
                        // Send off this chunk of data, with pose if necessary
                        if (pose == NULL)
                                Publish (device_addr, NULL, 
PLAYER_MSGTYPE_DATA, PLAYER_RANGER_DATA_INTNS, reinterpret_cast<void*> 
(&intensityData.data), sizeof (intensityData.data), NULL);
                        else
                        {
                                rangeData.geom = deviceGeom;
                                Publish (device_addr, NULL, 
PLAYER_MSGTYPE_DATA, PLAYER_RANGER_DATA_INTNSPOSE, reinterpret_cast<void*> 
(&intensityData), sizeof (intensityData), NULL);
                        }
                        // Delete the space we allocated for the data
                        delete[] intensityData.data.intensities;
                }
        }

        return 0;
}

bool LaserToRanger::HandleGeomRequest (player_laser_geom_t *data)
{
        deviceGeom.pose.px = data->pose.px;
        deviceGeom.pose.py = data->pose.py;
        deviceGeom.pose.pz = 0.0f;
        deviceGeom.pose.proll = 0.0f;
        deviceGeom.pose.ppitch = 0.0f;
        deviceGeom.pose.pyaw = data->pose.pa;
        deviceGeom.size.sw = data->size.sw;
        deviceGeom.size.sl = data->size.sl;
        deviceGeom.size.sh = 0.0f;

        *(deviceGeom.sensor_poses) = deviceGeom.pose;
        *(deviceGeom.sensor_sizes) = deviceGeom.size;

        return true;
}

int LaserToRanger::ProcessMessage (MessageQueue *respQueue, player_msghdr *hdr, 
void *data)
{
        // Check the parent message handler
        if (ToRanger::ProcessMessage (respQueue, hdr, data) == 0)
                return 0;

        // Check capabilities requests
        HANDLE_CAPABILITY_REQUEST (device_addr, respQueue, hdr, data, 
PLAYER_MSGTYPE_REQ, PLAYER_RANGER_REQ_POWER);
        HANDLE_CAPABILITY_REQUEST (device_addr, respQueue, hdr, data, 
PLAYER_MSGTYPE_REQ, PLAYER_RANGER_REQ_INTNS);
        HANDLE_CAPABILITY_REQUEST (device_addr, respQueue, hdr, data, 
PLAYER_MSGTYPE_REQ, PLAYER_RANGER_REQ_GET_GEOM);

        // Messages from the ranger interface
        // Power config request
        if (Message::MatchMessage (hdr, PLAYER_MSGTYPE_REQ, 
PLAYER_RANGER_REQ_POWER, device_addr))
        {
                // Tell the laser device to switch the power state
                player_laser_power_config_t req;
                req.state = reinterpret_cast<player_ranger_power_config_t*> 
(data)->state;
                inputDevice->PutMsg (InQueue, PLAYER_MSGTYPE_REQ, 
PLAYER_LASER_REQ_POWER, &req, sizeof (req), 0);
                // Store the return queue
                ret_queue = respQueue;
                return 0;
        }
        // Intensity data config request
        else if (Message::MatchMessage (hdr, PLAYER_MSGTYPE_REQ, 
PLAYER_RANGER_REQ_INTNS, device_addr))
        {
                // Tell the laser device to give intensity data
                intensityState = 
reinterpret_cast<player_ranger_intns_config_t*> (data)->state;
                PropertyChanged ();
                lastReqWasPropSet = false;
                return 0;
        }
        // Geometry request
        else if (Message::MatchMessage (hdr, PLAYER_MSGTYPE_REQ, 
PLAYER_RANGER_REQ_GET_GEOM, device_addr))
        {
                // Get geometry from the laser device
                inputDevice->PutMsg (InQueue, PLAYER_MSGTYPE_REQ, 
PLAYER_LASER_REQ_GET_GEOM, NULL, 0, NULL);
                ret_queue = respQueue;
                return 0;
        }


        // Messages from the laser interface
        // Reqest ACKs
        else if (Message::MatchMessage (hdr, PLAYER_MSGTYPE_RESP_ACK, 
PLAYER_LASER_REQ_POWER, inputDeviceAddr))
        {
                // Power request
                Publish (device_addr, ret_queue, PLAYER_MSGTYPE_RESP_ACK, 
PLAYER_RANGER_REQ_POWER, NULL, 0, NULL);
                return 0;
        }
        else if (Message::MatchMessage (hdr, PLAYER_MSGTYPE_RESP_ACK, 
PLAYER_LASER_REQ_SET_CONFIG, inputDeviceAddr))
        {
                // Config request (may have been triggered by a propset on the 
ranger interface)
                if (lastReqWasPropSet)
                        Publish (device_addr, ret_queue, 
PLAYER_MSGTYPE_RESP_ACK, PLAYER_SET_DBLPROP_REQ, NULL, 0, NULL);
                else
                        Publish (device_addr, ret_queue, 
PLAYER_MSGTYPE_RESP_ACK, PLAYER_RANGER_REQ_INTNS, NULL, 0, NULL);
                return 0;
        }
        else if (Message::MatchMessage (hdr, PLAYER_MSGTYPE_RESP_ACK, 
PLAYER_LASER_REQ_GET_CONFIG, inputDeviceAddr))
        {
                // Copy the config values into the properties
                player_laser_config_t *req = 
reinterpret_cast<player_laser_config_t*> (data);
                minAngle = req->min_angle;
                maxAngle = req->max_angle;
                resolution = req->resolution;
                maxRange = req->max_range;
                rangeRes = req->range_res;
                frequency = req->scanning_frequency;
                // Get config requests can only come from this driver, not 
clients to this driver, so no need to send a message to clients
                return 0;
        }
        else if (Message::MatchMessage (hdr, PLAYER_MSGTYPE_RESP_ACK, 
PLAYER_LASER_REQ_GET_GEOM, inputDeviceAddr))
        {
                // Geometry request - need to manage the info we just got
                if (HandleGeomRequest (reinterpret_cast<player_laser_geom_t*> 
(data)))
                        Publish (device_addr, ret_queue, 
PLAYER_MSGTYPE_RESP_ACK, PLAYER_RANGER_REQ_GET_GEOM, &deviceGeom, sizeof 
(deviceGeom), NULL);
                else
                        Publish (device_addr, ret_queue, 
PLAYER_MSGTYPE_RESP_NACK, PLAYER_RANGER_REQ_GET_GEOM, NULL, 0, NULL);
        }

        // Request NACKs
        else if (Message::MatchMessage (hdr, PLAYER_MSGTYPE_RESP_NACK, 
PLAYER_LASER_REQ_POWER, inputDeviceAddr))
        {
                // Power request
                Publish (device_addr, ret_queue, PLAYER_MSGTYPE_RESP_NACK, 
PLAYER_RANGER_REQ_POWER, NULL, 0, NULL);
                return 0;
        }
        else if (Message::MatchMessage (hdr, PLAYER_MSGTYPE_RESP_NACK, 
PLAYER_LASER_REQ_SET_CONFIG, inputDeviceAddr))
        {
                // Config request (may have been triggered by a propset on the 
ranger interface)
                if (lastReqWasPropSet)
                        Publish (device_addr, ret_queue, 
PLAYER_MSGTYPE_RESP_NACK, PLAYER_SET_DBLPROP_REQ, NULL, 0, NULL);
                else
                        Publish (device_addr, ret_queue, 
PLAYER_MSGTYPE_RESP_NACK, PLAYER_RANGER_REQ_INTNS, NULL, 0, NULL);
                return 0;
        }
        else if (Message::MatchMessage (hdr, PLAYER_MSGTYPE_RESP_NACK, 
PLAYER_LASER_REQ_GET_GEOM, inputDeviceAddr))
        {
                // Geometry request
                Publish (device_addr, ret_queue, PLAYER_MSGTYPE_RESP_NACK, 
PLAYER_RANGER_REQ_GET_GEOM, NULL, 0, NULL);
                return 0;
        }

        // Data
        else if (Message::MatchMessage (hdr, PLAYER_MSGTYPE_DATA, -1, 
inputDeviceAddr))
        {
                return ConvertData (hdr, data);
        }

        return -1;
}

--- NEW FILE: toranger.cc ---
/*
 *  Player - One Hell of a Robot Server
 *  Copyright (C) 2000  Brian Gerkey   &  Kasper Stoy
 *                      [EMAIL PROTECTED]    [EMAIL PROTECTED]
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either 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 General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

///////////////////////////////////////////////////////////////////////////
//
// Desc: Base class for ->ranger interface converter drivers.
// Author: Geoffrey Biggs
// Date: 06/05/2007
//
///////////////////////////////////////////////////////////////////////////

#include "toranger.h"

////////////////////////////////////////////////////////////////////////////////
//      Driver management
////////////////////////////////////////////////////////////////////////////////

// Constructor
// Nothing to do
ToRanger::ToRanger (ConfigFile* cf, int section)
        : Driver (cf, section, false, PLAYER_MSGQUEUE_DEFAULT_MAXLEN, 
PLAYER_RANGER_CODE)
{
        inputDevice = NULL;
}

// Destructor
ToRanger::~ToRanger (void)
{
        if (deviceGeom.sensor_poses != NULL)
                delete deviceGeom.sensor_poses;
        if (deviceGeom.sensor_sizes != NULL)
                delete deviceGeom.sensor_sizes;
}

// Setup function
// Cleans up the output data for use
int ToRanger::Setup (void)
{
        // Clean output
        memset (&deviceGeom, 0, sizeof (deviceGeom));
        // Clean properties
        minAngle = 0.0f;
        maxAngle = 0.0f;
        resolution = 0.0f;
        maxRange = 0.0f;
        rangeRes = 0.0f;
        frequency = 0.0f;

        return 0;
}

// Shutdown function
// Ensures all the ranger data memory is freed
int ToRanger::Shutdown (void)
{
        if (deviceGeom.sensor_poses != NULL)
        {
                delete deviceGeom.sensor_poses;
                deviceGeom.sensor_poses = NULL;
        }
        if (deviceGeom.sensor_sizes != NULL)
        {
                delete deviceGeom.sensor_sizes;
                deviceGeom.sensor_sizes = NULL;
        }

        return 0;
}

////////////////////////////////////////////////////////////////////////////////
//      Message handling
////////////////////////////////////////////////////////////////////////////////

// Message processing
int ToRanger::ProcessMessage (MessageQueue *respQueue, player_msghdr *hdr, void 
*data)
{
        // Check for capabilities requests first
        HANDLE_CAPABILITY_REQUEST (device_addr, respQueue, hdr, data, 
PLAYER_MSGTYPE_REQ, PLAYER_CAPABILTIES_REQ);

        // Override default handling of properties
        if (ProcessProperty (respQueue, hdr, data) == 0)
                return 0;

        // Pass other property get/set messages through to the input device
        if (Message::MatchMessage (hdr, PLAYER_MSGTYPE_REQ, 
PLAYER_GET_INTPROP_REQ, device_addr) ||
                        Message::MatchMessage (hdr, PLAYER_MSGTYPE_REQ, 
PLAYER_SET_INTPROP_REQ, device_addr) ||
                        Message::MatchMessage (hdr, PLAYER_MSGTYPE_REQ, 
PLAYER_GET_DBLPROP_REQ, device_addr) ||
                        Message::MatchMessage (hdr, PLAYER_MSGTYPE_REQ, 
PLAYER_SET_DBLPROP_REQ, device_addr) ||
                        Message::MatchMessage (hdr, PLAYER_MSGTYPE_REQ, 
PLAYER_GET_STRPROP_REQ, device_addr) ||
                        Message::MatchMessage (hdr, PLAYER_MSGTYPE_REQ, 
PLAYER_SET_STRPROP_REQ, device_addr))
        {
                inputDevice->PutMsg (InQueue, hdr, data);
                ret_queue = respQueue;
                return 0;
        }
        // Pass responses to them back to the client
        else if (Message::MatchMessage (hdr, PLAYER_MSGTYPE_RESP_ACK, 
PLAYER_GET_INTPROP_REQ, inputDeviceAddr) ||
                        Message::MatchMessage (hdr, PLAYER_MSGTYPE_RESP_ACK, 
PLAYER_SET_INTPROP_REQ, inputDeviceAddr) ||
                        Message::MatchMessage (hdr, PLAYER_MSGTYPE_RESP_ACK, 
PLAYER_GET_DBLPROP_REQ, inputDeviceAddr) ||
                        Message::MatchMessage (hdr, PLAYER_MSGTYPE_RESP_ACK, 
PLAYER_SET_DBLPROP_REQ, inputDeviceAddr) ||
                        Message::MatchMessage (hdr, PLAYER_MSGTYPE_RESP_ACK, 
PLAYER_GET_STRPROP_REQ, inputDeviceAddr) ||
                        Message::MatchMessage (hdr, PLAYER_MSGTYPE_RESP_ACK, 
PLAYER_SET_STRPROP_REQ, inputDeviceAddr) ||
                        Message::MatchMessage (hdr, PLAYER_MSGTYPE_RESP_NACK, 
PLAYER_GET_INTPROP_REQ, inputDeviceAddr) ||
                        Message::MatchMessage (hdr, PLAYER_MSGTYPE_RESP_NACK, 
PLAYER_SET_INTPROP_REQ, inputDeviceAddr) ||
                        Message::MatchMessage (hdr, PLAYER_MSGTYPE_RESP_NACK, 
PLAYER_GET_DBLPROP_REQ, inputDeviceAddr) ||
                        Message::MatchMessage (hdr, PLAYER_MSGTYPE_RESP_NACK, 
PLAYER_SET_DBLPROP_REQ, inputDeviceAddr) ||
                        Message::MatchMessage (hdr, PLAYER_MSGTYPE_RESP_NACK, 
PLAYER_GET_STRPROP_REQ, inputDeviceAddr) ||
                        Message::MatchMessage (hdr, PLAYER_MSGTYPE_RESP_NACK, 
PLAYER_SET_STRPROP_REQ, inputDeviceAddr))
        {
                hdr->addr = device_addr;
                Publish (ret_queue, hdr, data);
                return 0;
        }

        return -1;
}

// Property processing
// This overrides the default handling of properties from the Driver class.
// It only handles double properties, and only those we know about (the 5 
member variables).
// Anything else returns -1, so the Driver class property handling will catch 
it.
int ToRanger::ProcessProperty (MessageQueue *respQueue, player_msghdr *hdr, 
void *data)
{
        if(Message::MatchMessage(hdr, PLAYER_MSGTYPE_REQ, 
PLAYER_GET_DBLPROP_REQ, device_addr))
        {
                player_dblprop_req_t *req = 
reinterpret_cast<player_dblprop_req_t*> (data);
                if (strcmp (req->key, "min_angle") == 0)
                        req->value = minAngle;
                else if (strcmp (req->key, "max_angle") == 0)
                        req->value = maxAngle;
                else if (strcmp (req->key, "resolution") == 0)
                        req->value = resolution;
                else if (strcmp (req->key, "max_range") == 0)
                        req->value = maxRange;
                else if (strcmp (req->key, "range_res") == 0)
                        req->value = rangeRes;
                else if (strcmp (req->key, "frequency") == 0)
                        req->value = frequency;
                else
                        return -1;

                printf ("Handling prop get request for property %s, returning 
value %f\n", req->key, req->value);
                Publish (device_addr, respQueue, PLAYER_MSGTYPE_RESP_ACK, 
PLAYER_GET_DBLPROP_REQ, reinterpret_cast<void*> (req), 
sizeof(player_dblprop_req_t), NULL);
                return 0;
        }
        else if(Message::MatchMessage(hdr, PLAYER_MSGTYPE_REQ, 
PLAYER_SET_DBLPROP_REQ, device_addr))
        {
                player_dblprop_req_t *req = 
reinterpret_cast<player_dblprop_req_t*> (data);
                if (strcmp (req->key, "min_angle") == 0)
                        minAngle = req->value;
                else if (strcmp (req->key, "max_angle") == 0)
                        maxAngle = req->value;
                else if (strcmp (req->key, "resolution") == 0)
                        resolution = req->value;
                else if (strcmp (req->key, "max_range") == 0)
                        maxRange = req->value;
                else if (strcmp (req->key, "range_res") == 0)
                        rangeRes = req->value;
                else if (strcmp (req->key, "frequency") == 0)
                        frequency = req->value;
                else
                        return -1;

                // Notify the input device of the new property
                // Prop set request ACK will be sent when a reply is received 
from the input device
                PropertyChanged ();
                return 0;
        }

        return -1;
}


-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
Playerstage-commit mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/playerstage-commit

Reply via email to