Revision: 8548
          http://playerstage.svn.sourceforge.net/playerstage/?rev=8548&view=rev
Author:   thjc
Date:     2010-02-06 18:32:56 +0000 (Sat, 06 Feb 2010)

Log Message:
-----------
Applied patch 2938899: roboteq add position1d interface and motor_control_mode 
conf

Modified Paths:
--------------
    code/player/trunk/server/drivers/position/roboteq/roboteq.cc

Modified: code/player/trunk/server/drivers/position/roboteq/roboteq.cc
===================================================================
--- code/player/trunk/server/drivers/position/roboteq/roboteq.cc        
2010-02-06 18:30:17 UTC (rev 8547)
+++ code/player/trunk/server/drivers/position/roboteq/roboteq.cc        
2010-02-06 18:32:56 UTC (rev 8548)
@@ -37,6 +37,8 @@
 
 - @ref interface_position2d
   @ref interface_power
+  @ref interface_position1d
+  @ref interface_dio
 
 @par Requires
 
@@ -56,6 +58,11 @@
   - Default: 9600
   - The baud rate to be used.
 
+- motor_control_mode (integer)
+  - Default: ( 1 - open loop separate speed if no encoder, 197 - A&B mixed 
speed closed loop if encoders)
+  - options (0-255 see Roboteq Motor Control Mode documentation)
+    - 3 (A&B position analog feedback type)
+
 - encoder_ppr
   - Default: 500
   - The number of pulses per revolution for the encoders. Optional if no 
encoders are present.
@@ -96,6 +103,33 @@
   - Default: true (on)
   - Set the motor controller to RC mode when the driver shuts down.
 
+...@par Properties
+
+- ch1_min_pos
+  - Default -0.1
+  - Minimum position in rad/m limit for channel 1 mootor when using position1d 
interface
+
+- ch2_min_pos
+  - Default -0.1
+  - Minimum position in rad/m limit for channel 2 mootor when using position1d 
interface
+
+- ch1_max_pos
+  - Default 0.1
+  - Maximum position in rad/m limit for channel 1 mootor when using position1d 
interface
+
+- ch2_max_pos
+  - Default 0.1
+  - Maximum position in rad/m limit for channel 2 mootor when using position1d 
interface
+
+- ch1_dpos_per_tick (float)
+  - Default: 0.01
+  - change in channel 1 position in rad/m per roboteq tick when using 
position1d interface
+
+- ch2_dpos_per_tick (float)
+  - Default: 0.01
+  - change in channel 2 position per roboteq tick when using position1d 
interface
+
+- 
 @par Example
 
 @verbatim
@@ -107,6 +141,21 @@
 )
 @endverbatim
 
+...@verbatim
+# Position1d interfaces
+driver
+(
+  name "roboteq"
+  provides ["position1d:0" "position1d:1"]
+  devicepath "/dev/ttyS0"
+  motor_control_mode "3"
+  ch1_min_pos "-1.0"
+  ch1_max_pos "1.0"
+  ch2_min_pos "-10.0"
+  ch2_max_pos "10.0"
+)  
+
+
 @author Pablo Rivera [email protected]
 @author Mike Roddewig [email protected]
 
@@ -232,7 +281,19 @@
                unsigned char motor_control_mode;
                double max_forward_velocity;
                double max_rotational_velocity;
+               DoubleProperty min_position_motor_0;
+               DoubleProperty min_position_motor_1;
+               DoubleProperty* min_position_motor[2];
+               DoubleProperty max_position_motor_0;
+               DoubleProperty max_position_motor_1;
+               DoubleProperty* max_position_motor[2];
+               DoubleProperty dpos_per_tick_0;
+               DoubleProperty dpos_per_tick_1;
+               DoubleProperty* dpos_per_tick[2];
                bool motors_enabled;
+               bool motor0_enabled;
+               bool motor1_enabled;
+               bool* motor_enabled[2];
        
                // Config parameters.
 
@@ -254,16 +315,19 @@
                void UpdatePowerData (player_power_data_t *);
                void UpdatePositionData (player_position2d_data_t *);
                int WriteMotorVelocity (double, double);
+               int ProcessPosition1dCmd(const int, player_position1d_cmd_pos_t 
*);
 
                player_position2d_data_t position_data;
                player_power_data_t power_data;
-               player_devaddr_t position_addr;
+               player_devaddr_t position_addr; //position2d interface
+               player_devaddr_t position_addr_motor1;
+               player_devaddr_t position_addr_motor2;
                player_devaddr_t power_addr;
                player_pose2d current_position;
 
        public:
                roboteq(ConfigFile *, int);
-    
+               
                virtual int ProcessMessage(QueuePointer &, 
                        player_msghdr *, void *);
                virtual int MainSetup();
@@ -286,20 +350,55 @@
 }
 
 ///////////////////////////////////////////////////////////////////////////
-roboteq::roboteq( ConfigFile* cf, int section) : ThreadedDriver(cf, section) { 
 
+roboteq::roboteq( ConfigFile* cf, int section) : 
+       ThreadedDriver(cf, section),
+       min_position_motor_0("ch1_min_pos", -0.1, true, this, cf, section),
+       min_position_motor_1("ch2_min_pos", -0.1, true, this, cf, section),
+       max_position_motor_0("ch1_max_pos", 0.1, true, this, cf, section),
+       max_position_motor_1("ch2_max_pos", 0.1, true, this, cf, section),
+       dpos_per_tick_0("ch1_dpos_per_tick", 0.01, true, this, cf, section),
+       dpos_per_tick_1("ch2_dpos_per_tick", 0.01 , true, this, cf, section)
+{  
        
        memset (&this->position_addr, 0, sizeof (player_devaddr_t));
        memset (&this->power_addr, 0, sizeof (player_devaddr_t));
-       
-       // Check the config file to see if we are providing a position 
interface.
+       min_position_motor[0] = &min_position_motor_0;  
+       min_position_motor[1] = &min_position_motor_1;  
+       max_position_motor[0] = &max_position_motor_0;  
+       max_position_motor[1] = &max_position_motor_1;  
+       dpos_per_tick[0] = &dpos_per_tick_0;    
+       dpos_per_tick[1] = &dpos_per_tick_1;
+       motor_enabled[0] = &motor0_enabled;
+       motor_enabled[1] = &motor1_enabled;
+       // Check the config file to see if we are providing a position2d 
interface.
        if (cf->ReadDeviceAddr(&(this->position_addr), section, "provides",
                PLAYER_POSITION2D_CODE, -1, NULL) == 0) {
+               PLAYER_ERROR("Adding position2d interface.");
                if (this->AddInterface(this->position_addr) != 0) {
-                       PLAYER_ERROR("Error adding position interface.");
+                       PLAYER_ERROR("Error adding position2d interface.");
                        SetError(-1);
                        return;
                }
        }
+
+       // Check the config file to see if we are providing a position1d 
interface.
+       if (cf->ReadDeviceAddr(&(this->position_addr_motor1), section, 
"provides",
+               PLAYER_POSITION1D_CODE, 0, NULL) == 0) {
+               if (this->AddInterface(this->position_addr_motor1) != 0) {
+                       PLAYER_ERROR("Error adding position1d interface 0.");
+                       SetError(-1);
+                       return;
+               }
+       }
+       // Check the config file to see if we are providing a position1d 
interface.
+       if (cf->ReadDeviceAddr(&(this->position_addr_motor2), section, 
"provides",
+               PLAYER_POSITION1D_CODE, 1, NULL) == 0) {
+               if (this->AddInterface(this->position_addr_motor2) != 0) {
+                       PLAYER_ERROR("Error adding position1d interface 1.");
+                       SetError(-1);
+                       return;
+               }
+       }
        
        // Check the config file to see if we are providing a power interface.
        if (cf->ReadDeviceAddr(&(this->power_addr), section, "provides",
@@ -321,6 +420,14 @@
        
        // Optional parameters.
        
+       int modetmp = cf->ReadInt(section, "motor_control_mode", 
MOTOR_CONTROL_MODE_OPEN_LOOP);
+       if (modetmp < 0 || modetmp > 255) {
+               PLAYER_ERROR("ROBOTEQ: 'motor_control_mode' must be between 0 
and 255. See Roboteq Motor Control Mode documentation.");
+               this->SetError(-1);
+               return;
+       }
+       motor_control_mode = (unsigned char)modetmp;
+
        encoder_ppr = cf->ReadInt(section, "encoder_ppr", DEFAULT_ENCODER_PPR);
        if (encoder_ppr < 0) {
                PLAYER_ERROR("ROBOTEQ: 'encoder_ppr' must be positive.");
@@ -432,7 +539,7 @@
        }
        else{
                struct termios options;
-      
+                       
                tcgetattr(roboteq_fd, &options);
 
                // default is 9600 unless otherwise specified
@@ -492,6 +599,8 @@
        
        // Motors are disabled on startup.
        motors_enabled = false;
+       motor0_enabled = false;
+       motor1_enabled = false;
        
        // Enable new motor commands to overwrite old ones if they have not yet 
been processed.
        this->InQueue->AddReplaceRule(-1, -1, -1, -1, PLAYER_MSGTYPE_CMD, 
PLAYER_POSITION2D_CMD_VEL, true);
@@ -536,11 +645,10 @@
        write(roboteq_fd, serialout_buff, strlen(serialout_buff));
        tcdrain(roboteq_fd);
        usleep(25000);
-       
+
        memset(serialin_buff, 0, SERIAL_BUFF_SIZE);
        ret = read(roboteq_fd, serialin_buff, SERIAL_BUFF_SIZE-1);
        serialin_buff[SERIAL_BUFF_SIZE-1] = 0x00; // Null terminate our buffer 
to make sure sscanf doesn't run amok.
-       
        ret = sscanf(serialin_buff, "%*3c %2X", &returned_value);
        if (ret != 1) {
                PLAYER_ERROR("ROBOTEQ: Unable to communicate with the 
controller! Check the serial device.");
@@ -577,13 +685,17 @@
                }
        }
        
-       if (encoder_present == 1) {
-               motor_control_mode = MOTOR_CONTROL_MODE_CLOSED_LOOP;
-       }
-       else {
+       // If motor control mode is set to default, change to closed loop if 
encoders are present
+       //  otherwise leave as set by motor_control_mode command in config file
+       if ( motor_control_mode == MOTOR_CONTROL_MODE_OPEN_LOOP) {
+               if (encoder_present == 1) {
+                       motor_control_mode = MOTOR_CONTROL_MODE_CLOSED_LOOP;
+               }
+               else {
                motor_control_mode = MOTOR_CONTROL_MODE_OPEN_LOOP;
+               }
        }
-       
+
        // Set configuration parameters
 
        if (this->checkConfigParameter('^', MOTOR_CONTROL_MODE_ADDRESS, 
motor_control_mode) != 0) {
@@ -632,11 +744,11 @@
        }
        // Reboot the controller.
        strcpy(serialout_buff, "%rrrrrr\r");
-        write(roboteq_fd, serialout_buff, strlen(serialout_buff));
-        tcdrain(roboteq_fd);
-        sleep(2); // Sleep for two seconds to give the controller sufficient 
time to reboot.
+                               write(roboteq_fd, serialout_buff, 
strlen(serialout_buff));
+                               tcdrain(roboteq_fd);
+                               sleep(2); // Sleep for two seconds to give the 
controller sufficient time to reboot.
 
-        tcflush(roboteq_fd, TCIFLUSH); // Clear all the reboot crap out of the 
input buffer.
+                               tcflush(roboteq_fd, TCIFLUSH); // Clear all the 
reboot crap out of the input buffer.
 
        return 0;
 }
@@ -713,7 +825,7 @@
        }
 
        close(roboteq_fd);
-  
+       
        return;
 }
 
@@ -721,7 +833,9 @@
 // Process an incoming message
 
////////////////////////////////////////////////////////////////////////////////
 int roboteq::ProcessMessage (QueuePointer &resp_queue, player_msghdr * hdr, 
void * data) {
-       
+       PLAYER_MSG3(MESSAGE_DEBUG,"Received Message for addr.index %d type %d 
subtype %d",hdr->addr.index, hdr->type, hdr->subtype);
+       
//////////////////////////////////////////////////////////////////////////////  
+       // Process position2d messages
        if (Message::MatchMessage(hdr, PLAYER_MSGTYPE_CMD, 
PLAYER_POSITION2D_CMD_VEL, position_addr)) {
 
                assert(hdr->size == sizeof(player_position2d_cmd_vel_t));
@@ -794,9 +908,82 @@
                        this->Publish(position_addr, resp_queue, 
PLAYER_MSGTYPE_RESP_ACK, PLAYER_POSITION2D_REQ_SPEED_PID);
                }
        }
+       
//////////////////////////////////////////////////////////////////////////////
+
+       
//////////////////////////////////////////////////////////////////////////////  
+       // Process position1d messages
+       else if (Message::MatchMessage(hdr, PLAYER_MSGTYPE_REQ, 
PLAYER_POSITION1D_REQ_MOTOR_POWER,position_addr_motor1)) {
+               assert(hdr->size == sizeof(player_position1d_power_config_t));
+               
+               PLAYER_MSG1(MESSAGE_DEBUG,"Received position1d req motor power 
for index %d",hdr->addr.index);
+               player_position1d_power_config_t * power_config = 
reinterpret_cast<player_position1d_power_config_t *> (data);
+               motors_enabled = (bool) power_config->state;
+               motor0_enabled = (bool) power_config->state;
+               
+               this->Publish(position_addr_motor1, resp_queue, 
PLAYER_MSGTYPE_RESP_ACK, PLAYER_POSITION1D_REQ_MOTOR_POWER);
+       }
+       else if (Message::MatchMessage(hdr, PLAYER_MSGTYPE_REQ, 
PLAYER_POSITION1D_REQ_MOTOR_POWER,position_addr_motor2)) {
+               assert(hdr->size == sizeof(player_position1d_power_config_t));
+               
+               PLAYER_MSG1(MESSAGE_DEBUG,"Received position1d req motor power 
for index %d",hdr->addr.index);
+               player_position1d_power_config_t * power_config = 
reinterpret_cast<player_position1d_power_config_t *> (data);
+               motors_enabled = (bool) power_config->state;
+               motor1_enabled = (bool) power_config->state;
+               
+               this->Publish(position_addr_motor2, resp_queue, 
PLAYER_MSGTYPE_RESP_ACK, PLAYER_POSITION1D_REQ_MOTOR_POWER);
+       }
+       else if (Message::MatchMessage(hdr, PLAYER_MSGTYPE_CMD, 
PLAYER_POSITION1D_CMD_POS,position_addr_motor1)) {
+               assert(hdr->size == sizeof(player_position1d_cmd_pos_t));
+               PLAYER_MSG1(MESSAGE_DEBUG,"Received position1d pos cmd for 
motor at index %d",hdr->addr.index);
+               ProcessPosition1dCmd(0, 
reinterpret_cast<player_position1d_cmd_pos_t *>(data) );
+       }
+       else if (Message::MatchMessage(hdr, PLAYER_MSGTYPE_CMD, 
PLAYER_POSITION1D_CMD_POS,position_addr_motor2)) {
+               assert(hdr->size == sizeof(player_position1d_cmd_pos_t));
+               PLAYER_MSG1(MESSAGE_DEBUG,"Received position1d pos cmd for 
motor at index %d",hdr->addr.index);
+               ProcessPosition1dCmd(1, 
reinterpret_cast<player_position1d_cmd_pos_t *>(data) );
+       }
+       else if (Message::MatchMessage(hdr, PLAYER_MSGTYPE_REQ,
+                       PLAYER_GET_DBLPROP_REQ, position_addr_motor1)) {
+
+               player_dblprop_req_t &req = 
*reinterpret_cast<player_dblprop_req_t*> (data);
+               PLAYER_MSG1(MESSAGE_DEBUG,"motor1 PLAYER_GET_DBLPROP_REQ 
%s",req.key);
+               if (min_position_motor_0.KeyIsEqual(req.key))
+               {
+                       min_position_motor_0.GetValueToMessage 
(reinterpret_cast<void*> (&req));
+                       Publish(position_addr_motor1, resp_queue, 
PLAYER_MSGTYPE_RESP_ACK, PLAYER_GET_DBLPROP_REQ, reinterpret_cast<void*> 
(&req), sizeof(player_dblprop_req_t), NULL);
+                       return 0;
+               }
+               else if (max_position_motor_0.KeyIsEqual(req.key))
+               {
+                       max_position_motor_0.GetValueToMessage 
(reinterpret_cast<void*> (&req));
+                       Publish(position_addr_motor1, resp_queue, 
PLAYER_MSGTYPE_RESP_ACK, PLAYER_GET_DBLPROP_REQ, reinterpret_cast<void*> 
(&req), sizeof(player_dblprop_req_t), NULL);
+                       return 0;
+               }
+               return -1;
+       }
+       else if (Message::MatchMessage(hdr, PLAYER_MSGTYPE_REQ,
+                       PLAYER_GET_DBLPROP_REQ, position_addr_motor2)) {
+
+               player_dblprop_req_t &req = 
*reinterpret_cast<player_dblprop_req_t*> (data);
+               PLAYER_MSG1(MESSAGE_DEBUG,"motor2 PLAYER_GET_DBLPROP_REQ 
%s",req.key);
+               if (min_position_motor_1.KeyIsEqual(req.key))
+               {
+                       min_position_motor_1.GetValueToMessage 
(reinterpret_cast<void*> (&req));
+                       Publish(position_addr_motor2, resp_queue, 
PLAYER_MSGTYPE_RESP_ACK, PLAYER_GET_DBLPROP_REQ, reinterpret_cast<void*> 
(&req), sizeof(player_dblprop_req_t), NULL);
+                       return 0;
+               }
+               else if (max_position_motor_1.KeyIsEqual(req.key))
+               {
+                       max_position_motor_1.GetValueToMessage 
(reinterpret_cast<void*> (&req));
+                       Publish(position_addr_motor2, resp_queue, 
PLAYER_MSGTYPE_RESP_ACK, PLAYER_GET_DBLPROP_REQ, reinterpret_cast<void*> 
(&req), sizeof(player_dblprop_req_t), NULL);
+                       return 0;
+               }
+               return -1;
+       }
        else {
                this->Publish(position_addr, resp_queue, 
PLAYER_MSGTYPE_RESP_NACK, hdr->subtype);
        }
+       
//////////////////////////////////////////////////////////////////////////////  
        
        return 0;
 }
@@ -1049,6 +1236,62 @@
        position_data->pos = current_position;
 }
 
+int roboteq::ProcessPosition1dCmd(int motor_index, player_position1d_cmd_pos_t 
* data)
+{
+       int ret;
+       float position = data->pos;
+       unsigned char position_value;
+       char returned_value;
+       PLAYER_MSG1(MESSAGE_DEBUG,"Received position %0.2f",position);
+       if (invert_directions == true) {
+               position = -position;
+       }
+       if (position > *max_position_motor[motor_index]) {
+               PLAYER_WARN3("Position %f exceeds max position %f: limited to 
%f",
+                       position,
+                       max_position_motor[motor_index]->GetValue(),
+                       max_position_motor[motor_index]->GetValue());
+               position = *max_position_motor[motor_index];
+       }
+       if (position < *min_position_motor[motor_index]) {
+               PLAYER_WARN3("Position %f exceeds min position %f: limited to 
%f",
+                       position,
+                       min_position_motor[motor_index]->GetValue(),
+                       min_position_motor[motor_index]->GetValue());
+               position = *min_position_motor[motor_index];
+       }
+       position_value = (unsigned char) (fabs(position) / rad_per_tick);
+       PLAYER_MSG1(MESSAGE_DEBUG,"Setting position_value to 
%d",position_value);
+       if (motors_enabled == false || motor_enabled[motor_index] == false) {
+               position_value = 0;
+               PLAYER_MSG0(MESSAGE_INFO, "Warning, the motors are disabled! 
Enable them before use.");
+       }
+       if (position < 0) {
+               sprintf(serialout_buff, "!%c%.2X\r", (motor_index == 0 ? 'a' : 
'b'), position_value);
+       }
+       else {
+               sprintf(serialout_buff, "!%c%.2X\r", (motor_index == 0 ? 'A' : 
'B'), position_value);
+       }
+       PLAYER_MSG1(MESSAGE_DEBUG,"Sending Roboteq '%s'",serialout_buff);
+       write(roboteq_fd, serialout_buff, strlen(serialout_buff));
+       tcdrain(roboteq_fd);
+       usleep(25000);
+               
+       memset(serialin_buff, 0, SERIAL_BUFF_SIZE);
+       ret = read(roboteq_fd, serialin_buff, SERIAL_BUFF_SIZE-1);
+       serialin_buff[SERIAL_BUFF_SIZE-1] = 0x00; // Null terminate our buffer 
to make sure sscanf doesn't run amok.
+
+       ret = sscanf(serialin_buff, "%*4c %1c", &returned_value);
+               
+       if (returned_value != '+') {
+               // Some kind of error happened.
+               
+               PLAYER_ERROR("ROBOTEQ: Error writing position command.");
+               return -1;
+       }
+       return 0; 
+}
+
 ///////////////////////////////////////////////////////////////////////////
 // Main driver thread runs here.
 ///////////////////////////////////////////////////////////////////////////
@@ -1069,10 +1312,10 @@
                        (unsigned char *) &position_data, 
sizeof(position_data), NULL);
                this->Publish(power_addr, PLAYER_MSGTYPE_DATA, 
PLAYER_POWER_DATA_STATE,
                        (unsigned char *) &power_data, sizeof(power_data), 
NULL);
-               
+
                usleep(25000);
        }
-         
+               
        return;
 }
 


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

------------------------------------------------------------------------------
The Planet: dedicated and managed hosting, cloud storage, colocation
Stay online with enterprise data centers and the best network in the business
Choose flexible plans and management services without long-term contracts
Personal 24x7 support from experience hosting pros just a phone call away.
http://p.sf.net/sfu/theplanet-com
_______________________________________________
Playerstage-commit mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/playerstage-commit

Reply via email to