PTUDriver.cpp
Go to the documentation of this file.
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     * With the PTU comes a file, test.c, to be found with the purchasable driver version for the flir ptu.
00041     * In Line 632 a test function for the resolution is declared.
00042     * The value get_current delivers is devided by 3600 there to get min arc
00043     * Therefore it needs to be devided by another 60 to recieve degree.
00044     *
00045     * Be carefull: Calculation shown in the manual is NOT correct
00046     * If PTUFree is used the result that is returned via serial port and via PTUFree sticks to the manual,
00047     * but gets scaled by 60 in the code of this class to match the format that ptu.h returns
00048     */
00049    pan_resolution = get_current(PAN, RESOLUTION) / (3600 * 60.0);
00050    tilt_resolution = get_current(TILT, RESOLUTION) / (3600 * 60.0);
00051 
00052    //Important, let it in, do not change (other mode caused problems with our ptu)
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     //empty
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 //Possible extensions for error handling could be done here (e.g. extra info output)
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 //Do not use if you use a point determinded by checkForPossibleKollision or determineLegitEndPoint because it could lie minimal within a forbidden area (unprecise double calculations) or (normally) directly on the border.
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 //No Check should only be used if you use a point that can be minimal within a forbidden area and when you know that getting in touch with the border of the forbidden area is no problem
00452 //A typical case for that problem is a point derived from 'checkForPossibleKollision' or 'determineLegitEndPoint' - these can lay onto the border of a forbidden area or minimal within
00453 bool PTUDriver::setAbsoluteAngles(double pan_angle, double tilt_angle, bool no_forbidden_area_check) {
00454 
00455    // Maybe for later: use with path prediction, the problem that the new position must be returned to the layers above is currently only solved for the GUI, not for the PTU Controller
00456    //PTU Controller must be modified to support new end points to do so
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 //TODO: why is computation tolerance not used here? necessary?
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 * Needs to have the form a * x^2 + b * x + c = 0, where x is the variable who needs to be solved and a, b and c are constants
00664 *
00665 */
00666 std::vector<double> PTUDriver::solveSecondDegreePolynomial(double a, double b, double c) {
00667    std::vector<double> solutions;
00668    //midnight formula used (b +- sqrt(b^2 - 4 * a * c))/2a
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 //Returns a vector consisting of acceleration time (at position 0) and slew speed time (position 1). Do not forget that acceleration time is ONLY for acceleration and not for acceleration and deceleration.
00684 //Though, acceleration time and deceleration time are the same because ramp profile is used.
00685 //Returns empty vector on error.
00686 //All needs to be entered in steps!!!
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    //Because acceleration to BASE SPEED happens instantly according to the manual it needs to be subtracted from the desired speed (slew speed)
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    //In that case the PTU can not accelerate to full desired speed
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 //Pan at position 0, tilt at position 1, input in degree, output in degree!
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        //neccessary because before only max of pan and tilt complete time was checked
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        //neccessary because before only max of pan and tilt complete time was checked
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 //It is assumed that deccelleration_time is maximum as large as acceleration_time
00840 double PTUDriver::calculateCoveredDistance(double acceleration_time, double slew_speed_time, double decceleration_time, bool is_pan) {
00841    //char type;
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 //If non empty: First Value is Pan of intersection Point, second point is tilt of intersection point
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 //must have form a pan + b tilt = c   a at 0, b at 1, c at 2; returns empty vector if parallel (-> no intersection point or they are identical)
00934 std::vector<double> PTUDriver::calculateIntersectionPoint(std::vector<double> first_line_coordiante_form, std::vector<double> second_line_coordiante_form) {
00935    //Calculated with Cramer's rule
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    //needed to calculate distance with Hesse normal form
00958    double normal_vector_length = sqrt(pow(line_coordinate_form[0], 2) + pow(line_coordinate_form[1], 2));
00959 
00960    //Calculating distance with Hesse normal form
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    //Check if problem still exists, comment above seems old
00969 
00970 
00971    //We have already determinded that the point is less than tolerance from the line that passes through start_point and end_point.
00972    //To determine that the found point lies between start and endpoint we check if it inside the rectange induced by start and endpoint (+ tolerances)
00973    //If it is inside the rectangle it is also on the line between both points, because that it is "on" the line was already checked before and all in the rectangle is between the both points
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 //coordinate form a pan + b tilt = c
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    //The path that is taken changes because acceleration time and slew speed time changes - therefore, another collision that did not occure previously can now occure.
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        //In this case, possible_end_point and new_possible_end_point are litterally the same because they only differe because of unprecise double value (from the calculations).
01042        else if (getVectorLength(possible_end_point, new_possible_end_point) < double_computation_tolerance) {
01043            //At this point any of the 2 points could be returned because they only differe less than 'double_computation_tolerance' and therefore are literally the same
01044            return new_possible_end_point;
01045        }
01046        else {
01047            possible_end_point = new_possible_end_point;
01048        }
01049    }
01050 }
01051 
01052 //Returns empty vector if no collision is found, collsision point with forbidden area otherwise
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    //This is the maximum time needed to switch a pan and a tilt position while the ptu is moving
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    //Case TILT
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 //TYPE is atm almost never needed because only ABSOLUTE is used. If that changes, edit this method accordingly
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 }


asr_flir_ptu_driver
Author(s): Valerij Wittenbeck, Joachim Gehrung, Pascal Meißner, Patrick Schlosser
autogenerated on Thu Jun 6 2019 21:16:44