DroneController.cpp
Go to the documentation of this file.
00001 
00024 #include "DroneController.h"
00025 #include "gvars3/instances.h"
00026 #include "../HelperFunctions.h"
00027 #include "ControlNode.h"
00028 
00029 int sgn(double val) {
00030     return (0 < val) - (val < 0);
00031 }
00032 
00033 DroneController::DroneController(void)
00034 {
00035         target = DronePosition(TooN::makeVector(0.0,0.0,0.0),0.0);
00036         targetValid = false;
00037         last_err[2] = 0;
00038         lastTimeStamp = 0;
00039 
00040         hoverCommand.gaz = hoverCommand.pitch = hoverCommand.roll = hoverCommand.yaw = 0;
00041 
00042         node = NULL;
00043 }
00044 
00045 
00046 DroneController::~DroneController(void)
00047 {
00048 }
00049 
00050 double angleFromTo2(double angle, double min, double sup)
00051 {
00052         while(angle < min) angle += 360;
00053         while(angle >=  sup) angle -= 360;
00054         return angle;
00055 }
00056 
00057 // generates and sends a new control command to the drone,
00058 // based on the currently active command ant the drone's position.
00059 ControlCommand DroneController::update(uga_tum_ardrone::filter_stateConstPtr state)
00060 {
00061         TooN::Vector<3> pose = TooN::makeVector(state->x, state->y, state->z);
00062         double yaw = state->yaw;
00063         TooN::Vector<4> speeds = TooN::makeVector(state->dx, state->dy, state->dz, state->dyaw);
00064         ptamIsGood = state->ptamState == state->PTAM_BEST || state->ptamState == state->PTAM_GOOD || state->ptamState == state->PTAM_TOOKKF;
00065         scaleAccuracy = state->scaleAccuracy;
00066 
00067         // calculate (new) errors.
00068         TooN::Vector<4> new_err = TooN::makeVector(
00069                 target.pos[0] - pose[0],
00070                 target.pos[1] - pose[1],
00071                 target.pos[2] - pose[2],
00072                 target.yaw - yaw
00073                 );
00074 
00075         // yaw error needs special attention, it can always be pushed in between 180 and -180.
00076         // this does not affect speeds and makes the drone always take the quickest rotation side.
00077         new_err[3] = angleFromTo2(new_err[3],-180,180);
00078         TooN::Vector<4> d_err = TooN::makeVector(-speeds[0], -speeds[1], -speeds[2], -speeds[3]);
00079 
00080         if(targetValid)
00081                 calcControl(new_err, d_err, yaw, state->pitch, state->roll);
00082         else
00083         {
00084                 lastSentControl = hoverCommand;
00085         }
00086 
00087     if(node->logfileControl != NULL)
00088         {
00089                 pthread_mutex_lock(&node->logControl_CS);
00090                 if(node->logfileControl != NULL)
00091         {
00092                         (*(node->logfileControl)) << lastTimeStamp << " ";
00093 
00094                         for( int i = 0; i < logInfo.size(); i++)
00095                 (*(node->logfileControl)) << logInfo[i] << " ";
00096 
00097             (*(node->logfileControl)) << "\n";
00098         }
00099                 pthread_mutex_unlock(&node->logControl_CS);
00100         }
00101         last_err = new_err;
00102         return lastSentControl;
00103 }
00104 
00105 
00106 void DroneController::setTarget(DronePosition newTarget)
00107 {
00108         target = newTarget;
00109         target.yaw = angleFromTo2(target.yaw,-180,180);
00110         targetSetAtClock = getMS()/1000.0;
00111         targetNew = TooN::makeVector(1.0,1.0,1.0,1.0);
00112         targetValid = true;
00113         last_err = i_term = TooN::makeVector(0,0,0,0);
00114     lastTimeStamp = getMS()/1000.0 - 0.03; // prevent deltaT from being 0
00115 
00116         char buf[200];
00117         snprintf(buf,200,"New Target: xyz = %.3f, %.3f, %.3f,  yaw=%.3f", target.pos[0],target.pos[1],target.pos[2],target.yaw);
00118         ROS_INFO("%s", buf);
00119 
00120         if(node != NULL)
00121                 node->publishCommand(std::string("u l ") + buf);
00122 }
00123 
00124 
00125 DronePosition DroneController::getCurrentTarget()
00126 {
00127         return target;
00128 }
00129 
00130 void DroneController::clearTarget()
00131 {
00132         targetValid = false;
00133 }
00134 
00135 void i_term_increase(double& i_term, double new_err, double cap)
00136 {
00137         if(new_err < 0 && i_term > 0)
00138                 i_term = std::max(0.0, i_term + 2.5 * new_err);
00139         else if(new_err > 0 && i_term < 0)
00140                 i_term = std::min(0.0, i_term + 2.5 * new_err);
00141         else
00142                 i_term += new_err;
00143 
00144         if(i_term > cap) i_term =  cap;
00145         if(i_term < -cap) i_term =  -cap;
00146 }
00147 
00148 void DroneController::calcControl(TooN::Vector<4> new_err, TooN::Vector<4> new_velocity, double yaw, double pitch, double roll)
00149 {
00150 
00151         float agr = agressiveness;
00152         if(!ptamIsGood) agr *= 0.75;
00153         agr *= scaleAccuracy;
00154 
00155     double K_rp_agr = K_rp * agr;
00156     double K_direct_agr = K_direct * agr;
00157 
00158 
00159         TooN::Vector<4> vel_term = new_velocity;
00160         TooN::Vector<4> p_term = new_err;       // p-term is error.
00161 
00162         // rotate error to drone CS, invert pitch
00163         double yawRad = yaw * 2 * 3.141592 / 360;
00164         double pitchRad = pitch * 2 * 3.141592 / 360;
00165         double rollRad = roll * 2 * 3.141592 / 360;
00166         vel_term[0] = cos(yawRad)*new_velocity[0] - sin(yawRad)*new_velocity[1];
00167         vel_term[1] = - sin(yawRad)*new_velocity[0] - cos(yawRad)*new_velocity[1];
00168 
00169         p_term[0] = cos(yawRad)*new_err[0] - sin(yawRad)*new_err[1];
00170         p_term[1] = - sin(yawRad)*new_err[0] - cos(yawRad)*new_err[1];
00171 
00172 
00173     // calculate the damping coefficient assuming critically damped
00174     double c_direct = 2 * sqrt( K_direct * 50 * droneMassInKilos );
00175     double c_direct_agr = 2 * sqrt( K_direct_agr * droneMassInKilos );
00176     double c_rp = xy_damping_factor * 2 * sqrt( K_rp_agr * droneMassInKilos );
00177 
00178 
00179     // find target forces given the current state
00180     double springForceRoll = K_rp_agr * p_term[0];
00181     double springForcePitch = K_rp_agr * p_term[1];
00182     double springForceYaw = K_direct * 50 * new_err[3];
00183     double springForceGaz = K_direct_agr * new_err[2];
00184 
00185     double dampingForceRoll = c_rp * -vel_term[0];
00186     double dampingForcePitch = c_rp * -vel_term[1];
00187     double dampingForceYaw = c_direct * -new_velocity[3];
00188     double dampingForceGaz = c_direct_agr * -new_velocity[2];
00189 
00190     double totalForceRoll = springForceRoll - dampingForceRoll;
00191     double totalForcePitch = springForcePitch - dampingForcePitch;
00192     double totalForceYaw = springForceYaw - dampingForceYaw;
00193     double totalForceGaz = springForceGaz - dampingForceGaz;
00194 
00195     totalForceGaz = std::max((-9.8 * droneMassInKilos) *0.8, totalForceGaz); // the drone can't actually accelerate down, gravity does this.
00196                             // and we still need the engines available to provide pitch/roll control, don't shut them down completely
00197 
00198     // Integrate for yaw and gaz control
00199         double deltaT = getMS()/1000.0 - lastTimeStamp; lastTimeStamp = getMS()/1000.0;
00200 
00201         if (deltaT > 0.2) // guard against crazy timestamps
00202         deltaT = 0.2;
00203 
00204     double deltaYaw = deltaT * (totalForceYaw / droneMassInKilos) / 2;
00205     double deltaGaz = deltaT * (totalForceGaz / droneMassInKilos) / 2;
00206 
00207     // the new gaz command
00208         lastSentControl.gaz = -new_velocity[2] + deltaGaz;      // gaz can be translated directly
00209         lastSentControl.gaz = std::min(max_gaz_rise,std::max(max_gaz_drop, (double)(lastSentControl.gaz)));
00210 
00211     double clippedZForce = std::max((-9.8 * droneMassInKilos)*0.8, (2 * droneMassInKilos * (lastSentControl.gaz + new_velocity[2])) / deltaT);
00212 
00213     // how much force do the motors actually generate? need to remove gravity from this
00214     double appliedEngineForce = (/*clippedZForce +*/ 9.8 * droneMassInKilos) / (fabs(cos(pitchRad) * cos(rollRad)));
00215 
00216     if (fabs(totalForceRoll) > fabs(appliedEngineForce))
00217         totalForceRoll = fabs(appliedEngineForce)*sgn(totalForceRoll);
00218 
00219     if (fabs(totalForcePitch) > fabs(appliedEngineForce))
00220         totalForcePitch = fabs(appliedEngineForce)*sgn(totalForcePitch);
00221 
00222     // The new rotation commands
00223         lastSentControl.roll = (1.57 - acos(totalForceRoll / appliedEngineForce)) / max_rp_radians;
00224         lastSentControl.pitch = (1.57 - acos(totalForcePitch / appliedEngineForce)) / max_rp_radians;
00225         lastSentControl.yaw = ((-new_velocity[3] + deltaYaw) * (2 * 3.141592 / 360)) / 1.66;    // yaw can be translated directly, command is 1.0 = 1.66 rads/second
00226 
00227         // clip
00228         lastSentControl.roll = std::min(max_rp,std::max(-max_rp,(double)(lastSentControl.roll)));
00229         lastSentControl.pitch = std::min(max_rp,std::max(-max_rp,(double)(lastSentControl.pitch)));
00230         lastSentControl.yaw = std::min(max_yaw,std::max(-max_yaw,(double)(lastSentControl.yaw)));
00231 
00232 
00233         logInfo = TooN::makeVector(
00234                 springForceRoll, springForcePitch, springForceGaz, springForceYaw,
00235         dampingForceRoll, dampingForcePitch, dampingForceGaz, dampingForceYaw,
00236                 deltaT, deltaYaw, deltaGaz, new_velocity[0], new_velocity[1], new_velocity[2],
00237                 new_velocity[3], new_err[2], new_err[3], clippedZForce,
00238                 lastSentControl.roll, lastSentControl.pitch, lastSentControl.gaz, lastSentControl.yaw,
00239                 appliedEngineForce,yawRad,pitchRad,rollRad,
00240                 target.pos[0],target.pos[1],target.pos[2],target.yaw
00241                 );
00242 }
00243 
00244 TooN::Vector<4> DroneController::getLastErr()
00245 {
00246         return last_err;
00247 }
00248 ControlCommand DroneController::getLastControl()
00249 {
00250         return lastSentControl;
00251 }


uga_tum_ardrone
Author(s):
autogenerated on Sat Jun 8 2019 20:30:11