void acc_update( void ) { volatile avr32_adc_t *adc = &AVR32_ADC; // start + get from adc acc_get_value(adc, &acc.m) ; // ak = acceleration = m - k xyz_diff( acc.m , acc.k, &acc.ak ) ; acc.ak2 = xyz_sumsq( acc.ak ) ; if ( is_acc_slow() ) { // update g for next move acc.g.x = acc.m.x ; acc.g.y = acc.m.y ; acc.g.z = acc.m.z ; } else { xyz_diff( acc.m , acc.g, &acc.ag ) ; xyz_round0( acc.ag , 16, &acc.ag ) ; xyz_add( acc.s , acc.ag, &acc.s ) ; //xyz_round0( acc.s , 256, &acc.s ) ; //print_dbg("m = "); print_xyz( acc.m ) ; //print_dbg("k = "); print_xyz( acc.k ) ; //print_dbg("g = "); print_xyz( acc.g ) ; //print_dbg("ag = "); print_xyz( acc.ag ) ; //print_dbg("s = "); print_xyz( acc.s ) ; //print_dbg("\r\n"); ////acc.s2 = xyz_sumsq( acc.s ) ; //print_dbg("s2 = 0x"); print_dbg_hex(acc.s2); print_dbg("\r\n"); } }
// return norm(a - b) double xyz_distance( const xyz_t * const a, const xyz_t * const b ) { xyz_t diff; xyz_diff( &diff, a, b); return xyz_norm( &diff ); }
int project_o_tron(aero_table_output_t * out, aero_model_t * model, quat_t ref_to_body, int w, int h, int *pix_buf_panel) { int n = model->n_panels; // *** Input parameters xyz_t UU e_v_ref = { 1, 0, 0 }; // velocity unit vector in ref frame // todo: check that is normalized double res = 0.001 / MEGARES; // Resolution double sig_n = 0.8; // normal momentum exchange coeff double sig_t = 0.8; // tangential momentum exchange coeff // *** Let's choose a new "freestream" frame so that the velocity vector is just +X quat_t body_to_fs; xyz_t e_v_fs = { 1, 0, 0 }; // Don't need to rotate at all, the frames are already aligned // Now form the quaternion rotating the body frame to the freestream frame quat_inv(&body_to_fs, &ref_to_body); // *** Rotate "everything" into the new frame // // Rotate the center of mass xyz_t cg_fs; rot_vec_by_quat_a2b(&cg_fs, &body_to_fs, &model->cg); // Rotate the panels' coordinates panel_t panels_fs[model->n_panels]; for (int i = 0; i < n; i++) { rot_vec_by_quat_a2b(&panels_fs[i].origin, &body_to_fs, &model->panels[i].origin); rot_vec_by_quat_a2b(&panels_fs[i].side_a, &body_to_fs, &model->panels[i].side_a); rot_vec_by_quat_a2b(&panels_fs[i].side_b, &body_to_fs, &model->panels[i].side_b); } // Find the centroids xyz_t centroid_fs[n]; for (int i = 0; i < n; i++) { centroid_fs[i] = panels_fs[i].origin; // This handy function does (a <= a*A + b*B + c*C) xyz_sum_scale(¢roid_fs[i], 1, &panels_fs[i].side_a, 0.5, &panels_fs[i].side_b, 0.5); } // Sort by the X coordinate of the centroids struct indirect_element sort_list[n]; for (int i = 0; i < n; i++) { sort_list[i].index = i; sort_list[i].val = centroid_fs[i].x; } qsort(sort_list, n, sizeof(sort_list[0]), compare_indirect_elements); double *pix_buf_x = malloc(w * h * sizeof(double)); // Holds the fs frame X coordinate // of the panel element at each pixel if (!pix_buf_x) { fprintf(stderr, "Unable to allocate %zu bytes for pix_buf_x\n", w * h * sizeof(double)); return 1; } // Iterate over the panels, rearmost centroid first for (int i = 0; i < n; i++) { // if(sort_list[i].index==0){ panel_t *p = &panels_fs[sort_list[i].index]; //printf("Panel %d:::\n",sort_list[i].index); double res_a = res / xyz_norm(&p->side_a) / sqrt(2); double res_b = res / xyz_norm(&p->side_b) / sqrt(2); // Iterate over side a for (double a = 0; a <= 1; a += res_a) { // Iterate over side b for (double b = 0; b <= 1; b += res_b) { xyz_t panel_cell = p->origin; xyz_sum_scale(&panel_cell, 1, &p->side_a, a, &p->side_b, b); int pix_y = (int)round(panel_cell.y / res + w / 2); int pix_z = (int)round(panel_cell.z / res + h / 2); pix_buf_panel[pix_z + pix_y * w] = sort_list[i].index + 1; pix_buf_x[pix_z + pix_y * w] = panel_cell.x; // printf("\t%+7.4f\t%+7.4f\t%d\t%d\n",panel_cell.y,panel_cell.z,pix_y,pix_z); } } } // Find the unit normal vector in fs frame, and e_v.e_n for all panels xyz_t e_n_fs[n]; double e_v_dot_e_n[n]; for (int p = 0; p < n; p++) { xyz_cross(&e_n_fs[p], &panels_fs[p].side_a, &panels_fs[p].side_b); xyz_normalize_self(&e_n_fs[p]); e_v_dot_e_n[p] = xyz_dot(&e_n_fs[p], &e_v_fs); // if (e_v_dot_e_n[p] < 0) // printf("e_v dot e_n negative for panel %d\n",p); } // double A = 0; int n_pix[n]; memset(n_pix, 0, sizeof(n_pix)); xyz_t panel_sum_pos[n]; memset(panel_sum_pos, 0, sizeof(panel_sum_pos)); //printf("sizeof(n_pix)=%zu\n",sizeof(n_pix)); xyz_t F_fs = {0, 0, 0}; xyz_t T_fs = {0, 0, 0}; // Now iterate over the pixels for (int pix_y = 0; pix_y < w; pix_y++) for (int pix_z = 0; pix_z < h; pix_z++) { int p = pix_buf_panel[pix_z + pix_y * w]; if (p) { // There is a panel at this pixel. p--; // Actual panel index number is one less if (e_v_dot_e_n[p] < 0) { // Skip panels facing the wrong way continue; } n_pix[p]++; // Find the coordinates in the fs frame xyz_t fs_p; fs_p.x = pix_buf_x[pix_z * w + pix_y]; fs_p.y = (pix_y - w / 2) * res; fs_p.z = (pix_z - h / 2) * res; // Where is it wrt the center of mass? xyz_t r_from_cg_fs; xyz_diff(&r_from_cg_fs, &fs_p, &cg_fs); // Let's compute the forces on this element // ref: NASA SP-8058 eq 2-2 (page 5). // Dynamic pressure (1/2 rho v^2) factored out, hence leading 2 * xyz_t dF = { 0, 0, 0 }; xyz_sum_scale(&dF, 0, &e_n_fs[p], 2 * -1 * res * res * (2 - sig_n - sig_t) * xyz_dot(&e_v_fs, &e_n_fs[p]), &e_v_fs, 2 * -1 * res * res * sig_t); // Torque contribution from this element xyz_t dT; xyz_cross(&dT, &r_from_cg_fs, &dF); xyz_sum(&F_fs, &F_fs, &dF); xyz_sum(&T_fs, &T_fs, &dT); } } rot_vec_by_quat_b2a(&out->force, &body_to_fs, &F_fs); rot_vec_by_quat_b2a(&out->torque, &body_to_fs, &T_fs); printf("F = %f %f %f (norm=%f)\n",out->force.x, out->force.y, out->force.z, xyz_norm(&out->force)); printf("T = %f %f %f (norm=%f)\n",out->torque.x, out->torque.y, out->torque.z, xyz_norm(&out->torque)); // printf("%d pixels dropped due to e_v dot e_n negative\n",n_pix); free(pix_buf_x); return 0; }