Update of /cvsroot/playerstage/code/player/server/drivers/position/roboteq
In directory
sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv19142/server/drivers/position/roboteq
Added Files:
Makefile.am roboteq.cc
Log Message:
added roboteq driver patch 1754183
--- NEW FILE: Makefile.am ---
AM_CPPFLAGS = -Wall -I$(top_srcdir)
noinst_LTLIBRARIES =
if INCLUDE_ROBOTEQ
noinst_LTLIBRARIES += libroboteq.la
endif
libroboteq_la_SOURCES = roboteq.cc
--- NEW FILE: roboteq.cc ---
/*
* Player - One Hell of a Robot Server
* Copyright (C) 2000-2003 Brian Gerkey [EMAIL PROTECTED]
* Andrew Howard [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
*
*/
/** @ingroup drivers */
/** @{ */
/** @defgroup driver_roboteq roboteq
* @brief Motor control driver for Roboteq AX2550
Provides position2d interface to the Roboteq AX2550 motor controller
http://www.roboteq.com/ax2550-folder.html
This driver ignores all configuration requests and produces no data
although the hardware device supports a number of configurations
and data over the serial link. It simply accepts 2 types of commmands
translation and rotation, then converts these to the syntax used by
the Roboteq. This driver uses the configuration file options
max_rot_spd and max_trans_spd to scale commands sent to the controller.
These values can be determined by testing with RC -- or closed loop
could be implemented by integrating dead-reckoning devices.
@par Compile-time dependencies
- none
@par Provides
- @ref interface_position2d
@par Requires
- None
@par Configuration requests
- none
@par Configuration file options
- devicepath (string)
- Default: none
- The serial port to be used.
- baud (integer)
- Default: 9600
- The baud rate to be used.
- max_rot_spd (float)
- Default: none
- maximum rotational speed (in rad/sec) that would be achieved
by vehicle if full power where applied to that channel.
- max_trans_spd (float)
- Default: none
- maximum translational speed (in meters/sec) that would be achieved
by vehicle if full power where applied to that channel.
@par Example
@verbatim
driver
(
name "roboteq"
provides ["position2d:0"]
devicepath "/dev/ttyS0"
max_trans_spd 6.0
max_rot_spd 4.0
)
@endverbatim
@author Pablo Rivera [EMAIL PROTECTED]
*/
/** @} */
#include <time.h>
#include <assert.h>
#include <stdio.h>
#include <termios.h>
#include <sys/ioctl.h> // ioctl
#include <unistd.h> // close(2),fcntl(2),getpid(2),usleep(3),execvp(3),fork(2)
#include <netdb.h> // for gethostbyname(3)
#include <netinet/in.h> // for struct sockaddr_in, htons(3)
#include <sys/types.h> // for socket(2)
#include <sys/socket.h> // for socket(2)
#include <signal.h> // for kill(2)
#include <fcntl.h> // for fcntl(2)
#include <string.h> // for strncpy(3),memcpy(3)
#include <stdlib.h> // for atexit(3),atoi(3)
#include <pthread.h> // for pthread stuff
#include <sys/poll.h> // for poll and poll_fd
#include <math.h>
#include <libplayercore/playercore.h>
// settings
#define SERIAL_BUFF_SIZE 128
#define MAX_MOTOR_SPEED 127
#define ROBOTEQ_CON_TIMEOUT 10 // seconds to time-out on
setting RS-232 mode
#define ROBOTEQ_DEFAULT_BAUD 9600
// *************************************
// some assumptions made by this driver:
// ROBOTEQ is in "mixed mode" where
// channel 1 is translation
// channel 2 is rotation
// ROBOTEQ is set to be in RC mode by default
// the robot is a skid-steer vehicle where
// left wheel(s) are on one output,
// right wheel(s) on the other.
// directionality is implied by the following
// macros (FORWARD,REVERSE,LEFT,RIGHT)
// so outputs may need to be switched
// *************************************
#define FORWARD "!A"
#define REVERSE "!a"
#define LEFT "!B"
#define RIGHT "!b"
///////////////////////////////////////////////////////////////////////////
class roboteq:public Driver
{
private:
int roboteq_fd;
char serialin_buff[SERIAL_BUFF_SIZE];
char serialout_buff[SERIAL_BUFF_SIZE];
const char* devicepath;
int roboteq_baud;
double speed_scaling_factor, rot_scaling_factor;
int FormMotorCmd(char* cmd_str, short trans_command, short rot_command);
// current data
player_position2d_data_t data;
player_devaddr_t position2d_id;
public:
roboteq( ConfigFile* cf, int section);
virtual int ProcessMessage(MessageQueue * resp_queue,
player_msghdr * hdr, void *
data);
virtual int Setup();
virtual int Shutdown();
virtual void Main();
};
///////////////////////////////////////////////////////////////////////////
// initialization function
Driver* roboteq_Init( ConfigFile* cf, int section)
{
return((Driver*)(new roboteq( cf, section)));
}
///////////////////////////////////////////////////////////////////////////
// a driver registration function
void roboteq_Register(DriverTable* table)
{
table->AddDriver("roboteq", roboteq_Init);
}
///////////////////////////////////////////////////////////////////////////
roboteq::roboteq( ConfigFile* cf, int section) : Driver(cf, section)
{
memset (&this->position2d_id, 0, sizeof (player_devaddr_t));
// Outgoing position 2d interface
if(cf->ReadDeviceAddr(&(this->position2d_id), section, "provides",
PLAYER_POSITION2D_CODE, -1, NULL) == 0){
if(this->AddInterface(this->position2d_id) != 0){
this->SetError(-1);
return;
} }
double max_trans_spd, max_rot_spd;
// required parameter(s)
if(!(this->devicepath = (char*)cf->ReadString(section, "devicepath", NULL))){
PLAYER_ERROR("must specify devicepath");
this->SetError(-1);
return;
}
if(!(max_trans_spd = (double)cf->ReadFloat(section, "max_trans_spd", 0))){
PLAYER_ERROR("must specify maximum translational speed");
this->SetError(-1);
return;
}
if(!(max_rot_spd = (double)cf->ReadFloat(section, "max_rot_spd", 0))){
PLAYER_ERROR("must specify maximum rotational speed");
this->SetError(-1);
return;
}
fprintf(stderr, "Roboteq: using a max translational speed of %f m/s\n\tand
max rotational speed of %f rad/s to scale motor commands\n", max_trans_spd,
max_rot_spd);
speed_scaling_factor = ((double)(MAX_MOTOR_SPEED / max_trans_spd));
rot_scaling_factor = ((double)(MAX_MOTOR_SPEED / max_rot_spd));
// optional parameter(s)
roboteq_baud = cf->ReadInt(section, "baud", ROBOTEQ_DEFAULT_BAUD);
memset(&data,0,sizeof(data));
roboteq_fd = -1;
return;
}
///////////////////////////////////////////////////////////////////////////
int
roboteq::Setup()
{
int ret, i;
fprintf(stderr, "Configuring Roboteq serial port at %s..\n", devicepath);
roboteq_fd = open(devicepath, O_RDWR|O_NDELAY);
if (roboteq_fd == -1){
fputs("Unable to configure serial port for RoboteQ!", stderr);
return 0;
}else{
struct termios options;
tcgetattr(roboteq_fd, &options);
// default is 9600 unless otherwise specified
if (roboteq_baud == 4800){
cfsetispeed(&options, B4800);
cfsetospeed(&options, B4800);
}
else if (roboteq_baud == 19200){
cfsetispeed(&options, B19200);
cfsetospeed(&options, B19200);
}
else if (roboteq_baud == 38400){
cfsetispeed(&options, B38400);
cfsetospeed(&options, B38400);
}
else{
cfsetispeed(&options, B9600);
cfsetospeed(&options, B9600);
}
// set to 7bit even parity, no flow control
options.c_cflag |= (CLOCAL | CREAD);
options.c_cflag |= PARENB;
options.c_cflag &= ~PARODD;
options.c_cflag &= ~CSTOPB;
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS7;
options.c_cflag &= ~CRTSCTS;
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // non-canonical
tcsetattr(roboteq_fd, TCSANOW, &options);
ioctl(roboteq_fd, TCFLSH, 2);
}
// initialize RoboteQ to RS-232 mode
strcpy(serialout_buff, "\r");
for (i=0; i<10; i++){
write(roboteq_fd, serialout_buff, 1);
tcdrain(roboteq_fd);
usleep(25000);
}
// check response from RoboteQ
bzero(serialin_buff, SERIAL_BUFF_SIZE);
ret = read(roboteq_fd, serialin_buff, SERIAL_BUFF_SIZE);
int beg_time = time(NULL);
bool mode_changed = true;
while (! strchr(serialin_buff, 'W')){
if ((time(NULL) - beg_time)>ROBOTEQ_CON_TIMEOUT){
mode_changed = false;
break;
}
bzero(serialin_buff, SERIAL_BUFF_SIZE);
ret = read(roboteq_fd, serialin_buff, SERIAL_BUFF_SIZE);
}
if (!mode_changed)
fputs("Failed to set Roboteq to RS-232 mode!\n", stderr);
else
fputs("Successfully initialized Roboteq connection.\n", stderr);
fputs("Done.\n", stderr);
// now spawn reading thread
StartThread();
return(0);
}
///////////////////////////////////////////////////////////////////////////
int roboteq::Shutdown()
{
int ret;
StopThread();
// return RoboteQ to RC mode
strcpy(serialout_buff, "^00 00\r");
write(roboteq_fd, serialout_buff, 7);
tcdrain(roboteq_fd);
usleep(25000);
strcpy(serialout_buff, "%rrrrrr\r");
write(roboteq_fd, serialout_buff, 8);
tcdrain(roboteq_fd);
usleep(25000);
// check response from RoboteQ
bzero(serialin_buff, SERIAL_BUFF_SIZE);
ret = read(roboteq_fd, serialin_buff, SERIAL_BUFF_SIZE);
int beg_time = time(NULL);
while (! strchr(serialin_buff, 'W')){
if ((time(NULL) - beg_time)>ROBOTEQ_CON_TIMEOUT){
// no 'W's for ROBOTEQ_CON_TIMEOUT seconds
// means we're probably in RC mode again
// 07-09-07
// this test may need to change since the reset
// appears to fail quite often. is it really
// failing or is the test bad?
return 0;
}
bzero(serialin_buff, SERIAL_BUFF_SIZE);
ret = read(roboteq_fd, serialin_buff, SERIAL_BUFF_SIZE);
}
fputs("Unable to reset Roboteq to RC mode!", stderr);
close(roboteq_fd);
return(0);
}
////////////////////////////////////////////////////////////////////////////////
// Process an incoming message
////////////////////////////////////////////////////////////////////////////////
int roboteq::ProcessMessage (MessageQueue* resp_queue, player_msghdr * hdr,
void * data)
{
assert(hdr);
assert(data);
/*
fprintf(stderr, "ProcessMessage: type=%d subtype=%d\n",
hdr->type, hdr->subtype);
*/
if (Message::MatchMessage(hdr, PLAYER_POSITION2D_REQ_MOTOR_POWER,
PLAYER_POSITION2D_CMD_VEL, position2d_id)){
assert(hdr->size == sizeof(player_position2d_cmd_vel_t));
player_position2d_cmd_vel_t & command
= *reinterpret_cast<player_position2d_cmd_vel_t *> (data);
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// convert from the generic position interface
// to the Roboteq-specific command
// assumes "Mixed Mode" --
// channel 1 : FW/BW speed
// channel 2 : rotation
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
float vel_xtrans = command.vel.px;
//float vel_ytrans = command.vel.py;
float vel_yawspd = command.vel.pa;
//fprintf(stderr, "ProcessMessage: trans=%f, steer=%f\n", vel_trans,
vel_turret);
// scale and translate to Roboteq command
vel_xtrans = (double)vel_xtrans * speed_scaling_factor;
vel_yawspd = (double)vel_yawspd * rot_scaling_factor;
FormMotorCmd(serialout_buff, (short)vel_xtrans, (short)vel_yawspd);
// write motor cmd
write(roboteq_fd, serialout_buff, strlen(serialout_buff)+1);
tcdrain(roboteq_fd);
/*
char* temp;
while (temp = strchr(serialout_buff, '\r')) *temp = 32;
puts(serialout_buff);
fflush(stdout);
*/
return 0;
}
return -1;
}
///////////////////////////////////////////////////////////////////////////
// Main driver thread runs here.
///////////////////////////////////////////////////////////////////////////
void roboteq::Main()
{
double position_time=0;
pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,NULL);
for(;;){
ProcessMessages();
pthread_testcancel();
// publish dummy data
Publish(device_addr, NULL, PLAYER_MSGTYPE_DATA,
PLAYER_POSITION2D_DATA_STATE,
(unsigned char*) &data, sizeof(data), &position_time);
usleep(10);
}
pthread_exit(NULL);
return;
}
///////////////////////////////////////////////////////////////////////////
int roboteq::FormMotorCmd(char* cmd_str, short trans_command, short rot_command)
{
char speed[8];
char heading[8];
if (trans_command > MAX_MOTOR_SPEED) trans_command = MAX_MOTOR_SPEED;
else if (trans_command < -MAX_MOTOR_SPEED) trans_command = -MAX_MOTOR_SPEED;
if (rot_command > MAX_MOTOR_SPEED) rot_command = MAX_MOTOR_SPEED;
else if (rot_command < -MAX_MOTOR_SPEED) rot_command = -MAX_MOTOR_SPEED;
if (trans_command > 0)
strcpy(speed, FORWARD);
else strcpy(speed, REVERSE);
if (rot_command > 0)
strcpy(heading, LEFT);
else strcpy(heading, RIGHT);
// form motor cmd string
strcpy(cmd_str, speed);
snprintf(cmd_str+2, 4, "%.2x", abs(trans_command)); // start at char 3
strcat(cmd_str, "\r");
strcat(cmd_str, heading);
snprintf(cmd_str + strlen(cmd_str), 4, "%.2x", abs(rot_command));
strcat(cmd_str, "\r");
return 0;
}
-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems? Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
_______________________________________________
Playerstage-commit mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/playerstage-commit