#include "linmath.h" #include "survive_cal.h" #include #include #include #include #include #include #include #include // Dave talks about this poser here: https://www.youtube.com/watch?v=nSbEltdH9vM&feature=youtu.be&t=2h29m47s void OrthoSolve( FLT T[4][4], // OUTPUT: 4x4 transformation matrix FLT S_out[2][SENSORS_PER_OBJECT], // OUTPUT: array of screenspace points FLT S_in[2][SENSORS_PER_OBJECT], // INPUT: array of screenspace points FLT X_in[3][SENSORS_PER_OBJECT], // INPUT: array of offsets int nPoints); typedef struct { int nextaxis; float lengths[SENSORS_PER_OBJECT][NUM_LIGHTHOUSES][2]; float angles[SENSORS_PER_OBJECT][NUM_LIGHTHOUSES][2]; //Stuff } DummyData; int PoserDaveOrtho( SurviveObject * so, PoserData * pd ) { PoserType pt = pd->pt; SurviveContext * ctx = so->ctx; DummyData * dd = so->PoserData; if (!dd) so->PoserData = dd = calloc(sizeof(DummyData), 1); switch( pt ) { case POSERDATA_IMU: { PoserDataIMU * imu = (PoserDataIMU*)pd; //printf( "IMU:%s (%f %f %f) (%f %f %f)\n", so->codename, imu->accel[0], imu->accel[1], imu->accel[2], imu->gyro[0], imu->gyro[1], imu->gyro[2] ); break; } case POSERDATA_LIGHT: { PoserDataLight * l = (PoserDataLight*)pd; if (l->length > dd->lengths[l->sensor_id][l->lh][dd->nextaxis]) { dd->lengths[l->sensor_id][l->lh][dd->nextaxis] = l->length; dd->angles[l->sensor_id][l->lh][dd->nextaxis] = l->angle; } break; } case POSERDATA_SYNC: { PoserDataLight *l = (PoserDataLight *)pd; int lhid = l->lh; dd->nextaxis = l->acode & 1; if (dd->nextaxis == 0) { int i; int max_hits = 0; FLT S_in[2][SENSORS_PER_OBJECT]; FLT X_in[3][SENSORS_PER_OBJECT]; for (i = 0; i < SENSORS_PER_OBJECT; i++) { // Load all our valid points into something the LHFinder can use. if (dd->lengths[i][lhid][0] > 0 && dd->lengths[i][lhid][1] > 0) { S_in[0][max_hits] = dd->angles[i][lhid][0]; S_in[1][max_hits] = dd->angles[i][lhid][1]; dd->lengths[i][lhid][0] = -1; dd->lengths[i][lhid][1] = -1; X_in[0][max_hits] = so->sensor_locations[i * 3 + 0]; X_in[1][max_hits] = so->sensor_locations[i * 3 + 1]; X_in[2][max_hits] = so->sensor_locations[i * 3 + 2]; max_hits++; } } if (max_hits > 2) { // if( lhid == 0 ) { printf( "\033[H\033[2J" ); } // printf( "%d\n", max_hits ); FLT tOut[4][4]; FLT S_out[2][SENSORS_PER_OBJECT]; OrthoSolve(tOut, S_out, S_in, X_in, max_hits); // Now, we need to solve where we are as a function of where // the lighthouses are. SurvivePose objpose; FLT MT[4][4]; objpose.Pos[0] = tOut[0][3]; objpose.Pos[1] = tOut[1][3]; objpose.Pos[2] = tOut[2][3]; // matrix44transpose( MT, &tOut[0][0] ); matrix44copy(&MT[0][0], &tOut[0][0]); quatfrommatrix(objpose.Rot, &MT[0][0]); // printf( "QUAT: %f %f %f %f = %f\n", quat[0], quat[1], quat[2], quat[3], quatmagnitude(quat) ); // quat[2] -= 0.005; //fixes up lh0 in test data set. quatnormalize(objpose.Rot, objpose.Rot); SurvivePose lh2world = so->ctx->bsd[lhid].Pose; SurvivePose obj2world; ApplyPoseToPose(&obj2world, &lh2world, &objpose); PoserData_poser_pose_func(pd, so, &obj2world); if (0) { fprintf(stderr,"INQUAT: %f %f %f %f = %f [%f %f %f]\n", objpose.Rot[0], objpose.Rot[1], objpose.Rot[2], objpose.Rot[3], quatmagnitude(objpose.Rot), objpose.Pos[0], objpose.Pos[1], objpose.Pos[2]); // fprintf(stderr,"OUQUAT: %f %f %f %f = %f [%f %f %f]\n", poseout.Rot[0], poseout.Rot[1], poseout.Rot[2], // poseout.Rot[3], quatmagnitude(poseout.Rot), poseout.Pos[0], poseout.Pos[1], poseout.Pos[2]); } } } // if( so->codename[0] == 'H' ) printf( "LIG:%s %d @ %d rad, %f s (AX %d) (TC %d)\n", so->codename, // l->sensor_id, l->lh, l->length, dd->nextaxis, l->timecode ); break; } case POSERDATA_FULL_SCENE: { PoserDataFullScene * fs = (PoserDataFullScene*)pd; int LH_ID; SurvivePose alignLh0ToXAxis = {0}; for( LH_ID = 0; LH_ID < 2; LH_ID++ ) { int i; int max_hits = 0; FLT S_in[2][SENSORS_PER_OBJECT]; FLT X_in[3][SENSORS_PER_OBJECT]; for( i = 0; i < SENSORS_PER_OBJECT; i++ ) { //Load all our valid points into something the LHFinder can use. if( fs->lengths[i][LH_ID][0] > 0 ) { FLT out[2]; survive_apply_bsd_calibration(ctx, LH_ID, fs->angles[i][LH_ID], out); S_in[0][max_hits] = out[0]; S_in[1][max_hits] = out[1]; X_in[0][max_hits] = so->sensor_locations[i*3+0]; X_in[1][max_hits] = so->sensor_locations[i*3+1]; X_in[2][max_hits] = so->sensor_locations[i*3+2]; max_hits++; } } FLT tOut[4][4]; FLT S_out[2][SENSORS_PER_OBJECT]; OrthoSolve( tOut, S_out, S_in, X_in, max_hits ); //Now, we need to solve where we are as a function of where //the lighthouses are. // FLT quat[4]; // FLT posoff[3] = { tOut[0][3], tOut[1][3], tOut[2][3] }; SurvivePose objpose; FLT MT[4][4]; objpose.Pos[0] = tOut[0][3]; objpose.Pos[1] = tOut[1][3]; objpose.Pos[2] = tOut[2][3]; //matrix44transpose( MT, &tOut[0][0] ); matrix44copy( &MT[0][0], &tOut[0][0] ); quatfrommatrix(objpose.Rot, &MT[0][0]); //printf( "QUAT: %f %f %f %f = %f\n", quat[0], quat[1], quat[2], quat[3], quatmagnitude(quat) ); //quat[2] -= 0.005; //fixes up lh0 in test data set. quatnormalize(objpose.Rot, objpose.Rot); printf("QUAT: %f %f %f %f = %f [%f %f %f]\n", objpose.Rot[0], objpose.Rot[1], objpose.Rot[2], objpose.Rot[3], quatmagnitude(objpose.Rot), objpose.Pos[0], objpose.Pos[1], objpose.Pos[2]); if (0) ; for (i = 0; i < max_hits; i++) { FLT pt[3] = {X_in[0][i], X_in[1][i], X_in[2][i]}; quatrotatevector(pt, objpose.Rot, pt); add3d(pt, pt, objpose.Pos); printf("OUT %f %f %f ANGLE %f %f AOUT %f %f\n", pt[0], pt[1], pt[2], S_in[0][i], S_in[1][i], atan2(pt[0], pt[1]), atan2(pt[2], pt[1])); } /* so->FromLHPose[LH_ID].Pos[0] = objpose.Pos[0]; so->FromLHPose[LH_ID].Pos[1] = objpose.Pos[1]; so->FromLHPose[LH_ID].Pos[2] = objpose.Pos[2]; so->FromLHPose[LH_ID].Rot[0] = objpose.Rot[0]; so->FromLHPose[LH_ID].Rot[1] = objpose.Rot[1]; so->FromLHPose[LH_ID].Rot[2] = objpose.Rot[2]; so->FromLHPose[LH_ID].Rot[3] = objpose.Rot[3]; */ SurvivePose poseout; InvertPose(&poseout, &objpose); printf("INQUAT: %f %f %f %f = %f [%f %f %f]\n", objpose.Rot[0], objpose.Rot[1], objpose.Rot[2], objpose.Rot[3], quatmagnitude(objpose.Rot), objpose.Pos[0], objpose.Pos[1], objpose.Pos[2]); PoserData_lighthouse_pose_func(&fs->hdr, so, LH_ID, &alignLh0ToXAxis, &poseout, 0); printf("OUQUAT: %f %f %f %f = %f [%f %f %f]\n", poseout.Rot[0], poseout.Rot[1], poseout.Rot[2], poseout.Rot[3], quatmagnitude(poseout.Rot), poseout.Pos[0], poseout.Pos[1], poseout.Pos[2]); } break; } case POSERDATA_DISASSOCIATE: { free( dd ); so->PoserData = 0; //printf( "Need to disassociate.\n" ); break; } } return 0; } REGISTER_LINKTIME( PoserDaveOrtho ); #define PRINT_MAT(A,M,N) { \ int m,n; \ printf(#A "\n"); \ for (m=0; m 0 && err < bestErr) { x[1][0] = x_y; y[1][0] = y_y; z[1][0] = z_y; bestErr = err; } // if ( i == 0 && j == 0 && k == 0) { x[1][0]=x_y; y[1][0]=y_y; z[1][0]=z_y; bestErr=err; } z_y = -z_y; } y_y = -y_y; } x_y = -x_y; } // printf("bestErr %f\n", bestErr); /* //------------------------- // A test version of the rescaling to the proper length //------------------------- FLT ydist2 = ydist; FLT bestBestErr = 9999.0; FLT bestYdist = 0; for (ydist2=ydist-0.1; ydist2 %f %f %f\n", x_y, y_y, z_y ); // Exhaustively flip the minus sign of the z axis until we find the right one . . . FLT bestErr = 9999.0; FLT xy_dot2 = x2[0][0]*y2[0][0] + x2[2][0]*y2[2][0]; FLT yz_dot2 = y2[0][0]*z2[0][0] + y2[2][0]*z2[2][0]; FLT zx_dot2 = z2[0][0]*x2[0][0] + z2[2][0]*x2[2][0]; for (i=0;i<2;i++) { for (j=0;j<2;j++) { for(k=0;k<2;k++) { // Calculate the error term FLT xy_dot = xy_dot2 + x_y*y_y; FLT yz_dot = yz_dot2 + y_y*z_y; FLT zx_dot = zx_dot2 + z_y*x_y; FLT err = _ABS(xy_dot) + _ABS(yz_dot) + _ABS(zx_dot); // Calculate the handedness FLT cx,cy,cz; CrossProduct(cx,cy,cz,x2[0][0],x_y,x2[2][0],y2[0][0],y_y,y2[2][0]); FLT hand = cx*z2[0][0] + cy*z_y + cz*z2[2][0]; //printf("err %f hand %f\n", err, hand); // If we are the best right-handed frame so far if (hand > 0 && err < bestErr) { x2[1][0]=x_y; y2[1][0]=y_y; z2[1][0]=z_y; bestErr=err; } z_y = -z_y; } y_y = -y_y; } x_y = -x_y; } printf("ydist2 %f bestErr %f\n",ydist2,bestErr); if (bestErr < bestBestErr) { memcpy(x,x2,3*sizeof(FLT)); memcpy(y,y2,3*sizeof(FLT)); memcpy(z,z2,3*sizeof(FLT)); bestBestErr = bestErr; bestYdist = ydist2; } } ydist = bestYdist; */ /* for (i=0; i