00001
00008 #include "driver/PTUDriver.h"
00009
00010 namespace asr_flir_ptu_driver {
00011
00012 short int PTUDriver::POW_VAL_MOVE[3] = {PTU_LOW_POWER, PTU_REG_POWER, PTU_HI_POWER};
00013 short int PTUDriver::POW_VAL_HOLD[3] = {PTU_OFF_POWER, PTU_LOW_POWER, PTU_REG_POWER};
00014
00015 PTUDriver::PTUDriver(const char* port, int baud, bool speed_control) {
00016 ROS_DEBUG("PTUDriverConstructor");
00017 double_computation_tolerance = 0.00005;
00018 distance_factor = 10;
00019 this->speed_control = speed_control;
00020
00021 #ifndef __PTU_FREE_INCLUDED__
00022 set_baud_rate(baud);
00023 COMstream = open_host_port((char*)port);
00024 if (isConnected()) {
00025 char c = reset_ptu();
00026 ROS_DEBUG("ptu_status: %d", c);
00027 char d = reset_PTU_parser(1000);
00028 ROS_DEBUG("reset_PTU_parser: %d", d);
00029 } else {
00030 ROS_ERROR("PTU is not connected!");
00031 exit(1);
00032 }
00033 #endif // __PTU_FREE_INCLUDED__
00034 #ifdef __PTU_FREE_INCLUDED__
00035 long return_code = free_ptu.setNewSerialConnection(port, baud);
00036 ROS_DEBUG("Free PTU serial connection set with return code: %ld", return_code);
00037 #endif // __PTU_FREE_INCLUDED__
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049 pan_resolution = get_current(PAN, RESOLUTION) / (3600 * 60.0);
00050 tilt_resolution = get_current(TILT, RESOLUTION) / (3600 * 60.0);
00051
00052
00053 set_mode(POSITION_LIMITS_MODE, OFF_MODE);
00054
00055 setSpeedControlMode(speed_control);
00056 ROS_DEBUG("port: %s, baud: %d, speed_control: %d", port, baud, speed_control);
00057 setLimitAnglesToHardwareConstraints();
00058 }
00059
00060 PTUDriver::PTUDriver() {
00061 ROS_DEBUG("This constructor is only for the mock!");
00062 }
00063
00064 PTUDriver::~PTUDriver() {
00065
00066 }
00067
00068
00069 bool PTUDriver::isConnected() {
00070 #ifndef __PTU_FREE_INCLUDED__
00071 return COMstream > 0;
00072 #endif
00073 #ifdef __PTU_FREE_INCLUDED__
00074 return free_ptu.isOpen();
00075 #endif
00076 }
00077
00078 void PTUDriver::setComputationTolerance(double computation_tolerance) {
00079 this->double_computation_tolerance = computation_tolerance;
00080 }
00081
00082 void PTUDriver::setDistanceFactor(long distance_factor) {
00083 this->distance_factor = distance_factor;
00084 }
00085
00086
00087 void PTUDriver::setSettings(int pan_base, int tilt_base, int pan_speed, int tilt_speed,
00088 int pan_upper, int tilt_upper,int pan_accel, int tilt_accel,
00089 int pan_hold, int tilt_hold, int pan_move, int tilt_move) {
00090 createSettingsBackup();
00091 char return_val;
00092 bool no_error_occured = true;
00093 if(no_error_occured)
00094 {
00095 return_val = set_desired(PAN, BASE, (short int *)&pan_base, ABSOLUTE);
00096 ROS_DEBUG_STREAM("set_desired(PAN, BASE, " << pan_base << ", ABSOLUTE) returned " << getErrorString(return_val) );
00097 if(!checkReturnCode(return_val)) no_error_occured = false;
00098 }
00099 if(no_error_occured)
00100 {
00101 return_val = set_desired(PAN, UPPER_SPEED_LIMIT, (short int *)&pan_upper, ABSOLUTE);
00102 ROS_DEBUG_STREAM("set_desired(PAN, UPPER_SPEED_LIMIT, " << pan_upper << ", ABSOLUTE) returned " << getErrorString(return_val) );
00103 if(!checkReturnCode(return_val)) no_error_occured = false;
00104 }
00105 if(no_error_occured)
00106 {
00107 return_val = set_desired(PAN, SPEED, (short int *)&pan_speed, ABSOLUTE);
00108 ROS_DEBUG_STREAM("set_desired(PAN, SPEED, " <<pan_speed<< ", ABSOLUTE) returned " << getErrorString(return_val) );
00109 if(!checkReturnCode(return_val)) no_error_occured = false;
00110 }
00111
00112 if(no_error_occured)
00113 {
00114 return_val = set_desired(PAN, ACCELERATION, (short int *)&pan_accel, ABSOLUTE);
00115 ROS_DEBUG_STREAM("set_desired(PAN, ACCELERATION, " << pan_accel << ", ABSOLUTE) returned " << getErrorString(return_val) );
00116 if(!checkReturnCode(return_val)) no_error_occured = false;
00117 }
00118
00119 if(no_error_occured)
00120 {
00121 return_val = set_desired(PAN, HOLD_POWER_LEVEL, &POW_VAL_HOLD[pan_hold], ABSOLUTE);
00122 ROS_DEBUG_STREAM("set_desired(PAN, HOLD_POWER_LEVEL, " << POW_VAL_HOLD[pan_hold] << ", ABSOLUTE) returned " << getErrorString(return_val) );
00123 if(!checkReturnCode(return_val)) no_error_occured = false;
00124 }
00125
00126 if(no_error_occured)
00127 {
00128 return_val = set_desired(PAN, MOVE_POWER_LEVEL, &POW_VAL_MOVE[pan_move], ABSOLUTE);
00129 ROS_DEBUG_STREAM("set_desired(PAN, MOVE_POWER_LEVEL, " << POW_VAL_MOVE[pan_move] <<", ABSOLUTE) returned " << getErrorString(return_val) );
00130 if(!checkReturnCode(return_val)) no_error_occured = false;
00131 }
00132
00133 if(no_error_occured)
00134 {
00135 return_val = set_desired(TILT, BASE, (short int *)&tilt_base, ABSOLUTE);
00136 ROS_DEBUG_STREAM("set_desired(TILT, BASE, " << tilt_base << ", ABSOLUTE) returned " << getErrorString(return_val) );
00137 if(!checkReturnCode(return_val)) no_error_occured = false;
00138 }
00139
00140 if(no_error_occured)
00141 {
00142 return_val = set_desired(TILT, UPPER_SPEED_LIMIT, (short int *)&tilt_upper, ABSOLUTE);
00143 ROS_DEBUG_STREAM("set_desired(TILT, UPPER_SPEED_LIMIT, " << tilt_upper << ", ABSOLUTE) returned " << getErrorString(return_val) );
00144 if(!checkReturnCode(return_val)) no_error_occured = false;
00145 }
00146
00147 if(no_error_occured)
00148 {
00149 if(no_error_occured) return_val = set_desired(TILT, SPEED, (short int *)&tilt_speed, ABSOLUTE);
00150 ROS_DEBUG_STREAM("set_desired(TILT, SPEED, " <<tilt_speed<< ", ABSOLUTE) returned " << getErrorString(return_val) );
00151 if(!checkReturnCode(return_val)) no_error_occured = false;
00152 }
00153
00154
00155 if(no_error_occured)
00156 {
00157 return_val = set_desired(TILT, ACCELERATION, (short int *)&tilt_accel, ABSOLUTE);
00158 ROS_DEBUG_STREAM("set_desired(TILT, ACCELERATION, " << tilt_accel << ", ABSOLUTE) returned " << getErrorString(return_val) );
00159 if(!checkReturnCode(return_val)) no_error_occured = false;
00160 }
00161
00162 if(no_error_occured)
00163 {
00164 return_val = set_desired(TILT, HOLD_POWER_LEVEL, &POW_VAL_HOLD[tilt_hold], ABSOLUTE);
00165 ROS_DEBUG_STREAM("set_desired(TILT, HOLD_POWER_LEVEL, " << POW_VAL_HOLD[tilt_hold] << ", ABSOLUTE) returned " << getErrorString(return_val) );
00166 if(!checkReturnCode(return_val)) no_error_occured = false;
00167 }
00168
00169 if(no_error_occured)
00170 {
00171 return_val = set_desired(TILT, MOVE_POWER_LEVEL, &POW_VAL_MOVE[tilt_move], ABSOLUTE);
00172 ROS_DEBUG_STREAM("set_desired(TILT, MOVE_POWER_LEVEL, " << POW_VAL_MOVE[tilt_move] <<", ABSOLUTE) returned " << getErrorString(return_val) );
00173 if(!checkReturnCode(return_val)) no_error_occured = false;
00174 }
00175
00176
00177 if(!no_error_occured)
00178 {
00179 ROS_ERROR("Error occured while setting new settings! Old settings will be restored.");
00180 restoreSettingsFromBackup();
00181 setValuesToBackupValues(pan_base, tilt_base, pan_speed, tilt_speed, pan_upper, tilt_upper, pan_accel, tilt_accel, pan_hold, tilt_hold, pan_move, tilt_move);
00182 }
00183 }
00184
00185
00186
00187 void PTUDriver::setValuesToBackupValues(int & pan_base, int & tilt_base, int & pan_speed, int & tilt_speed,
00188 int & pan_upper, int & tilt_upper, int & pan_accel, int & tilt_accel,
00189 int & pan_hold, int & tilt_hold, int & pan_move, int & tilt_move)
00190 {
00191 pan_base = (int) backup_pan_base;
00192 pan_upper = (int) backup_pan_upper;
00193 pan_speed = (int) backup_pan_speed;
00194 pan_accel = (int) backup_pan_accel;
00195 if(POW_VAL_HOLD[0] == backup_pan_hold) {
00196 pan_hold = 0;
00197 }
00198 else if (POW_VAL_HOLD[1] == backup_pan_hold) {
00199 pan_hold = 1;
00200 }
00201 else {
00202 pan_hold = 2;
00203 }
00204
00205 if(POW_VAL_MOVE[0] == backup_pan_move) {
00206 pan_move = 0;
00207 }
00208 else if (POW_VAL_MOVE[1] == backup_pan_move) {
00209 pan_move = 1;
00210 }
00211 else {
00212 pan_move = 2;
00213 }
00214 tilt_base = (int) backup_tilt_base;
00215 tilt_upper = (int) backup_tilt_upper;
00216 tilt_speed = (int) backup_tilt_speed;
00217 tilt_accel = (int) backup_tilt_accel;
00218 if(POW_VAL_HOLD[0] == backup_tilt_hold) {
00219 tilt_hold = 0;
00220 }
00221 else if (POW_VAL_HOLD[1] == backup_tilt_hold) {
00222 tilt_hold = 1;
00223 }
00224 else {
00225 tilt_hold = 2;
00226 }
00227
00228 if(POW_VAL_MOVE[0] == backup_tilt_move) {
00229 tilt_move = 0;
00230 }
00231 else if (POW_VAL_MOVE[1] == backup_tilt_move) {
00232 tilt_move = 1;
00233 }
00234 else {
00235 tilt_move = 2;
00236 }
00237 }
00238
00239
00240 void PTUDriver::createSettingsBackup()
00241 {
00242 backup_pan_base = get_desired(PAN, BASE);
00243 backup_pan_upper = get_desired(PAN, UPPER_SPEED_LIMIT);
00244 backup_pan_speed = get_desired(PAN, SPEED);
00245 backup_pan_accel = get_desired(PAN, ACCELERATION);
00246 backup_pan_hold = get_desired(PAN, HOLD_POWER_LEVEL);
00247 backup_pan_move = get_desired(PAN, MOVE_POWER_LEVEL);
00248 backup_tilt_base = get_desired(TILT, BASE);
00249 backup_tilt_upper = get_desired(TILT, UPPER_SPEED_LIMIT);
00250 backup_tilt_speed = get_desired(TILT, SPEED);
00251 backup_tilt_accel = get_desired(TILT, ACCELERATION);
00252 backup_tilt_hold = get_desired(TILT, HOLD_POWER_LEVEL);
00253 backup_tilt_move = get_desired(TILT, MOVE_POWER_LEVEL);
00254 }
00255
00256
00257 bool PTUDriver::checkReturnCode(char return_code) {
00258 if(return_code == PTU_OK) return true;
00259 return false;
00260 }
00261
00262
00263 void PTUDriver::restoreSettingsFromBackup() {
00264 set_desired(PAN, BASE, (short int *)&backup_pan_base, ABSOLUTE);
00265 set_desired(PAN, UPPER_SPEED_LIMIT, (short int *)&backup_pan_upper, ABSOLUTE);
00266 set_desired(PAN, SPEED, (short int *)&backup_pan_speed, ABSOLUTE);
00267 set_desired(PAN, ACCELERATION, (short int *)&backup_pan_accel, ABSOLUTE);
00268 set_desired(PAN, HOLD_POWER_LEVEL, (short int *) &backup_pan_hold, ABSOLUTE);
00269 set_desired(PAN, MOVE_POWER_LEVEL, (short int *) &backup_pan_move, ABSOLUTE);
00270 set_desired(TILT, BASE, (short int *)&backup_tilt_base, ABSOLUTE);
00271 set_desired(TILT, UPPER_SPEED_LIMIT, (short int *)&backup_tilt_upper, ABSOLUTE);
00272 set_desired(TILT, SPEED, (short int *)&backup_tilt_speed, ABSOLUTE);
00273 set_desired(TILT, ACCELERATION, (short int *)&backup_tilt_accel, ABSOLUTE);
00274 set_desired(TILT, HOLD_POWER_LEVEL, (short int *)&backup_tilt_hold, ABSOLUTE);
00275 set_desired(TILT, MOVE_POWER_LEVEL, (short int *)&backup_tilt_move, ABSOLUTE);
00276 }
00277
00278 long PTUDriver::getLimitAngle(char pan_or_tilt, char upper_or_lower) {
00279 if(pan_or_tilt == 'p') {
00280 if (upper_or_lower == 'l') {
00281 return this->convertPanFromPositionToAngle(pan_min);
00282 }
00283 else if (upper_or_lower == 'u') {
00284 return this->convertPanFromPositionToAngle(pan_max);
00285 }
00286 else {
00287 return std::numeric_limits<double>::max();
00288 }
00289 }
00290 else if (pan_or_tilt == 't') {
00291 if (upper_or_lower == 'l') {
00292 return this->convertTiltFromPositionToAngle(tilt_min);
00293 }
00294 else if (upper_or_lower == 'u') {
00295 return this->convertTiltFromPositionToAngle(tilt_max);
00296 }
00297 else {
00298 return std::numeric_limits<double>::max();
00299 }
00300 }
00301 else {
00302 return std::numeric_limits<double>::max();
00303 }
00304 }
00305
00306
00307
00308 void PTUDriver::setForbiddenAreas(std::vector< std::map< std::string, double> > forbidden_areas) {
00309 std::vector< std::map< std::string, double> > legit_forbidden_areas;
00310 for (unsigned int i = 0; i < forbidden_areas.size(); i++)
00311 {
00312 std::map< std::string, double> area = forbidden_areas.at(i);
00313 double area_pan_min = area["pan_min"];
00314 double area_pan_max = area["pan_max"];
00315 double area_tilt_min = area["tilt_min"];
00316 double area_tilt_max = area["tilt_max"];
00317 if ( area_pan_min <= area_pan_max &&
00318 area_tilt_min <= area_tilt_max)
00319 {
00320 legit_forbidden_areas.push_back(area);
00321 }
00322 else
00323 {
00324 ROS_ERROR("Forbidden Area with pan_min %f, pan_max %f, tilt_min %f and tilt_max %f is not valid. One of the max values is larger than the related min value.\n", area_pan_min, area_pan_max, area_tilt_min, area_tilt_max);
00325 }
00326 }
00327 this->forbidden_areas = legit_forbidden_areas;
00328 precalculateForbiddenAreaCoodinateForms();
00329 }
00330
00331 void PTUDriver::setAbsoluteAngleSpeeds(double pan_speed, double tilt_speed) {
00332 ROS_DEBUG("Driver::SetAbsoluteAngleSpeed()");
00333 signed short pan_spd = (signed short) convertPanFromAngleToPosition(pan_speed);
00334 signed short tilt_spd = (signed short) convertTiltFromAngleToPosition(tilt_speed);
00335
00336 if ((getCurrentAngle(PAN) <= pan_min && pan_spd < 0) ||
00337 (getCurrentAngle(PAN) >= pan_max && pan_spd > 0)) {
00338 pan_spd = 0;
00339 ROS_DEBUG("Driver::PanSpeed=0");
00340 }
00341 if ((getCurrentAngle(TILT) <= tilt_min && tilt_spd < 0) ||
00342 (getCurrentAngle(TILT) >= tilt_max && tilt_spd > 0)) {
00343 tilt_spd = 0;
00344 ROS_DEBUG("Driver::TiltSpeed=0");
00345 }
00346 setAbsoluteAngleSpeeds(pan_spd, tilt_spd);
00347 ROS_DEBUG("Driver::SetAbsoluteAngleSpeed");
00348 }
00349
00350 void PTUDriver::setAbsoluteAngleSpeeds(signed short pan_speed, signed short tilt_speed) {
00351 char return_code;
00352 return_code = set_desired(PAN, SPEED, &pan_speed, ABSOLUTE);
00353 ROS_DEBUG_STREAM("set_desired(PAN, SPEED, " << pan_speed << ", ABSOLUTE) returned "
00354 << getErrorString(return_code) );
00355 return_code = set_desired(TILT, SPEED, &tilt_speed, ABSOLUTE);
00356 ROS_DEBUG_STREAM("set_desired(TILT, SPEED, " << tilt_speed << ", ABSOLUTE) returned "
00357 << getErrorString(return_code) );
00358
00359 }
00360
00361
00362 bool PTUDriver::isInForbiddenArea(double pan_angle, double tilt_angle)
00363 {
00364 ROS_DEBUG("Driver::isInForbiddenArea()");
00365 for (unsigned int i = 0; i < forbidden_areas.size(); i++)
00366 {
00367 ROS_DEBUG("area %d", i);
00368 std::map< std::string, double> area = forbidden_areas.at(i);
00369 double area_pan_min = area["pan_min"];
00370 double area_pan_max = area["pan_max"];
00371 double area_tilt_min = area["tilt_min"];
00372 double area_tilt_max = area["tilt_max"];
00373 ROS_DEBUG_STREAM("Checking forbidden area " << i << " with pan_min " << area_pan_min << ", pan_max " << area_pan_max << ", tilt_min " << area_tilt_min << ", tilt_max " << area_tilt_max);
00374
00375 if (area_pan_min < pan_angle && pan_angle < area_pan_max &&
00376 area_tilt_min < tilt_angle && tilt_angle < area_tilt_max)
00377 {
00378 ROS_ERROR("Value lies in forbidden area: %d", i);
00379 return true;
00380 }
00381 }
00382 return false;
00383 }
00384
00385 bool PTUDriver::isWithinPanTiltLimits(double pan, double tilt) {
00386 if((pan_min <= convertPanFromAngleToPosition(pan)) && (convertPanFromAngleToPosition(pan) <= pan_max)) {
00387 if((tilt_min <= convertTiltFromAngleToPosition(tilt)) && (convertTiltFromAngleToPosition(tilt) <= tilt_max)) {
00388 return true;
00389 }
00390 else{
00391 ROS_DEBUG("TILT %f is not between the lower limit %f and the upper limit %f", tilt, convertTiltFromPositionToAngle(tilt_min), convertTiltFromPositionToAngle(tilt_max));
00392 }
00393 }
00394 else {
00395 ROS_DEBUG("PAN %f is not between the lower limit %f and the upper limit %f", pan, convertPanFromPositionToAngle(pan_min), convertPanFromPositionToAngle(pan_max));
00396 }
00397 return false;
00398 }
00399
00400 bool PTUDriver::setValuesOutOfLimitsButWithinMarginToLimit(double * pan, double * tilt, double margin) {
00401 ROS_DEBUG("Before margin check: PAN: %f, TILT: %f\n", *pan, *tilt);
00402 long margin_as_position = convertPanFromAngleToPosition(margin);
00403 if(((pan_max - pan_min) <= margin_as_position) || ((tilt_max - tilt_min) <= margin_as_position)) {
00404
00405 ROS_ERROR("Margin in Positions (%ld) (Degree: (%f)) is too big. Bigger than distance between TILT max and TILT min (%ld Positions) or PAN max and PAN min (%ld Positions)",margin_as_position, margin, (tilt_max - tilt_min), (pan_max - pan_min));
00406 return false;
00407 }
00408 double pan_initial = *pan;
00409 double tilt_initial = *tilt;
00410 short int pan_as_position = convertPanFromAngleToPosition(*pan);
00411 short int tilt_as_position = convertTiltFromAngleToPosition(*tilt);
00412 if((pan_as_position < pan_min) && (pan_as_position >= (pan_min - margin_as_position))) {
00413 pan_as_position = pan_min;
00414 *pan = convertPanFromPositionToAngle(pan_min);
00415 ROS_WARN("PAN was out of limits, but within margin, so instead of the initial value %f the value %f is used", pan_initial, *pan);
00416 }
00417 else if ((pan_as_position > pan_max) && (pan_as_position <= (pan_max + margin_as_position))) {
00418 pan_as_position = pan_max;
00419 *pan = convertPanFromPositionToAngle(pan_max);
00420 ROS_WARN("PAN was out of limits, but within margin, so instead of the initial value %f the value %f is used", pan_initial, *pan);
00421 }
00422 if((tilt_as_position < tilt_min) && (tilt_as_position >= (tilt_min - margin_as_position))) {
00423 tilt_as_position = tilt_min;
00424 *tilt = convertTiltFromPositionToAngle(tilt_min);
00425 ROS_WARN("TILT was out of limits, but within margin, so instead of the initial value %f the value %f is used", tilt_initial, *tilt);
00426 }
00427 else if((tilt_as_position > tilt_max) && (tilt_as_position <= (tilt_max + margin_as_position))) {
00428 tilt_as_position = tilt_max;
00429 *tilt = convertTiltFromPositionToAngle(tilt_max);
00430 ROS_WARN("TILT was out of limits, but within margin, so instead of the initial value %f the value %f is used", tilt_initial, *tilt);
00431 }
00432
00433 if(isWithinPanTiltLimits(*pan, *tilt)) {
00434 ROS_DEBUG("After margin check: PAN: %f, TILT: %f\n", *pan, *tilt);
00435 return true;
00436 }
00437 else {
00438 ROS_ERROR("PAN/TILT out of bounds (PAN: %f, TILT: %f)", *pan, *tilt);
00439 return false;
00440 }
00441 }
00442
00443 void PTUDriver::setLimitAnglesToHardwareConstraints() {
00444 this->pan_min = (double) get_current(PAN, MINIMUM_POSITION);
00445 this->pan_max = (double) get_current(PAN, MAXIMUM_POSITION);
00446 this->tilt_min = (double) get_current(TILT, MINIMUM_POSITION);
00447 this->tilt_max = (double) get_current(TILT, MAXIMUM_POSITION);
00448 ROS_DEBUG("Limits set to Hardware Limits: PAN_MINIMUM: %f, PAN_MAXIMUM: %f, TILT_MINIMUM: %f, TILT_MAXIMUM: %f", convertPanFromPositionToAngle(pan_min), convertPanFromPositionToAngle(pan_max), convertTiltFromPositionToAngle(tilt_min), convertTiltFromPositionToAngle(tilt_max));
00449 }
00450
00451
00452
00453 bool PTUDriver::setAbsoluteAngles(double pan_angle, double tilt_angle, bool no_forbidden_area_check) {
00454
00455
00456
00457
00458 ROS_DEBUG("Driver::SetAbsoluteAngles()");
00459 if (isInForbiddenArea(pan_angle, tilt_angle) && !no_forbidden_area_check)
00460 {
00461 return false;
00462 }
00463 short int pan_short_angle = convertPanFromAngleToPosition(pan_angle);
00464 short int tilt_short_angle = convertTiltFromAngleToPosition(tilt_angle);
00465
00466 if ((pan_short_angle < pan_min)
00467 || (pan_short_angle > pan_max)
00468 || (tilt_short_angle < tilt_min)
00469 || (tilt_short_angle > tilt_max))
00470 {
00471 ROS_ERROR("PAN/TILT angle not within pan/tilt bounds");
00472 return false;
00473 }
00474 char return_code;
00475 ROS_DEBUG_STREAM("panShortAngle = " << pan_short_angle);
00476 return_code = set_desired(PAN, POSITION, &pan_short_angle, ABSOLUTE);
00477 ROS_DEBUG_STREAM("set_desired(PAN, POSITION, " << pan_short_angle << ", ABSOLUTE) returned "
00478 << getErrorString(return_code) );
00479 ROS_DEBUG_STREAM("tiltShortAngle = " << tilt_short_angle);
00480 return_code = set_desired(TILT, POSITION, &tilt_short_angle, ABSOLUTE);
00481 ROS_DEBUG_STREAM("set_desired(TILT, POSITION, " << tilt_short_angle << ", ABSOLUTE) returned "
00482 << getErrorString(return_code) );
00483 ROS_INFO("Successfully set Pan and Tilt. PAN: %f, TILT: %f\n", pan_angle, tilt_angle);
00484 return true;
00485 }
00486
00487 void PTUDriver::setLimitAngles(double pan_min, double pan_max, double tilt_min, double tilt_max) {
00488 long pan_min_candidate = convertPanFromAngleToPosition(pan_min);
00489 if(pan_min_candidate >= get_current(PAN, MINIMUM_POSITION)) {
00490 this->pan_min = pan_min_candidate;
00491 }
00492 else {
00493 this->pan_min = get_current(PAN, MINIMUM_POSITION);
00494 ROS_ERROR("Desired PAN_MIN Position was smaller than the hardware limit -> PAN_MIN set to hardware limit");
00495 }
00496 double pan_max_candidate = convertPanFromAngleToPosition(pan_max);
00497 if(pan_max_candidate <= get_current(PAN, MAXIMUM_POSITION)) {
00498 this->pan_max = pan_max_candidate;
00499 }
00500 else {
00501 this->pan_max = get_current(PAN, MAXIMUM_POSITION);
00502 ROS_ERROR("Desired PAN_MAX Position was greater than the hardware limit -> PAN_MAX set to hardware limit");
00503 }
00504 double tilt_min_candidate = convertTiltFromAngleToPosition(tilt_min);
00505 if(tilt_min_candidate >= get_current(TILT, MINIMUM_POSITION)) {
00506 this->tilt_min = tilt_min_candidate;
00507 }
00508 else {
00509 this->tilt_min = get_current(TILT, MINIMUM_POSITION);
00510 ROS_ERROR("Desired TILT_MIN Position was smaller than the hardware limit -> TILT_MIN set to hardware limit");
00511 }
00512 double tilt_max_candidate = convertTiltFromAngleToPosition(tilt_max);
00513 if(tilt_max_candidate <= get_current(TILT, MAXIMUM_POSITION)) {
00514 this->tilt_max = tilt_max_candidate;
00515 }
00516 else {
00517 this->tilt_max = get_current(TILT, MAXIMUM_POSITION);
00518 ROS_ERROR("Desired TILT_MAX Position was greater than the hardware limit -> TILT_MAX set to hardware limit");
00519 }
00520 ROS_DEBUG("Limits set to Virtual Limits: PAN_MINIMUM: %f, PAN_MAXIMUM: %f, TILT_MINIMUM: %f, TILT_MAXIMUM: %f", pan_min, pan_max, tilt_min, tilt_max);
00521 }
00522
00523 void PTUDriver::setSpeedControlMode(bool speed_control) {
00524 this->speed_control = speed_control;
00525 if (speed_control) {
00526 set_mode(SPEED_CONTROL_MODE, PTU_PURE_VELOCITY_SPEED_CONTROL_MODE);
00527 } else {
00528 set_mode(SPEED_CONTROL_MODE, PTU_INDEPENDENT_SPEED_CONTROL_MODE);
00529 }
00530 }
00531
00532 bool PTUDriver::isInSpeedControlMode() {
00533 return speed_control;
00534 }
00535
00536 double PTUDriver::getCurrentAngle(char type) {
00537 if (type == PAN) {
00538 return convertPanFromPositionToAngle(get_current(PAN, POSITION));
00539 }
00540 else if(type == TILT){
00541 return convertTiltFromPositionToAngle(get_current(TILT, POSITION));
00542 }
00543 else {
00544 throw std::exception();
00545 }
00546
00547 }
00548
00549 double PTUDriver::getDesiredAngle(char type) {
00550 if (type == PAN) {
00551 return convertPanFromPositionToAngle(get_desired(PAN, POSITION));
00552 }
00553 else if (type == TILT) {
00554 return convertTiltFromPositionToAngle(get_desired(TILT, POSITION));
00555 }
00556 else {
00557 throw std::exception();
00558 }
00559 }
00560
00561 double PTUDriver::getAngleSpeed(char type) {
00562 if (type == PAN) {
00563 return convertPanFromPositionToAngle(get_current(PAN, SPEED));
00564 }
00565 else if (type == TILT) {
00566 return convertTiltFromPositionToAngle(get_current(TILT, SPEED));
00567 }
00568 else {
00569 throw std::exception();
00570 }
00571 }
00572
00573 long PTUDriver::convertPanFromAngleToPosition(double angle) {
00574 return ((long) round(angle / pan_resolution));
00575 }
00576
00577 double PTUDriver::convertPanFromPositionToAngle(long position) {
00578 return ((double)position) * pan_resolution;
00579 }
00580
00581 long PTUDriver::convertTiltFromAngleToPosition(double angle) {
00582 return ((long) round(angle / tilt_resolution));
00583 }
00584
00585 double PTUDriver::convertTiltFromPositionToAngle(long position) {
00586 return ((double)position) * tilt_resolution;
00587 }
00588
00589 std::string PTUDriver::getErrorString(char status_code)
00590 {
00591 #ifndef __PTU_FREE_INCLUDED__
00592 switch (status_code)
00593 {
00594 case PTU_OK:
00595 return "PTU_OK"; break;
00596 case PTU_ILLEGAL_COMMAND:
00597 return "PTU_ILLEGAL_COMMAND"; break;
00598 case PTU_ILLEGAL_POSITION_ARGUMENT:
00599 return "PTU_ILLEGAL_POSITION_ARGUMENT"; break;
00600 case PTU_ILLEGAL_SPEED_ARGUMENT:
00601 return "PTU_ILLEGAL_SPEED_ARGUMENT"; break;
00602 case PTU_ACCEL_TABLE_EXCEEDED:
00603 return "PTU_ACCEL_TABLE_EXCEEDED"; break;
00604 case PTU_DEFAULTS_EEPROM_FAULT:
00605 return "PTU_DEFAULTS_EEPROM_FAULT"; break;
00606 case PTU_SAVED_DEFAULTS_CORRUPTED:
00607 return "PTU_SAVED_DEFAULTS_CORRUPTED"; break;
00608 case PTU_LIMIT_HIT:
00609 return "PTU_LIMIT_HIT"; break;
00610 case PTU_CABLE_DISCONNECTED:
00611 return "PTU_CABLE_DISCONNECTED"; break;
00612 case PTU_ILLEGAL_UNIT_ID:
00613 return"PTU_ILLEGAL_UNIT_ID"; break;
00614 case PTU_ILLEGAL_POWER_MODE:
00615 return "PTU_ILLEGAL_POWER_MODE"; break;
00616 case PTU_RESET_FAILED:
00617 return "PTU_RESET_FAILED"; break;
00618 case PTU_ILLEGAL_PARAMETERS:
00619 return "PTU_ILLEGAL_PARAMETERS"; break;
00620 case PTU_DUART_ERROR:
00621 return "PTU_DUART_ERROR"; break;
00622 case PTU_ERROR:
00623 return "PTU_ERROR"; break;
00624 case NOT_SUPPORTED_BY_THIS_FIRMWARE_VERSION:
00625 return "NOT_SUPPORTED_BY_THIS_FIRMWARE_VERSION"; break;
00626 case PTU_TILT_VANE_OUT_OF_RANGE_ERROR:
00627 return "PTU_TILT_VANE_OUT_OF_RANGE_ERROR"; break;
00628 default:
00629 return "UNDEFINED_RETURN_STATUS_ERROR"; break;
00630 }
00631 #endif
00632 #ifdef __PTU_FREE_INCLUDED__
00633 if(status_code == PTU_OK) {
00634 return "PTU_OK";
00635 }
00636 else {
00637 return "PTU_ERROR";
00638 }
00639 #endif
00640 }
00641
00642 bool PTUDriver::hasHaltedAndReachedGoal() {
00643 return hasHalted() && reachedGoal();
00644 }
00645
00646 bool PTUDriver::hasHalted() {
00647 long current_tilt_speed = get_current(TILT, SPEED);
00648 long current_pan_speed = get_current(PAN, SPEED);
00649 return (((current_tilt_speed == 0) && (current_pan_speed == 0)));
00650 }
00651
00652
00653 bool PTUDriver::reachedGoal() {
00654 long current_tilt = get_current(TILT, POSITION);
00655 long desired_tilt = get_desired(TILT, POSITION);
00656 long current_pan = get_current(PAN, POSITION);
00657 long desired_pan = get_desired(PAN, POSITION);
00658 return ((current_tilt == desired_tilt) && (current_pan == desired_pan));
00659 }
00660
00661
00662
00663
00664
00665
00666 std::vector<double> PTUDriver::solveSecondDegreePolynomial(double a, double b, double c) {
00667 std::vector<double> solutions;
00668
00669 double second_part_before_root = pow(b, 2) - 4 * a * c;
00670 if(second_part_before_root < 0){
00671 return solutions;
00672 }
00673 if(second_part_before_root == 0) {
00674 solutions.push_back(-b / (2 * a));
00675 return solutions;
00676 }
00677 double root_part = sqrt(second_part_before_root);
00678 solutions.push_back((-b + root_part) / (2 * a));
00679 solutions.push_back((-b - root_part) / (2 * a));
00680 return solutions;
00681 }
00682
00683
00684
00685
00686
00687 std::vector<double> PTUDriver::getAccelerationTimeAndSlewSpeedTime(double distance_in_steps, double base_speed, double acceleration, double slew_speed) {
00688 std::vector<double> solution;
00689 if(distance_in_steps == 0.0) {
00690 solution.push_back(0.0);
00691 solution.push_back(0.0);
00692 return solution;
00693 }
00694
00695 double speed_to_accelerate = slew_speed - base_speed;
00696 double acceleration_time_to_desired_speed = speed_to_accelerate / acceleration;
00697 double distance_for_full_acceleration_and_deceleration = 2.0 * (acceleration_time_to_desired_speed * base_speed
00698 + 1.0/2.0 * acceleration * pow(acceleration_time_to_desired_speed, 2));
00699
00700 if(distance_for_full_acceleration_and_deceleration >= distance_in_steps) {
00701 std::vector<double> speed_candidates = solveSecondDegreePolynomial(1.0 / acceleration, 2.0 * base_speed / acceleration, -distance_in_steps);
00702 if(speed_candidates.size() == 0) {
00703 ROS_DEBUG("PAN ACCELERATION TIME CALCULATION FAILED (getAccelerationTime-Method)");
00704 return solution;
00705 }
00706 else if(speed_candidates.size() == 1) {
00707 solution.push_back(speed_candidates[0]);
00708 return solution;
00709 }
00710 else {
00711 double new_acceleration_time_to_desired_speed_candidate_one = speed_candidates[0] / acceleration;
00712 double new_acceleration_time_to_desired_speed_candidate_two = speed_candidates[1] / acceleration;
00713 if(speed_candidates[0] > 0.0) {
00714 solution.push_back(new_acceleration_time_to_desired_speed_candidate_one);
00715 solution.push_back(0.0);
00716 return solution;
00717 }
00718 else {
00719 solution.push_back(new_acceleration_time_to_desired_speed_candidate_two);
00720 solution.push_back(0.0);
00721 return solution;
00722 }
00723 }
00724 }
00725 else {
00726 solution.push_back(acceleration_time_to_desired_speed);
00727 double remaining_distance_at_slew_speed = distance_in_steps - distance_for_full_acceleration_and_deceleration;
00728 double time_at_slew_speed = remaining_distance_at_slew_speed / slew_speed;
00729 solution.push_back(time_at_slew_speed);
00730 return solution;
00731 }
00732 }
00733
00734
00735
00736 std::vector<double> PTUDriver::predictPositionInTime(std::vector<double> start_point, std::vector<double> end_point, double point_in_time) {
00737 double pan_distance = end_point[0] - start_point[0];
00738 double tilt_distance = end_point[1] - start_point[1];
00739 double pan_distance_in_steps = convertPanFromAngleToPosition(pan_distance);
00740 double tilt_distance_in_steps = convertTiltFromAngleToPosition(tilt_distance);
00741
00742 std::vector<double> pan_time = getAccelerationTimeAndSlewSpeedTime(std::abs(pan_distance_in_steps), prefetched_pan_current_base, prefetched_pan_desired_acceleration, prefetched_pan_desired_speed);
00743 std::vector<double> tilt_time = getAccelerationTimeAndSlewSpeedTime(std::abs(tilt_distance_in_steps), prefetched_pan_current_base, prefetched_pan_desired_acceleration, prefetched_pan_desired_speed);
00744
00745 double pan_complete_time = 2.0 * pan_time[0] + pan_time[1];
00746 double tilt_complete_time = 2.0 * tilt_time[0] + tilt_time[1];
00747 double max_time = std::max(pan_complete_time, tilt_complete_time);
00748 if(max_time <= point_in_time) {
00749 return end_point;
00750 }
00751 else {
00752 std::vector<double> pan_tilt_distance;
00753 if(pan_time[0] >= point_in_time) {
00754 double acceleration_time = point_in_time;
00755 double slew_speed_time = 0.0;
00756 double decceleration_time = 0.0;
00757 if(pan_distance >= 0) {
00758 pan_tilt_distance.push_back(convertPanFromPositionToAngle(calculateCoveredDistance(acceleration_time,slew_speed_time,decceleration_time,true)));
00759 }
00760 else {
00761 pan_tilt_distance.push_back(-1.0 * convertPanFromPositionToAngle(calculateCoveredDistance(acceleration_time,slew_speed_time,decceleration_time,true)));
00762 }
00763 }
00764 else if((pan_time[0] + pan_time[1]) >= point_in_time) {
00765 double acceleration_time = pan_time[0];
00766 double slew_speed_time = point_in_time - pan_time[0];
00767 double decceleration_time = 0.0;
00768 if(pan_distance >= 0) {
00769 pan_tilt_distance.push_back(convertPanFromPositionToAngle(calculateCoveredDistance(acceleration_time,slew_speed_time,decceleration_time,true)));
00770 }
00771 else {
00772 pan_tilt_distance.push_back(-1.0 * convertPanFromPositionToAngle(calculateCoveredDistance(acceleration_time,slew_speed_time,decceleration_time,true)));
00773 }
00774 }
00775
00776 else if((2.0 * pan_time[0] + pan_time[1]) >= point_in_time){
00777 double acceleration_time = pan_time[0];
00778 double slew_speed_time = pan_time[1];
00779 double decceleration_time = point_in_time - pan_time[0] - pan_time[1];
00780 if(pan_distance >= 0) {
00781 pan_tilt_distance.push_back(convertPanFromPositionToAngle(calculateCoveredDistance(acceleration_time,slew_speed_time,decceleration_time,true)));
00782 }
00783 else {
00784 pan_tilt_distance.push_back(-1.0 * convertPanFromPositionToAngle(calculateCoveredDistance(acceleration_time,slew_speed_time,decceleration_time,true)));
00785 }
00786 }
00787 else {
00788 pan_tilt_distance.push_back(end_point[0] - start_point[0]);
00789 }
00790
00791
00792 if(tilt_time[0] >= point_in_time) {
00793 double acceleration_time = point_in_time;
00794 double slew_speed_time = 0.0;
00795 double decceleration_time = 0.0;
00796 if(tilt_distance >= 0) {
00797 pan_tilt_distance.push_back(convertTiltFromPositionToAngle(calculateCoveredDistance(acceleration_time,slew_speed_time,decceleration_time,false)));
00798 }
00799 else {
00800 pan_tilt_distance.push_back(-1.0 * convertTiltFromPositionToAngle(calculateCoveredDistance(acceleration_time,slew_speed_time,decceleration_time,false)));
00801 }
00802 }
00803 else if((tilt_time[0] + tilt_time[1]) >= point_in_time) {
00804 double acceleration_time = tilt_time[0];
00805 double slew_speed_time = point_in_time - tilt_time[0];
00806 double decceleration_time = 0.0;
00807 if(tilt_distance >= 0) {
00808 pan_tilt_distance.push_back(convertTiltFromPositionToAngle(calculateCoveredDistance(acceleration_time,slew_speed_time,decceleration_time,false)));
00809 }
00810 else {
00811 pan_tilt_distance.push_back(-1.0 * convertTiltFromPositionToAngle(calculateCoveredDistance(acceleration_time,slew_speed_time,decceleration_time,false)));
00812 }
00813 }
00814
00815 else if(((2.0 * tilt_time[0] + tilt_time[1]) >= point_in_time)){
00816 double acceleration_time = tilt_time[0];
00817 double slew_speed_time = tilt_time[1];
00818 double decceleration_time = point_in_time - tilt_time[0] - tilt_time[1];
00819 if(tilt_distance >= 0) {
00820 pan_tilt_distance.push_back(convertTiltFromPositionToAngle(calculateCoveredDistance(acceleration_time,slew_speed_time,decceleration_time,false)));
00821 }
00822 else {
00823 pan_tilt_distance.push_back(-1.0 * convertTiltFromPositionToAngle(calculateCoveredDistance(acceleration_time,slew_speed_time,decceleration_time,false)));
00824 }
00825 }
00826 else {
00827 pan_tilt_distance.push_back(end_point[1] - start_point[1]);
00828 }
00829
00830 std::vector<double> new_position;
00831 new_position.push_back(start_point[0] + pan_tilt_distance[0]);
00832 new_position.push_back(start_point[1] + pan_tilt_distance[1]);
00833
00834
00835 return new_position;
00836 }
00837 }
00838
00839
00840 double PTUDriver::calculateCoveredDistance(double acceleration_time, double slew_speed_time, double decceleration_time, bool is_pan) {
00841
00842 long prefetched_base;
00843 long prefetched_accel;
00844 if(is_pan) {
00845 prefetched_base = prefetched_pan_current_base;
00846 prefetched_accel = prefetched_pan_desired_acceleration;
00847 }
00848 else {
00849 prefetched_base = prefetched_tilt_current_base;
00850 prefetched_accel = prefetched_tilt_desired_acceleration;
00851 }
00852 double covered_distance = 0.0;
00853 double covered_distance_acceleration = prefetched_base * acceleration_time + 1.0/2.0 * prefetched_accel * pow(acceleration_time, 2);
00854 covered_distance += covered_distance_acceleration;
00855 if(slew_speed_time != 0.0) {
00856 double covered_distance_slew_speed = (prefetched_base + acceleration_time * prefetched_accel) * slew_speed_time;
00857 covered_distance += covered_distance_slew_speed;
00858 }
00859 if(decceleration_time != 0) {
00860 double covered_distance_decceleration = covered_distance_acceleration - 1.0/2.0 * pow((acceleration_time - decceleration_time),2) * prefetched_accel - (acceleration_time - decceleration_time) * prefetched_base;
00861 covered_distance += covered_distance_decceleration;
00862 }
00863 return covered_distance;
00864 }
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875 std::vector<double> PTUDriver::calculatePointOfIntersectionWithForbiddenAreas(std::vector<double> start_point, std::vector<double> end_point) {
00876
00877 double distance_from_start = std::numeric_limits<double>::max();
00878 std::vector<double> intersection_point;
00879 std::vector<double> route_coordiante_form = calculateCoordinateForm(start_point, end_point);
00880
00881 for (unsigned int i = 0; i < forbidden_areas.size(); i++) {
00882
00883 std::vector<double> first_intersection_point = calculateIntersectionPoint(route_coordiante_form, forbidden_area_first_line_coordinate_forms[i]);
00884 std::vector<double> second_intersection_point = calculateIntersectionPoint(route_coordiante_form, forbidden_area_second_line_coordinate_forms[i]);
00885 std::vector<double> third_intersection_point = calculateIntersectionPoint(route_coordiante_form, forbidden_area_third_line_coordinate_forms[i]);
00886 std::vector<double> fourth_intersection_point = calculateIntersectionPoint(route_coordiante_form, forbidden_area_fourth_line_coordinate_forms[i]);
00887 double new_distance_from_start;
00888 if((first_intersection_point.size() != 0)
00889 && isOnLineSegmentBetweenTwoPoints(start_point, end_point, route_coordiante_form, first_intersection_point, double_computation_tolerance)
00890 && isOnLineSegmentBetweenTwoPoints(max_pan_max_tilt_points[i], max_pan_min_tilt_points[i], forbidden_area_first_line_coordinate_forms[i], first_intersection_point, double_computation_tolerance)) {
00891 new_distance_from_start = getVectorLength(start_point, first_intersection_point);
00892 if(new_distance_from_start < distance_from_start) {
00893 distance_from_start = new_distance_from_start;
00894 intersection_point = first_intersection_point;
00895 }
00896 }
00897 if((second_intersection_point.size() != 0)
00898 && isOnLineSegmentBetweenTwoPoints(start_point, end_point, route_coordiante_form, second_intersection_point, double_computation_tolerance)
00899 && isOnLineSegmentBetweenTwoPoints(max_pan_min_tilt_points[i], min_pan_min_tilt_points[i], forbidden_area_second_line_coordinate_forms[i], second_intersection_point, double_computation_tolerance)) {
00900 new_distance_from_start = getVectorLength(start_point, second_intersection_point);
00901 if(new_distance_from_start < distance_from_start) {
00902 distance_from_start = new_distance_from_start;
00903 intersection_point = second_intersection_point;
00904 }
00905 }
00906 if((third_intersection_point.size() != 0)
00907 && isOnLineSegmentBetweenTwoPoints(start_point, end_point, route_coordiante_form, third_intersection_point, double_computation_tolerance)
00908 && isOnLineSegmentBetweenTwoPoints(min_pan_min_tilt_points[i], min_pan_max_tilt_points[i], forbidden_area_third_line_coordinate_forms[i], third_intersection_point, double_computation_tolerance)) {
00909 new_distance_from_start = getVectorLength(start_point, third_intersection_point);
00910 if(new_distance_from_start < distance_from_start) {
00911 distance_from_start = new_distance_from_start;
00912 intersection_point = third_intersection_point;
00913 }
00914 }
00915 if((fourth_intersection_point.size() != 0)
00916 && isOnLineSegmentBetweenTwoPoints(start_point, end_point, route_coordiante_form, fourth_intersection_point, double_computation_tolerance)
00917 && isOnLineSegmentBetweenTwoPoints(min_pan_max_tilt_points[i], max_pan_max_tilt_points[i], forbidden_area_fourth_line_coordinate_forms[i], fourth_intersection_point, double_computation_tolerance)) {
00918 new_distance_from_start = getVectorLength(start_point, fourth_intersection_point);
00919 if(new_distance_from_start < distance_from_start) {
00920 distance_from_start = new_distance_from_start;
00921 intersection_point = fourth_intersection_point;
00922 }
00923 }
00924 }
00925 if(intersection_point.size() != 0) {
00926 printf("Start Point: (%f,%f)\n", start_point[0], start_point[1]);
00927 printf("End Point: (%f,%f)\n", end_point[0], end_point[1]);
00928 printf("Intersection Point: (%f,%f)\n", intersection_point[0], intersection_point[1]);
00929 }
00930 return intersection_point;
00931 }
00932
00933
00934 std::vector<double> PTUDriver::calculateIntersectionPoint(std::vector<double> first_line_coordiante_form, std::vector<double> second_line_coordiante_form) {
00935
00936 std::vector<double> intersection_point;
00937 double denominator = first_line_coordiante_form[0] * second_line_coordiante_form[1] - first_line_coordiante_form[1] * second_line_coordiante_form[0];
00938 if((denominator >= -0.00001 && denominator <= 0.00001)) {
00939 return intersection_point;
00940 }
00941 double pan_intersection_point = first_line_coordiante_form[2] * second_line_coordiante_form[1] - first_line_coordiante_form[1] * second_line_coordiante_form[2];
00942 double tilt_intersection_point = first_line_coordiante_form[0] * second_line_coordiante_form[2] - first_line_coordiante_form[2] * second_line_coordiante_form[0];
00943 pan_intersection_point /= denominator;
00944 tilt_intersection_point /= denominator;
00945 intersection_point.push_back(pan_intersection_point);
00946 intersection_point.push_back(tilt_intersection_point);
00947 return intersection_point;
00948 }
00949
00950 bool PTUDriver::isOnLineSegmentBetweenTwoPoints(std::vector<double> start_point, std::vector<double> end_point, std::vector<double> line_coordinate_form, std::vector<double> point_to_check, double tolerance) {
00951 double distance_from_start_point = sqrt(pow((point_to_check[0] - start_point[0]), 2) + pow((point_to_check[1] - start_point[1]), 2));
00952 double distance_from_end_point = sqrt(pow((point_to_check[0] - end_point[0]), 2) + pow((point_to_check[1] - end_point[1]), 2));
00953 if((distance_from_start_point <= tolerance) || (distance_from_end_point <= tolerance)) {
00954 return true;
00955 }
00956
00957
00958 double normal_vector_length = sqrt(pow(line_coordinate_form[0], 2) + pow(line_coordinate_form[1], 2));
00959
00960
00961 double distance_from_line = (1/normal_vector_length) * (point_to_check[0] * line_coordinate_form[0] + point_to_check[1] * line_coordinate_form[1] - line_coordinate_form[2]);
00962
00963 if(distance_from_line > tolerance) {
00964 return false;
00965 }
00966
00968
00969
00970
00971
00972
00973
00974 double max_pan = std::max(start_point[0], end_point[0]);
00975 double min_pan = std::min(start_point[0], end_point[0]);
00976 double max_tilt = std::max(start_point[1], end_point[1]);
00977 double min_tilt = std::min(start_point[1], end_point[1]);
00978 max_pan += tolerance;
00979 min_pan -= tolerance;
00980 max_tilt += tolerance;
00981 min_tilt -= tolerance;
00982
00983 if((point_to_check[0] > max_pan) || (point_to_check[0] < min_pan) || (point_to_check[1] > max_tilt) || (point_to_check[1] < min_tilt)) {
00984 return false;
00985 }
00986 else {
00987 return true;
00988 }
00989 }
00990
00991
00992 std::vector<double> PTUDriver::calculateCoordinateForm(std::vector<double> start_point, std::vector<double> end_point) {
00993 std::vector<double> coordinate_form;
00994 if((start_point[0] == end_point[0]) && (start_point[1] == end_point[1])) {
00995 return coordinate_form;
00996 }
00997 double a = start_point[1] - end_point[1];
00998 double b = end_point[0] - start_point[0];
00999 double c = end_point[0] * start_point[1] - start_point[0] * end_point[1];
01000 coordinate_form.push_back(a);
01001 coordinate_form.push_back(b);
01002 coordinate_form.push_back(c);
01003 return coordinate_form;
01004 }
01005
01006
01007 double PTUDriver::getVectorLength(std::vector<double> input_vector) {
01008 double length = 0.0;
01009 for(unsigned int i = 0; i < input_vector.size(); i++) {
01010 length += pow(input_vector[i], 2);
01011 }
01012 return sqrt(length);
01013 }
01014
01015 double PTUDriver::getVectorLength(std::vector<double> start_point, std::vector<double> end_point) {
01016 if (start_point.size() != end_point.size()) {
01017 return -1.0;
01018 }
01019 std::vector<double> length_vector(start_point.size());
01020 for (unsigned int i = 0; i < start_point.size(); i++) {
01021 length_vector[i] = end_point[i] - start_point[i];
01022 }
01023 return getVectorLength(length_vector);
01024 }
01025
01026 std::vector<double> PTUDriver::determineLegitEndPoint(double end_point_pan_candidate, double end_point_tilt_candidate) {
01027 prefetchValues();
01028 std::vector<double> possible_end_point = checkForPossibleKollision(end_point_pan_candidate, end_point_tilt_candidate);
01029 if(possible_end_point.size() == 0) {
01030 std::vector<double> end_point;
01031 end_point.push_back(end_point_pan_candidate);
01032 end_point.push_back(end_point_tilt_candidate);
01033 return end_point;
01034 }
01035
01036 while(true) {
01037 std::vector<double> new_possible_end_point = checkForPossibleKollision(possible_end_point[0], possible_end_point[1]);
01038 if(new_possible_end_point.size() == 0) {
01039 return possible_end_point;
01040 }
01041
01042 else if (getVectorLength(possible_end_point, new_possible_end_point) < double_computation_tolerance) {
01043
01044 return new_possible_end_point;
01045 }
01046 else {
01047 possible_end_point = new_possible_end_point;
01048 }
01049 }
01050 }
01051
01052
01053 std::vector<double> PTUDriver::checkForPossibleKollision(double new_pan_angle, double new_tilt_angle) {
01054 std::vector<double> start_point;
01055 double start_pan_value = convertPanFromPositionToAngle(prefetched_pan_current_position);
01056 start_point.push_back(start_pan_value);
01057 double start_tilt_value = convertTiltFromPositionToAngle(prefetched_tilt_current_position);
01058 start_point.push_back(start_tilt_value);
01059
01060 std::vector<double> end_point;
01061 end_point.push_back(new_pan_angle);
01062 end_point.push_back(new_tilt_angle);
01063
01064
01065 double max_base_speed = std::max(prefetched_pan_current_base, prefetched_tilt_current_base);
01066
01067
01068 double time_per_position = 1.0 / max_base_speed;
01069
01070
01071
01072 double time_between_samples = time_per_position * distance_factor;
01073
01074 double counter = 1.0;
01075 std::vector<double> last_point = start_point;
01076 std::vector<double> intersection_point;
01077 std::vector<double> new_point;
01078 while(true){
01079 new_point = predictPositionInTime(start_point, end_point, (counter * time_between_samples));
01080 if((new_point[0] == last_point[0]) && (new_point[1] == last_point[1])) {
01081 return intersection_point;
01082 }
01083 intersection_point = calculatePointOfIntersectionWithForbiddenAreas(last_point, new_point);
01084 if(intersection_point.size() != 0) {
01085 return intersection_point;
01086 }
01087 else {
01088 last_point = new_point;
01089 counter += 1.0;
01090 }
01091 }
01092 }
01093
01094
01095 void PTUDriver::precalculateForbiddenAreaCoodinateForms() {
01096 for (unsigned int i = 0; i < forbidden_areas.size(); i++) {
01097 std::vector<double> max_pan_max_tilt_point;
01098 max_pan_max_tilt_point.push_back(forbidden_areas[i]["pan_max"]);
01099 max_pan_max_tilt_point.push_back(forbidden_areas[i]["tilt_max"]);
01100 max_pan_max_tilt_points.push_back(max_pan_max_tilt_point);
01101 std::vector<double> max_pan_min_tilt_point;
01102 max_pan_min_tilt_point.push_back(forbidden_areas[i]["pan_max"]);
01103 max_pan_min_tilt_point.push_back(forbidden_areas[i]["tilt_min"]);
01104 max_pan_min_tilt_points.push_back(max_pan_min_tilt_point);
01105 std::vector<double> min_pan_max_tilt_point;
01106 min_pan_max_tilt_point.push_back(forbidden_areas[i]["pan_min"]);
01107 min_pan_max_tilt_point.push_back(forbidden_areas[i]["tilt_max"]);
01108 min_pan_max_tilt_points.push_back(min_pan_max_tilt_point);
01109 std::vector<double> min_pan_min_tilt_point;
01110 min_pan_min_tilt_point.push_back(forbidden_areas[i]["pan_min"]);
01111 min_pan_min_tilt_point.push_back(forbidden_areas[i]["tilt_min"]);
01112 min_pan_min_tilt_points.push_back(min_pan_min_tilt_point);
01113 forbidden_area_first_line_coordinate_forms.push_back(calculateCoordinateForm(max_pan_max_tilt_point, max_pan_min_tilt_point));
01114 forbidden_area_second_line_coordinate_forms.push_back(calculateCoordinateForm(max_pan_min_tilt_point, min_pan_min_tilt_point));
01115 forbidden_area_third_line_coordinate_forms.push_back(calculateCoordinateForm(min_pan_min_tilt_point, min_pan_max_tilt_point));
01116 forbidden_area_fourth_line_coordinate_forms.push_back(calculateCoordinateForm(min_pan_max_tilt_point, max_pan_max_tilt_point));
01117 }
01118 }
01119
01120 void PTUDriver::prefetchValues() {
01121 prefetched_pan_current_base = get_current(PAN, BASE);
01122 prefetched_pan_desired_acceleration = get_desired(PAN, ACCELERATION);
01123 prefetched_pan_desired_speed = get_desired(PAN, SPEED);
01124 prefetched_pan_current_position = get_current(PAN, POSITION);
01125 prefetched_tilt_current_base = get_current(TILT, BASE);
01126 prefetched_tilt_desired_acceleration = get_desired(TILT, ACCELERATION);
01127 prefetched_tilt_desired_speed = get_desired(TILT, SPEED);
01128 prefetched_tilt_current_position = get_current(TILT, POSITION);
01129 }
01130
01131
01132 #ifdef __PTU_FREE_INCLUDED__
01133 long PTUDriver::get_current(char pan_or_tilt, char what) {
01134 if(pan_or_tilt == PAN) {
01135 switch(what) {
01136 case POSITION:
01137 return free_ptu.getCurrentPanPosition();
01138 break;
01139 case RESOLUTION:
01140 return (free_ptu.getPanResolution() * 60.0);
01141 break;
01142 case MINIMUM_POSITION:
01143 return free_ptu.getCurrentUsedMinimumPanPositionLimit();
01144 break;
01145 case MAXIMUM_POSITION:
01146 return free_ptu.getCurrentUsedMaximumPanPositionLimit();
01147 break;
01148 case SPEED:
01149 return free_ptu.getCurrentPanSpeed();
01150 break;
01151 case BASE:
01152 return free_ptu.getPanBaseSpeed();
01153 break;
01154 default:
01155 ROS_DEBUG("bad use of internal get_current method: input combination not legit");
01156 return ERROR;
01157 }
01158 }
01159
01160 else if(pan_or_tilt == TILT) {
01161 switch(what) {
01162 case POSITION:
01163 return free_ptu.getCurrentTiltPosition();
01164 break;
01165 case RESOLUTION:
01166 return (free_ptu.getTiltResolution() * 60);
01167 break;
01168 case MINIMUM_POSITION:
01169 return free_ptu.getCurrentUsedMinimumTiltPositionLimit();
01170 break;
01171 case MAXIMUM_POSITION:
01172 return free_ptu.getCurrentUsedMaximumTiltPositionLimit();
01173 break;
01174 case SPEED:
01175 return free_ptu.getCurrentTiltSpeed();
01176 break;
01177 case BASE:
01178 return free_ptu.getTiltBaseSpeed();
01179 break;
01180 default:
01181 ROS_DEBUG("bad use of internal get_current method: input combination not legit");
01182 return ERROR;
01183 }
01184 }
01185 else {
01186 ROS_DEBUG("bad use of internal get_current method: input combination not legit");
01187 return ERROR;
01188 }
01189 }
01190
01191
01192 char PTUDriver::set_desired(char pan_or_tilt, char what, short int * value, char type) {
01193 if(pan_or_tilt == PAN) {
01194 switch(what) {
01195 case BASE:
01196 if(free_ptu.setPanBaseSpeed(*value)) {
01197 return PTU_OK;
01198 }
01199 else {
01200 return PTU_NOT_OK;
01201 }
01202 break;
01203 case UPPER_SPEED_LIMIT:
01204 if(free_ptu.setDesiredPanUpperSpeedLimit(*value)) {
01205 return PTU_OK;
01206 }
01207 else {
01208 return PTU_NOT_OK;
01209 }
01210 break;
01211 case SPEED:
01212 if(free_ptu.setDesiredPanSpeedAbsolute(*value)) {
01213 return PTU_OK;
01214 }
01215 else {
01216 return PTU_NOT_OK;
01217 }
01218 break;
01219 case ACCELERATION:
01220 if(free_ptu.setDesiredPanAccelerationAbsolute(*value)) {
01221 return PTU_OK;
01222 }
01223 else {
01224 return PTU_NOT_OK;
01225 }
01226 break;
01227 case HOLD_POWER_LEVEL:
01228 if(*value == PTU_OFF_POWER){
01229 if(free_ptu.setPanStationaryPowerMode(OFF_HOLD_POWER_MODE)) {
01230 return PTU_OK;
01231 }
01232 else {
01233 return PTU_NOT_OK;
01234 }
01235 }
01236 else if (*value == PTU_LOW_POWER){
01237 if(free_ptu.setPanStationaryPowerMode(LOW_HOLD_POWER_MODE)) {
01238 return PTU_OK;
01239 }
01240 else {
01241 return PTU_NOT_OK;
01242 }
01243 }
01244 else if(*value == PTU_REG_POWER) {
01245 if(free_ptu.setPanStationaryPowerMode(REGULAR_HOLD_POWER_MODE)) {
01246 return PTU_OK;
01247 }
01248 else {
01249 return PTU_NOT_OK;
01250 }
01251 }
01252 else {
01253 ROS_DEBUG("bad use of internal set_desired method: input combination not legit");
01254 return PTU_NOT_OK;
01255 }
01256 break;
01257 case MOVE_POWER_LEVEL:
01258 if(*value == PTU_LOW_POWER){
01259 if(free_ptu.setPanInMotionPowerMode(LOW_MOVE_POWER_MODE)) {
01260 return PTU_OK;
01261 }
01262 else {
01263 return PTU_NOT_OK;
01264 }
01265 }
01266 else if (*value == PTU_REG_POWER){
01267 if(free_ptu.setPanInMotionPowerMode(REGULAR_MOVE_POWER_MODE)) {
01268 return PTU_OK;
01269 }
01270 else {
01271 return PTU_NOT_OK;
01272 }
01273 }
01274 else if (*value == PTU_HI_POWER) {
01275 if(free_ptu.setPanInMotionPowerMode(HIGH_MOVE_POWER_MODE)) {
01276 return PTU_OK;
01277 }
01278 else {
01279 return PTU_NOT_OK;
01280 }
01281 }
01282 else {
01283 ROS_DEBUG("bad use of internal set_desired method: input combination not legit");
01284 return PTU_NOT_OK;
01285 }
01286 break;
01287 case POSITION:
01288 if(free_ptu.setDesiredPanPositionAbsolute(*value)) {
01289 return PTU_OK;
01290 }
01291 else {
01292 return PTU_NOT_OK;
01293 }
01294 break;
01295 default:
01296 ROS_DEBUG("bad use of internal set_desired method: input combination not legit");
01297 return PTU_NOT_OK;
01298 }
01299 }
01300 else if(pan_or_tilt == TILT) {
01301 switch(what) {
01302 case BASE:
01303 if(free_ptu.setTiltBaseSpeed(*value)) {
01304 return PTU_OK;
01305 }
01306 else {
01307 return PTU_NOT_OK;
01308 }
01309 break;
01310 case UPPER_SPEED_LIMIT:
01311 if(free_ptu.setDesiredTiltUpperSpeedLimit(*value)) {
01312 return PTU_OK;
01313 }
01314 else {
01315 return PTU_NOT_OK;
01316 }
01317 break;
01318 case SPEED:
01319 if(free_ptu.setDesiredTiltSpeedAbsolute(*value)) {
01320 return PTU_OK;
01321 }
01322 else {
01323 return PTU_NOT_OK;
01324 }
01325 break;
01326 case ACCELERATION:
01327 if(free_ptu.setDesiredTiltAccelerationAbsolute(*value)) {
01328 return PTU_OK;
01329 }
01330 else {
01331 return PTU_NOT_OK;
01332 }
01333 break;
01334 case HOLD_POWER_LEVEL:
01335 if(*value == PTU_OFF_POWER){
01336 if(free_ptu.setTiltStationaryPowerMode(OFF_HOLD_POWER_MODE)) {
01337 return PTU_OK;
01338 }
01339 else {
01340 return PTU_NOT_OK;
01341 }
01342 }
01343 else if (*value == PTU_LOW_POWER){
01344 if(free_ptu.setTiltStationaryPowerMode(LOW_HOLD_POWER_MODE)) {
01345 return PTU_OK;
01346 }
01347 else {
01348 return PTU_NOT_OK;
01349 }
01350 }
01351 else if (*value == PTU_REG_POWER) {
01352 if(free_ptu.setTiltStationaryPowerMode(REGULAR_HOLD_POWER_MODE)) {
01353 return PTU_OK;
01354 }
01355 else {
01356 return PTU_NOT_OK;
01357 }
01358 }
01359 else {
01360 ROS_DEBUG("bad use of internal set_desired method: input combination not legit");
01361 return PTU_NOT_OK;
01362 }
01363 break;
01364 case MOVE_POWER_LEVEL:
01365 if(*value == PTU_LOW_POWER){
01366 if(free_ptu.setTiltInMotionPowerMode(LOW_MOVE_POWER_MODE)) {
01367 return PTU_OK;
01368 }
01369 else {
01370 return PTU_NOT_OK;
01371 }
01372 }
01373 else if (*value == PTU_REG_POWER){
01374 if(free_ptu.setTiltInMotionPowerMode(REGULAR_MOVE_POWER_MODE)) {
01375 return PTU_OK;
01376 }
01377 else {
01378 return PTU_NOT_OK;
01379 }
01380 }
01381 else if (*value == PTU_HI_POWER) {
01382 if(free_ptu.setTiltInMotionPowerMode(HIGH_MOVE_POWER_MODE)) {
01383 return PTU_OK;
01384 }
01385 else {
01386 return PTU_NOT_OK;
01387 }
01388 }
01389 else {
01390 ROS_DEBUG("bad use of internal set_desired method: input combination not legit");
01391 return PTU_NOT_OK;
01392 }
01393 break;
01394 case POSITION:
01395 if(free_ptu.setDesiredTiltPositionAbsolute(*value)) {
01396 return PTU_OK;
01397 }
01398 else {
01399 return PTU_NOT_OK;
01400 }
01401 break;
01402 default:
01403 ROS_DEBUG("bad use of internal set_desired method: input combination not legit");
01404 return PTU_NOT_OK;
01405 }
01406 }
01407 else {
01408 ROS_DEBUG("bad use of internal set_desired method: input combination not legit");
01409 return PTU_NOT_OK;
01410 }
01411
01412 }
01413
01414
01415 long PTUDriver::get_desired(char pan_or_tilt, char what) {
01416 long pow_mode;
01417 if(pan_or_tilt == PAN) {
01418 switch(what) {
01419 case UPPER_SPEED_LIMIT:
01420 return free_ptu.getPanUpperSpeedLimit();
01421 break;
01422 case SPEED:
01423 return free_ptu.getDesiredPanSpeed();
01424 break;
01425 case ACCELERATION:
01426 return free_ptu.getPanAcceleartion();
01427 break;
01428 case HOLD_POWER_LEVEL:
01429 pow_mode = free_ptu.getPanStationaryPowerMode();
01430 if(pow_mode == LOW_HOLD_POWER_MODE) {
01431 return PTU_LOW_POWER;
01432 }
01433 else if(pow_mode == OFF_HOLD_POWER_MODE) {
01434 return PTU_OFF_POWER;
01435 }
01436 else if(pow_mode == REGULAR_HOLD_POWER_MODE) {
01437 return PTU_REG_POWER;
01438 }
01439 else {
01440 return ERROR;
01441 }
01442 break;
01443 case MOVE_POWER_LEVEL:
01444 pow_mode = free_ptu.getPanInMotionPowerMode();
01445 if(pow_mode == LOW_MOVE_POWER_MODE) {
01446 return PTU_LOW_POWER;
01447 }
01448 else if(pow_mode == HIGH_MOVE_POWER_MODE) {
01449 return PTU_HI_POWER;
01450 }
01451 else if(pow_mode == REGULAR_MOVE_POWER_MODE) {
01452 return PTU_REG_POWER;
01453 }
01454 else {
01455 return ERROR;
01456 }
01457 break;
01458 case POSITION:
01459 return free_ptu.getDesiredPanPosition();
01460 break;
01461 case BASE:
01462 return free_ptu.getPanBaseSpeed();
01463 break;
01464 default:
01465 return ERROR;
01466 }
01467 }
01468 else if (pan_or_tilt == TILT) {
01469 switch(what) {
01470 case UPPER_SPEED_LIMIT:
01471 return free_ptu.getTiltUpperSpeedLimit();
01472 break;
01473 case SPEED:
01474 return free_ptu.getDesiredTiltSpeed();
01475 break;
01476 case ACCELERATION:
01477 return free_ptu.getTiltAcceleartion();
01478 break;
01479 case HOLD_POWER_LEVEL:
01480 pow_mode = free_ptu.getTiltStationaryPowerMode();
01481 if(pow_mode == LOW_HOLD_POWER_MODE) {
01482 return PTU_LOW_POWER;
01483 }
01484 else if(pow_mode == OFF_HOLD_POWER_MODE) {
01485 return PTU_OFF_POWER;
01486 }
01487 else if(pow_mode == REGULAR_HOLD_POWER_MODE) {
01488 return PTU_REG_POWER;
01489 }
01490 else {
01491 return ERROR;
01492 }
01493 break;
01494 case MOVE_POWER_LEVEL:
01495 pow_mode = free_ptu.getTiltInMotionPowerMode();
01496 if(pow_mode == LOW_MOVE_POWER_MODE) {
01497 return PTU_LOW_POWER;
01498 }
01499 else if(pow_mode == HIGH_MOVE_POWER_MODE) {
01500 return PTU_HI_POWER;
01501 }
01502 else if(pow_mode == REGULAR_MOVE_POWER_MODE) {
01503 return PTU_REG_POWER;
01504 }
01505 else {
01506 return ERROR;
01507 }
01508 break;
01509 case POSITION:
01510 return free_ptu.getDesiredTiltPosition();
01511 break;
01512 case BASE:
01513 return free_ptu.getTiltBaseSpeed();
01514 break;
01515 default:
01516 return ERROR;
01517 }
01518 }
01519 else {
01520 ROS_DEBUG("bad use of internal get_desired method: input combination not legit");
01521 return ERROR;
01522 }
01523 }
01524
01525 char PTUDriver::set_mode(char mode_type, char mode) {
01526 if(mode_type == POSITION_LIMITS_MODE) {
01527 switch(mode) {
01528 case OFF_MODE:
01529 if(free_ptu.setPositionLimitEnforcementMode(LIMITS_DISABLED)) {
01530 return PTU_OK;
01531 }
01532 else {
01533 return PTU_NOT_OK;
01534 }
01535 break;
01536 default:
01537 return PTU_NOT_OK;
01538 }
01539 }
01540 else if (mode_type == SPEED_CONTROL_MODE) {
01541 switch(mode) {
01542 case PTU_PURE_VELOCITY_SPEED_CONTROL_MODE:
01543 if(free_ptu.setSpeedControlMode(PURE_VELOCITY_CONTROL_MODE)) {
01544 return PTU_OK;
01545 }
01546 else {
01547 return PTU_NOT_OK;
01548 }
01549 break;
01550 case PTU_INDEPENDENT_SPEED_CONTROL_MODE:
01551 if(free_ptu.setSpeedControlMode(INDEPENDENT_SPEED_MODE)) {
01552 return PTU_OK;
01553 }
01554 else {
01555 return PTU_NOT_OK;
01556 }
01557 break;
01558 default:
01559 return PTU_NOT_OK;
01560 }
01561 }
01562 else {
01563 ROS_DEBUG("bad use of internal set_mode method: input combination not legit");
01564 return PTU_NOT_OK;
01565 }
01566 }
01567
01568 #endif // __PTU_FREE_INCLUDED__
01569
01570 }