Revision: 9004
http://playerstage.svn.sourceforge.net/playerstage/?rev=9004&view=rev
Author: jpgr87
Date: 2010-12-11 21:25:28 +0000 (Sat, 11 Dec 2010)
Log Message:
-----------
Applied patch #3134439: differential driver 2xPosition1d --> position2d
Modified Paths:
--------------
code/player/trunk/server/drivers/position/CMakeLists.txt
Added Paths:
-----------
code/player/trunk/config/nxt.cfg
code/player/trunk/server/drivers/position/differential/
code/player/trunk/server/drivers/position/differential/CMakeLists.txt
code/player/trunk/server/drivers/position/differential/chronos.cc
code/player/trunk/server/drivers/position/differential/chronos.hh
code/player/trunk/server/drivers/position/differential/driver.cc
Added: code/player/trunk/config/nxt.cfg
===================================================================
--- code/player/trunk/config/nxt.cfg (rev 0)
+++ code/player/trunk/config/nxt.cfg 2010-12-11 21:25:28 UTC (rev 9004)
@@ -0,0 +1,28 @@
+unit_length "m"
+unit_angle "radians"
+
+# Example using the nxt LEGO driver.
+# Standard configured brick with B and C motors in use.
+
+# The NXT driver
+driver
+(
+ name "nxt"
+ provides [ "B:::position1d:0" "C:::position1d:1" ]
+ max_power [ 100 100 100 ]
+ max_speed [ 0.5 0.5 0.5 ]
+
+ period 0.05
+
+ alwayson 1
+)
+
+driver
+(
+ name "differential"
+ requires [ "left:::position1d:0" "right:::position1d:1" ]
+ provides [ "position2d:0" ]
+
+ axis_length 0.2
+ period 0.1
+)
Modified: code/player/trunk/server/drivers/position/CMakeLists.txt
===================================================================
--- code/player/trunk/server/drivers/position/CMakeLists.txt 2010-12-06
05:23:17 UTC (rev 9003)
+++ code/player/trunk/server/drivers/position/CMakeLists.txt 2010-12-11
21:25:28 UTC (rev 9004)
@@ -2,6 +2,7 @@
ADD_SUBDIRECTORY (blobposition)
ADD_SUBDIRECTORY (bumpersafe)
ADD_SUBDIRECTORY (deadstop)
+ADD_SUBDIRECTORY (differential)
ADD_SUBDIRECTORY (globalize)
ADD_SUBDIRECTORY (goto)
ADD_SUBDIRECTORY (isense)
Added: code/player/trunk/server/drivers/position/differential/CMakeLists.txt
===================================================================
--- code/player/trunk/server/drivers/position/differential/CMakeLists.txt
(rev 0)
+++ code/player/trunk/server/drivers/position/differential/CMakeLists.txt
2010-12-11 21:25:28 UTC (rev 9004)
@@ -0,0 +1,13 @@
+if (NOT HAVE_STL)
+ PLAYERDRIVER_OPTION (differential build_differential OFF "STL not found")
+else(NOT HAVE_STL)
+ PLAYERDRIVER_OPTION (differential build_differential ON)
+endif(NOT HAVE_STL)
+
+PLAYERDRIVER_ADD_DRIVER(
+ differential build_differential
+
+ SOURCES
+ chronos.cc
+ driver.cc
+ )
Added: code/player/trunk/server/drivers/position/differential/chronos.cc
===================================================================
--- code/player/trunk/server/drivers/position/differential/chronos.cc
(rev 0)
+++ code/player/trunk/server/drivers/position/differential/chronos.cc
2010-12-11 21:25:28 UTC (rev 9004)
@@ -0,0 +1,55 @@
+/*
+ * Player - One Hell of a Robot Server
+ * Copyright (C) 2010
+ * Alejandro R. Mosteo
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <cerrno>
+#include "chronos.hh"
+#include <cstring>
+#include <stdexcept>
+#include <sys/time.h>
+
+using namespace driver_differential;
+
+Chronos::Chronos ( double seconds_since_epoch )
+{
+ clock_ = seconds_since_epoch;
+}
+
+double Chronos::elapsed ( void ) const
+ {
+ return now() - clock_;
+ }
+
+void Chronos::reset ( void )
+{
+ clock_ = now();
+}
+
+double Chronos::now ( void )
+ {
+ struct timeval clock;
+
+ if ( gettimeofday ( &clock, NULL ) != 0 )
+ throw std::runtime_error ( strerror ( errno ) );
+
+ return
+ static_cast<double> ( clock.tv_sec ) +
+ static_cast<double> ( clock.tv_usec ) * 1e-6;
+ }
Added: code/player/trunk/server/drivers/position/differential/chronos.hh
===================================================================
--- code/player/trunk/server/drivers/position/differential/chronos.hh
(rev 0)
+++ code/player/trunk/server/drivers/position/differential/chronos.hh
2010-12-11 21:25:28 UTC (rev 9004)
@@ -0,0 +1,42 @@
+/*
+ * Player - One Hell of a Robot Server
+ * Copyright (C) 2010
+ * Alejandro R. Mosteo
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _chronos_
+#define _chronos_
+
+namespace driver_differential {
+
+class Chronos
+ {
+ public:
+ Chronos ( double seconds_since_epoch = now() );
+ double elapsed ( void ) const;
+ void reset ( void );
+
+ private:
+ double clock_;
+
+ static double now ( void ) ;
+ };
+
+}
+
+#endif
Added: code/player/trunk/server/drivers/position/differential/driver.cc
===================================================================
--- code/player/trunk/server/drivers/position/differential/driver.cc
(rev 0)
+++ code/player/trunk/server/drivers/position/differential/driver.cc
2010-12-11 21:25:28 UTC (rev 9004)
@@ -0,0 +1,366 @@
+/*
+ * Player - One Hell of a Robot Server
+ * Copyright (C) 2010
+ * Alejandro R. Mosteo
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/** @ingroup drivers */
+/** @{ */
+/** @defgroup driver_differential differential
+ * @brief Differential steering (also skid-steering)
+
+This driver takes two @ref interface_position1d sources
+and considers them the two motors of a differential steer machine,
+providing in turn a @ref interface_position2d for control of such machine.
+
+...@par Compile-time dependencies
+
+- none
+
+...@par Requires
+
+- @ref interface_position1d
+ - Two, with "left" and "right" keys
+ - Velocity commands (x, 0, ω) are transformed and delivered to these
interfaces.
+ - Position commands not supported.
+
+...@par Provides
+
+- @ref interface_position2d
+ - The differential steer interface obtained coupling the two position1d
interfaces.
+
+...@par Configuration file options
+
+- axis_length (float [length] default 25cm)
+ - Distance between wheels at its pivot point.
+
+- period (float [s] default 0.05)
+ - Period used for integration of odometry, since we have unsyncronized
sources for each wheel.
+
+...@par Example
+
+...@verbatim
+
+# Example with the differential LEGO driver with two actuators.
+# Standard configured brick with B and C motors in use.
+
+unit_length "m"
+unit_angle "radians"
+
+# The NXT driver
+driver
+(
+ name "differential"
+ provides [ "B:::position1d:0" "C:::position1d:1" ]
+)
+
+# The differential driver that provides simplified position2d management
+driver
+(
+ name "differential"
+ requires [ "left:::position1d:0" "right:::position1d:1" ]
+ provides [ "position2d:0" ]
+
+ axis_length 0.25
+)
+
+...@endverbatim
+
+...@author Alejandro R. Mosteo
+*/
+/** @} */
+#include "libplayercore/playercore.h"
+
+#include "chronos.hh"
+#include <cstring>
+#include <cmath>
+#include <stdexcept>
+
+using namespace driver_differential;
+
+const int kNumMotors = 2;
+const int kL = 0;
+const int kR = 1;
+const char *kMotorNames[kNumMotors] = { "left", "right" };
+
+
+class Differential : public ThreadedDriver
+ {
+ public:
+ Differential ( ConfigFile* cf, int section );
+
+ virtual void Main ( void );
+ virtual int MainSetup ( void );
+ // virtual void MainQuit ( void );
+
+ virtual int ProcessMessage ( QueuePointer &resp_queue, player_msghdr *
hdr, void * data );
+
+ private:
+ player_devaddr_t p1d_addr_[kNumMotors];
+ player_devaddr_t p2d_addr_;
+
+ Device *p1d_dev_[kNumMotors];
+
+ player_position2d_data_t p2d_state_;
+
+ player_position1d_data_t p1d_state_ [kNumMotors]; // Just read status.
+ player_position1d_data_t p1d_state_prev_[kNumMotors]; // Previous status
to integrate speed.
+
+ double axis_length_;
+
+ double period_;
+ Chronos timer_period_;
+
+ void CheckMotors ( void );
+ int GetMotor ( const player_devaddr_t & addr ) const;
+ void SetVel ( const player_pose2d_t & vel );
+ };
+
+Driver* differential_Init ( ConfigFile* cf, int section )
+{
+ return static_cast<Driver*> ( new Differential ( cf, section ) );
+}
+
+void differential_Register ( DriverTable* table )
+{
+ table->AddDriver ( "differential", differential_Init );
+}
+
+Differential::Differential ( ConfigFile *cf, int section )
+ : ThreadedDriver ( cf, section ),
+ axis_length_ ( cf->ReadLength ( section, "axis_length", 0.25 ) ),
+ period_ ( cf->ReadFloat ( section, "period", 0.05 ) )
+{
+ for ( int i = 0; i < kNumMotors; i++ )
+ {
+
+ if ( cf->ReadDeviceAddr ( &p1d_addr_[i], section, "requires",
PLAYER_POSITION1D_CODE, -1, kMotorNames[i] ) != 0 )
+ {
+ PLAYER_ERROR1 ( "position1d required for motor %s not found",
kMotorNames[i] );
+ SetError ( -1 );
+ return;
+ }
+ else
+ {
+ memset ( &p1d_state_[i], 0, sizeof ( p1d_state_[i] ) );
+ memset ( &p1d_state_prev_[i], 0, sizeof ( p1d_state_[i] ) );
+ }
+ }
+
+ if ( cf->ReadDeviceAddr ( &p2d_addr_, section, "provides",
PLAYER_POSITION2D_CODE, -1, NULL ) == 0 )
+ {
+ if ( AddInterface ( p2d_addr_ ) != 0 )
+ throw std::runtime_error ( "Cannot add position2d interface" );
+ else
+ memset ( &p2d_state_, 0, sizeof ( p2d_state_ ) );
+ }
+ else
+ throw std::runtime_error ( "Cannot find position2d interface" );
+}
+
+int Differential::MainSetup ( void )
+{
+ for ( int i = 0 ; i < kNumMotors; i++ )
+ if ( ! ( p1d_dev_[i] = deviceTable->GetDevice ( p1d_addr_[i] ) ) )
+ {
+ PLAYER_ERROR1 ( "Unable to locate position1d device at given address
with key: %s", kMotorNames[i] );
+ return -1;
+ }
+ else if ( p1d_dev_[i]->Subscribe ( InQueue ) != 0 )
+ {
+ PLAYER_ERROR1 ( "Unable to subscribe to position1d driver with key:
%s", kMotorNames[i] );
+ return -1;
+ }
+
+ return 0;
+}
+
+void Differential::Main ( void )
+{
+ while ( true )
+ {
+ // Wait till we get new data or we need to measure something
+ Wait ( period_ );
+
+ pthread_testcancel();
+
+ ProcessMessages ( 0 );
+
+ CheckMotors();
+ }
+}
+
+void Differential::CheckMotors ( void )
+{
+ // THESE CALCULATIONS ARE mostly TAKEN FROM
+ // http://rossum.sourceforge.net/papers/DiffSteer/
+
+ if ( timer_period_.elapsed() < period_ )
+ return;
+
+ timer_period_.reset();
+
+ p2d_state_.stall = p1d_state_[kL].stall || p1d_state_[kR].stall;
+
+ p2d_state_.vel.px = ( p1d_state_[kL].vel + p1d_state_[kR].vel ) / 2.0;
+ p2d_state_.vel.py = 0.0;
+ p2d_state_.vel.pa = ( p1d_state_[kR].vel - p1d_state_[kL].vel ) /
axis_length_;
+
+ const double dist = ( p1d_state_[kL].pos - p1d_state_prev_[kL].pos +
p1d_state_[kR].pos - p1d_state_prev_[kR].pos ) / 2.0;
+ p2d_state_.pos.pa += ( ( p1d_state_[kR].pos - p1d_state_prev_[kR].pos ) -
+ ( p1d_state_[kL].pos - p1d_state_prev_[kL].pos ) ) /
( 2.0 * axis_length_ );
+ p2d_state_.pos.px += dist * cos ( p2d_state_.pos.pa );
+ p2d_state_.pos.py += dist * sin ( p2d_state_.pos.pa );
+
+ if ( HasSubscriptions() )
+ Publish ( p2d_addr_,
+ PLAYER_MSGTYPE_DATA,
+ PLAYER_POSITION2D_DATA_STATE,
+ static_cast<void*> ( &p2d_state_ ) );
+
+ for ( int i = 0; i < kNumMotors; i++ )
+ p1d_state_prev_[i] = p1d_state_[i];
+
+ PLAYER_MSG5 ( 4, "differential: odom update is ( px, py, pa )( vx, 0.0, va)
= ( %7.2f, %7.2f, %7.2f )( %7.2f, 0.0, %7.2f)",
+ p2d_state_.pos.px, p2d_state_.pos.py, p2d_state_.pos.pa,
p2d_state_.vel.px, p2d_state_.vel.pa );
+
+}
+
+int Differential::ProcessMessage ( QueuePointer & resp_queue,
+ player_msghdr * hdr,
+ void * data )
+{
+ if ( Message::MatchMessage ( hdr, PLAYER_MSGTYPE_DATA,
PLAYER_POSITION1D_DATA_STATE ) )
+ {
+ // Store last odometry until next integration deadline
+ p1d_state_[ GetMotor ( hdr->addr ) ] =
*static_cast<player_position1d_data_t*> ( data );
+ return 0;
+ }
+
+ if ( Message::MatchMessage ( hdr, PLAYER_MSGTYPE_CMD,
PLAYER_POSITION2D_CMD_POS ) ||
+ Message::MatchMessage ( hdr, PLAYER_MSGTYPE_REQ,
PLAYER_POSITION2D_REQ_POSITION_PID ) )
+ {
+ PLAYER_WARN ( "differential: position commands not supported" );
+ return 0;
+ }
+
+ if ( Message::MatchMessage ( hdr, PLAYER_MSGTYPE_CMD,
PLAYER_POSITION2D_CMD_VEL ) )
+ {
+ player_position2d_cmd_vel_t &vel =
*static_cast<player_position2d_cmd_vel_t*> ( data );
+ SetVel ( vel.vel );
+
+ return 0;
+ }
+
+ if ( Message::MatchMessage ( hdr, PLAYER_MSGTYPE_REQ,
PLAYER_POSITION2D_REQ_GET_GEOM ) )
+ {
+ player_position2d_geom_t geom;
+ memset(&geom, 0, sizeof(geom));
+ geom.pose.px = p2d_state_.pos.px;
+ geom.pose.py = p2d_state_.pos.py;
+ geom.pose.pyaw = p2d_state_.pos.pa;
+
+ geom.size.sw = axis_length_;
+
+ Publish(hdr->addr, PLAYER_MSGTYPE_RESP_ACK, hdr->subtype, &geom);
+ PLAYER_WARN ( "differential: geometry only partially supported" );
+ return 0;
+ }
+
+ if ( Message::MatchMessage ( hdr, PLAYER_MSGTYPE_REQ,
PLAYER_POSITION2D_REQ_POSITION_MODE ) )
+ {
+ PLAYER_WARN ( "differential: mode is always speed" );
+ return 0;
+ }
+
+ if ( Message::MatchMessage ( hdr, PLAYER_MSGTYPE_REQ,
PLAYER_POSITION2D_REQ_MOTOR_POWER ) )
+ {
+ PLAYER_WARN ( "differential: motors are always on" );
+ return 0;
+ }
+
+ if ( Message::MatchMessage ( hdr, PLAYER_MSGTYPE_REQ,
PLAYER_POSITION2D_REQ_RESET_ODOM ) )
+ {
+ p1d_dev_[kL]->PutMsg ( InQueue, PLAYER_MSGTYPE_REQ,
PLAYER_POSITION1D_REQ_RESET_ODOM, NULL, 0, NULL );
+ p1d_dev_[kR]->PutMsg ( InQueue, PLAYER_MSGTYPE_REQ,
PLAYER_POSITION1D_REQ_RESET_ODOM, NULL, 0, NULL );
+ return 0;
+ }
+
+ if ( Message::MatchMessage ( hdr, PLAYER_MSGTYPE_REQ,
PLAYER_POSITION2D_REQ_SET_ODOM ) )
+ {
+ PLAYER_WARN ( "differential: odometry setting to arbitrary values not
supported" );
+ return 0;
+ }
+
+ if ( Message::MatchMessage ( hdr, PLAYER_MSGTYPE_REQ,
PLAYER_POSITION2D_REQ_SPEED_PID ) )
+ {
+ PLAYER_WARN ( "differential: speed profiles not supported" );
+ return 0;
+ }
+
+ if ( Message::MatchMessage ( hdr, PLAYER_MSGTYPE_REQ,
PLAYER_POSITION2D_REQ_SPEED_PROF ) )
+ {
+ player_position2d_speed_prof_req_t & req =
*static_cast<player_position2d_speed_prof_req_t*> ( data );
+ player_position1d_speed_prof_req_t cmd = { req.speed, req.acc };
+
+ p1d_dev_[kL]->PutMsg ( InQueue, PLAYER_MSGTYPE_REQ,
PLAYER_POSITION1D_REQ_SPEED_PROF,
+ static_cast<void*> ( &cmd ), 0, NULL );
+ p1d_dev_[kR]->PutMsg ( InQueue, PLAYER_MSGTYPE_REQ,
PLAYER_POSITION1D_REQ_SPEED_PROF,
+ static_cast<void*> ( &cmd ), 0, NULL );
+
+ return 0;
+ }
+
+ PLAYER_WARN4 ( "differential: Message not processed idx:%d type:%d sub:%d
seq:%d\n", hdr->addr.index, hdr->type, hdr->subtype, hdr->seq );
+ return -1;
+}
+
+
+int Differential::GetMotor ( const player_devaddr_t &addr ) const
+ {
+ for ( int i = 0; i < kNumMotors; i++ )
+ if ( ( addr.host == p1d_addr_[i].host ) &&
+ ( addr.robot == p1d_addr_[i].robot ) &&
+ ( addr.index == p1d_addr_[i].index ) &&
+ ( addr.interf == p1d_addr_[i].interf ) )
+ return i;
+
+ throw std::runtime_error ( "differential: received request for unknown
motor" );
+ }
+
+void Differential::SetVel ( const player_pose2d_t &vel )
+{
+ player_position1d_cmd_vel_t sl = { vel.px - vel.pa * axis_length_ / 2.0, 0 };
+ player_position1d_cmd_vel_t sr = { vel.px + vel.pa * axis_length_ / 2.0, 0 };
+
+ PLAYER_MSG4 ( 4, "differential: speed CMD: [vx, va --> vl, vr] = [ %8.2f,
%8.2f --> %8.2f, %8.2f ]",
+ vel.px, vel.pa, sl.vel, sr.vel );
+
+ p1d_dev_[kL]->PutMsg ( InQueue,
+ PLAYER_MSGTYPE_CMD,
+ PLAYER_POSITION1D_CMD_VEL,
+ static_cast<void*> ( &sl ), 0, NULL );
+ p1d_dev_[kR]->PutMsg ( InQueue,
+ PLAYER_MSGTYPE_CMD,
+ PLAYER_POSITION1D_CMD_VEL,
+ static_cast<void*> ( &sr ), 0, NULL );
+
+ if ( vel.py != 0 )
+ PLAYER_WARN1 ( "differential: Y speed requested is not null; impossible
with skid-steering: %8.2f (ignored)", vel.py );
+}
+
This was sent by the SourceForge.net collaborative development platform, the
world's largest Open Source development site.
------------------------------------------------------------------------------
Oracle to DB2 Conversion Guide: Learn learn about native support for PL/SQL,
new data types, scalar functions, improved concurrency, built-in packages,
OCI, SQL*Plus, data movement tools, best practices and more.
http://p.sf.net/sfu/oracle-sfdev2dev
_______________________________________________
Playerstage-commit mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/playerstage-commit