aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile4
-rw-r--r--dave/AffineSolve.c322
-rw-r--r--include/libsurvive/poser.h54
-rw-r--r--include/libsurvive/survive.h (renamed from include/survive.h)31
-rw-r--r--include/libsurvive/survive_types.h29
-rw-r--r--src/survive_cal_lhfind.c2
-rw-r--r--src/survive_internal.h5
-rw-r--r--src/survive_vive.c22
-rw-r--r--tools/plot_lighthouse/Makefile2
9 files changed, 444 insertions, 27 deletions
diff --git a/Makefile b/Makefile
index 4938e28..470cbe3 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
all : lib data_recorder test calibrate calibrate_client
-CFLAGS:=-Iinclude -I. -fPIC -g -O0 -Iredist -flto -DUSE_DOUBLE -std=gnu99
+CFLAGS:=-Iinclude/libsurvive -I. -fPIC -g -O0 -Iredist -flto -DUSE_DOUBLE -std=gnu99
LDFLAGS:=-lpthread -lusb-1.0 -lz -lX11 -lm -flto -g
@@ -27,7 +27,7 @@ lib/libsurvive.so : src/survive.o src/survive_usb.o src/survive_data.o src/survi
gcc -o $@ $^ $(LDFLAGS) -shared
clean :
- rm -rf *.o src/*.o *~ src/*~ test data_recorder lib/libsurvive.so
+ rm -rf *.o src/*.o *~ src/*~ test data_recorder lib/libsurvive.so redist/*.o redist/*~
diff --git a/dave/AffineSolve.c b/dave/AffineSolve.c
new file mode 100644
index 0000000..36587e6
--- /dev/null
+++ b/dave/AffineSolve.c
@@ -0,0 +1,322 @@
+//
+// main.c
+// AffineSolve
+//
+// Created by user on 3/2/17.
+// Copyright © 2017 user. All rights reserved.
+//
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+
+#define LH_ID 0
+#define NUM_HMD 32
+
+float hmd_pos[NUM_HMD][3];
+void ReadHmdPoints()
+{
+ int i;
+ FILE *fin = fopen("HMD_points.csv","r");
+ if (fin==NULL) {
+ printf("ERROR: could not open HMD_points.csv for reading\n");
+ exit(1);
+ }
+
+ for (i=0; i<NUM_HMD; i++) {
+ fscanf(fin, "%f %f %f", &(hmd_pos[i][0]), &(hmd_pos[i][1]), &(hmd_pos[i][2]));
+ }
+
+ fclose(fin);
+}
+
+#define MAX_POINTS 128
+#define _ABS(a) ( (a)<=0 ? -(a) : (a) )
+#define _SIGN(a) ( (a)<=0 ? -1.0f : 1.0f )
+#define RANDF ( (float)rand() / (float)RAND_MAX )
+
+#define STEP_SIZE_ROT 1.0
+#define STEP_SIZE_POS 1.0
+#define FALLOFF 0.99999
+#define NITER 2000000
+#define TOO_SMALL 0.0001
+#define ORTHOG_PENALTY 1.0
+
+#define PRINT_MAT(A,M,N) { \
+ int m,n; \
+ printf(#A "\n"); \
+ for (m=0; m<M; m++) { \
+ for (n=0; n<N; n++) { \
+ printf("%f\t", A[m][n]); \
+ } \
+ printf("\n"); \
+ } \
+}
+
+void AffineSolve(
+ float T[4][4], // OUTPUT: transform
+ float O[MAX_POINTS][4], // INPUT: points, offsets
+ float N[MAX_POINTS][3], // INPUT: plane normals
+ float D[MAX_POINTS], // INPUT: plane offsets
+ int nPoints, int nIter,
+ float stepSizeRot, float stepSizePos, float falloff, int constrain)
+{
+ int i,j,k,iter;
+ //T[3][3] = 1.0f;
+
+ printf("iter x y z error\n");
+
+ float gradDot = 1.0;
+ float prevGradDot = 1.0;
+ float de_dT[3][4]; // the gradient
+ float conj[3][4]; // the conjugate
+ float errorSq=0.0;
+ for (iter=0; iter<nIter; iter++)
+ {
+ //----------------------------------
+ // Calculate the gradient direction
+ //----------------------------------
+ errorSq = 0.0;
+ memset(de_dT, 0, 3*4*sizeof(float));
+ for (i=0; i<nPoints; i++)
+ {
+ // What is the plane deviation error
+ float Ei = -D[i];
+ for (j=0; j<3; j++) {
+ float Tj_oi = 0.0f;
+ for (k=0; k<4; k++) {
+ Tj_oi += T[j][k] * O[i][k];
+ }
+ Ei += N[i][j] * Tj_oi;
+ }
+// printf("E[%d] %f\n", i, Ei);
+
+ // Figure out contribution to the error
+ for (j=0; j<3; j++) {
+ for (k=0; k<4; k++) {
+ de_dT[j][k] += N[i][j] * O[i][k] * Ei;
+ }
+ }
+
+ errorSq += Ei*Ei;
+ }
+
+ printf("%d %f %f %f %f\n", iter, T[0][3], T[1][3], T[2][3], sqrt(errorSq));
+
+ // Constrain the gradient (such that dot products are zero)
+ if (constrain)
+ {
+ float T0T1 = 0.0, T1T2 = 0.0, T2T0 = 0.0;
+ for (k=0; k<3; k++) {
+ T0T1 += T[0][k] * T[1][k];
+ T1T2 += T[1][k] * T[2][k];
+ T2T0 += T[2][k] * T[0][k];
+ }
+// printf("T0T1 %f T1T2 %f T2T0 %f\n", T0T1, T1T2, T2T0);
+ for (k=0; k<3; k++) {
+ de_dT[0][k] += ORTHOG_PENALTY * 2.0 * T0T1 * T[1][k];
+ de_dT[0][k] += ORTHOG_PENALTY * 2.0 * T2T0 * T[2][k];
+ de_dT[1][k] += ORTHOG_PENALTY * 2.0 * T1T2 * T[2][k];
+ de_dT[1][k] += ORTHOG_PENALTY * 2.0 * T0T1 * T[0][k];
+ de_dT[2][k] += ORTHOG_PENALTY * 2.0 * T1T2 * T[1][k];
+ de_dT[2][k] += ORTHOG_PENALTY * 2.0 * T2T0 * T[0][k];
+ }
+ }
+
+ // Calculate the gradient dot product
+ // (used by conjugate gradient method)
+ prevGradDot = gradDot;
+ gradDot = 0.0;
+ for (j=0; j<3; j++) {
+ for (k=0; k<4; k++) {
+ gradDot += de_dT[j][k] * de_dT[j][k];
+ }
+ }
+
+// printf("Iter %d error %f gradDot %f prevGradDot %f\n", iter, sqrt(errorSq), gradDot, prevGradDot);
+
+ //----------------------------------
+ // Calculate the conjugate direction
+ //----------------------------------
+// if (iter==0) {
+ // First iteration, just use the gradient
+ for (j=0; j<3; j++) {
+ for (k=0; k<4; k++) {
+ conj[j][k] = -de_dT[j][k];
+ }
+ }
+/* } else {
+ // Calculate "beta" for Fletcher Reeves method
+ float beta = gradDot / prevGradDot;
+//printf("gradDot %f prevGradDot %f beta %f\n", gradDot, prevGradDot, beta);
+
+ // Update the conjugate
+ for (j=0; j<3; j++) {
+ for (k=0; k<4; k++) {
+ conj[j][k] = beta*conj[j][k] - de_dT[j][k];
+ }
+ }
+ }
+*/
+
+// PRINT_MAT(de_dT,4,4);
+// exit(1);
+
+ //----------------------------------
+ // How large is the gradient ?
+ //----------------------------------
+
+ double gradSizeRot = 0.0;
+ double gradSizePos = 0.0;
+ for (j=0; j<3; j++) {
+ for (k=0; k<3; k++) {
+ gradSizeRot += _ABS(conj[j][k]);
+ }
+ gradSizePos += _ABS(conj[j][k]);
+ }
+ if (gradSizeRot <= TOO_SMALL && gradSizePos <= TOO_SMALL) { break; } // Quit, we've totally converged
+
+ //----------------------------------
+ // Descend in the gradient direction
+ //----------------------------------
+ if (gradSizeRot > TOO_SMALL) {
+ float scaleRot = stepSizeRot / gradSizeRot;
+ for (j=0; j<3; j++) {
+ for (k=0; k<3; k++) {
+ T[j][k] += scaleRot * conj[j][k];
+ }
+ }
+ stepSizeRot *= falloff;
+ }
+
+ if (gradSizePos > TOO_SMALL) {
+ float scalePos = stepSizePos / gradSizePos;
+ for (j=0; j<3; j++) {
+ T[j][3] += scalePos * conj[j][3];
+ }
+ stepSizePos *= falloff;
+ }
+
+ // Constrain the gradient (such that scaling is one)
+ if (constrain)
+ {
+ // Measure the scales
+ float len[3] = {0.0, 0.0, 0.0};
+ for (j=0; j<3; j++) {
+ double lenSq = 0.0;
+ for (k=0; k<3; k++) { lenSq += (double)T[j][k] * (double)T[j][k]; }
+ len[j] = sqrt(lenSq);
+ }
+
+ // How far off is the scale?
+ float xzLen = 0.5 * (len[0] + len[2]);
+ if (xzLen > TOO_SMALL) {
+ float inv_xzLen = 1.0 / xzLen;
+ for (j=0; j<3; j++) {
+ T[3][j] *= inv_xzLen;
+ }
+ }
+
+ // Rescale the thing
+ for (j=0; j<3; j++)
+ {
+ if (len[j] > TOO_SMALL) {
+ float inv_len = 1.0 / len[j];
+ for (k=0; k<3; k++) { T[j][k] *= inv_len; }
+ }
+ }
+ }
+ }
+
+}
+
+int main()
+{
+ int i,j,k;
+ float Tcalc[4][4];
+ float O[MAX_POINTS][4];
+ float N[MAX_POINTS][3];
+ float D[MAX_POINTS];
+ int nPoints = 0;
+
+ // Read the hmd points
+ ReadHmdPoints();
+
+ //-------------------------
+ // Read the lighthouse data
+ //-------------------------
+ FILE *fin = fopen("ptinfo.csv", "r");
+ if (fin==NULL) { printf("ERROR: could not open ptinfo.csv for reading\n"); exit(1); }
+ while (!feof(fin))
+ {
+ // Read the angle
+ int sen,lh,axis,count;
+ float angle, avglen, stddevang, stddevlen;
+ float max_outlier_length, max_outlier_angle;
+ int rt = fscanf( fin, "%d %d %d %d %f %f %f %f %f %f\n",
+ &sen, &lh, &axis, &count,
+ &angle, &avglen, &stddevang, &stddevlen,
+ &max_outlier_length, &max_outlier_angle);
+ if (rt != 10) { break; }
+
+ if (lh == LH_ID && sen < NUM_HMD) {
+ // Set the offset
+ O[nPoints][0] = hmd_pos[sen][0];
+ O[nPoints][1] = hmd_pos[sen][1];
+ O[nPoints][2] = hmd_pos[sen][2];
+ O[nPoints][3] = 1.0;
+
+ // Calculate the plane equation
+ if (axis == 1) { // Horizontal
+ N[nPoints][0] = -cos(angle);
+ N[nPoints][1] = -sin(angle);
+ N[nPoints][2] = 0.0;
+ D[nPoints] = 0.0;
+ } else { // Vertical
+ N[nPoints][0] = 0.0;
+ N[nPoints][1] = -sin(angle);
+ N[nPoints][2] = cos(angle);
+ D[nPoints] = 0.0;
+ }
+
+ printf("pt %d O %.3f %.3f %.3f %.3f N %.3f %.3f %.3f D %.3f\n",
+ nPoints,
+ O[nPoints][0], O[nPoints][1], O[nPoints][2], O[nPoints][3],
+ N[nPoints][0], N[nPoints][1], N[nPoints][2],
+ D[nPoints]);
+
+ nPoints++;
+ }
+ }
+ fclose(fin);
+
+ printf("nPoints %d\n", nPoints);
+
+ // Run the calculation for Tcalc
+ int run;
+ //for (run=0; run<100; run++) {
+
+ // Initialize Tcalc to the identity matrix
+ //memcpy(Tcalc, Torig, 4*4*sizeof(float));
+ memset(Tcalc, 0, 4*4*sizeof(float));
+ for (i=0; i<4; i++) { Tcalc[i][i] = 1.0f; }
+
+ // Solve it!
+ AffineSolve(
+ Tcalc, // OUTPUT: transform
+ O, // INPUT: points, offsets
+ N, // INPUT: plane normals
+ D, // INPUT: plane offsets
+ nPoints, NITER,
+ STEP_SIZE_ROT, STEP_SIZE_POS, FALLOFF,
+ 1);
+ //}
+
+ PRINT_MAT(Tcalc,4,4);
+
+
+ // insert code here...
+ printf("Hello, World!\n");
+ return 0;
+}
diff --git a/include/libsurvive/poser.h b/include/libsurvive/poser.h
new file mode 100644
index 0000000..4894acf
--- /dev/null
+++ b/include/libsurvive/poser.h
@@ -0,0 +1,54 @@
+#ifndef _LSPOSER_H
+#define _LSPOSER_H
+
+#include "survive_types.h"
+
+typedef enum PoserType_t
+{
+ POSERDATA_NONE = 0,
+ POSERDATA_IMU,
+ POSERDATA_LIGHT, //Single lighting event.
+ POSERDATA_FULL_SCENE, //Full, statified X, Y sweep data for both lighthouses.
+} PoserType;
+
+struct PoserData
+{
+ PoserType pt;
+ uint8_t data[0];
+};
+
+struct PoserDataIMU
+{
+ PoserType pt;
+ uint8_t datamask; //0 = accel present, 1 = gyro present, 2 = mag present.
+ FLT accel[3];
+ FLT gyro[3];
+ FLT mag[3];
+};
+
+struct PoserDataLight
+{
+ PoserType pt;
+ int sensor_id;
+ int acode; //OOTX Code associated with this sweep. base_station = acode >> 2; axis = acode & 1;
+ uint32_t timecode; //In object-local ticks.
+ FLT length; //In seconds
+ FLT angle; //In radians from center of lighthouse.
+};
+
+struct PoserDataFullScene
+{
+ PoserType pt;
+
+ //If "lengths[...]" < 0, means not a valid piece of sweep information.
+ FLT lengths[SENSORS_PER_OBJECT][NUM_LIGHTHOUSES][2];
+ FLT angles [SENSORS_PER_OBJECT][NUM_LIGHTHOUSES][2]; //2 Axes
+
+ struct PoserDataIMU lastimu;
+};
+
+//When you register your posers using the internal system,
+typedef int (*PoserCB)( struct SurviveObject * so, struct PoserData * pd );
+
+
+#endif
diff --git a/include/survive.h b/include/libsurvive/survive.h
index 51910a6..536c7fb 100644
--- a/include/survive.h
+++ b/include/libsurvive/survive.h
@@ -2,24 +2,13 @@
#define _SURVIVE_H
#include <stdint.h>
-
-#ifndef FLT
-#ifdef USE_DOUBLE
-#define FLT double
-#else
-#define FLT float
-#endif
-#endif
+#include "poser.h"
struct SurviveContext;
//DANGER: This structure may be redefined. Note that it is logically split into 64-bit chunks
//for optimization on 32- and 64-bit systems.
-//Careful with this, you can't just add another one right now, would take minor changes in survive_data.c and the cal tools.
-//It will also require a recompile. TODO: revisit this and correct the comment once fixed.
-#define NUM_LIGHTHOUSES 2
-
struct SurviveObject
{
struct SurviveContext * ctx;
@@ -36,9 +25,17 @@ struct SurviveObject
int8_t ison:1;
int8_t additional_flags:6;
+ //Pose Information, also "resolver" field.
+ FLT PoseConfidence; //0..1
+ FLT Position[3];
+ FLT Rotation[4];
+ void * PoserData; //Initialized to zero, configured by poser, can be anything the poser wants.
+ PoserCB * PoserFn;
+
+ //Device-specific information about the location of the sensors. This data will be used by the poser.
+ int8_t nr_locations;
FLT * sensor_locations;
FLT * sensor_normals;
- int8_t nr_locations;
//Timing sensitive data (mostly for disambiguation)
int32_t timebase_hz; //48,000,000 for normal vive hardware. (checked)
@@ -51,7 +48,7 @@ struct SurviveObject
int32_t pulse_synctime_slack; //5,000 for normal vive hardware. (guessed)
//Flood info, for calculating which laser is currently sweeping.
- int8_t oldcode;
+ int8_t oldcode;
int8_t sync_set_number; //0 = master, 1 = slave, -1 = fault.
int8_t did_handle_ootx; //If unset, will send lightcap data for sync pulses next time a sensor is hit.
uint32_t last_time[NUM_LIGHTHOUSES];
@@ -60,15 +57,11 @@ struct SurviveObject
uint32_t last_lighttime; //May be a 24- or 32- bit number depending on what device.
+
//Debug
int tsl;
};
-typedef void (*text_feedback_func)( struct SurviveContext * ctx, const char * fault );
-typedef void (*light_process_func)( struct SurviveObject * so, int sensor_id, int acode, int timeinsweep, uint32_t timecode, uint32_t length );
-typedef void (*imu_process_func)( struct SurviveObject * so, int16_t * accelgyro, uint32_t timecode, int id );
-typedef void (*angle_process_func)( struct SurviveObject * so, int sensor_id, int acode, uint32_t timecode, FLT length, FLT angle );
-
struct SurviveContext * survive_init( int headless );
//For any of these, you may pass in 0 for the function pointer to use default behavior.
diff --git a/include/libsurvive/survive_types.h b/include/libsurvive/survive_types.h
new file mode 100644
index 0000000..593819f
--- /dev/null
+++ b/include/libsurvive/survive_types.h
@@ -0,0 +1,29 @@
+#ifndef _SURVIVE_TYPES_H
+#define _SURVIVE_TYPES_H
+
+#ifndef FLT
+#ifdef USE_DOUBLE
+#define FLT double
+#else
+#define FLT float
+#endif
+#endif
+
+
+//Careful with this, you can't just add another one right now, would take minor changes in survive_data.c and the cal tools.
+//It will also require a recompile. TODO: revisit this and correct the comment once fixed.
+#define NUM_LIGHTHOUSES 2
+
+#define INTBUFFSIZE 64
+#define SENSORS_PER_OBJECT 32
+
+struct SurviveObject;
+struct SurviveContext;
+
+typedef void (*text_feedback_func)( struct SurviveContext * ctx, const char * fault );
+typedef void (*light_process_func)( struct SurviveObject * so, int sensor_id, int acode, int timeinsweep, uint32_t timecode, uint32_t length );
+typedef void (*imu_process_func)( struct SurviveObject * so, int16_t * accelgyro, uint32_t timecode, int id );
+typedef void (*angle_process_func)( struct SurviveObject * so, int sensor_id, int acode, uint32_t timecode, FLT length, FLT angle );
+
+#endif
+
diff --git a/src/survive_cal_lhfind.c b/src/survive_cal_lhfind.c
index e1e5fc9..93d9dc0 100644
--- a/src/survive_cal_lhfind.c
+++ b/src/survive_cal_lhfind.c
@@ -129,7 +129,7 @@ int survive_cal_lhfind( struct SurviveCalData * cd )
fullrange *= 0.25;
}
- if( beste > 0.005 )
+ if( beste > 0.01 )
{
//Error too high
SV_ERROR( "LH: %d / Best E %f Error too high\n", lh, beste );
diff --git a/src/survive_internal.h b/src/survive_internal.h
index 5962623..9d04d93 100644
--- a/src/survive_internal.h
+++ b/src/survive_internal.h
@@ -1,4 +1,4 @@
-//<>< (C) 2016 C. N. Lohr, MOSTLY Under MIT/x11 License.
+//<>< (C) 2016-2017 C. N. Lohr, MOSTLY Under MIT/x11 License.
//
//Based off of https://github.com/collabora/OSVR-Vive-Libre
// Originally Copyright 2016 Philipp Zabel
@@ -27,8 +27,6 @@
//XXX TODO This one needs to be rewritten.
#define SV_KILL() exit(0)
-#define INTBUFFSIZE 64
-#define SENSORS_PER_OBJECT 32
struct SurviveContext;
struct SurviveUSBInterface;
@@ -36,7 +34,6 @@ struct SurviveUSBInterface;
typedef int (*DeviceDriverCb)( struct SurviveContext * ctx, void * driver );
typedef int (*DeviceDriverMagicCb)( struct SurviveContext * ctx, void * driver, int magic_code, void * data, int datalen );
-
//This is defined in survive.h
struct SurviveObject;
struct SurviveCalData;
diff --git a/src/survive_vive.c b/src/survive_vive.c
index a402153..47886c9 100644
--- a/src/survive_vive.c
+++ b/src/survive_vive.c
@@ -20,6 +20,7 @@
#include <unistd.h> //sleep if I ever use it.
#include <errno.h>
#include <string.h>
+#include <sys/stat.h>
struct SurviveViveData;
@@ -976,6 +977,27 @@ static int LoadConfig( struct SurviveViveData * sv, struct SurviveObject * so, i
//TODO: Cleanup any remaining USB stuff.
return 1;
}
+
+ char fname[20];
+ mkdir( "calinfo", 0755 );
+
+ sprintf( fname, "calinfo/%s_points.csv", so->codename );
+ FILE * f = fopen( fname, "w" );
+ int j;
+ for( j = 0; j < so->nr_locations; j++ )
+ {
+ fprintf( f, "%f %f %f\n", so->sensor_locations[j*3+0], so->sensor_locations[j*3+1], so->sensor_locations[j*3+2] );
+ }
+ fclose( f );
+
+ sprintf( fname, "calinfo/%s_normals.csv", so->codename );
+ f = fopen( fname, "w" );
+ for( j = 0; j < so->nr_locations; j++ )
+ {
+ fprintf( f, "%f %f %f\n", so->sensor_normals[j*3+0], so->sensor_normals[j*3+1], so->sensor_normals[j*3+2] );
+ }
+ fclose( f );
+
return 0;
}
diff --git a/tools/plot_lighthouse/Makefile b/tools/plot_lighthouse/Makefile
index db382ea..38eece0 100644
--- a/tools/plot_lighthouse/Makefile
+++ b/tools/plot_lighthouse/Makefile
@@ -6,7 +6,7 @@ endif
# Darwin is Mac OSX !!
ifeq ($(UNAME), Darwin)
-CFLAGS:= -w -framework OpenGL -framework GLUT
+CFLAGS:= -I../../redist -w -framework OpenGL -framework GLUT
endif
all: