Revision: 8650
          http://playerstage.svn.sourceforge.net/playerstage/?rev=8650&view=rev
Author:   thjc
Date:     2010-05-03 17:55:28 +0000 (Mon, 03 May 2010)

Log Message:
-----------
Applied patch 2960374: New driver (speechcmd) and new option to inhibitor

Modified Paths:
--------------
    code/player/trunk/server/drivers/shell/CMakeLists.txt
    code/player/trunk/server/drivers/shell/inhibitor.cc

Added Paths:
-----------
    code/player/trunk/server/drivers/shell/speechcmd.cc

Modified: code/player/trunk/server/drivers/shell/CMakeLists.txt
===================================================================
--- code/player/trunk/server/drivers/shell/CMakeLists.txt       2010-05-03 
17:49:32 UTC (rev 8649)
+++ code/player/trunk/server/drivers/shell/CMakeLists.txt       2010-05-03 
17:55:28 UTC (rev 8650)
@@ -57,3 +57,6 @@
 
 PLAYERDRIVER_OPTION (opaquecmd build_opaquecmd ON)
 PLAYERDRIVER_ADD_DRIVER (opaquecmd build_opaquecmd SOURCES opaquecmd.cc)
+
+PLAYERDRIVER_OPTION (speechcmd build_speechcmd ON)
+PLAYERDRIVER_ADD_DRIVER (speechcmd build_speechcmd SOURCES speechcmd.cc)

Modified: code/player/trunk/server/drivers/shell/inhibitor.cc
===================================================================
--- code/player/trunk/server/drivers/shell/inhibitor.cc 2010-05-03 17:49:32 UTC 
(rev 8649)
+++ code/player/trunk/server/drivers/shell/inhibitor.cc 2010-05-03 17:55:28 UTC 
(rev 8650)
@@ -71,6 +71,11 @@
 - block_data
   - Default: 0
   - If set to 1, data flow is also blocked
+- msg_interval
+  - Default: 0.0
+  - If greater than 0.0 (seconds), commands will be passed with this interval
+    (all commands sent more frequently will be thrown away). When this interval
+    is set to 0.0, all commands are passed (as long as inhibitor state is 
right).
 
 @par Example
 
@@ -92,10 +97,12 @@
 #include <stddef.h> // for NULL and size_t
 #include <stdlib.h> // for malloc() and free()
 #include <string.h> // for memset()
+#include <math.h> // for fabs()
 #include <assert.h>
 #include <libplayercore/playercore.h>
 
 #define RQ_QUEUE_LEN 10
+#define EPS 0.0000001
 
 class Inhibitor : public Driver
 {
@@ -115,6 +122,8 @@
   private: uint32_t bitmask;
   private: int neg;
   private: int block_data;
+  private: double msg_interval;
+  private: double lastTime;
   private: int switch_state;
   private: int last_rq;
   private: player_msghdr_t rq_hdrs[RQ_QUEUE_LEN];
@@ -139,6 +148,8 @@
   this->bitmask = 0;
   this->neg = 0;
   this->block_data = 0;
+  this->msg_interval = 0.0;
+  this->lastTime = 0.0;
   this->switch_state = 0;
   this->last_rq = -1;
   memset(this->rq_hdrs, 0, sizeof this->rq_hdrs);
@@ -219,6 +230,13 @@
   }
   this->neg = cf->ReadInt(section, "neg", 0);
   this->block_data = cf->ReadInt(section, "block_data", 0);
+  this->msg_interval = cf->ReadFloat(section, "msg_interval", 0.0);
+  if ((this->msg_interval) < 0.0)
+  {
+    PLAYER_ERROR("invalid msg_interval");
+    this->SetError(-1);
+    return;
+  }
 }
 
 Inhibitor::~Inhibitor()
@@ -290,6 +308,7 @@
       return -1;
     }
   }
+  this->lastTime = 0.0;
   return 0;
 }
 
@@ -319,6 +338,7 @@
   QueuePointer null;
   int i;
   int n;
+  double t;
 
   assert(hdr);
   if (this->use_dio)
@@ -375,6 +395,14 @@
   {
     pass = (this->neg) ? (!(this->switch_state)) : (this->switch_state);
     if (!pass) return 0;
+    if ((this->msg_interval) > EPS)
+    {
+      GlobalTime->GetTimeDouble(&t);
+      if ((fabs(t - (this->lastTime))) > (this->msg_interval))
+      {
+        this->lastTime = t;
+      } else return 0;
+    }
     newhdr = *hdr;
     newhdr.addr = this->comm_required_addr;
     this->comm_required_dev->PutMsg(this->InQueue, &newhdr, data, true); // 
copy = true

Added: code/player/trunk/server/drivers/shell/speechcmd.cc
===================================================================
--- code/player/trunk/server/drivers/shell/speechcmd.cc                         
(rev 0)
+++ code/player/trunk/server/drivers/shell/speechcmd.cc 2010-05-03 17:55:28 UTC 
(rev 8650)
@@ -0,0 +1,286 @@
+/*
+ *  Player - One Hell of a Robot Server
+ *  Copyright (C) 2000  Brian Gerkey et al.
+ *
+ *  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: Speech commands sender
+// Author: Paul Osmialowski
+// Date: 27 Feb 2010
+//
+/////////////////////////////////////////////////////////////////////////////
+
+/** @ingroup drivers */
+/** @{ */
+/** @defgroup driver_speechcmd speechcmd
+ * @brief Speech commands sender
+
+The speechcmd driver keeps on repeating configured speech command.
+
+...@par Compile-time dependencies
+
+- none
+
+...@par Provides
+
+- @ref interface_opaque
+
+...@par Requires
+
+- @ref interface_speech
+
+...@par Configuration requests
+
+- none
+
+...@par Configuration file options
+
+- sleep_sec (integer)
+  - Default: 0
+  - timespec value for nanosleep() (sec resolution).
+- sleep_nsec (integer)
+  - Default: 100000000 (however, when sleep_sec is greater than 0, default 
sleep_nsec is 0)
+  - timespec value for nanosleep() (nanosec resolution).
+- message (string)
+  - Default: "foo"
+  - Message to be spoken.
+
+...@par Example
+
+...@verbatim
+driver
+(
+  name "speechcmd"
+  provides ["opaque:100"]
+  requires ["speech:0"]
+  message "hello world"
+  alwayson 1
+)
+...@endverbatim
+
+...@author Paul Osmialowski
+
+*/
+/** @} */
+
+#include <stddef.h> // for NULL and size_t
+#include <stdlib.h> // for malloc() and free()
+#include <string.h> // for memset()
+#include <stdio.h>  // for snprintf()
+#include <pthread.h>
+#include <libplayercore/playercore.h>
+
+#define MAX_MSG_LEN 255
+
+class SpeechCmd : public ThreadedDriver
+{
+  public:
+    // Constructor; need that
+    SpeechCmd(ConfigFile * cf, int section);
+
+    virtual ~SpeechCmd();
+
+    // 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:
+    virtual void Main();
+    player_devaddr_t provided_opaque_addr;
+    player_devaddr_t required_speech_addr;
+    Device * required_speech_dev;
+
+    int sleep_sec;
+    int sleep_nsec;
+    char message[MAX_MSG_LEN + 1];
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// Constructor.  Retrieve options from the configuration file and do any
+// pre-Setup() setup.
+//
+SpeechCmd::SpeechCmd(ConfigFile * cf, int section) : ThreadedDriver(cf, 
section, true, PLAYER_MSGQUEUE_DEFAULT_MAXLEN)
+{
+  int default_nsec;
+  const char * str;
+
+  memset(&(this->provided_opaque_addr), 0, sizeof(player_devaddr_t));
+  memset(&(this->required_speech_addr), 0, sizeof(player_devaddr_t));
+  this->required_speech_dev = NULL;
+  this->sleep_sec = 0;
+  this->sleep_nsec = 0;
+  this->message[0] = '\0';
+  if (cf->ReadDeviceAddr(&(this->provided_opaque_addr), section, "provides",
+                         PLAYER_OPAQUE_CODE, -1, NULL))
+  {
+    PLAYER_ERROR("Nothing is provided");
+    this->SetError(-1);
+    return;
+  }
+  if (this->AddInterface(this->provided_opaque_addr))
+  {
+    this->SetError(-1);
+    return;
+  }
+  if (cf->ReadDeviceAddr(&(this->required_speech_addr), section, "requires",
+                         PLAYER_SPEECH_CODE, -1, NULL))
+  {
+    PLAYER_ERROR("Cannot require speech device");
+    this->SetError(-1);
+    return;
+  }
+  this->sleep_sec = cf->ReadInt(section, "sleep_sec", 0);
+  if ((this->sleep_sec) < 0)
+  {
+    PLAYER_ERROR("Invalid sleep_sec value");
+    this->SetError(-1);
+    return;
+  }
+  default_nsec = 100000000;
+  if ((this->sleep_sec) > 0) default_nsec = 0;
+  this->sleep_nsec = cf->ReadInt(section, "sleep_nsec", default_nsec);
+  if ((this->sleep_nsec) < 0)
+  {
+    PLAYER_ERROR("Invalid sleep_nsec value");
+    this->SetError(-1);
+    return;
+  }
+  str = cf->ReadString(section, "message", "foo");
+  if (!str)
+  {
+    PLAYER_ERROR("NULL message");
+    this->SetError(-1);
+    return;
+  }
+  if (!(strlen(str) > 0))
+  {
+    PLAYER_ERROR("Message too short");
+    this->SetError(-1);
+    return;
+  }
+  if (strlen(str) >= (sizeof this->message))
+  {
+    PLAYER_ERROR("Message too long");
+    this->SetError(-1);
+    return;
+  }
+#if defined (WIN32)
+  _snprintf(this->message, sizeof this->message, "%s", str);
+#else
+  snprintf(this->message, sizeof this->message, "%s", str);
+#endif
+}
+
+SpeechCmd::~SpeechCmd() { }
+
+int SpeechCmd::MainSetup()
+{
+  this->required_speech_dev = 
deviceTable->GetDevice(this->required_speech_addr);
+  if (!(this->required_speech_dev))
+  {
+    PLAYER_ERROR("unable to locate suitable speech device");
+    return -1;
+  }
+  if (this->required_speech_dev->Subscribe(this->InQueue))
+  {
+    PLAYER_ERROR("unable to subscribe to speech device");
+    this->required_speech_dev = NULL;
+    return -1;
+  }
+  return 0;
+}
+
+void SpeechCmd::MainQuit()
+{
+  if (this->required_speech_dev) 
this->required_speech_dev->Unsubscribe(this->InQueue);
+  this->required_speech_dev = NULL;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Main function for device thread
+void SpeechCmd::Main()
+{
+  struct timespec tspec;
+  player_opaque_data_t data;
+  player_speech_cmd_t cmd;
+
+  cmd.string_count = strlen(this->message) + 1;
+  cmd.string = this->message;
+  for (;;)
+  {
+    // Test if we are supposed to cancel
+    pthread_testcancel();
+
+    // Process incoming messages
+    this->ProcessMessages();
+
+    // Test if we are supposed to cancel
+    pthread_testcancel();
+
+    this->required_speech_dev->PutMsg(this->InQueue, PLAYER_MSGTYPE_CMD, 
PLAYER_SPEECH_CMD_SAY, reinterpret_cast<void *>(&cmd), 0, NULL);
+
+    // Test if we are supposed to cancel
+    pthread_testcancel();
+
+    memset(&data, 0, sizeof data);
+    data.data_count = 0;
+    data.data = NULL;
+    this->Publish(this->provided_opaque_addr,
+                  PLAYER_MSGTYPE_DATA, PLAYER_OPAQUE_DATA_STATE,
+                  reinterpret_cast<void *>(&data), 0, NULL, true); // copy = 
true, do not dispose data placed on local stack!
+    // Test if we are supposed to cancel
+    pthread_testcancel();
+
+    if (((this->sleep_sec) > 0) || ((this->sleep_nsec) > 0))
+    {
+      // sleep for a while
+      tspec.tv_sec = this->sleep_sec;
+      tspec.tv_nsec = this->sleep_nsec;
+      nanosleep(&tspec, NULL);
+    }
+  }
+}
+
+int SpeechCmd::ProcessMessage(QueuePointer & resp_queue, player_msghdr * hdr, 
void * data)
+{
+  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 * SpeechCmd_Init(ConfigFile * cf, int section)
+{
+  // Create and return a new instance of this driver
+  return reinterpret_cast<Driver *>(new SpeechCmd(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 speechcmd_Register(DriverTable * table)
+{
+  table->AddDriver("speechcmd", SpeechCmd_Init);
+}


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

------------------------------------------------------------------------------
_______________________________________________
Playerstage-commit mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/playerstage-commit

Reply via email to