void duqumul() { double q0[4], q1[4]; double v0[3], v1[3]; double d0[8], d1[8]; double ra[8], rb[8]; aa_vrand( 4, q0 ); aa_vrand( 4, q1 ); aa_tf_qnormalize(q0); aa_tf_qnormalize(q1); aa_vrand( 3, v0 ); aa_vrand( 3, v1 ); aa_tf_qv2duqu( q0, v0, d0 ); aa_tf_qv2duqu( q1, v1, d1 ); aa_tf_duqu_mul(q0,q1,ra); aa_vecm_duqu_mul(q0,q1,rb); aveq( "duqu_mul-equal", 8, ra, rb, .0001 ); aa_tick("duqu-mul non-vec: "); for( size_t i = 0; i < N; i ++ ) { aa_tf_duqu_mul(d0,d1,ra); } aa_tock(); aa_tick("duqu-mul vec: "); for( size_t i = 0; i < N; i ++ ) { aa_vecm_duqu_mul(q0,q1,rb); } aa_tock(); }
void rel_d() { // random transforms double q0[4], v0[3], q1[4], v1[4]; aa_vrand(4,q0); aa_vrand(4,q1); aa_tf_qnormalize(q0); aa_tf_qnormalize(q1); aa_vrand(3,v0); aa_vrand(3,v1); // dual quat transforms double d0[8], drel[8], d1[8], d1p[8]; aa_tf_qv2duqu(q0,v0, d0); aa_tf_qv2duqu(q1,v1, d1); // d0 * drel = d1 // drel = conj(d0) * d1 aa_tf_duqu_cmul( d0, d1, drel ); aa_tf_duqu_mul( d0, drel, d1p ); aveq("duqu-relmul", 8, d1, d1p, .001 ); // random velocity double dx0[6], dd0[8]; aa_vrand(6,dx0); aa_tf_duqu_vel2diff(d0, dx0, dd0); // second velocity // d1 = d0*drel // d1/dt = d0/dt * drel + d0 * drel/dt, and drel/dt = 0 double dd1[8]; aa_tf_duqu_mul( dd0, drel, dd1 ); // integrate double d0_1[8], d1_1[8]; double dt = .1; aa_tf_duqu_sdiff( d0, dd0, dt, d0_1 ); aa_tf_duqu_sdiff( d1, dd1, dt, d1_1 ); aa_tf_duqu_normalize( d0_1 ); aa_tf_duqu_normalize( d1_1 ); // new relative double drel_1[8]; // drel = d0*inv(d1) aa_tf_duqu_cmul( d0_1, d1_1, drel_1 ); // twist double d0_1t[8], d1_1t[8], drel_1t[8]; aa_tf_duqu_svel( d0, dx0, dt, d0_1t ); aa_tf_duqu_sdiff( d1, dd1, dt, d1_1t ); aa_tf_duqu_cmul( d0_1t, d1_1t, drel_1t ); // check aveq("rel_d", 8, drel, drel_1t, 1e-6); }
void tf_conj(double E[2][7], double S[2][8] ) { double S2[8], SE[7], E2[8]; aa_tf_duqu_conj(S[0], S2); aa_tf_qutr_conj(E[0], E2); aa_tf_duqu2qutr(S2, SE); aveq( "duqu/qutr conj", 7, E2, SE, 1e-7 ); aa_tf_duqu_mul(S[0], S[1], S2); aa_tf_qutr_mul(E[0], E[1], E2); aa_tf_duqu2qutr(S2, SE); aveq( "duqu/qutr mul", 7, E2, SE, 1e-7 ); aa_tf_duqu_mulc(S[0], S[1], S2); aa_tf_qutr_mulc(E[0], E[1], E2); aa_tf_duqu2qutr(S2, SE); aveq( "duqu/qutr mulc", 7, E2, SE, 1e-7 ); aa_tf_duqu_cmul(S[0], S[1], S2); aa_tf_qutr_cmul(E[0], E[1], E2); aa_tf_duqu2qutr(S2, SE); aveq( "duqu/qutr cmul", 7, E2, SE, 1e-7 ); }
static void chain(double E[2][7], double S[2][8], double T[2][12] ) { double E3[7]; // rotation { double q3[4]={0}; double R3[9]={0}; double qc[4]={0}; aa_tf_qmul( E[0], E[1], q3 ); aa_tf_9mul( T[0], T[1], R3 ); aa_tf_rotmat2quat( R3, qc ); aa_tf_qminimize( q3 ); aa_tf_qminimize( qc ); aveq("chain-rot q/9", 4, q3, qc, 1e-6 ); } // Transformation aa_tf_qutr_mul( E[0], E[1], E3 ); aa_tf_qminimize( E3 ); // duqu { double S3[8]={0}, Ec[7]={0}; aa_tf_duqu_mul( S[0], S[1], S3 ); aa_tf_duqu2qutr( S3, Ec ); aa_tf_qminimize( Ec ); aveq("chain-tf qutr/duqu", 7, E3, Ec, 1e-6 ); } // qutr_norm { double N3[7]={0}; aa_tf_qutr_mulnorm(E[0], E[1], N3); aa_tf_qminimize( N3 ); aveq("chain-tf qutr/qutrnorm", 7, E3, N3, 1e-6 ); } // tfmat { double T3[12]={0}, Ec[7]={0}; aa_tf_12chain( T[0], T[1], T3 ); aa_tf_tfmat2qutr( T3, Ec ); aa_tf_qminimize( Ec ); aveq("chain-tf qutr/tfmat", 7, E3, Ec, 1e-6 ); } }
static void duqu() { // random tf aa_tf_tfmat_t T; aa_tf_duqu_t H; double E[7]; double S_ident[8] = AA_TF_DUQU_IDENT_INITIALIZER; double Q_ident[4] = AA_TF_QUAT_IDENT_INITIALIZER; double v_ident[3] = {0}; double p0[3]; rand_tf( E, H.data, T.data ); aa_vrand( 3, p0 ); { double A[8], B[8]; aa_vrand(8,A); aa_vrand(8,B); // mul { double A_L[8*8], B_R[8*8]; double C[8], Cl[8], Cr[8]; aa_tf_duqu_mul(A,B,C); aa_tf_duqu_matrix_l(A, A_L, 8); cblas_dgemv( CblasColMajor, CblasNoTrans, 8, 8, 1.0, A_L, 8, B, 1, 0, Cl, 1 ); aveq( "duqu-mul-L", 8, C, Cl, 1e-6 ); aa_tf_duqu_matrix_r(B, B_R, 8); cblas_dgemv( CblasColMajor, CblasNoTrans, 8, 8, 1.0, B_R, 8, A, 1, 0, Cr, 1 ); aveq( "duqu-mul-R", 8, C, Cr, 1e-6 ); } // add / sub { double Ca[8], Cs[8], mB[8]; for( size_t i = 0; i < 8; i ++ ) mB[i] = -B[i]; aa_tf_duqu_add(A,B,Ca); aa_tf_duqu_sub(A,mB,Cs); aveq( "duqu-add-sub", 8, Ca, Cs, 1e-6 ); double Cra[4], Crs[4]; double Cda[4], Cds[4]; aa_tf_duqu_sub(A,B,Cs); aa_tf_qadd(A+AA_TF_DUQU_REAL, B+AA_TF_DUQU_REAL,Cra); aa_tf_qadd(A+AA_TF_DUQU_DUAL, B+AA_TF_DUQU_DUAL,Cda); aa_tf_qsub(A+AA_TF_DUQU_REAL, B+AA_TF_DUQU_REAL,Crs); aa_tf_qsub(A+AA_TF_DUQU_DUAL, B+AA_TF_DUQU_DUAL,Cds); aveq( "duqu-qadd-real", 4, Cra, Ca+AA_TF_DUQU_REAL, 1e-6); aveq( "duqu-qadd-dual", 4, Cda, Ca+AA_TF_DUQU_DUAL, 1e-6); aveq( "duqu-qsub-real", 4, Crs, Cs+AA_TF_DUQU_REAL, 1e-6); aveq( "duqu-qsub-dual", 4, Cds, Cs+AA_TF_DUQU_DUAL, 1e-6); } } //double q[4], v[3], p0[3]; //aa_vrand( 3, v ); //aa_tf_qurand( q ); //AA_MEM_SET( v, 0, 3 ); // tfmat //aa_tf_quat2rotmat(q, T.R); //AA_MEM_CPY( &T.t.x, v, 3 ); // dual quat //aa_tf_qv2duqu( q, v, H.data ); //aa_tf_qv2duqu( aa_tf_quat_ident, v, H_tran.data ); // check trans double hv[3]; aa_tf_duqu_trans(H.data, hv); aveq("duqu-trans", 3, T.v.data, hv, .001 ); //double nreal,ndual; //aa_tf_duqu_norm( H.data, &nreal, &ndual ); //printf("norm: %f + %f \\epsilon \n", nreal, ndual ); // transform points double p1H[3], p1qv[3], p1T[3]; aa_tf_12( T.data, p0, p1T ); aa_tf_tf_qv( H.real.data, T.v.data, p0, p1qv ); aa_tf_tf_duqu( H.data, p0, p1H ); aveq( "tf-qv", 3, p1T, p1qv, .001 ); aveq( "tf-duqu", 3, p1T, p1H, .001 ); // conjugate { double S_conj[8]; double qv_conj[7], E_conj[7]; double SSc[8], EEc[7]; double Scv[3]; aa_tf_duqu_conj(H.data, S_conj); aa_tf_qv_conj(H.real.data, T.v.data, qv_conj, qv_conj+4); aa_tf_qutr_conj(E, E_conj); aa_tf_duqu_trans(S_conj, Scv); aveq( "duqu/qutr conj q", 4, S_conj, E_conj, 1e-6 ); aveq( "duqu/qv conj q", 4, S_conj, qv_conj, 1e-6 ); aveq( "duqu/qutr conj v", 3, Scv, E_conj+4, 1e-6 ); aveq( "duqu/qv conj v", 3, Scv, qv_conj+4, 1e-6 ); aa_tf_duqu_mul( H.data, S_conj, SSc ); aa_tf_qv_chain( H.real.data, T.v.data, qv_conj, qv_conj+4, EEc, EEc+4 ); aveq( "duqu conj", 8, SSc, S_ident, 1e-6 ); aveq( "qv conj q", 4, EEc, Q_ident, 1e-6 ); aveq( "qv conj v", 3, EEc+4, v_ident, 1e-6 ); } // derivative { double dx[6], dd[8], dq[4]; aa_vrand(6, dx); double dt = aa_frand() / 100; aa_tf_duqu_vel2diff( H.data, dx, dd ); aa_tf_qvel2diff( H.real.data, dx+3, dq ); // back to velocity double dx1[6]; aa_tf_duqu_diff2vel( H.data, dd, dx1 ); aveq( "duqu-vel invert", 6, dx, dx1, .001 ); // integrate double H1[8], q1[4], v1[3], H1qv[8]; double H1_sdd[8], H1_sdx[8]; for( size_t i = 0; i < 8; i ++ ) H1[i] = H.data[i] + dd[i]*dt; // some numerical error here... for( size_t i = 0; i < 3; i ++ ) v1[i] = T.v.data[i] + dx[i]*dt; aa_tf_duqu_normalize( H1 ); aa_tf_qsvel( H.real.data, dx+3, dt, q1 ); aa_tf_qv2duqu( q1, v1, H1qv ); aveq( "duqu-vel_real", 4, dq, dd, .001 ); aveq( "duqu-vel-int real", 4, H1, H1qv, .001 ); aveq( "duqu-vel-int dual", 4, H1+4, H1qv+4, .001 ); aa_tf_duqu_svel( H.data, dx, dt, H1_sdx ); aa_tf_duqu_sdiff( H.data, dd, dt, H1_sdd ); aveq( "duqu-int vel", 8, H1qv, H1_sdx, .001 ); aveq( "duqu-int diff", 8, H1_sdx, H1_sdd, .0001 ); /* // twist */ double tw[8], dxtw[6]; aa_tf_duqu_vel2twist(H.data, dx, tw ); aa_tf_duqu_twist2vel(H.data, tw, dxtw ); aveq( "duqu twist<->vel", 6, dx, dxtw, 1e-6 ); } // exponential { double expd[8], lnexpd[8]; aa_tf_duqu_exp(H.data, expd ); aa_tf_duqu_ln( expd, lnexpd ); aveq( "duqu-exp-ln", 8, H.data, lnexpd, .001 ); aa_tf_duqu_ln( H.data, lnexpd ); aa_tf_duqu_exp(lnexpd, expd ); aveq( "duqu-ln-exp", 8, H.data, expd, .001 ); } // Logarithm { double HI[8], HIln[8], dxi[6], dx0[6] = {0}; aa_tf_duqu_mulc( H.data, H.data, HI ); aa_tf_duqu_ln(HI, HIln); aa_tf_duqu_twist2vel(HI, HIln, dxi ); aveq( "duqu ln 0 near", 6, dx0, dxi, .0001 ); aa_tf_duqu_ln(aa_tf_duqu_ident, HIln); aa_tf_duqu_twist2vel(HI, HIln, dxi ); aveq( "duqu ln 0 exact", 6, dx0, dxi, 0.0 ); } // Pure translation { double S[8], v[3], v1[3]; aa_vrand(3,v); aa_tf_xyz2duqu( v[0], v[1], v[2], S ); aa_tf_duqu_trans(S, v1); aveq( "duqu trans orientation", 4, S, aa_tf_quat_ident, 0.0 ); aveq( "duqu trans translation", 3, v, v1, 1e-6 ); } }