ptu46_driver.cc
Go to the documentation of this file.
1 
2 /*
3  * PTU46 ROS Package
4  * Copyright (C) 2009 Erik Karulf (erik@cse.wustl.edu)
5  *
6  */
7 
8 /*
9  * Player - One Hell of a Robot Server
10  * Copyright (C) 2000 Brian Gerkey & Kasper Stoy
11  * gerkey@usc.edu kaspers@robotics.usc.edu
12  *
13  * $Id$
14  *
15  * Author: Toby Collett (University of Auckland)
16  * Date: 2003-02-10
17  *
18  */
24 /*
25  * This program is free software; you can redistribute it and/or modify
26  * it under the terms of the GNU General Public License as published by
27  * the Free Software Foundation; either version 2 of the License, or
28  * (at your option) any later version.
29  *
30  * This program is distributed in the hope that it will be useful,
31  * but WITHOUT ANY WARRANTY; without even the implied warranty of
32  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33  * GNU General Public License for more details.
34  *
35  * You should have received a copy of the GNU General Public License
36  * along with this program; if not, write to the Free Software
37  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
38  *
39  */
40 
41 // class declaration
42 #include <ptu46/ptu46_driver.h>
43 
44 // serial includes
45 #include <sys/types.h>
46 #include <sys/stat.h>
47 #include <fcntl.h>
48 #include <termios.h>
49 #include <stdio.h>
50 #include <strings.h>
51 #include <unistd.h>
52 #include <stdlib.h>
53 #include <errno.h>
54 #include <string.h>
55 #include <math.h>
56 
57 namespace PTU46 {
58 
59 //
60 // Pan-Tilt Control Class
61 //
62 
63 // Constructor opens the serial port, and read the config info from it
64 PTU46::PTU46(const char * port, int rate) {
65  tr = pr = 1;
66  fd = -1;
67 
68  // open the serial port
69 
70  fd = open(port, O_RDWR | O_NOCTTY | O_NDELAY);
71  if ( fd<0 ) {
72  fprintf(stderr, "Could not open serial device %s\n",port);
73  return;
74  }
75  fcntl(fd,F_SETFL, 0);
76 
77  // save the current io settings
78  tcgetattr(fd, &oldtio);
79 
80  // rtv - CBAUD is pre-POSIX and doesn't exist on OS X
81  // should replace this with ispeed and ospeed instead.
82 
83  // set up new settings
84  struct termios newtio;
85  memset(&newtio, 0,sizeof(newtio));
86  newtio.c_cflag = /*(rate & CBAUD) |*/ CS8 | CLOCAL | CREAD;
87  newtio.c_iflag = IGNPAR;
88  newtio.c_oflag = 0;
89  newtio.c_lflag = ICANON;
90 
91  speed_t sp = B9600;
92  switch (rate) {
93  case 0:
94  sp = B0;
95  break;
96  case 50:
97  sp = B50;
98  break;
99  case 75:
100  sp = B75;
101  break;
102  case 110:
103  sp = B110;
104  break;
105  case 134:
106  sp = B134;
107  break;
108  case 150:
109  sp = B150;
110  break;
111  case 200:
112  sp = B200;
113  break;
114  case 300:
115  sp = B300;
116  break;
117  case 600:
118  sp = B600;
119  break;
120  case 1200:
121  sp = B1200;
122  break;
123  case 2400:
124  sp = B2400;
125  break;
126  case 4800:
127  sp = B4800;
128  break;
129  case 9600:
130  sp = B9600;
131  break;
132  case 19200:
133  sp = B19200;
134  break;
135  case 38400:
136  sp = B38400;
137  break;
138  default:
139  fprintf(stderr,"Failed to set serial baud rate: %d\n", rate);
140  Disconnect();
141  return;
142  }
143 
144  if (cfsetispeed(&newtio, sp) < 0 || cfsetospeed(&newtio, sp) < 0) {
145  fprintf(stderr,"Failed to set serial baud rate: %d\n", rate);
146  Disconnect();
147  return;
148  }
149  // activate new settings
150  tcflush(fd, TCIFLUSH);
151  tcsetattr(fd, TCSANOW, &newtio);
152 
153  // now set up the pan tilt camera
154  Write(" "); // terse feedback
155  usleep(100000);
156  tcflush(fd, TCIFLUSH);
157 
158  Write("ft "); // terse feedback
159  Write("ed "); // disable echo
160  Write("ci "); // position mode
161 
162  // delay here so data has arrived at serial port so we can flush it
163  usleep(200000);
164  tcflush(fd, TCIFLUSH);
165 
166  // get pan tilt encoder res
167  tr = GetRes(PTU46_TILT);
168  pr = GetRes(PTU46_PAN);
169 
170  PMin = GetLimit(PTU46_PAN, PTU46_MIN);
171  PMax = GetLimit(PTU46_PAN, PTU46_MAX);
172  TMin = GetLimit(PTU46_TILT, PTU46_MIN);
173  TMax = GetLimit(PTU46_TILT, PTU46_MAX);
174  PSMin = GetLimit(PTU46_PAN, PTU46_MIN_SPEED);
175  PSMax = GetLimit(PTU46_PAN, PTU46_MAX_SPEED);
176  TSMin = GetLimit(PTU46_TILT, PTU46_MIN_SPEED);
177  TSMax = GetLimit(PTU46_TILT, PTU46_MAX_SPEED);
178 
179  if (tr <= 0 || pr <= 0 || PMin == 0 || PMax == 0 || TMin == 0 || TMax == 0) {
180  // if limit request failed try resetting the unit and then getting limits..
181  Write(" r "); // reset pan-tilt unit (also clears any bad input on serial port)
182 
183  // wait for reset to complete
184  int len = 0;
185  char temp;
186  char response[10] = "!T!T!P!P*";
187 
188  for (int i = 0; i < 9; ++i) {
189  while ((len = read(fd, &temp, 1 )) == 0) {};
190  if ((len != 1) || (temp != response[i])) {
191  fprintf(stderr,"Error Resetting Pan Tilt unit\n");
192  fprintf(stderr,"Stopping access to pan-tilt unit\n");
193  Disconnect();
194  }
195  }
196 
197  // delay here so data has arrived at serial port so we can flush it
198  usleep(100000);
199  tcflush(fd, TCIFLUSH);
200 
201 
202  // get pan tilt encoder res
203  tr = GetRes(PTU46_TILT);
204  pr = GetRes(PTU46_PAN);
205 
206  PMin = GetLimit(PTU46_PAN, PTU46_MIN);
207  PMax = GetLimit(PTU46_PAN, PTU46_MAX);
208  TMin = GetLimit(PTU46_TILT, PTU46_MIN);
209  TMax = GetLimit(PTU46_TILT, PTU46_MAX);
210  PSMin = GetLimit(PTU46_PAN, PTU46_MIN_SPEED);
211  PSMax = GetLimit(PTU46_PAN, PTU46_MAX_SPEED);
212  TSMin = GetLimit(PTU46_TILT, PTU46_MIN_SPEED);
213  TSMax = GetLimit(PTU46_TILT, PTU46_MAX_SPEED);
214 
215  if (tr <= 0 || pr <= 0 || PMin == 0 || PMax == 0 || TMin == 0 || TMax == 0) {
216  // if it really failed give up and disable the driver
217  fprintf(stderr,"Error getting pan-tilt resolution...is the serial port correct?\n");
218  fprintf(stderr,"Stopping access to pan-tilt unit\n");
219  Disconnect();
220  }
221  }
222 }
223 
224 
225 PTU46::~PTU46() {
226  Disconnect();
227 }
228 
229 void PTU46::Disconnect() {
230  if (fd > 0) {
231  // restore old port settings
232  tcsetattr(fd, TCSANOW, &oldtio);
233  // close the connection
234  close(fd);
235  fd = -1;
236  }
237 }
238 
239 int PTU46::Write(const char * data, int length) {
240 
241  if (fd < 0)
242  return -1;
243 
244  // autocalculate if using short form
245  if (length == 0)
246  length = strlen(data);
247 
248  // ugly error handling, if write fails then shut down unit
249  if (write(fd, data, length) < length) {
250  fprintf(stderr,"Error writing to Pan Tilt Unit, disabling\n");
251  Disconnect();
252  return -1;
253  }
254  return 0;
255 }
256 
257 
258 // get radians/count resolution
259 float PTU46::GetRes(char type) {
260  if (fd < 0)
261  return -1;
262  char cmd[4] = " r ";
263  cmd[0] = type;
264 
265  // get pan res
266  int len = 0;
267  Write(cmd);
268  len = read(fd, buffer, PTU46_BUFFER_LEN );
269 
270  if (len < 3 || buffer[0] != '*') {
271  fprintf(stderr,"Error getting pan-tilt res\n");
272  return -1;
273  }
274 
275  buffer[len] = '\0';
276  double z = strtod(&buffer[2],NULL);
277  z = z/3600; // degrees/count
278  return z*M_PI/180; //radians/count
279 }
280 
281 // get position limit
282 int PTU46::GetLimit(char type, char LimType) {
283  if (fd < 0)
284  return -1;
285  char cmd[4] = " ";
286  cmd[0] = type;
287  cmd[1] = LimType;
288 
289  // get limit
290  int len = 0;
291  Write(cmd);
292  len = read(fd, buffer, PTU46_BUFFER_LEN );
293 
294  if (len < 3 || buffer[0] != '*') {
295  fprintf(stderr,"Error getting pan-tilt limit\n");
296  return -1;
297  }
298 
299  buffer[len] = '\0';
300  return strtol(&buffer[2],NULL,0);
301 }
302 
303 
304 // get position in radians
305 float PTU46::GetPosition (char type) {
306  if (fd < 0)
307  return -1;
308 
309  char cmd[4] = " p ";
310  cmd[0] = type;
311 
312  // get pan pos
313  int len = 0;
314  Write (cmd);
315  len = read (fd, buffer, PTU46_BUFFER_LEN );
316 
317  if (len < 3 || buffer[0] != '*') {
318  fprintf(stderr,"Error getting pan-tilt pos\n");
319  return -1;
320  }
321 
322  buffer[len] = '\0';
323 
324  return strtod (&buffer[2],NULL) * GetResolution(type);
325 }
326 
327 
328 // set position in radians
329 bool PTU46::SetPosition (char type, float pos, bool Block) {
330  if (fd < 0)
331  return false;
332 
333  // get raw encoder count to move
334  int Count = static_cast<int> (pos/GetResolution(type));
335 
336  // Check limits
337  if (Count < (type == PTU46_TILT ? TMin : PMin) || Count > (type == PTU46_TILT ? TMax : PMax)) {
338  fprintf (stderr,"Pan Tilt Value out of Range: %c %f(%d) (%d-%d)\n", type, pos, Count, (type == PTU46_TILT ? TMin : PMin),(type == PTU46_TILT ? TMax : PMax));
339  return false;
340  }
341 
342  char cmd[16];
343  snprintf (cmd,16,"%cp%d ",type,Count);
344 
345  // set pos
346  int len = 0;
347  Write (cmd);
348  len = read (fd, buffer, PTU46_BUFFER_LEN );
349 
350  if (len <= 0 || buffer[0] != '*') {
351  fprintf(stderr,"Error setting pan-tilt pos\n");
352  return false;
353  }
354 
355  if (Block)
356  while (GetPosition (type) != pos) {};
357 
358  return true;
359 }
360 
361 // get speed in radians/sec
362 float PTU46::GetSpeed (char type) {
363  if (fd < 0)
364  return -1;
365 
366  char cmd[4] = " s ";
367  cmd[0] = type;
368 
369  // get speed
370  int len = 0;
371  Write (cmd);
372  len = read (fd, buffer, PTU46_BUFFER_LEN );
373 
374  if (len < 3 || buffer[0] != '*') {
375  fprintf (stderr,"Error getting pan-tilt speed\n");
376  return -1;
377  }
378 
379  buffer[len] = '\0';
380 
381  return strtod(&buffer[2],NULL) * GetResolution(type);
382 }
383 
384 
385 
386 // set speed in radians/sec
387 bool PTU46::SetSpeed (char type, float pos) {
388  if (fd < 0)
389  return false;
390 
391  // get raw encoder speed to move
392  int Count = static_cast<int> (pos/GetResolution(type));
393  // Check limits
394  if (abs(Count) < (type == PTU46_TILT ? TSMin : PSMin) || abs(Count) > (type == PTU46_TILT ? TSMax : PSMax)) {
395  fprintf (stderr,"Pan Tilt Speed Value out of Range: %c %f(%d) (%d-%d)\n", type, pos, Count, (type == PTU46_TILT ? TSMin : PSMin),(type == PTU46_TILT ? TSMax : PSMax));
396  return false;
397  }
398 
399  char cmd[16];
400  snprintf (cmd,16,"%cs%d ",type,Count);
401 
402  // set speed
403  int len = 0;
404  Write (cmd);
405  len = read (fd, buffer, PTU46_BUFFER_LEN );
406 
407  if (len <= 0 || buffer[0] != '*') {
408  fprintf (stderr,"Error setting pan-tilt speed\n");
409  return false;
410  }
411  return true;
412 }
413 
414 
415 // set movement mode (position/velocity)
416 bool PTU46::SetMode (char type) {
417  if (fd < 0)
418  return false;
419 
420  char cmd[4] = "c ";
421  cmd[1] = type;
422 
423  // set mode
424  int len = 0;
425  Write (cmd);
426  len = read (fd, buffer, PTU46_BUFFER_LEN );
427 
428  if (len <= 0 || buffer[0] != '*') {
429  fprintf (stderr,"Error setting pan-tilt move mode\n");
430  return false;
431  }
432  return true;
433 }
434 
435 // get ptu mode
436 char PTU46::GetMode () {
437  if (fd < 0)
438  return -1;
439 
440  // get pan tilt mode
441  int len = 0;
442  Write ("c ");
443  len = read (fd, buffer, PTU46_BUFFER_LEN );
444 
445  if (len < 3 || buffer[0] != '*') {
446  fprintf (stderr,"Error getting pan-tilt pos\n");
447  return -1;
448  }
449 
450  if (buffer[2] == 'p')
451  return PTU46_VELOCITY;
452  else if (buffer[2] == 'i')
453  return PTU46_POSITION;
454  else
455  return -1;
456 }
457 
458 }
#define PTU46_MAX
Definition: ptu46_driver.h:22
PTU46 Pan Tilt Unit Driver Copyright (C) 2009 Erik Karulf (erik@cse.wustl.edu)
Definition: ptu46_driver.h:58
#define PTU46_POSITION
Definition: ptu46_driver.h:26
#define PTU46_BUFFER_LEN
Definition: ptu46_driver.h:14
#define PTU46_MAX_SPEED
Definition: ptu46_driver.h:24
#define PTU46_MIN_SPEED
Definition: ptu46_driver.h:23
#define PTU46_PAN
Definition: ptu46_driver.h:19
#define PTU46_TILT
Definition: ptu46_driver.h:20
ptu control header. Defines commands for ptu control.
#define PTU46_MIN
Definition: ptu46_driver.h:21
#define PTU46_VELOCITY
Definition: ptu46_driver.h:25


ptu46
Author(s): Erik Karulf, David Lu
autogenerated on Mon Mar 2 2015 01:32:49