📄 sonyevid30.cc
字号:
/* * Player - One Hell of a Robot Server * Copyright (C) 2000 Brian Gerkey & Kasper Stoy * gerkey@usc.edu kaspers@robotics.usc.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: sonyevid30.cc,v 1.2 2002/11/29 18:02:39 gerkey Exp $ * * methods for initializing, commanding, and getting data out of * the Sony EVI-D30 PTZ camera */#if HAVE_CONFIG_H #include <config.h>#endif#if HAVE_STRINGS_H #include <strings.h>#endif#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 <device.h>#include <drivertable.h>#include <player.h>#define PTZ_SLEEP_TIME_USEC 100000#define MAX_PTZ_PACKET_LENGTH 16#define MAX_PTZ_MESSAGE_LENGTH 14#define MAX_PTZ_REPLY_LENGTH 11/* here we calculate our conversion factors. * 0x370 is max value for the PTZ pan command, and in the real * world, it has +- 25.0 range. * 0x12C is max value for the PTZ tilt command, and in the real * world, it has +- 100.0 range. */#define PTZ_PAN_MAX 100.0#define PTZ_TILT_MAX 25.0#define PTZ_PAN_CONV_FACTOR (0x370 / PTZ_PAN_MAX)#define PTZ_TILT_CONV_FACTOR (0x12C / PTZ_TILT_MAX)#define DEFAULT_PTZ_PORT "/dev/ttyS2"class SonyEVID30:public CDevice { private: bool command_pending1; // keep track of how many commands are pending; bool command_pending2; // that way, we can cancel them if necessary bool ptz_fd_blocking; // internal methods int Send(unsigned char* str, int len, unsigned char* reply); int Receive(unsigned char* reply); int SendCommand(unsigned char* str, int len); int CancelCommand(char socket); int SendRequest(unsigned char* str, int len, unsigned char* reply); // this function will be run in a separate thread virtual void Main(); virtual int SendAbsPanTilt(short pan, short tilt); virtual int SendAbsZoom(short zoom); virtual int GetAbsZoom(short* zoom); virtual int GetAbsPanTilt(short* pan, short* tilt); virtual void PrintPacket(char* str, unsigned char* cmd, int len); public: player_ptz_cmd_t* command; player_ptz_data_t* data; int ptz_fd; // ptz device file descriptor /* device used to communicate with the ptz */ char ptz_serial_port[MAX_FILENAME_SIZE]; // Min and max values for camera field of view (degrees). // These are used to compute appropriate zoom values. int maxfov, minfov; SonyEVID30(char* interface, ConfigFile* cf, int section); virtual int Setup(); virtual int Shutdown();}; // initialization functionCDevice* SonyEVID30_Init(char* interface, ConfigFile* cf, int section){ if(strcmp(interface, PLAYER_PTZ_STRING)) { PLAYER_ERROR1("driver \"sonyevid30\" does not support interface \"%s\"\n", interface); return(NULL); } else return((CDevice*)(new SonyEVID30(interface, cf, section)));}// a driver registration functionvoid SonyEVID30_Register(DriverTable* table){ table->AddDriver("sonyevid30", PLAYER_ALL_MODE, SonyEVID30_Init);}SonyEVID30::SonyEVID30(char* interface, ConfigFile* cf, int section) : CDevice(sizeof(player_ptz_data_t),sizeof(player_ptz_cmd_t),0,0){ ptz_fd = -1; command_pending1 = false; command_pending2 = false; player_ptz_data_t data; player_ptz_cmd_t cmd; // TODO: check field of view values. this->minfov = (int) cf->ReadTupleAngle(section, "fov", 0, 3); this->maxfov = (int) cf->ReadTupleAngle(section, "fov", 1, 30); data.pan = data.tilt = data.zoom = 0; cmd.pan = cmd.tilt = cmd.zoom = 0; PutData((unsigned char*)&data,sizeof(data),0,0); PutCommand(this,(unsigned char*)&cmd,sizeof(cmd)); strncpy(ptz_serial_port, cf->ReadString(section, "port", DEFAULT_PTZ_PORT), sizeof(ptz_serial_port));}int SonyEVID30::Setup(){ struct termios term; short pan,tilt; int flags; player_ptz_cmd_t cmd; cmd.pan = cmd.tilt = 0; cmd.zoom = this->maxfov; printf("PTZ connection initializing (%s)...", ptz_serial_port); fflush(stdout); // open it. non-blocking at first, in case there's no ptz unit. if((ptz_fd = open(ptz_serial_port, O_RDWR | O_SYNC | O_NONBLOCK, S_IRUSR | S_IWUSR )) < 0 ) { perror("SonyEVID30::Setup():open():"); return(-1); } if(tcflush(ptz_fd, TCIFLUSH ) < 0 ) { perror("SonyEVID30::Setup():tcflush():"); close(ptz_fd); ptz_fd = -1; return(-1); } if(tcgetattr(ptz_fd, &term) < 0 ) { perror("SonyEVID30::Setup():tcgetattr():"); close(ptz_fd); ptz_fd = -1; return(-1); } #if HAVE_CFMAKERAW cfmakeraw(&term);#endif cfsetispeed(&term, B9600); cfsetospeed(&term, B9600); if(tcsetattr(ptz_fd, TCSAFLUSH, &term) < 0 ) { perror("SonyEVID30::Setup():tcsetattr():"); close(ptz_fd); ptz_fd = -1; return(-1); } ptz_fd_blocking = false; /* try to get current state, just to make sure we actually have a camera */ if(GetAbsPanTilt(&pan,&tilt)) { printf("Couldn't connect to PTZ device most likely because the camera\n" "is not connected or is connected not to %s\n", ptz_serial_port); close(ptz_fd); ptz_fd = -1; return(-1); } /* ok, we got data, so now set NONBLOCK, and continue */ if((flags = fcntl(ptz_fd, F_GETFL)) < 0) { perror("SonyEVID30::Setup():fcntl()"); close(ptz_fd); ptz_fd = -1; return(1); } if(fcntl(ptz_fd, F_SETFL, flags ^ O_NONBLOCK) < 0) { perror("SonyEVID30::Setup():fcntl()"); close(ptz_fd); ptz_fd = -1; return(1); } ptz_fd_blocking = true; puts("Done."); // zero the command buffer PutCommand(this,(unsigned char*)&cmd,sizeof(cmd)); // start the thread to talk with the camera StartThread(); return(0);}int SonyEVID30::Shutdown(){ puts("SonyEVID30::Shutdown"); if(ptz_fd == -1) return(0); StopThread(); // put the camera back to center usleep(PTZ_SLEEP_TIME_USEC); SendAbsPanTilt(0,0); usleep(PTZ_SLEEP_TIME_USEC); SendAbsZoom(0); if(close(ptz_fd)) perror("SonyEVID30::Shutdown():close():"); ptz_fd = -1; puts("PTZ camera has been shutdown"); return(0);}intSonyEVID30::Send(unsigned char* str, int len, unsigned char* reply){ unsigned char command[MAX_PTZ_PACKET_LENGTH]; int i; if(len > MAX_PTZ_MESSAGE_LENGTH) { fprintf(stderr, "SonyEVID30::Send(): message is too large (%d bytes)\n", len); return(-1); } command[0] = 0x81; // controller address is 0, camera address 1 for(i=0;i<len;i++) command[i+1] = str[i]; command[i+1] = 0xFF; // packet terminator //PrintPacket("Sending", command, i+2); // send the command if(write(ptz_fd, command, i+2) < 0) { perror("SonyEVID30::Send():write():"); return(-1); } //puts("Send(): calling Receive()"); return(Receive(reply));}intSonyEVID30::Receive(unsigned char* reply){ static unsigned char buffer[MAX_PTZ_PACKET_LENGTH]; static int numread = 0; unsigned char temp_reply[MAX_PTZ_PACKET_LENGTH]; int newnumread = 0; int bufptr = -1; int i; int temp; // if we're non-blocking, then we should wait a bit to give the // camera a chance to respond. if(!ptz_fd_blocking) usleep(PTZ_SLEEP_TIME_USEC); bzero(temp_reply,MAX_PTZ_PACKET_LENGTH); bzero(reply,MAX_PTZ_PACKET_LENGTH); if(numread > 0) { //printf("copying %d old bytes\n", numread); memcpy(temp_reply,buffer,numread); // look for the terminator for(i=0;i<numread;i++) { if(temp_reply[i] == 0xFF) { bufptr = i; break; } } } while(bufptr < 0) { newnumread = read(ptz_fd, temp_reply+numread, MAX_PTZ_REPLY_LENGTH-numread); if((numread += newnumread) < 0) { perror("SonyEVID30::Send():read():"); return(-1); } else if(!newnumread) { // hmm...we were expecting something, yet we read // zero bytes. some glitch. drain input, and return // zero. we'll get a message next time through //puts("Receive(): read() returned 0"); if(tcflush(ptz_fd, TCIFLUSH ) < 0 ) { perror("SonyEVID30::Send():tcflush():"); return(-1); } numread = 0; return(0); } // look for the terminator for(i=0;i<numread;i++) { if(temp_reply[i] == 0xFF) { bufptr = i; break; } } } temp = numread; // if we read extra bytes, keep them around if(bufptr == numread-1) numread = 0; else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -