Based on the original Rocket Workbench on SourceForge in CVS at: https://sourceforge.net/projects/rocketworkbench
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

532 lines
13 KiB

  1. #include <stdlib.h>
  2. #include <string.h>
  3. #include <math.h>
  4. #include "gpcp.h"
  5. #include "libcompat/include/getopt.h"
  6. #include "profiler.h"
  7. #define M_PI2 9.869604401
  8. Options rocket_options[] = {
  9. {"global", PARENT, NULL},
  10. {"length_units", STRING, "global"},
  11. {"mass_units", STRING, "global"},
  12. {"rocket", PARENT, NULL},
  13. {"name", STRING, "rocket"},
  14. {"cg", FLOAT, "rocket"},
  15. {"body", PARENT, "rocket"},
  16. {"type", STRING, "body"},
  17. {"length", FLOAT, "body"},
  18. {"diameter", FLOAT, "body"},
  19. {"density", FLOAT, "body"},
  20. {"mass", FLOAT, "body"},
  21. {"fin", PARENT, "rocket"},
  22. {"num", INTEGER, "fin"},
  23. {"pos", FLOAT, "fin"},
  24. {"root_chord", FLOAT, "fin"},
  25. {"tip_chord", FLOAT, "fin"},
  26. {"root_tip_d", FLOAT, "fin"},
  27. {"semispan", FLOAT, "fin"},
  28. {"body_radius", FLOAT, "fin"},
  29. {"mass", FLOAT, "fin"},
  30. {"motor", PARENT, "rocket"},
  31. {"zpos", FLOAT, "motor"},
  32. {"rpos", FLOAT, "motor"},
  33. {"diameter", FLOAT, "motor"},
  34. {"length", FLOAT, "motor"},
  35. {"empty_mass", FLOAT, "motor"},
  36. {"full_mass", FLOAT, "motor"},
  37. {"tank", PARENT, "rocket"},
  38. {"zpos", FLOAT, "tank"},
  39. {"rpos", FLOAT, "tank"},
  40. {"diameter", FLOAT, "tank"},
  41. {"length", FLOAT, "tank"},
  42. {"empty_mass", FLOAT, "tank"},
  43. {"full_mass", FLOAT, "tank"},
  44. {"other", PARENT, "rocket"},
  45. {"shape", STRING, "other"},
  46. {"zpos", FLOAT, "other"},
  47. {"rpos", FLOAT, "other"},
  48. {"Ix", FLOAT, "other"},
  49. {"Iy", FLOAT, "other"},
  50. {"mass", FLOAT, "other"},
  51. {NULL, 0, NULL}
  52. };
  53. int read_value(Data *d, rocket_t *r);
  54. int profile_rocket(rocket_t *r);
  55. int profile_fins(rocket_t *r);
  56. int profile_body(rocket_t *r);
  57. void usage(void);
  58. int main(int argc, char *argv[])
  59. {
  60. int c;
  61. Data *data;
  62. rocket_t rocket;
  63. char filename[FILENAME_MAX] = "";
  64. rocket.body.n_body_parts = 0;
  65. rocket.body.body_parts = NULL;
  66. rocket.n_fin_set = 0;
  67. rocket.fin_set = NULL;
  68. rocket.Lr = 0;
  69. rocket.Ar = 0;
  70. while (1)
  71. {
  72. c = getopt(argc, argv, "f:");
  73. if (c == EOF)
  74. break;
  75. switch (c)
  76. {
  77. case 'f':
  78. if (strlen(optarg) > FILENAME_MAX)
  79. {
  80. printf("Filename too long!\n");
  81. return -1;
  82. break;
  83. }
  84. strncpy (filename, optarg, FILENAME_MAX);
  85. break;
  86. case 'h':
  87. usage();
  88. break;
  89. }
  90. }
  91. if (strcmp(filename, "") == 0)
  92. {
  93. printf("A rocket description file must be provide.\n");
  94. usage();
  95. return -1;
  96. }
  97. GPCP_RegisterOptions(rocket_options);
  98. if (GPCP_ReadFile(filename, &data))
  99. {
  100. printf("Error parsing configuration file.\n");
  101. return -1;
  102. }
  103. read_value(data, &rocket);
  104. /* GPCP_PrintData(data); */
  105. GPCP_FreeData(&data);
  106. profile_rocket(&rocket);
  107. free (rocket.fin_set);
  108. free (rocket.body.body_parts);
  109. return 0;
  110. };
  111. void usage(void)
  112. {
  113. printf("Usage:");
  114. printf("\n\tprofiler -f infile");
  115. printf("\n\nArguments:\n");
  116. printf("-f file \t Perform an analysis of the specified rocket.\n");
  117. printf("-h \t Print usage.\n");
  118. }
  119. int profile_rocket(rocket_t *r)
  120. {
  121. int i, n;
  122. fin_t *f;
  123. r->m = 0;
  124. /* reference area of the rocket */
  125. r->Ar = M_PI * pow(r->Lr, 2)/4;
  126. r->n_mach = 20;
  127. r->mach = (double *) malloc(sizeof(double) * r->n_mach);
  128. /* fill the table of the mach number */
  129. for (i = 0; i < r->n_mach; i++)
  130. {
  131. r->mach[i] = (1.0/r->n_mach) * i;
  132. }
  133. profile_fins(r);
  134. profile_body(r);
  135. /* tables in function of the mach number */
  136. r->X = (double *) malloc(sizeof(double) * r->n_mach);
  137. r->C_N_alpha = (double *) malloc(sizeof(double) * r->n_mach);
  138. r->C_mq = (double *) malloc(sizeof(double) * r->n_mach);
  139. r->C_m_alpha = (double *) malloc(sizeof(double) * r->n_mach);
  140. for (i = 0; i < r->n_mach; i++)
  141. {
  142. r->C_N_alpha[i] = r->body.C_N_alpha_b;
  143. /* formula 3-106 */
  144. for (n = 0; n < r->n_fin_set; n++)
  145. {
  146. f = r->fin_set + n;
  147. r->C_N_alpha[i] += f->C_N_alpha_tb_m * f->C_N_alpha_1[i];
  148. r->C_N_alpha[i] += f->C_N_alpha_bt_m * f->C_N_alpha_1[i];
  149. }
  150. /* rocket center of pressure location */
  151. r->X[i] = r->body.Xb * r->body.C_N_alpha_b;
  152. /* formula 3-107 */
  153. for (n = 0; n < r->n_fin_set; n++)
  154. {
  155. f = r->fin_set + n;
  156. r->X[i] += f->Xt * f->C_N_alpha_tb_m * f->C_N_alpha_1[i];
  157. r->X[i] += f->Xbt * f->C_N_alpha_bt_m * f->C_N_alpha_1[i];
  158. }
  159. r->X[i] = r->X[i] / r->C_N_alpha[i];
  160. /* formula 3-115 CHECKME, formula was badly print,
  161. i redevelop it myself */
  162. r->C_mq[i] = 0;
  163. for (n = 0; n < r->n_fin_set; n++)
  164. {
  165. f = r->fin_set + n;
  166. r->C_mq[i] += 2 * f->C_N_alpha_tb_m * f->C_N_alpha_1[i] *
  167. pow((f->Xt - r->Xcg)/r->Lr, 2);
  168. }
  169. r->C_m_alpha[i] = 0;
  170. for (n = 0; n < r->n_fin_set; n++)
  171. {
  172. f = r->fin_set + n;
  173. r->C_m_alpha[i] += f->C_N_alpha_tb_m * f->C_N_alpha_1[i] *
  174. (r->X[i] - r->Xcg) / r->Lr;
  175. }
  176. /*
  177. printf("Aerodynamic properties of the entire rocket.\n"
  178. "--------------------------------------------\n");
  179. printf("Reference area (Ar) = % f m2\n", r->Ar);
  180. printf("C_N_alpha = % f\n", r->C_N_alpha);
  181. printf("X = % f\n", r->X);
  182. printf("Cmq = % f\n", r->C_mq);
  183. */
  184. }
  185. for (i = 0; i < r->n_mach; i++)
  186. {
  187. printf("M = %.2f -> C_N_alpha = %.3f, Cmq = %.3f, Cm_alpha = %.3f,"
  188. " X = %.2f\n",
  189. r->mach[i], r->C_N_alpha[i], r->C_mq[i], r->C_m_alpha[i], r->X[i]);
  190. }
  191. return 0;
  192. }
  193. int profile_fins(rocket_t *r)
  194. {
  195. int i, n;
  196. float cr, ct, rt, lt, xt, s;
  197. float beta;
  198. float lambda;
  199. float sac; /* midchord sweep angle cosine */
  200. float tau; /* (s + rt)/rt */
  201. float tau2; /* tau^2 */
  202. float tau3;
  203. fin_t *f;
  204. /* fin treatment */
  205. for (n = 0; n < r->n_fin_set; n++)
  206. {
  207. f = r->fin_set + n;
  208. f->C_N_alpha_1 = (double *) malloc(sizeof(double) * r->n_mach);
  209. cr = f->cr;
  210. ct = f->ct;
  211. rt = f->rt;
  212. lt = f->lt;
  213. xt = f->xt;
  214. s = f->s;
  215. /* add fin mass to the rocket mass */
  216. r->m += f->N * f->m;
  217. /* inertial properties */
  218. f->Xcg = 0;
  219. f->Ixx = 0;
  220. f->Iyy = 0;
  221. /* center of pressure of the fins */
  222. /* formula 3-27 */
  223. f->Yt = rt + (s/3)*(cr + 2*ct)/(cr + ct);
  224. /* formula 3-30 */
  225. f->Xt = lt + (xt/3)*(cr + 2*ct)/(cr + ct) +
  226. (cr + ct - cr*ct/(cr+ct))/6;
  227. /* formula 3-101 */
  228. f->Xbt = lt + cr/4 +
  229. ((sqrt(s*s - rt*rt)*acosh(s/rt) - s + M_PI*rt/2)/
  230. (rt*acosh(s/rt)/sqrt(s*s - rt*rt) + s/rt - M_PI/2) - rt) *
  231. (xt + 0.25*(ct-cr))/s; /* check this part (tan(sweepback)) */
  232. /* fin area */
  233. f->Af = cr*s - xt*s/2 + (xt + ct - cr)*s/2;
  234. /* fin aspect ratio */
  235. f->AR = pow(s,2)/f->Af;
  236. /* cosine of the midchord sweep angle */
  237. sac = s/sqrt(pow(xt + ct - cr/2 - ct/2, 2) + pow(s, 2));
  238. for (i = 0; i < r->n_mach; i++)
  239. {
  240. /* M is the mach number */
  241. beta = sqrt(1 - pow(r->mach[i], 2));
  242. /* formula 3-6 */
  243. f->C_N_alpha_1[i] = 2 * M_PI * f->AR *
  244. (f->Af/r->Ar) / (2 + sqrt(4 + pow(beta*f->AR/sac, 2) ));
  245. }
  246. /* formula 3-35 */
  247. f->C_l_delta_m = f->N * f->Yt / r->Lr; /* *f->C_N_alpha_1 */
  248. lambda = ct / cr;
  249. /* formula 3-51 */
  250. f->C_l_p_m = -(f->N * cr * s / (6*pow(r->Lr, 2)))*
  251. ((1+3*lambda)*pow(s, 2) + 4*(1+2*lambda)*s*rt + 6*(1+lambda)*pow(rt, 2));
  252. /* * f->C_N_alpha_1;*/
  253. tau = (s + rt)/rt;
  254. tau2 = pow(tau, 2);
  255. tau3 = pow(tau, 3);
  256. /* formula 3-96 */
  257. f->Ktb_alpha = 2*((1 + pow(tau, -4))*(0.5*atan(0.5*(tau-1/tau))) -
  258. pow(tau, -2)*((tau-1/tau) + 2*atan(1/tau)))/
  259. (M_PI * pow(1-1/tau, 2));
  260. /*formula 3-98 */
  261. f->Kbt = pow((1 - 1/tau2)/(1 - 1/tau), 2) - f->Ktb_alpha;
  262. /* formula 3-105 */
  263. /* CHECK THIS : when optimize with -O2 or -O3 in gcc, the value is nan
  264. but is good with -O ???? */
  265. f->Ktb_delta =
  266. (M_PI2 * pow(1+1/tau, 2)/4 +
  267. M_PI * pow( (tau2 + 1)/(tau2-tau), 2)*asin((tau2-1)/(tau2+1)) -
  268. 2*M_PI*(tau+1)/(tau2 - tau) +
  269. pow((tau2+1)/(tau2-tau), 2)*pow(asin((tau2-1)/(tau2+1)), 2) -
  270. 4*(tau+1)*asin((tau2-1)/(tau2+1))/(tau2-tau) +
  271. 8*log((tau2+1)/(2*tau))/pow(tau-1,2))/M_PI2;
  272. /* formula 3-122 */
  273. f->Krb = 1 + ((tau-lambda)/tau - (1-lambda)*log(tau)/(tau-1))/
  274. ((tau+1)*(tau-lambda)/2 - (1-lambda)*(tau3-1)/(3*(tau-1)));
  275. f->C_N_alpha_tb_m = f->N * f->Ktb_alpha / 2; /* * f->C_N_alpha_1 */
  276. f->C_N_alpha_bt_m = f->N * f->Kbt / 2; /* * f->C_N_alpha_1 */
  277. f->C_l_delta_tb_m = f->C_l_delta_m * f->Ktb_delta;
  278. f->C_l_p_tb_m = f->C_l_p_m * f->Krb;
  279. printf("Aerodynamic properties of the fin set number %d\n"
  280. "-----------------------------------------------\n", n+1);
  281. printf("Fin area (Af) = % f m2\n", f->Af);
  282. printf("Aspect ratio (AR) = % f\n", f->AR);
  283. printf("\n");
  284. printf("Interference factors.\n");
  285. printf("Ktb_alpha = % f\n", f->Ktb_alpha);
  286. printf("Kbt = % f\n", f->Kbt);
  287. printf("Ktb_delta = % f\n", f->Ktb_delta);
  288. printf("Krb = % f\n", f->Krb);
  289. printf("\n");
  290. printf("Fin center of pressure location.\n");
  291. printf("Yt = % .3f m\n", f->Yt);
  292. printf("Xt = % .3f m\n", f->Xt);
  293. printf("Xbt = % .3f m\n", f->Xbt);
  294. printf("\n");
  295. printf("Fin stability coefficients.\n");
  296. for (i = 0; i < r->n_mach; i++)
  297. {
  298. printf("M = % .2f -> C_N_alpha_1 = % .4f\n",
  299. r->mach[i], f->C_N_alpha_1[i]);
  300. }
  301. printf("C_l_delta_m = % f\n", f->C_l_delta_m);
  302. printf("C_l_p_m = % f\n", f->C_l_p_m);
  303. printf("\n");
  304. printf("Fin stability coefficients with interference factors.\n");
  305. printf("C_N_alpha_tb_m = % f\n", f->C_N_alpha_tb_m);
  306. printf("C_N_alpha_bt_m = % f\n", f->C_N_alpha_bt_m);
  307. printf("C_N_delta_tb_m = % f\n", f->C_l_delta_tb_m);
  308. printf("C_l_p_tb_m = % f\n", f->C_l_p_tb_m);
  309. }
  310. return 0;
  311. }
  312. int profile_body(rocket_t *r)
  313. {
  314. int i, n;
  315. float fn;
  316. float dp; /* diameter of the previous part */
  317. body_part_t *previous_part = NULL;
  318. body_part_t *part = NULL;
  319. /* body parts treatment */
  320. for (n = 0; n < r->body.n_body_parts; n++)
  321. {
  322. part = r->body.body_parts + n;
  323. if (n != 0)
  324. previous_part = r->body.body_parts + n - 1;
  325. r->m += part->m;
  326. switch (part->type)
  327. {
  328. case OGIVE_NOSE:
  329. fn = part->l / part->d;
  330. part->A = 0;
  331. part->V = 0;
  332. part->Xof = 0;
  333. part->Xcg = 0.466 * part->l;
  334. part->Ix = 0;
  335. part->Iy = 0;
  336. break;
  337. case ELLIPTIC_NOSE:
  338. break;
  339. case CONIC_NOSE:
  340. part->A = M_PI * part->d *
  341. sqrt(pow(part->d/2, 2) + pow(part->l, 2)) / 2;
  342. part->V = M_PI * pow(part->d/2, 2) * part->l / 3;
  343. part->Xof = 0;
  344. part->Xcg = 2 * part->l / 3;
  345. part->Ix = part->m * pow(part->d, 2) / 8;
  346. /* moment of inertia about the axis passing at the tip of the cone */
  347. part->Iy = part->m * (pow(part->d, 2)/16 + pow(part->l, 2)/2);
  348. break;
  349. case PARABOLIC_NOSE:
  350. break;
  351. case TUBE:
  352. part->A = M_PI * part->d * part->l;
  353. part->V = M_PI * pow(part->d, 2) * part->l / 4;
  354. if (previous_part == NULL)
  355. return -1;
  356. part->Xof = previous_part->Xof + previous_part->l;
  357. part->Xcg = part->Xof + part->l / 2;
  358. part->Ix = part->m * pow(part->d, 2) / 4;
  359. part->Iy = part->m * (pow(part->d, 2)/8 + pow(part->l, 2)/12);
  360. break;
  361. case TRANSITION:
  362. dp = r->body.body_parts[n - 1].d;
  363. part->A = M_PI*(part->d*sqrt(pow(part->d/2, 2) +
  364. pow(part->l/(1 - part->d/dp), 2))/2 -
  365. dp*sqrt(pow(dp/2, 2) +
  366. pow(part->l*part->d/(dp*(1-part->d/dp)), 2))/2);
  367. part->V = M_PI * part->l *
  368. (pow(part->d/2, 2) - pow(dp/2, 2)*dp/part->d)/(3*(1 - dp/part->d));
  369. /*part->Ix = ;*/
  370. break;
  371. default:
  372. printf("Unknown type : %d\n", part->type);
  373. break;
  374. }
  375. }
  376. r->body.V = 0;
  377. r->body.lo = 0;
  378. r->body.Ab = 0;
  379. for (i = 0; i < r->body.n_body_parts; i++)
  380. {
  381. part = r->body.body_parts + i;
  382. r->body.V += part->V;
  383. r->body.lo += part->l;
  384. /* compute it only for the last part */
  385. r->body.Ab = M_PI * pow(part->d, 2) / 4;
  386. printf("Part geometric characteristics.\n");
  387. printf("Volume = %e m3\n", part->V);
  388. printf("Area = %e m2\n", part->A);
  389. printf("Mass = %e kg\n", part->m);
  390. printf("Ixx = %e kg-m2\n", part->Ix);
  391. printf("Iyy = %e kg-m2\n", part->Iy);
  392. printf("Xof = %e m\n", part->Xof);
  393. printf("Xcg = %e m\n", part->Xcg);
  394. }
  395. /* formula 3-66 */
  396. r->body.C_N_alpha_b = 2 * r->body.Ab / r->Ar;
  397. r->body.Xb = r->body.lo - r->body.V/r->body.Ab;
  398. printf("\n");
  399. printf("Aerodynamic properties of the body.\n"
  400. "-----------------------------------\n");
  401. printf("Ab = % f\n", r->body.Ab);
  402. printf("lo = % f\n", r->body.lo);
  403. printf("C_N_alpha_b = % f\n", r->body.C_N_alpha_b);
  404. printf("Xb = % f\n", r->body.Xb);
  405. return 0;
  406. }