Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
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 ");
00073 ser_->read(20);
00074 Lim = false;
00075 return true;
00076 }
00077
00078 bool PTU::initialize()
00079 {
00080 ser_->write("ft ");
00081 ser_->write("ed ");
00082 ser_->write("ci ");
00083 ser_->read(20);
00084
00085
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
00125 ser_->flush();
00126 ser_->write(" r ");
00127
00128 std::string actual_response, expected_response("!T!T!P!P*");
00129
00130
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
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;
00162 return z * M_PI / 180;
00163 }
00164
00165
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
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
00200 bool PTU::setPosition(char type, float pos, bool block)
00201 {
00202 if (!initialized()) return false;
00203
00204
00205 int count = static_cast<int>(pos / getResolution(type));
00206
00207
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
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
00257 bool PTU::setSpeed(char type, float pos)
00258 {
00259 if (!initialized()) return false;
00260
00261
00262 int count = static_cast<int>(pos / getResolution(type));
00263
00264
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
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
00302 char PTU::getMode()
00303 {
00304 if (!initialized()) return -1;
00305
00306
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 }