00001 00013 #include "DJI_Flight.h" 00014 #include <string.h> 00015 #include <math.h> 00016 00017 using namespace DJI; 00018 using namespace DJI::onboardSDK; 00019 00020 Flight::Flight(DJI::onboardSDK::CoreAPI *ControlAPI) 00021 { 00022 api = ControlAPI; 00023 #ifdef USE_SIMULATION //! @note This functionality is not supported in this release. 00024 simulating = 0; 00025 #endif // USE_SIMULATION 00026 } 00027 00028 CoreAPI *Flight::getApi() const { return api; } 00029 00030 void Flight::setApi(CoreAPI *value) { api = value; } 00031 00032 #ifdef USE_SIMULATION //! @note This functionality is not supported in this release. 00033 bool Flight::isSimulating() const { return simulating; } 00034 void Flight::setSimulating(bool value) { simulating = value; } 00035 #endif // USE_SIMULATION 00036 00037 void Flight::task(TASK taskname, CallBack TaskCallback, UserData userData) 00038 { 00039 taskData.cmdData = taskname; 00040 taskData.cmdSequence++; 00041 00042 api->send(2, encrypt, SET_CONTROL, CODE_TASK, (unsigned char *)&taskData, sizeof(taskData), 00043 100, 3, TaskCallback ? TaskCallback : Flight::taskCallback, userData); 00044 } 00045 00046 unsigned short Flight::task(TASK taskname, int timeout) 00047 { 00048 taskData.cmdData = taskname; 00049 taskData.cmdSequence++; 00050 00051 api->send(2, encrypt, SET_CONTROL, CODE_TASK, (unsigned char *)&taskData, sizeof(taskData), 00052 100, 3, 0, 0); 00053 00054 api->serialDevice->lockACK(); 00055 api->serialDevice->wait(timeout); 00056 api->serialDevice->freeACK(); 00057 00058 return api->missionACKUnion.simpleACK; 00059 } 00060 00061 void Flight::setArm(bool enable, CallBack ArmCallback, UserData userData) 00062 { 00063 uint8_t data = enable ? 1 : 0; 00064 api->send(2, encrypt, SET_CONTROL, CODE_SETARM, &data, 1, 0, 1, 00065 ArmCallback ? ArmCallback : Flight::armCallback, userData); 00066 } 00067 00068 unsigned short Flight::setArm(bool enable, int timeout) 00069 { 00070 uint8_t data = enable ? 1 : 0; 00071 api->send(2, encrypt, SET_CONTROL, CODE_SETARM, &data, 1, 0, 1, 0, 0); 00072 00073 00074 api->serialDevice->lockACK(); 00075 api->serialDevice->wait(timeout); 00076 api->serialDevice->freeACK(); 00077 00078 return api->missionACKUnion.simpleACK; 00079 } 00080 00081 void Flight::control(uint8_t flag, float32_t x, float32_t y, float32_t z, float32_t yaw) 00082 { 00083 FlightData data; 00084 data.flag = flag; 00085 data.x = x; 00086 data.y = y; 00087 data.z = z; 00088 data.yaw = yaw; 00089 setFlight(&data); 00090 } 00091 00092 00093 void Flight::setMovementControl(uint8_t flag, float32_t x, float32_t y, float32_t z, float32_t yaw) 00094 { 00095 FlightData data; 00096 data.flag = flag; 00097 data.x = x; 00098 data.y = y; 00099 data.z = z; 00100 data.yaw = yaw; 00101 api->send(0, encrypt, SET_CONTROL, CODE_CONTROL, &data, sizeof(FlightData)); 00102 } 00103 00104 00105 void Flight::setFlight(FlightData *data) 00106 { 00107 api->send(0, encrypt, SET_CONTROL, CODE_CONTROL, (unsigned char *)data, sizeof(FlightData)); 00108 } 00109 00110 QuaternionData Flight::getQuaternion() const 00111 { 00112 #ifdef USE_SIMULATION 00113 if (simulating) 00114 { 00115 QuaternionData ans; 00117 00118 return ans; 00119 } 00120 else 00121 #endif // USE_SIMULATION 00122 return api->getBroadcastData().q; 00123 } 00124 00125 EulerAngle Flight::getEulerAngle() const {return Flight::toEulerAngle(api->getBroadcastData().q); } 00126 00127 PositionData Flight::getPosition() const { return api->getBroadcastData().pos; } 00128 00129 VelocityData Flight::getVelocity() const { return api->getBroadcastData().v; } 00130 00132 CommonData Flight::getAcceleration() const { return api->getBroadcastData().a; } 00134 CommonData Flight::getYawRate() const { return api->getBroadcastData().w; } 00135 00137 MagnetData Flight::getMagnet() const { return api->getBroadcastData().mag; } 00138 00139 Flight::Device Flight::getControlDevice() const 00140 { 00141 return (Flight::Device)api->getBroadcastData().ctrlInfo.deviceStatus; 00142 } 00143 00144 Flight::Status Flight::getStatus() const 00145 { 00146 return (Flight::Status)api->getBroadcastData().status; 00147 } 00148 00149 Flight::Mode Flight::getControlMode() const 00150 { 00151 if (api->getSDKVersion() != versionM100_23) 00152 return (Flight::Mode)api->getBroadcastData().ctrlInfo.mode; 00153 return MODE_NOT_SUPPORTED; 00154 } 00155 00156 Angle Flight::getYaw() const 00157 { 00158 #ifdef USE_SIMULATION 00159 if (simulating) 00160 return AngularSim.yaw; 00161 else 00162 #endif // USE_SIMULATION 00163 return toEulerAngle(api->getBroadcastData().q).yaw; 00164 } 00165 00166 Angle Flight::getRoll() const 00167 { 00168 #ifdef USE_SIMULATION 00169 if (simulating) 00170 return AngularSim.roll; 00171 else 00172 #endif // USE_SIMULATION 00173 return toEulerAngle(api->getBroadcastData().q).roll; 00174 } 00175 00176 Angle Flight::getPitch() const 00177 { 00178 #ifdef USE_SIMULATION 00179 if (simulating) 00180 return AngularSim.pitch; 00181 else 00182 #endif // USE_SIMULATION 00183 return toEulerAngle(api->getBroadcastData().q).pitch; 00184 } 00185 00186 void Flight::armCallback(CoreAPI *api, Header *protocolHeader, UserData userData __UNUSED) 00187 { 00188 unsigned short ack_data; 00189 if (protocolHeader->length - EXC_DATA_SIZE <= 2) 00190 { 00191 memcpy((unsigned char *)&ack_data, ((unsigned char *)protocolHeader) + sizeof(Header), 00192 (protocolHeader->length - EXC_DATA_SIZE)); 00193 switch (ack_data) 00194 { 00195 case ACK_ARM_SUCCESS: 00196 API_LOG(api->getDriver(), STATUS_LOG, "Success,0x000%x\n", ack_data); 00197 break; 00198 case ACK_ARM_NEED_CONTROL: 00199 API_LOG(api->getDriver(), STATUS_LOG, "Need to obtain control first, 0x000%x\n", ack_data); 00200 break; 00201 case ACK_ARM_ALREADY_ARMED: 00202 API_LOG(api->getDriver(), STATUS_LOG, "Already done, 0x000%x\n", ack_data); 00203 break; 00204 case ACK_ARM_IN_AIR: 00205 API_LOG(api->getDriver(), STATUS_LOG, "Cannot execute while in air, 0x000%x\n", ack_data); 00206 break; 00207 } 00208 } 00209 else 00210 { 00211 API_LOG(api->getDriver(), ERROR_LOG, "ACK is exception,session id %d,sequence %d\n", 00212 protocolHeader->sessionID, protocolHeader->sequenceNumber); 00213 } 00214 } 00215 00216 void Flight::taskCallback(CoreAPI *api, Header *protocolHeader, UserData userData __UNUSED) 00217 { 00218 unsigned short ack_data; 00219 if (protocolHeader->length - EXC_DATA_SIZE <= 2) 00220 { 00221 memcpy((unsigned char *)&ack_data, ((unsigned char *)protocolHeader) + sizeof(Header), 00222 (protocolHeader->length - EXC_DATA_SIZE)); 00223 API_LOG(api->getDriver(), STATUS_LOG, "Task running successfully,%d\n", ack_data); 00224 } 00225 else 00226 { 00227 API_LOG(api->getDriver(), ERROR_LOG, "ACK is exception,session id %d,sequence %d\n", 00228 protocolHeader->sessionID, protocolHeader->sequenceNumber); 00229 } 00230 } 00231 00233 EulerianAngle Flight::toEulerianAngle(QuaternionData data) 00234 { 00235 EulerianAngle ans; 00236 00237 double q2sqr = data.q2 * data.q2; 00238 double t0 = -2.0 * (q2sqr + data.q3 * data.q3) + 1.0; 00239 double t1 = +2.0 * (data.q1 * data.q2 + data.q0 * data.q3); 00240 double t2 = -2.0 * (data.q1 * data.q3 - data.q0 * data.q2); 00241 double t3 = +2.0 * (data.q2 * data.q3 + data.q0 * data.q1); 00242 double t4 = -2.0 * (data.q1 * data.q1 + q2sqr) + 1.0; 00243 00244 t2 = t2 > 1.0 ? 1.0 : t2; 00245 t2 = t2 < -1.0 ? -1.0 : t2; 00246 00247 ans.pitch = asin(t2); 00248 ans.roll = atan2(t3, t4); 00249 ans.yaw = atan2(t1, t0); 00250 00251 return ans; 00252 } 00253 00254 00255 EulerAngle Flight::toEulerAngle(QuaternionData quaternionData) 00256 { 00257 EulerAngle ans; 00258 00259 double q2sqr = quaternionData.q2 * quaternionData.q2; 00260 double t0 = -2.0 * (q2sqr + quaternionData.q3 * quaternionData.q3) + 1.0; 00261 double t1 = +2.0 * (quaternionData.q1 * quaternionData.q2 + quaternionData.q0 * quaternionData.q3); 00262 double t2 = -2.0 * (quaternionData.q1 * quaternionData.q3 - quaternionData.q0 * quaternionData.q2); 00263 double t3 = +2.0 * (quaternionData.q2 * quaternionData.q3 + quaternionData.q0 * quaternionData.q1); 00264 double t4 = -2.0 * (quaternionData.q1 * quaternionData.q1 + q2sqr) + 1.0; 00265 00266 t2 = t2 > 1.0 ? 1.0 : t2; 00267 t2 = t2 < -1.0 ? -1.0 : t2; 00268 00269 ans.pitch = asin(t2); 00270 ans.roll = atan2(t3, t4); 00271 ans.yaw = atan2(t1, t0); 00272 00273 return ans; 00274 } 00275 00276 QuaternionData Flight::toQuaternion(EulerianAngle eulerAngleData) 00277 { 00278 QuaternionData ans; 00279 double t0 = cos(eulerAngleData.yaw * 0.5); 00280 double t1 = sin(eulerAngleData.yaw * 0.5); 00281 double t2 = cos(eulerAngleData.roll * 0.5); 00282 double t3 = sin(eulerAngleData.roll * 0.5); 00283 double t4 = cos(eulerAngleData.pitch * 0.5); 00284 double t5 = sin(eulerAngleData.pitch * 0.5); 00285 00286 ans.q0 = t2 * t4 * t0 + t3 * t5 * t1; 00287 ans.q1 = t3 * t4 * t0 - t2 * t5 * t1; 00288 ans.q2 = t2 * t5 * t0 + t3 * t4 * t1; 00289 ans.q3 = t2 * t4 * t1 - t3 * t5 * t0; 00290 return ans; 00291 }