Revision: 7967
          http://playerstage.svn.sourceforge.net/playerstage/?rev=7967&view=rev
Author:   gbiggs
Date:     2009-07-10 00:34:17 +0000 (Fri, 10 Jul 2009)

Log Message:
-----------
Applied patch #2816685

Modified Paths:
--------------
    code/player/trunk/server/drivers/position/CMakeLists.txt

Added Paths:
-----------
    code/player/trunk/server/drivers/position/globalize/
    code/player/trunk/server/drivers/position/globalize/CMakeLists.txt
    code/player/trunk/server/drivers/position/globalize/globalize.cc
    code/player/trunk/server/drivers/position/goto/
    code/player/trunk/server/drivers/position/goto/CMakeLists.txt
    code/player/trunk/server/drivers/position/goto/goto.cc

Modified: code/player/trunk/server/drivers/position/CMakeLists.txt
===================================================================
--- code/player/trunk/server/drivers/position/CMakeLists.txt    2009-07-10 
00:27:48 UTC (rev 7966)
+++ code/player/trunk/server/drivers/position/CMakeLists.txt    2009-07-10 
00:34:17 UTC (rev 7967)
@@ -1,5 +1,7 @@
 ADD_SUBDIRECTORY (ascension)
 ADD_SUBDIRECTORY (bumpersafe)
+ADD_SUBDIRECTORY (globalize)
+ADD_SUBDIRECTORY (goto)
 ADD_SUBDIRECTORY (isense)
 ADD_SUBDIRECTORY (lasersafe)
 ADD_SUBDIRECTORY (mbicp)

Added: code/player/trunk/server/drivers/position/globalize/CMakeLists.txt
===================================================================
--- code/player/trunk/server/drivers/position/globalize/CMakeLists.txt          
                (rev 0)
+++ code/player/trunk/server/drivers/position/globalize/CMakeLists.txt  
2009-07-10 00:34:17 UTC (rev 7967)
@@ -0,0 +1,2 @@
+PLAYERDRIVER_OPTION (globalize build_globalize ON)
+PLAYERDRIVER_ADD_DRIVER (globalize build_globalize SOURCES globalize.cc)

Added: code/player/trunk/server/drivers/position/globalize/globalize.cc
===================================================================
--- code/player/trunk/server/drivers/position/globalize/globalize.cc            
                (rev 0)
+++ code/player/trunk/server/drivers/position/globalize/globalize.cc    
2009-07-10 00:34:17 UTC (rev 7967)
@@ -0,0 +1,305 @@
+/*
+ *  Player - One Hell of a Robot Server
+ *  Copyright (C) 2004  Brian Gerkey [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
+ *
+ */
+
+/*
+ *
+ * This driver replaces local (odometry) position data with global position.
+ */
+
+/** @ingroup drivers */
+/** @{ */
+/** @defgroup driver_Globalize Globalize
+ * @brief This driver replaces local (odometry) position data with global 
position.
+
+...@par Provides
+
+- @ref interface_position2d
+  - commands will be passed to "local" position2d device (VELOCITY COMMANDS 
ONLY!)
+
+...@par Requires
+
+- @ref interface_position2d
+  - key "local" - local position2d device
+  - key "global" - global positioning device (amcl or something)
+
+...@par Configuration requests
+
+- cmd_interval (float)
+  - default: -1.0
+  - if greater than zero, commands will be sent with this interval
+
+...@par Configuration file options
+
+- None
+
+...@par Example
+
+...@verbatim
+driver
+(
+  name "globalize"
+  provides ["position2d:10"]
+  requires ["local:::position2d:0" "global:::position2d:1"]
+)
+...@endverbatim
+
+...@author Paul Osmialowski
+
+*/
+
+/** @} */
+
+#include <stddef.h>
+#include <string.h>
+#include <assert.h>
+#include <libplayercore/playercore.h>
+
+#define RQ_QUEUE_LEN 10
+
+extern PlayerTime * GlobalTime;
+
+class Globalize : public Driver
+{
+  public:
+    Globalize(ConfigFile * cf, int section);
+    virtual ~Globalize();
+    virtual int Setup();
+    virtual int Shutdown();
+    virtual int ProcessMessage(QueuePointer & resp_queue,
+                               player_msghdr * hdr,
+                               void * data);
+  private:
+    Device * r_local_pos_dev;
+    Device * r_global_pos_dev;
+    player_devaddr_t r_local_pos_addr;
+    player_devaddr_t r_global_pos_addr;
+    player_devaddr_t p_pos_addr;
+    player_msghdr_t rq_hdrs[RQ_QUEUE_LEN];
+    QueuePointer rq_ptrs[RQ_QUEUE_LEN];
+    int rq;
+    double cmd_interval;
+    double cmd_time;
+    uint8_t stall;
+};
+
+Globalize::Globalize(ConfigFile* cf, int section) : Driver(cf, section, true, 
PLAYER_MSGQUEUE_DEFAULT_MAXLEN)
+{
+  this->r_local_pos_dev = NULL;
+  this->r_global_pos_dev = NULL;
+  memset(&(this->r_local_pos_addr), 0, sizeof(player_devaddr_t));
+  memset(&(this->r_global_pos_addr), 0, sizeof(player_devaddr_t));
+  memset(&(this->p_pos_addr), 0, sizeof(player_devaddr_t));
+  memset(this->rq_hdrs, 0, sizeof this->rq_hdrs);
+  this->rq = -1;
+  this->cmd_interval = 0.0;
+  this->cmd_time = 0.0;
+  this->stall = 0;
+  if (cf->ReadDeviceAddr(&(this->p_pos_addr), section, "provides",
+      PLAYER_POSITION2D_CODE, -1, NULL))
+  {
+    this->SetError(-1);
+    return;
+  }
+  if (this->AddInterface(this->p_pos_addr))
+  {
+    this->SetError(-1);
+    return;
+  }
+  if (cf->ReadDeviceAddr(&(this->r_local_pos_addr), section, "requires",
+      PLAYER_POSITION2D_CODE, -1, "local"))
+  {
+    this->SetError(-1);
+    return;
+  }
+  if (cf->ReadDeviceAddr(&(this->r_global_pos_addr), section, "requires",
+      PLAYER_POSITION2D_CODE, -1, "global"))
+  {
+    this->SetError(-1);
+    return;
+  }
+  this->cmd_interval = cf->ReadFloat(section, "cmd_interval", -1.0);
+}
+
+Globalize::~Globalize() { }
+
+int Globalize::Setup()
+{
+  this->r_local_pos_dev = NULL;
+  this->r_global_pos_dev = NULL;
+  this->cmd_time = 0.0;
+  this->stall = 0;
+  memset(this->rq_hdrs, 0, sizeof this->rq_hdrs);
+  this->rq = -1;
+  if ((Device::MatchDeviceAddress(this->r_local_pos_addr, this->p_pos_addr))
+      || (Device::MatchDeviceAddress(this->r_global_pos_addr, 
this->p_pos_addr)))
+  {
+    PLAYER_ERROR("attempt to subscribe to self");
+    return -1;
+  }
+  this->r_local_pos_dev = deviceTable->GetDevice(this->r_local_pos_addr);
+  if (!(this->r_local_pos_dev))
+  {
+    PLAYER_ERROR("unable to locate suitable local position2d device");
+    return -1;
+  }
+  if (this->r_local_pos_dev->Subscribe(this->InQueue))
+  {
+    PLAYER_ERROR("unable to subscribe to local position2d device");
+    this->r_local_pos_dev = NULL;
+    return -1;
+  }
+  this->r_global_pos_dev = deviceTable->GetDevice(this->r_global_pos_addr);
+  if (!(this->r_global_pos_dev))
+  {
+    PLAYER_ERROR("unable to locate suitable global position2d device");
+    this->r_local_pos_dev->Unsubscribe(this->InQueue);
+    this->r_local_pos_dev = NULL;
+    return -1;
+  }
+  if (this->r_global_pos_dev->Subscribe(this->InQueue))
+  {
+    PLAYER_ERROR("unable to subscribe to global position2d device");
+    this->r_local_pos_dev->Unsubscribe(this->InQueue);
+    this->r_local_pos_dev = NULL;
+    this->r_global_pos_dev = NULL;
+    return -1;
+  }
+  return 0;
+}
+
+int Globalize::Shutdown()
+{
+  if (this->r_local_pos_dev) this->r_local_pos_dev->Unsubscribe(this->InQueue);
+  this->r_local_pos_dev = NULL;
+  if (this->r_global_pos_dev) 
this->r_global_pos_dev->Unsubscribe(this->InQueue);
+  this->r_global_pos_dev = NULL;
+  return 0;
+}
+
+int Globalize::ProcessMessage(QueuePointer &resp_queue,
+                              player_msghdr * hdr,
+                              void * data)
+{
+  player_msghdr_t newhdr;
+  player_position2d_data_t pos_data;
+  double d;
+  QueuePointer null;
+
+  if (!hdr)
+  {
+    PLAYER_ERROR("NULL hdr");
+    return -1;
+  }
+  if (Message::MatchMessage(hdr, PLAYER_MSGTYPE_CMD, 
PLAYER_POSITION2D_CMD_VEL, this->p_pos_addr))
+  {
+    if (!data)
+    {
+      PLAYER_ERROR("NULL data");
+      return -1;
+    }
+    if ((this->cmd_interval) > 0.0)
+    {
+      GlobalTime->GetTimeDouble(&d);
+      if ((d - (this->cmd_time)) < (this->cmd_interval)) return 0;
+    }
+    this->r_local_pos_dev->PutMsg(this->InQueue, hdr, data);
+    GlobalTime->GetTimeDouble(&(this->cmd_time));
+    return 0;
+  }
+  if (Message::MatchMessage(hdr, PLAYER_MSGTYPE_REQ, -1, this->p_pos_addr))
+  {
+    if ((this->rq) >= RQ_QUEUE_LEN) return -1;
+    this->rq++;
+    assert((this->rq) >= 0);
+    this->rq_hdrs[this->rq] = *hdr;
+    this->rq_ptrs[this->rq] = resp_queue;
+    if (!(this->rq))
+    {
+      newhdr = this->rq_hdrs[this->rq];
+      newhdr.addr = this->r_local_pos_addr;
+      this->r_local_pos_dev->PutMsg(this->InQueue, &newhdr, data);
+    }
+    return 0;
+  }
+  if ((Message::MatchMessage(hdr, PLAYER_MSGTYPE_RESP_ACK, -1, 
this->r_local_pos_addr)) || (Message::MatchMessage(hdr, 
PLAYER_MSGTYPE_RESP_NACK, -1, this->r_local_pos_addr)))
+  {
+    assert((this->rq) >= 0);
+    assert((hdr->subtype) == (this->rq_hdrs[this->rq].subtype));
+    this->Publish(this->p_pos_addr, rq_ptrs[this->rq], hdr->type, 
hdr->subtype, data, 0, &(hdr->timestamp));
+    this->rq_ptrs[this->rq] = null;
+    this->rq--;
+    if ((this->rq) >= 0)
+    {
+      newhdr = this->rq_hdrs[this->rq];
+      newhdr.addr = this->r_local_pos_addr;
+      this->r_local_pos_dev->PutMsg(this->InQueue, &newhdr, data);
+    }
+    return 0;
+  }
+  if (Message::MatchMessage(hdr, PLAYER_MSGTYPE_DATA,
+                            PLAYER_POSITION2D_DATA_STATE,
+                            this->r_global_pos_addr))
+  {
+    if (!data)
+    {
+      PLAYER_ERROR("NULL data");
+      return -1;
+    }
+    pos_data = *(reinterpret_cast<player_position2d_data_t *>(data));
+    pos_data.stall = this->stall;
+    newhdr = *hdr;
+    newhdr.addr = this->p_pos_addr;
+    this->Publish(&newhdr, reinterpret_cast<void *>(&pos_data));
+    return 0;
+  }
+  if (Message::MatchMessage(hdr, PLAYER_MSGTYPE_DATA,
+                            PLAYER_POSITION2D_DATA_STATE,
+                            this->r_local_pos_addr))
+  {
+    if (!data)
+    {
+      PLAYER_ERROR("NULL data");
+      return -1;
+    }
+    pos_data = *(reinterpret_cast<player_position2d_data_t *>(data));
+    this->stall = pos_data.stall;
+    return 0;
+  }
+  return -1;
+}
+
+// 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 * Globalize_Init(ConfigFile * cf, int section)
+{
+  // Create and return a new instance of this driver
+  return reinterpret_cast<Driver *>(new Globalize(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 globalize_Register(DriverTable * table)
+{
+  table->AddDriver("globalize", Globalize_Init);
+}

Added: code/player/trunk/server/drivers/position/goto/CMakeLists.txt
===================================================================
--- code/player/trunk/server/drivers/position/goto/CMakeLists.txt               
                (rev 0)
+++ code/player/trunk/server/drivers/position/goto/CMakeLists.txt       
2009-07-10 00:34:17 UTC (rev 7967)
@@ -0,0 +1,2 @@
+PLAYERDRIVER_OPTION (goto build_goto ON)
+PLAYERDRIVER_ADD_DRIVER (goto build_goto SOURCES goto.cc)

Added: code/player/trunk/server/drivers/position/goto/goto.cc
===================================================================
--- code/player/trunk/server/drivers/position/goto/goto.cc                      
        (rev 0)
+++ code/player/trunk/server/drivers/position/goto/goto.cc      2009-07-10 
00:34:17 UTC (rev 7967)
@@ -0,0 +1,662 @@
+/*
+ *  Player - One Hell of a Robot Server
+ *  Copyright (C) 2004  Brian Gerkey [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
+ *
+ */
+
+/*
+ *
+ * A robot controller that drives a robot to a given target.
+ */
+
+/** @ingroup drivers */
+/** @{ */
+/** @defgroup driver_Goto Goto
+ * @brief A robot controller that drives a robot to a given target.
+
+...@par Provides
+
+- @ref interface_position2d
+- @ref interface_dio
+
+...@par Requires
+
+- @ref interface_position2d
+
+...@par Configuration requests
+
+- None
+
+...@par Configuration file options
+
+- dist_tol (float)
+  - Default: DEFAULT_DIST_TOL
+  - Distance to the target tollerance
+- angle_tol (float)
+  - Default: DEFAULT_ANGLE_TOL
+  - Angle difference tollerance
+- max_dist (float)
+  - Default: 0.5
+  - Maximum distance between checkpoints
+- debug (integer)
+  - Default: 0
+  - Debug
+- reactive (integer)
+  - Default: 0
+  - Shall we react for stall states?
+- forward_enabled (integer)
+  - Default: 0
+  - Shall we forward position2d velocity commands?
+- early_check (integer)
+  - Default: 1
+  - If set to 1, do not wait for newer position data to check if at target
+- send_everything (integer)
+  - Default: 1
+  - If set to 1, data and commands are sent at once
+
+...@par Example
+
+...@verbatim
+driver
+(
+  name "goto"
+  provides ["position2d:100" "dio:0"]
+  requires ["position2d:0"]
+  debug 1
+  reactive 1
+)
+...@endverbatim
+
+...@author Paul Osmialowski
+
+*/
+
+/** @} */
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <math.h>
+#include <assert.h>
+#include <libplayercore/playercore.h>
+
+#define EPS 0.000000000000001
+
+#define DEFAULT_DIST_TOL 0.04
+#define DEFAULT_ANGLE_TOL 3.0
+#define AMIN 5.0
+#define AMAX 20.0
+#define AVMIN 10.0
+#define AVMAX 45.0
+#define MAXD 2.0
+#define TVMIN 0.1
+#define TVMAX 0.7
+
+#ifndef M_PI
+#define M_PI        3.14159265358979323846
+#endif
+
+#ifndef M_SQRT2
+#define M_SQRT2        1.41421356237309504880
+#endif
+
+// Convert degrees to radians
+#ifndef DTOR
+#define DTOR(d) ((d) * (M_PI) / 180.0)
+#endif
+
+// Normalize angle to domain -pi, pi
+#ifndef NORMALIZE
+#define NORMALIZE(z) atan2(sin(z), cos(z))
+#endif
+
+#define RQ_QUEUE_LEN 10
+
+extern PlayerTime * GlobalTime;
+
+class Goto : public Driver
+{
+  public:
+    Goto(ConfigFile * cf, int section);
+    virtual ~Goto();
+    virtual int Setup();
+    virtual int Shutdown();
+    virtual int ProcessMessage(QueuePointer & resp_queue,
+                               player_msghdr * hdr,
+                               void * data);
+  private:
+    Device * position2d_required_dev;
+    player_devaddr_t position2d_required_addr;
+    player_devaddr_t position2d_provided_addr;
+    player_devaddr_t dio_provided_addr;
+    player_position2d_cmd_pos_t position2d_cmd_pos;
+    player_position2d_data_t prev_pos_data;
+    bool prev_pos_data_valid;
+    double stopping_time;
+    double stall_start_time;
+    double stall_length;
+    double stall_turn;
+    double dist_tol;
+    double angle_tol;
+    double max_dist;
+    int debug;
+    int reactive;
+    int forward_enabled;
+    int early_check;
+    int send_everything;
+    int enabled;
+    int stopping;
+    int last_dir;
+    int stall_state;
+    int skip;
+    player_msghdr_t rq_hdrs[RQ_QUEUE_LEN];
+    QueuePointer rq_ptrs[RQ_QUEUE_LEN];
+    int rq;
+    static double mod(double x, double y);
+    static double angle_map(double d);
+    static double angle_diff(double a, double b);
+};
+
+double Goto::mod(double x, double y)
+{
+    return x - (static_cast<double>((static_cast<int>(x / y))) * y);
+}
+
+double Goto::angle_map(double d)
+{
+  if ((d + M_PI) < 0.0)
+  {
+    return M_PI - Goto::mod(-(d + M_PI), M_PI + M_PI);
+  } else return Goto::mod(d + M_PI, M_PI + M_PI) - M_PI;
+}
+
+double Goto::angle_diff(double a, double b)
+{
+  double d1, d2;
+  a = NORMALIZE(a);
+  b = NORMALIZE(b);
+  d1 = a - b;
+  d2 = 2 * M_PI - fabs(d1);
+  if (d1 > 0.0) d2 *= -1.0;
+  if (fabs(d1) < fabs(d2)) return d1;
+  return d2;
+}
+
+Goto::Goto(ConfigFile* cf, int section) : Driver(cf, section, true, 
PLAYER_MSGQUEUE_DEFAULT_MAXLEN)
+{
+  srand(time(NULL));
+  this->stopping_time = 0.0;
+  this->stall_start_time = 0.0;
+  this->stall_length = 0.0;
+  this->stall_turn = 0.0;
+  this->dist_tol = DEFAULT_DIST_TOL;
+  this->angle_tol = DEFAULT_ANGLE_TOL;
+  this->max_dist = 0.0;
+  this->debug = 0;
+  this->reactive = 0;
+  this->forward_enabled = 0;
+  this->early_check = 0;
+  this->send_everything = 0;
+  this->enabled = 0;
+  this->stopping = 0;
+  this->last_dir = 0;
+  this->stall_state = 0;
+  this->skip = 0;
+  this->position2d_required_dev = NULL;
+  memset(&(this->position2d_required_addr), 0, sizeof(player_devaddr_t));
+  memset(&(this->position2d_provided_addr), 0, sizeof(player_devaddr_t));
+  memset(&(this->dio_provided_addr), 0, sizeof(player_devaddr_t));
+  memset(&(this->prev_pos_data), 0, sizeof(this->prev_pos_data));
+  this->prev_pos_data_valid = false;
+  memset(&(this->rq_hdrs), 0, sizeof this->rq_hdrs);
+  this->rq = -1;
+  if (cf->ReadDeviceAddr(&(this->position2d_provided_addr), section, 
"provides",
+                         PLAYER_POSITION2D_CODE, -1, NULL))
+  {
+    this->SetError(-1);
+    return;
+  }
+  if (this->AddInterface(this->position2d_provided_addr))
+  {
+    this->SetError(-1);
+    return;
+  }
+  if (cf->ReadDeviceAddr(&(this->dio_provided_addr), section, "provides",
+                         PLAYER_DIO_CODE, -1, NULL))
+  {
+    this->SetError(-1);
+    return;
+  }
+  if (this->AddInterface(this->dio_provided_addr))
+  {
+    this->SetError(-1);
+    return;
+  }
+  if (cf->ReadDeviceAddr(&(this->position2d_required_addr), section, 
"requires",
+                         PLAYER_POSITION2D_CODE, -1, NULL))
+  {
+    this->SetError(-1);
+    return;
+  }
+  this->dist_tol = cf->ReadFloat(section, "dist_tol", DEFAULT_DIST_TOL);
+  if ((this->dist_tol) < 0.0)
+  {
+    PLAYER_ERROR1("Invalid dist_tol %.4f", this->dist_tol);
+    this->SetError(-1);
+    return;
+  }
+  this->angle_tol = cf->ReadFloat(section, "angle_tol", DEFAULT_ANGLE_TOL);
+  if ((this->angle_tol) < 0.0)
+  {
+    PLAYER_ERROR1("Invalid angle_tol %.4f", this->angle_tol);
+    this->SetError(-1);
+    return;
+  }
+  this->max_dist = cf->ReadFloat(section, "max_dist", 0.5);
+  if ((this->max_dist) < 0.0)
+  {
+    PLAYER_ERROR1("Invalid max_dist %.4f", this->max_dist);
+    this->SetError(-1);
+    return;
+  }
+  if ((this->dist_tol) >= (this->max_dist))
+  {
+    PLAYER_ERROR("dist_tol should not be greater or equal to max_dist");
+    this->SetError(-1);
+    return;    
+  }
+  this->debug = cf->ReadInt(section, "debug", 0);
+  this->reactive = cf->ReadInt(section, "reactive", 0);
+  this->forward_enabled = cf->ReadInt(section, "forward_enabled", 0);
+  this->early_check = cf->ReadInt(section, "early_check", 1);
+  this->send_everything = cf->ReadInt(section, "send_everything", 1);
+}
+
+Goto::~Goto() { }
+
+int Goto::Setup()
+{
+  this->position2d_required_dev = NULL;
+  memset(&(this->prev_pos_data), 0, sizeof(this->prev_pos_data));
+  this->prev_pos_data_valid = false;
+  memset(&(this->rq_hdrs), 0, sizeof this->rq_hdrs);
+  this->rq = -1;
+  // Only for driver that provides the same interface as it requires
+  if (Device::MatchDeviceAddress(this->position2d_required_addr, 
this->position2d_provided_addr))
+  {
+    PLAYER_ERROR("attempt to subscribe to self");
+    return -1;
+  }
+  this->position2d_required_dev = 
deviceTable->GetDevice(this->position2d_required_addr);
+  if (!(this->position2d_required_dev))
+  {
+    PLAYER_ERROR("unable to locate suitable position2d device");
+    return -1;
+  }
+  if (this->position2d_required_dev->Subscribe(this->InQueue))
+  {
+    PLAYER_ERROR("unable to subscribe to position2d device");
+    this->position2d_required_dev = NULL;
+    return -1;
+  }
+  this->stall_start_time = 0.0;
+  this->stall_length = 0.0;
+  this->stall_turn = 0.0;
+  this->stall_state = 0;
+  this->skip = 0;
+  this->enabled = 0;
+  this->stopping = !0;
+  this->last_dir = 0;
+  GlobalTime->GetTimeDouble(&(this->stopping_time));
+  return 0;
+}
+
+int Goto::Shutdown()
+{
+  if (this->position2d_required_dev) 
this->position2d_required_dev->Unsubscribe(this->InQueue);
+  this->position2d_required_dev = NULL;
+  return 0;
+}
+
+int Goto::ProcessMessage(QueuePointer &resp_queue,
+                                player_msghdr * hdr,
+                                void * data)
+{
+  player_dio_data_t dio_data;
+  player_position2d_cmd_vel_t vel_cmd;
+  player_position2d_data_t pos_data;
+  player_msghdr_t newhdr;
+  QueuePointer null;
+  double t;
+  double newtx, newty;
+  double dist;
+  double ad, av, tv;
+  int i;
+
+  if (!hdr)
+  {
+    PLAYER_ERROR("NULL header");
+    return -1;
+  }
+  if (Message::MatchMessage(hdr, PLAYER_MSGTYPE_CMD, 
PLAYER_POSITION2D_CMD_POS, this->position2d_provided_addr))
+  {
+    if (!data) return -1;
+    this->position2d_cmd_pos = *(reinterpret_cast<player_position2d_cmd_pos_t 
*>(data));
+    if (this->debug) PLAYER_WARN3("position command: px = %.4f, py = %.4f pa = 
%.4f", this->position2d_cmd_pos.pos.px, this->position2d_cmd_pos.pos.py, 
this->position2d_cmd_pos.pos.pa);
+    if ((this->early_check) && (this->prev_pos_data_valid))
+    {
+      dist = sqrt((((this->position2d_cmd_pos.pos.px) - 
(this->prev_pos_data.pos.px)) * \
+                    ((this->position2d_cmd_pos.pos.px) - 
(this->prev_pos_data.pos.px))) + \
+                    (((this->position2d_cmd_pos.pos.py) - 
(this->prev_pos_data.pos.py)) * \
+                    ((this->position2d_cmd_pos.pos.py) - 
(this->prev_pos_data.pos.py))));
+      if (!(dist >= (this->dist_tol)))
+      {
+        ad = Goto::angle_diff(this->prev_pos_data.pos.pa, 
Goto::angle_map(this->position2d_cmd_pos.pos.pa));
+        if (!(fabs(ad) > DTOR(this->angle_tol)))
+        {
+          if (this->debug) PLAYER_WARN6("==> (early check) at target: px = 
%.4f, py = %.4f pa = %.4f; prev pos: px = %.4f, py = %.4f pa = %.4f", 
this->position2d_cmd_pos.pos.px, this->position2d_cmd_pos.pos.py, 
this->position2d_cmd_pos.pos.pa, this->prev_pos_data.pos.px, 
this->prev_pos_data.pos.py, this->prev_pos_data.pos.pa);
+          this->stopping = !0;
+          GlobalTime->GetTimeDouble(&(this->stopping_time));
+          return 0;
+        }
+      }
+    }
+    this->enabled = !0;
+    this->stopping = 0;
+    this->last_dir = 0;
+    return 0;
+  }
+  if (Message::MatchMessage(hdr, PLAYER_MSGTYPE_CMD, 
PLAYER_POSITION2D_CMD_VEL, this->position2d_provided_addr))
+  {
+    if (!data) return -1;
+    vel_cmd = *(reinterpret_cast<player_position2d_cmd_vel_t *>(data));
+    hdr->addr = this->position2d_required_addr;
+    if (this->forward_enabled)
+    {
+      this->position2d_required_dev->PutMsg(this->InQueue, hdr, data);
+    }
+    if ((this->enabled) && (fabs(vel_cmd.vel.px) < EPS) && 
(fabs(vel_cmd.vel.py) < EPS) && (fabs(vel_cmd.vel.pa) < EPS))
+    {
+      if (this->debug) PLAYER_WARN3("STOP COMMAND while going to target: px = 
%.4f, py = %.4f pa = %.4f", this->position2d_cmd_pos.pos.px, 
this->position2d_cmd_pos.pos.py, this->position2d_cmd_pos.pos.pa);
+      this->enabled = 0;
+      this->stopping = !0;
+      GlobalTime->GetTimeDouble(&(this->stopping_time));
+    }
+    return 0;
+  }
+  if (Message::MatchMessage(hdr, PLAYER_MSGTYPE_REQ, -1, 
this->position2d_provided_addr))
+  {
+    if ((this->rq) >= RQ_QUEUE_LEN) return -1;
+    this->rq++;
+    assert((this->rq) >= 0);
+    this->rq_hdrs[this->rq] = *hdr;
+    this->rq_ptrs[this->rq] = resp_queue;
+    if (!(this->rq))
+    {
+      newhdr = this->rq_hdrs[this->rq];
+      newhdr.addr = this->position2d_required_addr;
+      this->position2d_required_dev->PutMsg(this->InQueue, &newhdr, data);
+    }
+    return 0;
+  }
+  if ((Message::MatchMessage(hdr, PLAYER_MSGTYPE_RESP_ACK, -1, 
this->position2d_required_addr)) || (Message::MatchMessage(hdr, 
PLAYER_MSGTYPE_RESP_NACK, -1, this->position2d_required_addr)))
+  {
+    assert((this->rq) >= 0);
+    assert((hdr->subtype) == (this->rq_hdrs[this->rq].subtype));
+    this->Publish(this->position2d_provided_addr, rq_ptrs[this->rq], 
hdr->type, hdr->subtype, data, 0, &(hdr->timestamp));
+    this->rq_ptrs[this->rq] = null;
+    this->rq--;
+    if ((this->rq) >= 0)
+    {
+      newhdr = this->rq_hdrs[this->rq];
+      newhdr.addr = this->position2d_required_addr;
+      this->position2d_required_dev->PutMsg(this->InQueue, &newhdr, data);
+    }
+    return 0;
+  }
+  if (Message::MatchMessage(hdr, PLAYER_MSGTYPE_DATA,
+                            PLAYER_POSITION2D_DATA_STATE,
+                            this->position2d_required_addr))
+  {
+    if (!data) return -1;
+    pos_data = *(reinterpret_cast<player_position2d_data_t *>(data));
+    if ((this->enabled) && (this->prev_pos_data_valid) && 
(!(this->stall_state)))
+    {
+      dist = sqrt(((pos_data.pos.px - (this->prev_pos_data.pos.px)) * \
+                    (pos_data.pos.px - (this->prev_pos_data.pos.px))) + \
+                    ((pos_data.pos.py - (this->prev_pos_data.pos.py)) * \
+                    (pos_data.pos.py - (this->prev_pos_data.pos.py))));
+      this->prev_pos_data_valid = false;
+      if (dist >= (this->max_dist))
+      {
+        if (this->debug) PLAYER_WARN("position changed too much; STOPPING!");
+        GlobalTime->GetTimeDouble(&(this->stopping_time));
+        this->stopping = !0;
+      }
+    }
+    this->prev_pos_data = pos_data;
+    this->prev_pos_data_valid = true;
+    // main routine here:
+    memset(&vel_cmd, 0, sizeof vel_cmd);    
+    if ((this->enabled) && (!(this->stopping)))
+    {
+      newtx = this->position2d_cmd_pos.pos.px;
+      newty = this->position2d_cmd_pos.pos.py;
+      for (i = 0; i < 100; i++)
+      {
+        dist = sqrt(((pos_data.pos.px - newtx) * \
+                    (pos_data.pos.px - newtx)) + \
+                    ((pos_data.pos.py - newty) * \
+                    (pos_data.pos.py - newty)));
+        if (dist <= (this->max_dist)) break;
+        newtx = pos_data.pos.px + ((newtx - pos_data.pos.px) / 2.0);
+        newty = pos_data.pos.py + ((newty - pos_data.pos.py) / 2.0);
+        if ((this->debug) && ((i + 1) == 100)) PLAYER_WARN("100 times divided 
in half and still nothing?!");
+      }
+      if (dist >= (this->dist_tol))
+      {
+        ad = Goto::angle_diff(atan2(newty - (pos_data.pos.py), newtx - 
(pos_data.pos.px)), pos_data.pos.pa);
+        if (fabs(ad) > (DTOR(AMIN) + (dist / (MAXD)) * (DTOR(AMAX) - 
DTOR(AMIN))))
+        {
+          tv = 0.0;
+        } else
+        {
+          tv = (TVMIN) + (dist / ((M_SQRT2) * (MAXD))) * ((TVMAX) - (TVMIN));
+        }
+        av = DTOR(AVMIN) + (fabs(ad) / (M_PI)) * (DTOR(AVMAX) - DTOR(AVMIN));
+        if (ad < 0.0) av = -av;
+        vel_cmd.vel.px = tv;
+        vel_cmd.vel.py = 0.0;
+        vel_cmd.vel.pa = av;
+        this->last_dir = 0;
+      } else
+      {
+        ad = Goto::angle_diff(pos_data.pos.pa, 
Goto::angle_map(this->position2d_cmd_pos.pos.pa));
+        if (fabs(ad) > DTOR(this->angle_tol))
+        {
+          switch (this->last_dir)
+          {
+          case -1:
+            av = 0.8;
+            break;
+          case 0:
+            if (ad < 0.0)
+            {
+              this->last_dir = -1;
+              av = 0.8;
+            } else
+            {
+              this->last_dir = 1;
+              av = -0.8;
+            }
+            break;
+          case 1:
+            av = -0.8;
+            break;
+          default:
+            PLAYER_ERROR("Invalid internal state!");
+            return -1;
+          }
+          if (this->debug) PLAYER_WARN2("angle diff: %.4f, av: %.4f", ad, av);
+          vel_cmd.vel.px = 0.0;
+          vel_cmd.vel.py = 0.0;
+          vel_cmd.vel.pa = av;
+        } else
+        {
+          if (this->debug) PLAYER_WARN6("==> at target: px = %.4f, py = %.4f 
pa = %.4f; current pos: px = %.4f, py = %.4f pa = %.4f", 
this->position2d_cmd_pos.pos.px, this->position2d_cmd_pos.pos.py, 
this->position2d_cmd_pos.pos.pa, pos_data.pos.px, pos_data.pos.py, 
pos_data.pos.pa);
+          GlobalTime->GetTimeDouble(&(this->stopping_time));
+          this->stopping = !0;
+          this->enabled = 0;
+          this->last_dir = 0;
+        }
+      }
+    }
+    if ((this->reactive) && (this->enabled) && (!(this->stopping)))
+    {
+      switch (this->stall_state)
+      {
+      case 0:
+        if (pos_data.stall)
+        {
+          GlobalTime->GetTimeDouble(&(this->stall_start_time));
+          this->stall_length = (static_cast<double>(rand()) / 
static_cast<double>(RAND_MAX)) + 0.3;
+          this->stall_turn = ((static_cast<double>(rand()) / 
static_cast<double>(RAND_MAX)) * 4.0) - 2.0;
+          vel_cmd.vel.px = -(TVMAX);
+          vel_cmd.vel.py = 0.0;
+          vel_cmd.vel.pa = this->stall_turn;
+          this->stall_state++;
+        }
+        break;
+      case 1:
+        GlobalTime->GetTimeDouble(&t);
+        if ((t - (this->stall_start_time)) >= (this->stall_length))
+        {
+          this->stall_start_time = t;
+          vel_cmd.vel.px = ((TVMAX) * 0.65);
+          vel_cmd.vel.py = 0.0;
+          vel_cmd.vel.pa = 0.0;
+          this->stall_state++;
+        } else
+        {
+          vel_cmd.vel.px = -(TVMAX);
+          vel_cmd.vel.py = 0.0;
+          vel_cmd.vel.pa = this->stall_turn;
+        }
+        break;
+      case 2:
+        GlobalTime->GetTimeDouble(&t);
+        if ((t - (this->stall_start_time)) >= ((this->stall_length) / 3.0))
+        {
+          this->stall_start_time = t;
+          vel_cmd.vel.px = 0.0;
+          vel_cmd.vel.py = 0.0;
+          vel_cmd.vel.pa = 0.0;
+          this->stall_state++;
+        } else
+        {
+          vel_cmd.vel.px = ((TVMAX) * 0.65);
+          vel_cmd.vel.py = 0.0;
+          vel_cmd.vel.pa = 0.0;
+        }
+        break;
+      case 3:
+        GlobalTime->GetTimeDouble(&t);
+        if ((t - (this->stall_start_time)) >= 0.4)
+        {
+          this->stall_state = 0;
+          GlobalTime->GetTimeDouble(&(this->stopping_time));
+          this->stopping = !0; // will never go back to this->stall_state 
switch until it's fully stopped
+        } else
+        {
+          vel_cmd.vel.px = 0.0;
+          vel_cmd.vel.py = 0.0;
+          vel_cmd.vel.pa = 0.0;
+        }
+        break;
+      default:
+        PLAYER_ERROR("Invalid stall_state");
+        return -1;
+      }
+    }
+    if (this->stopping)
+    {
+      vel_cmd.vel.px = 0.0;
+      vel_cmd.vel.py = 0.0;
+      vel_cmd.vel.pa = 0.0;
+      GlobalTime->GetTimeDouble(&t);
+      if ((t - (this->stopping_time)) >= 1.5) (this->stopping) = 0;
+    }
+    if (this->send_everything) this->skip = 0;
+    switch (this->skip)
+    {
+    case 0:
+      if ((this->stopping) || (this->enabled))
+      {
+        vel_cmd.state = !0;
+        this->position2d_required_dev->PutMsg(this->InQueue, 
PLAYER_MSGTYPE_CMD, PLAYER_POSITION2D_CMD_VEL, reinterpret_cast<void 
*>(&vel_cmd), 0, NULL);
+        if (!(this->send_everything))
+        {
+          this->skip = 1;
+          break;
+        }
+      }
+    case 1:
+      if (this->reactive) pos_data.stall = 0; // let's manage stall state with 
reactive manner
+      this->Publish(this->position2d_provided_addr,
+                    PLAYER_MSGTYPE_DATA, PLAYER_POSITION2D_DATA_STATE,
+                    reinterpret_cast<void *>(&pos_data), 0, NULL, true); // 
copy = true, do not dispose data placed on local stack!
+      if (!(this->send_everything))
+      {
+        this->skip = 2;
+        break;
+      }
+    case 2:
+      memset(&dio_data, 0, sizeof dio_data);
+      dio_data.count = 1;
+      dio_data.bits |= ((this->enabled) || (this->stopping)) ? 1 : 0;
+      this->Publish(this->dio_provided_addr, PLAYER_MSGTYPE_DATA, 
PLAYER_DIO_DATA_VALUES,
+                    reinterpret_cast<void *>(&dio_data), 0, NULL, true); // 
copy = true
+      this->skip = 0;
+      break;
+    default:
+      PLAYER_ERROR("Internal error: invalid switch value");
+      return -1;
+    }
+    return 0;
+  }
+  return -1;
+}
+
+// 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 * Goto_Init(ConfigFile * cf, int section)
+{
+  // Create and return a new instance of this driver
+  return reinterpret_cast<Driver *>(new Goto(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 goto_Register(DriverTable * table)
+{
+  table->AddDriver("goto", Goto_Init);
+}


This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.

------------------------------------------------------------------------------
Enter the BlackBerry Developer Challenge  
This is your chance to win up to $100,000 in prizes! For a limited time, 
vendors submitting new applications to BlackBerry App World(TM) will have
the opportunity to enter the BlackBerry Developer Challenge. See full prize  
details at: http://p.sf.net/sfu/Challenge
_______________________________________________
Playerstage-commit mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/playerstage-commit

Reply via email to