$search
00001 /* 00002 * Description: Generic servo controller interface. 00003 * 00004 * The actual servo device controllers are subclasses of this one. 00005 * 00006 * Copyright (C) 2005, 2007, 2009 Austin Robot Technology 00007 * 00008 * License: Modified BSD Software License Agreement 00009 * 00010 * $Id: servo.h 2 2010-01-17 01:54:03Z jack.oquin $ 00011 */ 00012 00013 #ifndef _SERVO_H_ 00014 #define _SERVO_H_ 00015 00016 #include <fcntl.h> 00017 #include <stdio.h> 00018 #include <stdlib.h> 00019 #include <string.h> 00020 #include <termios.h> 00021 #include <unistd.h> 00022 #include <errno.h> 00023 #include <sys/types.h> 00024 #include <sys/stat.h> 00025 00026 #include <ros/ros.h> 00027 00028 #define MAX_SERVO_CMD_BUFFER 48 00029 00030 class Servo 00031 { 00032 public: 00033 00034 virtual ~Servo() {}; 00035 00036 virtual int Open(const char *device) 00037 {return Open(device, (O_RDWR|O_NOCTTY));} 00038 00039 virtual int Open(const char *device, int flags) 00040 { 00041 int rc = 0; 00042 have_tty = (strcmp(device, "/dev/null") != 0); 00043 strncpy(devName, (char *) device, sizeof(devName)); 00044 fd = open(devName, flags); 00045 if (fd < 0) 00046 { 00047 rc = errno; 00048 ROS_ERROR("Servo::Open(%s) error: %s", devName, strerror(rc)); 00049 } 00050 else 00051 { 00052 ROS_DEBUG("Servo::Open(%s) successful", devName); 00053 } 00054 return rc; 00055 } 00056 00057 virtual int Close(void) 00058 { 00059 int rc = close(fd); 00060 if (rc < 0) 00061 { 00062 rc = errno; 00063 ROS_ERROR("Servo::Close() error: %s", strerror(rc)); 00064 } 00065 return rc; 00066 } 00067 00068 protected: 00069 00070 int fd; 00071 bool have_tty; 00072 char devName[FILENAME_MAX]; 00073 char buffer[MAX_SERVO_CMD_BUFFER]; 00074 00075 /* We prefer to use the raw serial port for servo devices. That 00076 * minimizes processing in the kernel tty driver, which might get in 00077 * the way of an accurate perception of the true state of the device. 00078 */ 00079 virtual int configure_raw_port(int cflags, int iflags) 00080 { 00081 if (!have_tty) return 0; // no config for /dev/null 00082 00083 int rc; 00084 struct termios newtio; 00085 memset(&newtio, 0, sizeof(newtio)); /* clear struct for new port settings */ 00086 00087 /* 00088 BAUDRATE: Set bps rate. You could also use cfsetispeed and cfsetospeed. 00089 CRTSCTS : output hardware flow control (only used if the cable has 00090 all necessary lines. See sect. 7 of Serial-HOWTO) Note: this fails 00091 badly for the ART brake servo (maybe the cable was built wrong). 00092 CS8 : 8n1 (8bit,no parity,1 stopbit) 00093 CLOCAL : local connection, no modem contol 00094 CREAD : enable receiving characters 00095 */ 00096 newtio.c_cflag = cflags | CLOCAL | CREAD; 00097 00098 /* 00099 IGNPAR : ignore bytes with parity errors 00100 ICRNL : map CR to NL (otherwise a CR input on the other computer 00101 will not terminate input) 00102 otherwise make device raw (no other input processing) 00103 */ 00104 newtio.c_iflag = iflags | IGNPAR; 00105 newtio.c_oflag = ONLCR; // QuickSilver TODO: is this relevant?? 00106 newtio.c_lflag = 0; 00107 00108 /* 00109 initialize all control characters 00110 default values can be found in /usr/include/termios.h, and are given 00111 in the comments, but we don't need them here 00112 */ 00113 newtio.c_cc[VTIME] = 0; /* timeout in units of .1 sec (unused) */ 00114 newtio.c_cc[VMIN] = 0; /* non-blocking read */ 00115 00116 /* 00117 now clean the modem line and activate the settings for the port 00118 */ 00119 tcflush(fd, TCIOFLUSH); 00120 rc = tcsetattr(fd,TCSANOW,&newtio); 00121 if (rc < 0) 00122 { 00123 ROS_ERROR("tcsetattr() error: %s", strerror(errno)); 00124 } 00125 return rc; 00126 } 00127 }; 00128 00129 #endif