dynamics0.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. #include "dynamics0.h"
  2. double getAltitude(double lat, double rad) {
  3. // 迭代求椭球体地球模型的高度
  4. // lat : 飞行器质心的地心纬度
  5. // rad : 飞行器质心的地心距离
  6. // alt : 高度
  7. int cnt;
  8. double ae, alphae, e, tol, B, Re, alt, late, error, alt0;
  9. // 1.地球参数
  10. ae = 6378140;// 长半轴
  11. alphae = 1 / 298.257;// 扁率
  12. e = 1 - alphae;// 偏心率
  13. tol = 1e-1;// 高度迭代误差容限 单位 m
  14. // 2.迭代
  15. // 初值
  16. B = atan(tan(lat) / (e * e));
  17. Re = ae * e / sqrt(sin(lat) * sin(lat) + (e * e) * cos(lat) * cos(lat));
  18. alt = sqrt(rad * rad - Re * Re * sin(B - lat) * sin(B - lat)) - Re * cos(B - lat);
  19. late = lat - asin(alt * sin(B - lat) / rad);
  20. // 迭代
  21. error = tol + 100;
  22. cnt = 0;
  23. while (error >= tol) {
  24. alt0 = alt;
  25. B = atan(tan(late) / (e * e));
  26. Re = ae * e / sqrt(sin(late) * sin(late) + (e * e) * cos(late) * cos(late));
  27. alt = sqrt(rad * rad - Re * Re * sin(B - late) * sin(B - late)) - Re * cos(B - late);
  28. late = lat - asin(alt * sin(B - late) / rad);
  29. error = alt - alt0;
  30. if (error < 0)
  31. {
  32. error = -error;
  33. }
  34. cnt = cnt + 1;
  35. if (cnt >= 3) {
  36. break;
  37. }
  38. }
  39. return alt;
  40. }
  41. // 气动系数
  42. void getCxCyCz(double* Cx, double* Cy, double* Cz, double ma, double alt) {
  43. double a0, a1, a2, a3, a4, a5, ma2, ma3, ma4;
  44. Cz[0] = 0;
  45. if (alt < 95 * 1000)
  46. {
  47. if (ma < 0.5) {
  48. ma = 0.5;
  49. }
  50. else if (ma > 32.2) {
  51. ma = 32.2;
  52. }
  53. // 升力拟合公式
  54. if (ma < 1.1) {
  55. a0 = 5.036;
  56. a1 = -12.73;
  57. a2 = 9.024;
  58. a3 = -0.902;
  59. ma2 = ma * ma;
  60. Cy[0] = a0 + a1 * sqrt(ma) + a2 * ma + a3 * ma2;
  61. }
  62. else if ((ma >= 1.1) & (ma < 2.0)) {
  63. a0 = -3.317;
  64. a1 = 7.158;
  65. a2 = -3.583;
  66. a3 = 0.2245;
  67. ma2 = ma * ma;
  68. Cy[0] = a0 + a1 * sqrt(ma) + a2 * ma + a3 * ma2;
  69. }
  70. else {
  71. a0 = 0.7223;
  72. a1 = -0.1853;
  73. a2 = 0.03965;
  74. a3 = -0.0007835;
  75. a4 = 8.993e-06;
  76. ma2 = ma * ma;
  77. ma3 = ma2 * ma;
  78. Cy[0] = a0 + a1 * sqrt(ma) + a2 * ma + a3 * ma2 + a4 * ma3;
  79. }
  80. // 阻力拟合公式
  81. if (ma < 2.0) {
  82. a0 = 5.298;
  83. a1 = -14.51;
  84. a2 = 13.27;
  85. a3 = -3.429;
  86. a4 = 0.4542;
  87. ma2 = ma * ma;
  88. ma3 = ma2 * ma;
  89. Cx[0] = a0 + a1 * sqrt(ma) + a2 * ma + a3 * ma2 + a4 * ma3;
  90. }
  91. else if ((ma >= 2.0) & (ma < 4.0)) {
  92. a0 = 4.631;
  93. a1 = -4.847;
  94. a2 = 1.901;
  95. a3 = -0.08711;
  96. ma2 = ma * ma;
  97. Cx[0] = a0 + a1 * sqrt(ma) + a2 * ma + a3 * ma2;
  98. }
  99. else {
  100. a0 = 1.391;
  101. a1 = -0.2907;
  102. a2 = 0.09618;
  103. a3 = -0.003022;
  104. a4 = 6.594e-05;
  105. a5 = -6.096e-07;
  106. ma2 = ma * ma;
  107. ma3 = ma2 * ma;
  108. ma4 = ma3 * ma;
  109. Cx[0] = a0 + a1 * sqrt(ma) + a2 * ma + a3 * ma2 + a4 * ma3 + a5 * ma4;
  110. }
  111. }
  112. else
  113. {
  114. Cx[0] = 0;
  115. Cy[0] = 0;
  116. }
  117. }
  118. // 大气密度和马赫数
  119. void getDensityMach(double* rho, double* ma, double alt, double speed) {
  120. double rho0, R0, H, Z, W, T;
  121. rho0 = 1.225;
  122. R0 = 6356.766;
  123. H = alt / 1000;
  124. Z = R0 * H / (R0 + H);
  125. // 计算密度,温度
  126. if (H <= 11.0191) {
  127. W = (1 - Z / 44.3308);
  128. T = 288.15 * W;
  129. rho[0] = rho0 * pow(W, 4.2559);
  130. }
  131. else if (H <= 20.0631) {
  132. W = exp((14.9647 - Z) / 6.3416);
  133. T = 216.650;
  134. rho[0] = rho0 * 1.5898 * 0.1 * W;
  135. }
  136. else if (H <= 32.1619) {
  137. W = 1 + (Z - 24.9021) / 221.552;
  138. T = 221.552 * W;
  139. rho[0] = rho0 * 3.2722 * 0.01 * pow(W, -35.1629);
  140. }
  141. else if (H <= 47.3501) {
  142. W = 1 + (Z - 39.7499) / 89.4107;
  143. T = 250.350 * W;
  144. rho[0] = rho0 * 3.2618 * (1e-3) * pow(W, -13.2011);
  145. }
  146. else if (H <= 51.4125) {
  147. W = exp((48.6252 - Z) / 7.9223);
  148. T = 270.650;
  149. rho[0] = rho0 * 9.4920 * (1e-4) * W;
  150. }
  151. else if (H <= 71.8020) {
  152. W = 1 - (Z - 59.4390) / 88.2218;
  153. T = 247.021 * W;
  154. rho[0] = rho0 * 2.5280 * (1e-4) * pow(W, 11.2011);
  155. }
  156. else if (H < 86) {
  157. W = 1 - (Z - 78.0303) / 100.2950;
  158. T = 200.590 * W;
  159. rho[0] = rho0 * 1.7632 * (1e-5) * pow(W, 16.0816);
  160. }
  161. else {
  162. W = exp((87.2848 - Z) / 5.4700);
  163. T = 186.870;
  164. rho[0] = rho0 * 3.6411 * (1e-6) * W;
  165. }
  166. // 马赫数计算公式
  167. ma[0] = speed / (20.0468 * sqrt(T));
  168. }
  169. // 地球引力加速度
  170. void getGravity(double* gr, double* gw, double rad, double lat, cmscp_auxdata* auxdata) {
  171. double mu, ae, J2, J;
  172. mu = auxdata->mu;
  173. ae = 6378140;
  174. J2 = 1.08263e-3;
  175. J = 1.5 * J2;
  176. gr[0] = -mu / (rad * rad) * (1 + J * (ae * ae / (rad * rad)) * (1 - 5 * sin(lat) * sin(lat)));
  177. gw[0] = -2 * mu / (rad * rad) * J * ae * ae / (rad * rad) * sin(lat);
  178. }
  179. void dynamics0(double* dynRhs, double* path, double* state, double* control, cmscp_auxdata* auxdata) {
  180. double we, g0, lon0, lat0, B0, A0, Isp, S, rad, lon, lat, speed, fpa, azi, mass, time, thrust, attAngle, sideAngle, bankAngle, Pxh, Pyh, Pzh, alt, range, crossRange, downRange, A1, rho, ma, q, Cx, Cy, Cz, X, Y, Z, load, gr, gw, slat, clat, tlat, sfpa, cfpa, tfpa, sazi, cazi, cbank, sbank, C_V2, C_f1, C_f2, C_a1, C_a2, raddot, londot, latdot, speeddot, fpadot, azidot, massdot, timedot;
  181. demat* H2B;
  182. we = auxdata->omega;// rotational angular velocity of the Earth
  183. g0 = auxdata->g0;// mean gravitational acceleration at sea level
  184. lon0 = auxdata->launchLon;// lontitude of the launch site
  185. lat0 = auxdata->launchLat;// geocentric latitude of the launch site
  186. B0 = auxdata->launchB;// geodetic latitude of the launch site
  187. A0 = auxdata->launchA;// azimuth of the launch site
  188. Isp = auxdata->Isp;// Specific impulse of the rocket engine
  189. S = auxdata->S;// aerodynamic reference aera
  190. // state variables
  191. rad = state[0];// radial distance from Earth's center
  192. lon = state[1];// lontitude
  193. lat = state[2];// geocentric latitude
  194. speed = state[3];// earth - relative velocity
  195. fpa = state[4];// fight - path angle
  196. azi = state[5];// negative azimuth angle
  197. mass = state[6];// mass
  198. time = state[7];// time
  199. // control variables
  200. thrust = control[0];// total thrust of rocket engines
  201. attAngle = control[1];// angle of attack
  202. sideAngle = control[2]; // angle of sideship
  203. bankAngle = control[3]; // angle of bank
  204. // some auxillary variables
  205. // computing the thrust vector
  206. if (fabs(thrust) < 1)
  207. {
  208. Pxh = 0.0;
  209. Pyh = 0.0;
  210. Pzh = 0.0;
  211. }
  212. else
  213. {
  214. H2B = createDeMat(3, 3);
  215. C_H2B(H2B, bankAngle, sideAngle, attAngle); // direction cosine matrix from half-velocity to body frame
  216. Pxh = H2B->v[0] * thrust;
  217. Pyh = H2B->v[1] * thrust;
  218. Pzh = H2B->v[2] * thrust;
  219. freeDeMat(H2B, 2);// 释放空间
  220. }
  221. // computing the altitude
  222. alt = getAltitude(lat, rad);
  223. // computing the range, crossrange, and downrange
  224. range = acos(sin(B0) * sin(lat) + cos(B0) * cos(lat) * cos(lon - lon0));
  225. A1 = acos((sin(lat) - sin(B0) * cos(range)) / (cos(B0) * sin(range)));
  226. crossRange = asin(sin(range) * sin(A0 - A1));
  227. downRange = acos(cos(range) / cos(crossRange));
  228. // aerodynamic forces in velocity coordinate frame(速度坐标系中的分解)
  229. getDensityMach(&rho, &ma, alt, speed); // air density
  230. q = 0.5 * rho * speed * speed;// dynamic press
  231. getCxCyCz(&Cx, &Cy, &Cz, ma, alt);
  232. X = Cx * q * S; // aerodynamic drag force
  233. Y = Cy * q * S; // aerodynamic lift force
  234. Z = Cz * q * S; // aerodynamic Lateral force
  235. // normal load
  236. load = sqrt(Y * Y + X * X + Z * Z) / (mass * g0);
  237. // The decomposition of gravity in the radial direction of the center of
  238. // the earthand the angular velocity of the earth's rotation
  239. getGravity(&gr, &gw, rad, lat, auxdata);
  240. // abbreviations
  241. slat = sin(lat);
  242. clat = cos(lat);
  243. tlat = tan(lat);
  244. sfpa = sin(fpa);
  245. cfpa = cos(fpa);
  246. tfpa = tan(fpa);
  247. sazi = sin(azi);
  248. cazi = cos(azi);
  249. cbank = cos(bankAngle);
  250. sbank = sin(bankAngle);
  251. // terms related to tthe rotation of the earth
  252. C_V2 = -(we * we) * rad * clat * (slat * cazi * cfpa - clat * sfpa);
  253. C_f1 = -2 * we * clat * sazi;
  254. C_f2 = (we * we) * rad / speed * clat * (slat * cazi * sfpa + clat * cfpa);
  255. C_a1 = 2 * we * (clat * cazi * tfpa - slat);
  256. C_a2 = (we * we) * rad * clat * slat * sazi / (speed * cfpa);
  257. // Right-hand side (RHS) of dynamic equations
  258. raddot = speed * sfpa;
  259. londot = -speed * cfpa * sazi / (rad * clat);
  260. latdot = speed * cfpa * cazi / rad;
  261. speeddot = Pxh / mass - X / mass + gr * sfpa + gw * (cazi * cfpa * clat + sfpa * slat) + C_V2;
  262. fpadot = Pyh / (mass * speed) + (Y * cbank - Z * sbank) / (mass * speed) + gr * cfpa / speed + gw / speed * (slat * cfpa - clat * cazi * sfpa) + speed * cfpa / rad + C_f1 + C_f2;
  263. azidot = -Pzh / (mass * speed * cfpa) - (Z * cbank + Y * sbank) / (mass * speed * cfpa)
  264. - gw * clat * sazi / (speed * cfpa) + speed / rad * tlat * cfpa * sazi + C_a1 + C_a2;
  265. massdot = -thrust / (Isp * g0);
  266. timedot = 1.0;
  267. // output
  268. dynRhs[0] = raddot;
  269. dynRhs[1] = londot;
  270. dynRhs[2] = latdot;
  271. dynRhs[3] = speeddot;
  272. dynRhs[4] = fpadot;
  273. dynRhs[5] = azidot;
  274. dynRhs[6] = massdot;
  275. dynRhs[7] = timedot;
  276. path[0] = alt;
  277. path[1] = q;
  278. path[2] = load;
  279. path[3] = downRange;
  280. path[4] = crossRange;
  281. }
  282. double denseSum(double* vecIn, int length) {
  283. int i;
  284. double vecOut = 0;
  285. for ( i = 0; i < length; i++)
  286. {
  287. vecOut = vecOut + vecIn[i];
  288. }
  289. return vecOut;
  290. }