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
00058
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
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
00076
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;
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;
00161
00162
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
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
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);
00196
00197
00198
00199 double deltaT = getMS()/1000.0 - lastTimeStamp; lastTimeStamp = getMS()/1000.0;
00200
00201 if (deltaT > 0.2)
00202 deltaT = 0.2;
00203
00204 double deltaYaw = deltaT * (totalForceYaw / droneMassInKilos) / 2;
00205 double deltaGaz = deltaT * (totalForceGaz / droneMassInKilos) / 2;
00206
00207
00208 lastSentControl.gaz = -new_velocity[2] + deltaGaz;
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
00214 double appliedEngineForce = ( 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
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;
00226
00227
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 }