⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 amtecpowercube.cc

📁 机器人仿真软件
💻 CC
📖 第 1 页 / 共 2 页
字号:
/* *  Player - One Hell of a Robot Server *  Copyright (C) 2003  Brian Gerkey gerkey@robotics.stanford.edu * *  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 * *//* * $Id: amtecpowercube.cc,v 1.17.2.2 2006/09/25 15:54:58 gerkey Exp $ *//** @ingroup drivers *//** @{ *//** @defgroup driver_amtecpowercube amtecpowercube * @brief Amtec PowerCube pan-tilt unitThe amtecpowercube driver controls the Amtec PowerCube Wrist,a powerful pan-tilt unit that can, for example, carry a SICK laser(@ref driver_sicklms200).This driver communicates with the PowerCube via RS232, and does NOT handlethe newer CAN-based units.  Please submit a patch to support the CANprotocol.The amtecpowercube driver supports both position and velocity control,via the PLAYER_PTZ_CONTROL_MODE_REQ request.  For constant swiveling,the PowerCube works better under velocity control.Note that this driver is relatively new and not thoroughly tested.@par Compile-time dependencies- none@par Provides- @ref interface_ptz@par Requires- none@par Configuration requests- PLAYER_PTZ_CONTROL_MODE_REQ@par Configuration file options- port (string)  - Default: "/dev/ttyS0"  - Serial port where the unit is attached.- home (integer)  - Default: 0  - Whether to home (i.e., reset to the zero position) the unit before    commanding it- speed (angle)  - Default: 40 deg/sec  - Maximum pan/tilt speed @par Example@verbatimdriver(  name "amtecpowercube"  port "/dev/ttyS0"  home 1)@endverbatim@author Brian Gerkey*//** @} */#ifdef HAVE_CONFIG_H  #include "config.h"#endif#include <errno.h>#include <fcntl.h>#include <stdio.h>#include <string.h>#include <sys/types.h>#include <sys/stat.h>#include <termios.h>#include <stdlib.h>#include <unistd.h>#include <netinet/in.h>  /* for struct sockaddr_in, htons(3) */#include <math.h>#include <libplayercore/playercore.h>#include <replace/replace.h>#define AMTEC_DEFAULT_PORT "/dev/ttyS0"#define AMTEC_SLEEP_TIME_USEC 20000/* angular velocity used when in position control mode */#define AMTEC_DEFAULT_SPEED_DEG_PER_SEC DTOR(40)// start, end, and escape chars#define AMTEC_STX       0x02#define AMTEC_ETX       0x03#define AMTEC_DLE       0x10// sizes#define AMTEC_MAX_CMDSIZE     48// module IDs#define AMTEC_MODULE_TILT       11#define AMTEC_MODULE_PAN        12// command IDs#define AMTEC_CMD_RESET        0x00#define AMTEC_CMD_HOME         0x01#define AMTEC_CMD_HALT         0x02#define AMTEC_CMD_SET_EXT      0x08#define AMTEC_CMD_GET_EXT      0x0a#define AMTEC_CMD_SET_MOTION   0x0b#define AMTEC_CMD_SET_ISTEP    0x0d// parameter IDs#define AMTEC_PARAM_ACT_POS   0x3c#define AMTEC_PARAM_MIN_POS   0x45#define AMTEC_PARAM_MAX_POS   0x46#define AMTEC_PARAM_CUBESTATE 0x27#define AMTEC_PARAM_MAXCURR   0x4c#define AMTEC_PARAM_ACT_VEL   0x41// motion IDs#define AMTEC_MOTION_FRAMP       4#define AMTEC_MOTION_FRAMP_ACK  14#define AMTEC_MOTION_FSTEP_ACK  16#define AMTEC_MOTION_FVEL_ACK   17// module state bitmasks#define AMTEC_STATE_ERROR     0x01#define AMTEC_STATE_HOME_OK   0x02#define AMTEC_STATE_HALTED    0x04class AmtecPowerCube:public Driver {  private:    // this function will be run in a separate thread    virtual void Main();    // bookkeeping    bool fd_blocking;    int return_to_home;    int minpan, maxpan;    int mintilt, maxtilt;    int speed;    uint8_t controlmode;    // low-level methods to interact with the device    int SendCommand(int id, unsigned char* cmd, size_t len);    int WriteData(unsigned char *buf, size_t len);    int AwaitAnswer(unsigned char* buf, size_t len);    int AwaitETX(unsigned char* buf, size_t len);    int ReadAnswer(unsigned char* buf, size_t len);    size_t ConvertBuffer(unsigned char* buf, size_t len);    int GetFloatParam(int id, int param, float* val);    int GetUint32Param(int id, int param, unsigned int* val);    int SetFloatParam(int id, int param, float val);    // data (de)marshalling helpers    // NOTE: these currently assume little-endianness, which is NOT    //       portable (but works fine on x86).    float BytesToFloat(unsigned char* bytes);    unsigned int BytesToUint32(unsigned char* bytes);    void FloatToBytes(unsigned char *bytes, float f);    void Uint16ToBytes(unsigned char *bytes, unsigned short s);    // higher-level methods for common use    int GetPanTiltPos(short* pan, short* tilt);    int GetPanTiltVel(short* panspeed, short* tiltspeed);    int SetPanPos(short oldpan, short pan);    int SetTiltPos(short oldtilt, short tilt);    int SetPanVel(short panspeed);    int SetTiltVel(short tiltspeed);    int Home();    int Halt();    int Reset();    int SetLimits();    // helper for dealing with config requests.    //void HandleConfig(void *client, unsigned char *buf, size_t len);      short lastpan, lasttilt;      short lastpanspeed, lasttiltspeed;  public:    int fd; // amtec device file descriptor    /* device used to communicate with the ptz */    const char* serial_port;    AmtecPowerCube( ConfigFile* cf, int section);    // MessageHandler    int ProcessMessage(MessageQueue* resp_queue, player_msghdr * hdr, void * data);    virtual int Setup();    virtual int Shutdown();};// initialization functionDriver* AmtecPowerCube_Init( ConfigFile* cf, int section){  return((Driver*)(new AmtecPowerCube( cf, section)));}// a driver registration functionvoid AmtecPowerCube_Register(DriverTable* table){  table->AddDriver("amtecpowercube",  AmtecPowerCube_Init);}AmtecPowerCube::AmtecPowerCube( ConfigFile* cf, int section)         : Driver(cf, section, true, PLAYER_MSGQUEUE_DEFAULT_MAXLEN, PLAYER_PTZ_CODE){  fd = -1;/*  player_ptz_data_t data;  player_ptz_cmd_t cmd;  data.pan = data.tilt = data.zoom = 0;  cmd.pan = cmd.tilt = cmd.zoom = 0;  PutData((unsigned char*)&data,sizeof(data),NULL);  PutCommand(this->device_id,(unsigned char*)&cmd,sizeof(cmd),NULL);*/  this->serial_port = cf->ReadString(section, "port", AMTEC_DEFAULT_PORT);  this->return_to_home = cf->ReadInt(section, "home", 0);  this->speed = (int)rint(RTOD(cf->ReadAngle(section, "speed",                                              AMTEC_DEFAULT_SPEED_DEG_PER_SEC)));}int AmtecPowerCube::Reset(){  unsigned char buf[AMTEC_MAX_CMDSIZE];  unsigned char cmd[1];  cmd[0] = AMTEC_CMD_RESET;  if(SendCommand(AMTEC_MODULE_PAN,cmd,1) < 0)  {    PLAYER_ERROR("SendCommand() failed");    return(-1);  }  if(ReadAnswer(buf,sizeof(buf)) < 0)  {    PLAYER_ERROR("ReadAnswer() failed");    return(-1);  }  if(SendCommand(AMTEC_MODULE_TILT,cmd,1) < 0)  {    PLAYER_ERROR("SendCommand() failed");    return(-1);  }  if(ReadAnswer(buf,sizeof(buf)) < 0)  {    PLAYER_ERROR("ReadAnswer() failed");    return(-1);  }  return(0);}int AmtecPowerCube::Home(){  unsigned char buf[AMTEC_MAX_CMDSIZE];  unsigned char cmd[1];  unsigned int state;  cmd[0] = AMTEC_CMD_HOME;  if(SendCommand(AMTEC_MODULE_PAN,cmd,1) < 0)  {    PLAYER_ERROR("SendCommand() failed");    return(-1);  }  if(ReadAnswer(buf,sizeof(buf)) < 0)  {    PLAYER_ERROR("ReadAnswer() failed");    return(-1);  }  // poll the device state, wait for homing to finish  for(;;)  {    usleep(AMTEC_SLEEP_TIME_USEC);    if(GetUint32Param(AMTEC_MODULE_PAN, AMTEC_PARAM_CUBESTATE, &state) < 0)    {      PLAYER_ERROR("GetUint32Param() failed");      return(-1);    }    if(state & AMTEC_STATE_HOME_OK)      break;  }  if(SendCommand(AMTEC_MODULE_TILT,cmd,1) < 0)  {    PLAYER_ERROR("SendCommand() failed");    return(-1);  }  if(ReadAnswer(buf,sizeof(buf)) < 0)  {    PLAYER_ERROR("ReadAnswer() failed");    return(-1);  }  // poll the device state, wait for homing to finish  for(;;)  {    usleep(AMTEC_SLEEP_TIME_USEC);    if(GetUint32Param(AMTEC_MODULE_TILT, AMTEC_PARAM_CUBESTATE, &state) < 0)    {      PLAYER_ERROR("GetUint32Param() failed");      return(-1);    }    if(state & AMTEC_STATE_HOME_OK)      break;  }  return(0);}int AmtecPowerCube::Halt(){  unsigned char buf[AMTEC_MAX_CMDSIZE];  unsigned char cmd[1];  cmd[0] = AMTEC_CMD_HALT;  if(SendCommand(AMTEC_MODULE_PAN,cmd,1) < 0)  {    PLAYER_ERROR("SendCommand() failed");    return(-1);  }  if(ReadAnswer(buf,sizeof(buf)) < 0)  {    PLAYER_ERROR("ReadAnswer() failed");    return(-1);  }  if(SendCommand(AMTEC_MODULE_TILT,cmd,1) < 0)  {    PLAYER_ERROR("SendCommand() failed");    return(-1);  }  if(ReadAnswer(buf,sizeof(buf)) < 0)  {    PLAYER_ERROR("ReadAnswer() failed");    return(-1);  }  return(0);}int AmtecPowerCube::Setup(){  struct termios term;  short pan,tilt;  int flags;  // default to position control  this->controlmode = PLAYER_PTZ_POSITION_CONTROL;  player_ptz_cmd_t cmd;  cmd.pan = cmd.tilt = cmd.zoom = 0;  printf("Amtec PowerCube connection initializing (%s)...", serial_port);  fflush(stdout);  // open it.  non-blocking at first, in case there's no ptz unit.  if((fd = open(serial_port, O_RDWR | O_SYNC | O_NONBLOCK, S_IRUSR | S_IWUSR )) < 0 )  {    PLAYER_ERROR1("open() failed: %s", strerror(errno));    return(-1);  }     if(tcflush(fd, TCIFLUSH ) < 0 )  {    PLAYER_ERROR1("tcflush() failed: %s", strerror(errno));    close(fd);    fd = -1;    return(-1);  }  if(tcgetattr(fd, &term) < 0 )  {    PLAYER_ERROR1("tcgetattr() failed: %s", strerror(errno));    close(fd);    fd = -1;    return(-1);  }    cfmakeraw(&term);  cfsetispeed(&term, B38400);  cfsetospeed(&term, B38400);    if(tcsetattr(fd, TCSAFLUSH, &term) < 0 )  {    PLAYER_ERROR1("tcsetattr() failed: %s", strerror(errno));    close(fd);    fd = -1;    return(-1);  }  fd_blocking = false;  /* try to get current state, just to make sure we actually have a camera */  if(GetPanTiltPos(&pan,&tilt))  {    printf("Couldn't connect to Amtec PowerCube most likely because the unit\n"                    "is not connected or is connected not to %s\n",                     serial_port);    close(fd);    fd = -1;    return(-1);  }  /* ok, we got data, so now set NONBLOCK, and continue */  if((flags = fcntl(fd, F_GETFL)) < 0)  {    PLAYER_ERROR1("fcntl() failed: %s", strerror(errno));    close(fd);    fd = -1;    return(1);  }  if(fcntl(fd, F_SETFL, flags ^ O_NONBLOCK) < 0)  {    PLAYER_ERROR1("fcntl() failed: %s", strerror(errno));    close(fd);    fd = -1;    return(1);  }  fd_blocking = true;  puts("Done.");  // zero the command buffer  //PutCommand(this->device_id,(unsigned char*)&cmd,sizeof(cmd),NULL);  // reset and home the unit.  if(Reset() < 0)  {    PLAYER_ERROR("Reset() failed; bailing.");    close(fd);    fd = -1;    return(-1);  }  if(Home() < 0)  {    PLAYER_ERROR("Home() failed; bailing.");    close(fd);    fd = -1;    return(-1);  }  // start the thread to talk with the camera  StartThread();  return(0);}intAmtecPowerCube::Shutdown(){  if(fd == -1)    return(0);  StopThread();  // stop the unit  if(Halt())    PLAYER_WARN("Halt() failed.");  // maybe return it to home  if(return_to_home && Home())    PLAYER_WARN("Home() failed.");  if(close(fd))    PLAYER_ERROR1("close() failed:%s",strerror(errno));  fd = -1;  puts("Amtec PowerCube has been shutdown");  return(0);}////////////////////////////////////////////////////////////////////////////// The following methods are based on some found in CARMEN.  Thanks to the// authors.// NOTE: these conversion methods only work on little-endian machines// (the Amtec protocol also uses little-endian).floatAmtecPowerCube::BytesToFloat(unsigned char *bytes){  float f;  memcpy((void*)&f, bytes, 4);  return(f);}unsigned intAmtecPowerCube::BytesToUint32(unsigned char* bytes){  unsigned int i;  memcpy((void*)&i, bytes, 4);  return(i);}voidAmtecPowerCube::FloatToBytes(unsigned char *bytes, float f){  memcpy(bytes, (void*)&f, 4);}voidAmtecPowerCube::Uint16ToBytes(unsigned char *bytes, unsigned short s){  memcpy(bytes, (void*)&s, 2);}int AmtecPowerCube::SendCommand(int id, unsigned char* cmd, size_t len){  size_t i;  int ctr, add;  unsigned char rcmd[AMTEC_MAX_CMDSIZE];  unsigned char bcc;  unsigned char umnr;  unsigned char lmnr;  add  = 0;  lmnr = id & 7;  lmnr = lmnr << 5;  umnr = id >> 3;  umnr = umnr | 4;  for (i=0;i<len;i++) {    if ( (cmd[i]==0x02) ||	 (cmd[i]==0x03) ||	 (cmd[i]==0x10) ) {      add++;    }  }  lmnr = lmnr + len;  rcmd[0] = AMTEC_STX;  rcmd[1] = umnr;  rcmd[2] = lmnr;  ctr = 3;  for (i=0;i<len;i++) {    switch(cmd[i]) {    case 0x02:      rcmd[ctr] = 0x10;      rcmd[++ctr] = 0x82;      break;    case 0x03:      rcmd[ctr] = 0x10;      rcmd[++ctr] = 0x83;      break;    case 0x10:      rcmd[ctr] = 0x10;      rcmd[++ctr] = 0x90;      break;    default:      rcmd[ctr] = cmd[i];    }    ctr++;  }  bcc = id;  for (i=0;i<len;i++) {    bcc += cmd[i];  }  bcc = bcc + (bcc>>8);  switch(bcc) {  case 0x02:    rcmd[ctr++] = 0x10;    rcmd[ctr++] = 0x82;    break;  case 0x03:    rcmd[ctr++] = 0x10;    rcmd[ctr++] = 0x83;    break;  case 0x10:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -