driver.cpp
Go to the documentation of this file.
00001 /*
00002  * flir_ptu_driver ROS package
00003  * Copyright (C) 2014 Mike Purvis (mpurvis@clearpathrobotics.com)
00004  *
00005  * PTU ROS Package
00006  * Copyright (C) 2009 Erik Karulf (erik@cse.wustl.edu)
00007  *
00008  * Author: Toby Collett (University of Auckland)
00009  * Date: 2003-02-10
00010  *
00011  * Player - One Hell of a Robot Server
00012  * Copyright (C) 2000  Brian Gerkey   &  Kasper Stoy
00013  *                     gerkey@usc.edu    kaspers@robotics.usc.edu
00014  *
00015  *  This program is free software; you can redistribute it and/or modify
00016  *  it under the terms of the GNU General Public License as published by
00017  *  the Free Software Foundation; either version 2 of the License, or
00018  *  (at your option) any later version.
00019  *
00020  *  This program is distributed in the hope that it will be useful,
00021  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00022  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00023  *  GNU General Public License for more details.
00024  *
00025  *  You should have received a copy of the GNU General Public License
00026  *  along with this program; if not, write to the Free Software
00027  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00028  *
00029  */
00030 
00031 #include <boost/lexical_cast.hpp>
00032 #include <boost/algorithm/string/trim.hpp>
00033 #include <flir_ptu_driver/driver.h>
00034 #include <serial/serial.h>
00035 #include <ros/console.h>
00036 
00037 #include <math.h>
00038 #include <string>
00039 
00040 using boost::lexical_cast;
00041 
00042 
00043 namespace flir_ptu_driver
00044 {
00045 
00049 template<typename T>
00050 T parseResponse(std::string responseBuffer)
00051 {
00052   std::string trimmed = responseBuffer.substr(1);
00053   boost::trim(trimmed);
00054 
00055   if (trimmed.empty())
00056   {
00057       trimmed = "0";
00058   }
00059 
00060   T parsed = lexical_cast<T>(trimmed);
00061   ROS_DEBUG_STREAM("Parsed response value: " << parsed);
00062   return parsed;
00063 }
00064 
00065 bool PTU::initialized()
00066 {
00067   return !!ser_ && ser_->isOpen() && initialized_;
00068 }
00069 
00070 bool PTU::disableLimits()
00071 {
00072   ser_->write("ld ");  // Disable Limits
00073   ser_->read(20);
00074   Lim = false;
00075   return true;
00076 }
00077 
00078 bool PTU::initialize()
00079 {
00080   ser_->write("ft ");  // terse feedback
00081   ser_->write("ed ");  // disable echo
00082   ser_->write("ci ");  // position mode
00083   ser_->read(20);
00084 
00085   // get pan tilt encoder res
00086   tr = getRes(PTU_TILT);
00087   pr = getRes(PTU_PAN);
00088 
00089   PMin = getLimit(PTU_PAN, PTU_MIN);
00090   PMax = getLimit(PTU_PAN, PTU_MAX);
00091   TMin = getLimit(PTU_TILT, PTU_MIN);
00092   TMax = getLimit(PTU_TILT, PTU_MAX);
00093   PSMin = getLimit(PTU_PAN, PTU_MIN_SPEED);
00094   PSMax = getLimit(PTU_PAN, PTU_MAX_SPEED);
00095   TSMin = getLimit(PTU_TILT, PTU_MIN_SPEED);
00096   TSMax = getLimit(PTU_TILT, PTU_MAX_SPEED);
00097   Lim = true;
00098 
00099   if (tr <= 0 || pr <= 0 || PMin == -1 || PMax == -1 || TMin == -1 || TMax == -1)
00100   {
00101     initialized_ = false;
00102   }
00103   else
00104   {
00105     initialized_ = true;
00106   }
00107 
00108   return initialized();
00109 }
00110 
00111 std::string PTU::sendCommand(std::string command)
00112 {
00113   ser_->write(command);
00114   ROS_DEBUG_STREAM("TX: " << command);
00115   std::string buffer = ser_->readline(PTU_BUFFER_LEN);
00116   ROS_DEBUG_STREAM("RX: " << buffer);
00117   return buffer;
00118 }
00119 
00120 bool PTU::home()
00121 {
00122   ROS_INFO("Sending command to reset PTU.");
00123 
00124   // Issue reset command
00125   ser_->flush();
00126   ser_->write(" r ");
00127 
00128   std::string actual_response, expected_response("!T!T!P!P*");
00129 
00130   // 30 seconds to receive full confirmation of reset action completed.
00131   for (int i = 0; i < 300; i++)
00132   {
00133     usleep(100000);
00134 
00135     if (ser_->available() >= expected_response.length())
00136     {
00137       ROS_INFO("PTU reset command response received.");
00138       ser_->read(actual_response, expected_response.length());
00139       return (actual_response == expected_response);
00140     }
00141   }
00142 
00143   ROS_WARN("PTU reset command response not received before timeout.");
00144   return false;
00145 }
00146 
00147 // get radians/count resolution
00148 float PTU::getRes(char type)
00149 {
00150   if (!ser_ || !ser_->isOpen()) return -1;
00151 
00152   std::string buffer = sendCommand(std::string() + type + "r ");
00153 
00154   if (buffer.length() < 3 || buffer[0] != '*')
00155   {
00156     ROS_ERROR_THROTTLE(30, "Error getting pan-tilt res");
00157     return -1;
00158   }
00159 
00160   double z = parseResponse<double>(buffer);
00161   z = z / 3600;  // degrees/count
00162   return z * M_PI / 180;  // radians/count
00163 }
00164 
00165 // get position limit
00166 int PTU::getLimit(char type, char limType)
00167 {
00168   if (!ser_ || !ser_->isOpen()) return -1;
00169 
00170   std::string buffer = sendCommand(std::string() + type + limType + " ");
00171 
00172   if (buffer.length() < 3 || buffer[0] != '*')
00173   {
00174     ROS_ERROR_THROTTLE(30, "Error getting pan-tilt limit");
00175     return -1;
00176   }
00177 
00178   return parseResponse<int>(buffer);
00179 }
00180 
00181 
00182 // get position in radians
00183 float PTU::getPosition(char type)
00184 {
00185   if (!initialized()) return -1;
00186 
00187   std::string buffer = sendCommand(std::string() + type + "p ");
00188 
00189   if (buffer.length() < 3 || buffer[0] != '*')
00190   {
00191     ROS_ERROR_THROTTLE(30, "Error getting pan-tilt pos");
00192     return -1;
00193   }
00194 
00195   return parseResponse<double>(buffer) * getResolution(type);
00196 }
00197 
00198 
00199 // set position in radians
00200 bool PTU::setPosition(char type, float pos, bool block)
00201 {
00202   if (!initialized()) return false;
00203 
00204   // get raw encoder count to move
00205   int count = static_cast<int>(pos / getResolution(type));
00206 
00207   // Check limits
00208   if (Lim)
00209   {
00210     if (count < (type == PTU_TILT ? TMin : PMin) || count > (type == PTU_TILT ? TMax : PMax))
00211     {
00212       ROS_ERROR_THROTTLE(30, "Pan Tilt Value out of Range: %c %f(%d) (%d-%d)\n",
00213                 type, pos, count, (type == PTU_TILT ? TMin : PMin), (type == PTU_TILT ? TMax : PMax));
00214       return false;
00215     }
00216   }
00217 
00218   std::string buffer = sendCommand(std::string() + type + "p" +
00219                                    lexical_cast<std::string>(count) + " ");
00220 
00221   if (buffer.empty() || buffer[0] != '*')
00222   {
00223     ROS_ERROR("Error setting pan-tilt pos");
00224     return false;
00225   }
00226 
00227   if (block)
00228   {
00229     while (getPosition(type) != pos)
00230     {
00231       usleep(1000);
00232     }
00233   }
00234 
00235   return true;
00236 }
00237 
00238 // get speed in radians/sec
00239 float PTU::getSpeed(char type)
00240 {
00241   if (!initialized()) return -1;
00242 
00243   std::string buffer = sendCommand(std::string() + type + "s ");
00244 
00245   if (buffer.length() < 3 || buffer[0] != '*')
00246   {
00247     ROS_ERROR("Error getting pan-tilt speed");
00248     return -1;
00249   }
00250 
00251   return parseResponse<double>(buffer) * getResolution(type);
00252 }
00253 
00254 
00255 
00256 // set speed in radians/sec
00257 bool PTU::setSpeed(char type, float pos)
00258 {
00259   if (!initialized()) return false;
00260 
00261   // get raw encoder speed to move
00262   int count = static_cast<int>(pos / getResolution(type));
00263 
00264   // Check limits
00265   if (abs(count) < (type == PTU_TILT ? TSMin : PSMin) || abs(count) > (type == PTU_TILT ? TSMax : PSMax))
00266   {
00267     ROS_ERROR("Pan Tilt Speed Value out of Range: %c %f(%d) (%d-%d)\n",
00268               type, pos, count, (type == PTU_TILT ? TSMin : PSMin), (type == PTU_TILT ? TSMax : PSMax));
00269     return false;
00270   }
00271 
00272   std::string buffer = sendCommand(std::string() + type + "s" +
00273                                    lexical_cast<std::string>(count) + " ");
00274 
00275   if (buffer.empty() || buffer[0] != '*')
00276   {
00277     ROS_ERROR("Error setting pan-tilt speed\n");
00278     return false;
00279   }
00280 
00281   return true;
00282 }
00283 
00284 
00285 // set movement mode (position/velocity)
00286 bool PTU::setMode(char type)
00287 {
00288   if (!initialized()) return false;
00289 
00290   std::string buffer = sendCommand(std::string("c") + type + " ");
00291 
00292   if (buffer.empty() || buffer[0] != '*')
00293   {
00294     ROS_ERROR("Error setting pan-tilt move mode");
00295     return false;
00296   }
00297 
00298   return true;
00299 }
00300 
00301 // get ptu mode
00302 char PTU::getMode()
00303 {
00304   if (!initialized()) return -1;
00305 
00306   // get pan tilt mode
00307   std::string buffer = sendCommand("c ");
00308 
00309   if (buffer.length() < 3 || buffer[0] != '*')
00310   {
00311     ROS_ERROR("Error getting pan-tilt pos");
00312     return -1;
00313   }
00314 
00315   if (buffer[2] == 'p')
00316     return PTU_VELOCITY;
00317   else if (buffer[2] == 'i')
00318     return PTU_POSITION;
00319   else
00320     return -1;
00321 }
00322 
00323 }  // namespace flir_ptu_driver


flir_ptu_driver
Author(s): Erik Karulf , David V. Lu , Nick Hawes
autogenerated on Tue Mar 19 2019 09:36:57