From 7d1d930dcb99559eee95fc8a94cc68d12a968353 Mon Sep 17 00:00:00 2001 From: Justin Berger Date: Tue, 3 Apr 2018 16:08:00 -0600 Subject: Added simple API --- api_example.c | 33 +++++ include/libsurvive/survive.h | 34 +++-- include/libsurvive/survive_api.h | 30 +++++ include/libsurvive/survive_types.h | 19 ++- src/survive_api.c | 167 +++++++++++++++++++++++++ src/survive_cal.c | 1 - src/survive_reproject.c | 2 +- winbuild/libsurvive.sln | 23 ++++ winbuild/libsurvive/libsurvive.vcxproj | 2 + winbuild/libsurvive/libsurvive.vcxproj.filters | 6 + 10 files changed, 289 insertions(+), 28 deletions(-) create mode 100644 api_example.c create mode 100644 include/libsurvive/survive_api.h create mode 100644 src/survive_api.c diff --git a/api_example.c b/api_example.c new file mode 100644 index 0000000..f2d9bd6 --- /dev/null +++ b/api_example.c @@ -0,0 +1,33 @@ +#include +#include +#include +#include + +int main(int argc, char **argv) { + SurviveAsyncContext *actx = survive_asyc_init(argc, argv); + if (actx == 0) // implies -help or similiar + return 0; + + survive_async_start_thread(actx); + + while (survive_async_is_running(actx)) { + OGUSleep(30000); + + SurvivePose pose; + + for (const SurviveAsyncObject* it = survive_async_get_first_tracked(actx); it != 0; it = survive_async_get_next_tracked(actx, it)) { + uint32_t timecode = survive_async_object_get_latest_pose(it, &pose); + printf("%s (%u): %f %f %f %f %f %f %f\n", survive_async_object_name(it), timecode, + pose.Pos[0], pose.Pos[1], pose.Pos[2], pose.Rot[0], pose.Rot[1], pose.Rot[2], pose.Rot[3]); + } + + OGUSleep(30000); + for (const SurviveAsyncObject* it = survive_async_get_next_updated(actx); it != 0; it = survive_async_get_next_updated(actx)) { + printf("%s changed since last checked\n", survive_async_object_name(it)); + } + + } + + survive_async_close(actx); + return 0; +} diff --git a/include/libsurvive/survive.h b/include/libsurvive/survive.h index 65343b7..52dcc0d 100644 --- a/include/libsurvive/survive.h +++ b/include/libsurvive/survive.h @@ -10,19 +10,13 @@ extern "C" { #endif -#ifdef _WIN32 -#define SURVIVE_EXPORT __declspec(dllexport) -#else -#define SURVIVE_EXPORT __attribute__((visibility("default"))) -#endif - /** * This struct encodes what the last effective angles seen on a sensor were, and when they occured. */ typedef struct { FLT angles[SENSORS_PER_OBJECT][NUM_LIGHTHOUSES][2]; // 2 Axes (Angles in LH space) - uint32_t timecode[SENSORS_PER_OBJECT][NUM_LIGHTHOUSES][2]; // Timecode per axis in ticks - uint32_t lengths[SENSORS_PER_OBJECT][NUM_LIGHTHOUSES][2]; // Timecode per axis in ticks + survive_timecode timecode[SENSORS_PER_OBJECT][NUM_LIGHTHOUSES][2]; // Timecode per axis in ticks + survive_timecode lengths[SENSORS_PER_OBJECT][NUM_LIGHTHOUSES][2]; // Timecode per axis in ticks FLT accel[3]; FLT gyro[3]; @@ -43,15 +37,15 @@ void SurviveSensorActivations_add_imu(SurviveSensorActivations *self, struct Pos * Returns true iff both angles for the given sensor and lighthouse were seen at most `tolerance` ticks before the given * `timecode_now`. */ -bool SurviveSensorActivations_isPairValid(const SurviveSensorActivations *self, uint32_t tolerance, - uint32_t timecode_now, uint32_t sensor_idx, int lh); +bool SurviveSensorActivations_isPairValid(const SurviveSensorActivations *self, survive_timecode tolerance, + survive_timecode timecode_now, uint32_t sensor_idx, int lh); /** * Default tolerance that gives a somewhat accuate representation of current state. * * Don't rely on this to be a given value. */ -extern uint32_t SurviveSensorActivations_default_tolerance; +extern survive_timecode SurviveSensorActivations_default_tolerance; // DANGER: This structure may be redefined. Note that it is logically split into 64-bit chunks // for optimization on 32- and 64-bit systems. @@ -75,7 +69,7 @@ struct SurviveObject { // Pose Information, also "poser" field. FLT PoseConfidence; // 0..1 SurvivePose OutPose; // Final pose? (some day, one can dream!) - uint32_t OutPose_timecode; + survive_timecode OutPose_timecode; SurvivePose FromLHPose[NUM_LIGHTHOUSES]; // Filled out by poser, contains computed position from each lighthouse. void *PoserData; // Initialized to zero, configured by poser, can be anything the poser wants. PoserCB PoserFn; @@ -101,11 +95,11 @@ struct SurviveObject { 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_sync_time[NUM_LIGHTHOUSES]; - uint32_t last_sync_length[NUM_LIGHTHOUSES]; - uint32_t recent_sync_time; + survive_timecode last_sync_time[NUM_LIGHTHOUSES]; + survive_timecode last_sync_length[NUM_LIGHTHOUSES]; + survive_timecode recent_sync_time; - uint32_t last_lighttime; // May be a 24- or 32- bit number depending on what device. + survive_timecode last_lighttime; // May be a 24- or 32- bit number depending on what device. FLT *acc_bias; // size is FLT*3. contains x,y,z FLT *acc_scale; // size is FLT*3. contains x,y,z @@ -305,14 +299,14 @@ SURVIVE_EXPORT int survive_haptic(SurviveObject *so, uint8_t reserved, uint16_t // Call these from your callback if overridden. // Accept higher-level data. SURVIVE_EXPORT void survive_default_light_process(SurviveObject *so, int sensor_id, int acode, int timeinsweep, - uint32_t timecode, uint32_t length, uint32_t lh); -SURVIVE_EXPORT void survive_default_imu_process(SurviveObject *so, int mode, FLT *accelgyro, uint32_t timecode, int id); -SURVIVE_EXPORT void survive_default_angle_process(SurviveObject *so, int sensor_id, int acode, uint32_t timecode, + survive_timecode timecode, survive_timecode length, uint32_t lh); +SURVIVE_EXPORT void survive_default_imu_process(SurviveObject *so, int mode, FLT *accelgyro, survive_timecode timecode, int id); +SURVIVE_EXPORT void survive_default_angle_process(SurviveObject *so, int sensor_id, int acode, survive_timecode timecode, FLT length, FLT angle, uint32_t lh); SURVIVE_EXPORT void survive_default_button_process(SurviveObject *so, uint8_t eventType, uint8_t buttonId, uint8_t axis1Id, uint16_t axis1Val, uint8_t axis2Id, uint16_t axis2Val); -SURVIVE_EXPORT void survive_default_raw_pose_process(SurviveObject *so, uint32_t timecode, SurvivePose *pose); +SURVIVE_EXPORT void survive_default_raw_pose_process(SurviveObject *so, survive_timecode timecode, SurvivePose *pose); SURVIVE_EXPORT void survive_default_lighthouse_pose_process(SurviveContext *ctx, uint8_t lighthouse, SurvivePose *lh_pose, SurvivePose *obj_pose); SURVIVE_EXPORT int survive_default_htc_config_process(SurviveObject *so, char *ct0conf, int len); diff --git a/include/libsurvive/survive_api.h b/include/libsurvive/survive_api.h new file mode 100644 index 0000000..30e30ac --- /dev/null +++ b/include/libsurvive/survive_api.h @@ -0,0 +1,30 @@ +#include "survive_types.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + + struct SurviveAsyncContext; + typedef struct SurviveAsyncContext SurviveAsyncContext; + + SURVIVE_EXPORT SurviveAsyncContext *survive_asyc_init(int argc, char *const *argv); + SURVIVE_EXPORT void survive_async_close(SurviveAsyncContext* actx); + + SURVIVE_EXPORT void survive_async_start_thread(SurviveAsyncContext* actx); + SURVIVE_EXPORT int survive_async_stop_thread(SurviveAsyncContext* actx); + SURVIVE_EXPORT bool survive_async_is_running(SurviveAsyncContext* actx); + + struct SurviveAsyncObject; + typedef struct SurviveAsyncObject SurviveAsyncObject; + + SURVIVE_EXPORT const SurviveAsyncObject* survive_async_get_first_tracked(SurviveAsyncContext* actx); + SURVIVE_EXPORT const SurviveAsyncObject* survive_async_get_next_tracked(SurviveAsyncContext* actx, const SurviveAsyncObject* curr); + SURVIVE_EXPORT const SurviveAsyncObject* survive_async_get_next_updated(SurviveAsyncContext* actx); + + SURVIVE_EXPORT survive_timecode survive_async_object_get_latest_pose(const SurviveAsyncObject* sao, SurvivePose* pose); + SURVIVE_EXPORT const char* survive_async_object_name(SurviveAsyncObject* sao); + +#ifdef __cplusplus +} +#endif diff --git a/include/libsurvive/survive_types.h b/include/libsurvive/survive_types.h index 367c391..b9d145f 100644 --- a/include/libsurvive/survive_types.h +++ b/include/libsurvive/survive_types.h @@ -4,6 +4,12 @@ #include "linmath.h" #include "stdint.h" +#ifdef _WIN32 +#define SURVIVE_EXPORT __declspec(dllexport) +#else +#define SURVIVE_EXPORT __attribute__((visibility("default"))) +#endif + #ifdef __cplusplus extern "C" { #endif @@ -38,6 +44,8 @@ typedef LinmathPose SurvivePose; #define BUTTON_EVENT_BUTTON_UP 2 #define BUTTON_EVENT_AXIS_CHANGED 3 +typedef uint32_t survive_timecode; + typedef struct SurviveObject SurviveObject; typedef struct SurviveContext SurviveContext; typedef struct BaseStationData BaseStationData; @@ -45,13 +53,12 @@ typedef struct SurviveCalData SurviveCalData; //XXX Warning: This may be remov typedef int (*htc_config_func)(SurviveObject *so, char *ct0conf, int len); typedef void (*text_feedback_func)( SurviveContext * ctx, const char * fault ); -typedef void (*light_process_func)( SurviveObject * so, int sensor_id, int acode, int timeinsweep, uint32_t timecode, uint32_t length, uint32_t lighthouse); -typedef void (*imu_process_func)( SurviveObject * so, int mask, FLT * accelgyro, uint32_t timecode, int id ); -typedef void (*angle_process_func)( SurviveObject * so, int sensor_id, int acode, uint32_t timecode, FLT length, FLT angle, uint32_t lh); +typedef void (*light_process_func)( SurviveObject * so, int sensor_id, int acode, int timeinsweep, survive_timecode timecode, survive_timecode length, uint32_t lighthouse); +typedef void (*imu_process_func)( SurviveObject * so, int mask, FLT * accelgyro, survive_timecode timecode, int id ); +typedef void (*angle_process_func)( SurviveObject * so, int sensor_id, int acode, survive_timecode timecode, FLT length, FLT angle, uint32_t lh); typedef void(*button_process_func)(SurviveObject * so, uint8_t eventType, uint8_t buttonId, uint8_t axis1Id, uint16_t axis1Val, uint8_t axis2Id, uint16_t axis2Val); -typedef void (*pose_func)(SurviveObject *so, uint32_t timecode, SurvivePose *pose); -typedef void (*lighthouse_pose_func)(SurviveContext *ctx, uint8_t lighthouse, SurvivePose *lighthouse_pose, - SurvivePose *object_pose); +typedef void (*pose_func)(SurviveObject *so, survive_timecode timecode, SurvivePose *pose); +typedef void (*lighthouse_pose_func)(SurviveContext *ctx, uint8_t lighthouse, SurvivePose *lighthouse_pose, SurvivePose *object_pose); // For lightcap, etc. Don't change this structure at all. Regular vive is dependent on it being exactly as-is. // When you write drivers, you can use this to send survive lightcap data. diff --git a/src/survive_api.c b/src/survive_api.c new file mode 100644 index 0000000..9883c9f --- /dev/null +++ b/src/survive_api.c @@ -0,0 +1,167 @@ +#include "survive_api.h" +#include "os_generic.h" +#include "survive.h" +#include "stdio.h" + +struct SurviveAsyncObject { + struct SurviveAsyncContext* actx; + + enum SurviveAsyncObject_type { + SurviveAsyncObject_LIGHTHOUSE, + SurviveAsyncObject_OBJECT + } type; + + union { + int lighthosue; + struct SurviveObject* so; + } data; + + char name[32]; + bool has_update; +}; + +struct SurviveAsyncContext { + SurviveContext* ctx; + + bool running; + og_thread_t thread; + og_mutex_t poll_mutex; + + size_t object_ct; + struct SurviveAsyncObject objects[]; +}; + +static void pose_fn(SurviveObject *so, uint32_t timecode, SurvivePose *pose) { + survive_default_raw_pose_process(so, timecode, pose); + + struct SurviveAsyncContext* actx = so->ctx->user_ptr; + int idx = so->user_ptr; + actx->objects[idx].has_update = true; +} +static void lh_fn(SurviveContext *ctx, uint8_t lighthouse, SurvivePose *lighthouse_pose, + SurvivePose *object_pose) { + survive_default_lighthouse_pose_process(ctx, lighthouse, lighthouse_pose, object_pose); + + struct SurviveAsyncContext* actx = ctx->user_ptr; + actx->objects[lighthouse].has_update = true; +} + +struct SurviveAsyncContext *survive_asyc_init(int argc, char *const *argv) { + SurviveContext* ctx = survive_init(argc, argv); + if (ctx == 0) + return 0; + + survive_startup(ctx); + + int object_ct = ctx->activeLighthouses + ctx->objs_ct; + struct SurviveAsyncContext * actx = calloc(1, sizeof(struct SurviveAsyncContext) + sizeof(struct SurviveAsyncObject) * object_ct ); + actx->object_ct = object_ct; + actx->ctx = ctx; + actx->poll_mutex = OGCreateMutex(); + ctx->user_ptr = actx; + int i = 0; + for (i = 0; i < ctx->activeLighthouses; i++) { + struct SurviveAsyncObject* obj = &actx->objects[i]; + obj->data.lighthosue = i; + obj->type = SurviveAsyncObject_LIGHTHOUSE; + obj->actx = actx; + obj->has_update = ctx->bsd[i].PositionSet; + snprintf(obj->name, 32, "LH%d", i); + } + for (; i < object_ct; i++) { + struct SurviveAsyncObject* obj = &actx->objects[i]; + int so_idx = i - ctx->activeLighthouses; + obj->data.so = ctx->objs[so_idx]; + obj->type = SurviveAsyncObject_OBJECT; + obj->actx = actx; + obj->data.so->user_ptr = (void*)i; + snprintf(obj->name, 32, "%s", obj->data.so->codename); + } + + survive_install_pose_fn(ctx, pose_fn); + survive_install_lighthouse_pose_fn(ctx, lh_fn); + return actx; +} + +void survive_async_close(struct SurviveAsyncContext* actx) { + if (actx->running) { + survive_async_stop_thread(actx); + } + + survive_close(actx->ctx); +} + +static inline void* __async_thread(void* _actx) { + struct SurviveAsyncContext* actx = _actx; + int error = 0; + while (actx->running && error == 0) { + OGLockMutex(actx->poll_mutex); + error = survive_poll(actx->ctx); + OGUnlockMutex(actx->poll_mutex); + } + actx->running = false; + return (void*)error; +} +bool survive_async_is_running(struct SurviveAsyncContext* actx) { + return actx->running; +} +void survive_async_start_thread(struct SurviveAsyncContext* actx) { + actx->running = true; + actx->thread = OGCreateThread(__async_thread, actx); +} +int survive_async_stop_thread(struct SurviveAsyncContext* actx) { + actx->running = false; + int error = (int)OGJoinThread(actx->thread); + if (error != 0) { + SurviveContext* ctx = actx->ctx; + SV_INFO("Warning: Loope exited with error %d", error); + } + return error; +} + +const struct SurviveAsyncObject* survive_async_get_next_tracked(struct SurviveAsyncContext* actx, const struct SurviveAsyncObject* curr) { + const struct SurviveAsyncObject* next = curr + 1; + if (next >= actx->objects + actx->object_ct) + return 0; + return next; +} + +const struct SurviveAsyncObject* survive_async_get_first_tracked(struct SurviveAsyncContext* actx) { + return actx->objects; +} + +const struct SurviveAsyncObject* survive_async_get_next_updated(struct SurviveAsyncContext* actx) { + for (int i = 0; i < actx->object_ct; i++) { + if (actx->objects[i].has_update) { + actx->objects[i].has_update = false; + return &actx->objects[i]; + } + } + return 0; +} + +uint32_t survive_async_object_get_latest_pose(const struct SurviveAsyncObject* sao, SurvivePose* pose) { + uint32_t timecode = 0; + OGLockMutex(sao->actx->poll_mutex); + + switch (sao->type) { + case SurviveAsyncObject_LIGHTHOUSE: { + if(pose) + *pose = sao->actx->ctx->bsd[sao->data.lighthosue].Pose; + break; + } + case SurviveAsyncObject_OBJECT: + if(pose) + *pose = sao->data.so->OutPose; + timecode = sao->data.so->OutPose_timecode; + break; + } + + OGUnlockMutex(sao->actx->poll_mutex); + return timecode; +} + +const char * survive_async_object_name(const SurviveAsyncObject * sao) +{ + return sao->name; +} diff --git a/src/survive_cal.c b/src/survive_cal.c index 3015b68..36e0a31 100755 --- a/src/survive_cal.c +++ b/src/survive_cal.c @@ -188,7 +188,6 @@ void survive_cal_install( struct SurviveContext * ctx ) } } - const char * DriverName; cd->ConfigPoserFn = GetDriverByConfig(ctx, "Poser", "configposer", "SBA", 0); ootx_packet_clbk = ootx_packet_clbk_d; diff --git a/src/survive_reproject.c b/src/survive_reproject.c index d6ba70b..8d8f0ed 100644 --- a/src/survive_reproject.c +++ b/src/survive_reproject.c @@ -99,5 +99,5 @@ void survive_apply_bsd_calibration(SurviveContext *ctx, int lh, const FLT *in, F void survive_reproject_from_pose_with_config(const SurviveContext *ctx, struct survive_calibration_config *config, int lighthouse, const SurvivePose *pose, FLT *point3d, FLT *out) { - return survive_reproject_from_pose_with_bsd(&ctx->bsd[lighthouse], config, pose, point3d, out); + survive_reproject_from_pose_with_bsd(&ctx->bsd[lighthouse], config, pose, point3d, out); } diff --git a/winbuild/libsurvive.sln b/winbuild/libsurvive.sln index b525975..1872a5a 100644 --- a/winbuild/libsurvive.sln +++ b/winbuild/libsurvive.sln @@ -11,6 +11,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "data_recorder", "data_recor EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test", "test\test.vcxproj", "{EF083B79-F1D7-408A-9902-502B9A0639E0}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "simple_pose_test", "simple_pose_test\simple_pose_test.vcxproj", "{308708B5-DDC9-49EE-BF31-C83E187AFE15}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "api_example", "api_example\api_example.vcxproj", "{545316AE-4E07-49DD-A2B8-7A2DE9676EFF}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 @@ -51,8 +55,27 @@ Global {EF083B79-F1D7-408A-9902-502B9A0639E0}.Release|x64.Build.0 = Release|x64 {EF083B79-F1D7-408A-9902-502B9A0639E0}.Release|x86.ActiveCfg = Release|Win32 {EF083B79-F1D7-408A-9902-502B9A0639E0}.Release|x86.Build.0 = Release|Win32 + {308708B5-DDC9-49EE-BF31-C83E187AFE15}.Debug|x64.ActiveCfg = Debug|x64 + {308708B5-DDC9-49EE-BF31-C83E187AFE15}.Debug|x64.Build.0 = Debug|x64 + {308708B5-DDC9-49EE-BF31-C83E187AFE15}.Debug|x86.ActiveCfg = Debug|Win32 + {308708B5-DDC9-49EE-BF31-C83E187AFE15}.Debug|x86.Build.0 = Debug|Win32 + {308708B5-DDC9-49EE-BF31-C83E187AFE15}.Release|x64.ActiveCfg = Release|x64 + {308708B5-DDC9-49EE-BF31-C83E187AFE15}.Release|x64.Build.0 = Release|x64 + {308708B5-DDC9-49EE-BF31-C83E187AFE15}.Release|x86.ActiveCfg = Release|Win32 + {308708B5-DDC9-49EE-BF31-C83E187AFE15}.Release|x86.Build.0 = Release|Win32 + {545316AE-4E07-49DD-A2B8-7A2DE9676EFF}.Debug|x64.ActiveCfg = Debug|x64 + {545316AE-4E07-49DD-A2B8-7A2DE9676EFF}.Debug|x64.Build.0 = Debug|x64 + {545316AE-4E07-49DD-A2B8-7A2DE9676EFF}.Debug|x86.ActiveCfg = Debug|Win32 + {545316AE-4E07-49DD-A2B8-7A2DE9676EFF}.Debug|x86.Build.0 = Debug|Win32 + {545316AE-4E07-49DD-A2B8-7A2DE9676EFF}.Release|x64.ActiveCfg = Release|x64 + {545316AE-4E07-49DD-A2B8-7A2DE9676EFF}.Release|x64.Build.0 = Release|x64 + {545316AE-4E07-49DD-A2B8-7A2DE9676EFF}.Release|x86.ActiveCfg = Release|Win32 + {545316AE-4E07-49DD-A2B8-7A2DE9676EFF}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {EA7B8D68-188A-4190-B011-8A7F4EC52C38} + EndGlobalSection EndGlobal diff --git a/winbuild/libsurvive/libsurvive.vcxproj b/winbuild/libsurvive/libsurvive.vcxproj index 4b76c99..85e9f5a 100644 --- a/winbuild/libsurvive/libsurvive.vcxproj +++ b/winbuild/libsurvive/libsurvive.vcxproj @@ -178,6 +178,7 @@ + @@ -197,6 +198,7 @@ + diff --git a/winbuild/libsurvive/libsurvive.vcxproj.filters b/winbuild/libsurvive/libsurvive.vcxproj.filters index 1f98c68..61cec4c 100644 --- a/winbuild/libsurvive/libsurvive.vcxproj.filters +++ b/winbuild/libsurvive/libsurvive.vcxproj.filters @@ -135,6 +135,9 @@ Source Files + + Source Files + @@ -188,6 +191,9 @@ Source Files + + Header Files + -- cgit v1.2.3 From be7593dc945ed4025f81c6876760807310a67319 Mon Sep 17 00:00:00 2001 From: Justin Berger Date: Tue, 3 Apr 2018 22:56:40 -0600 Subject: Minor cleanup --- Makefile | 2 +- include/libsurvive/survive_api.h | 7 ++++--- include/libsurvive/survive_types.h | 2 ++ redist/linmath.h | 2 ++ src/survive_api.c | 4 ++-- 5 files changed, 11 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index c5763cb..8493f18 100644 --- a/Makefile +++ b/Makefile @@ -40,7 +40,7 @@ ifeq ($(UNAME), Darwin) REDISTS:=$(REDISTS) redist/hid-osx.c endif -LIBSURVIVE_CORE:=src/survive.o src/survive_usb.o src/survive_charlesbiguator.o src/survive_process.o src/ootx_decoder.o src/survive_driverman.o src/survive_default_devices.o src/survive_vive.o src/survive_playback.o src/survive_config.o src/survive_cal.o src/survive_reproject.o src/poser.o src/epnp/epnp.o src/survive_sensor_activations.o src/survive_turveybiguator.o src/survive_disambiguator.o src/survive_statebased_disambiguator.o src/poser_charlesrefine.o src/survive_imu.o src/poser_imu.o +LIBSURVIVE_CORE:=src/survive.o src/survive_usb.o src/survive_charlesbiguator.o src/survive_process.o src/ootx_decoder.o src/survive_driverman.o src/survive_default_devices.o src/survive_vive.o src/survive_playback.o src/survive_config.o src/survive_cal.o src/survive_reproject.o src/poser.o src/epnp/epnp.o src/survive_sensor_activations.o src/survive_turveybiguator.o src/survive_disambiguator.o src/survive_statebased_disambiguator.o src/poser_charlesrefine.o src/survive_imu.o src/poser_imu.o src/survive_api.o #If you want to use HIDAPI on Linux. #CFLAGS:=$(CFLAGS) -DHIDAPI diff --git a/include/libsurvive/survive_api.h b/include/libsurvive/survive_api.h index 30e30ac..aacd47a 100644 --- a/include/libsurvive/survive_api.h +++ b/include/libsurvive/survive_api.h @@ -8,7 +8,7 @@ extern "C" { struct SurviveAsyncContext; typedef struct SurviveAsyncContext SurviveAsyncContext; - SURVIVE_EXPORT SurviveAsyncContext *survive_asyc_init(int argc, char *const *argv); + SURVIVE_EXPORT SurviveAsyncContext *survive_async_init(int argc, char *const *argv); SURVIVE_EXPORT void survive_async_close(SurviveAsyncContext* actx); SURVIVE_EXPORT void survive_async_start_thread(SurviveAsyncContext* actx); @@ -22,8 +22,9 @@ extern "C" { SURVIVE_EXPORT const SurviveAsyncObject* survive_async_get_next_tracked(SurviveAsyncContext* actx, const SurviveAsyncObject* curr); SURVIVE_EXPORT const SurviveAsyncObject* survive_async_get_next_updated(SurviveAsyncContext* actx); - SURVIVE_EXPORT survive_timecode survive_async_object_get_latest_pose(const SurviveAsyncObject* sao, SurvivePose* pose); - SURVIVE_EXPORT const char* survive_async_object_name(SurviveAsyncObject* sao); + SURVIVE_EXPORT survive_timecode survive_async_object_get_latest_pose(const SurviveAsyncObject *sao, + SurvivePose *OUTPUT); + SURVIVE_EXPORT const char *survive_async_object_name(const SurviveAsyncObject *sao); #ifdef __cplusplus } diff --git a/include/libsurvive/survive_types.h b/include/libsurvive/survive_types.h index b9d145f..7fa5e0f 100644 --- a/include/libsurvive/survive_types.h +++ b/include/libsurvive/survive_types.h @@ -4,11 +4,13 @@ #include "linmath.h" #include "stdint.h" +#ifndef SURVIVE_EXPORT #ifdef _WIN32 #define SURVIVE_EXPORT __declspec(dllexport) #else #define SURVIVE_EXPORT __attribute__((visibility("default"))) #endif +#endif #ifdef __cplusplus extern "C" { diff --git a/redist/linmath.h b/redist/linmath.h index e268e96..bafdbe8 100644 --- a/redist/linmath.h +++ b/redist/linmath.h @@ -7,11 +7,13 @@ extern "C" { #endif +#ifndef LINMATH_EXPORT #ifdef _WIN32 #define LINMATH_EXPORT __declspec(dllexport) #else #define LINMATH_EXPORT __attribute__((visibility("default"))) #endif +#endif // Yes, I know it's kind of arbitrary. #define DEFAULT_EPSILON 0.001 diff --git a/src/survive_api.c b/src/survive_api.c index 9883c9f..2aaf31a 100644 --- a/src/survive_api.c +++ b/src/survive_api.c @@ -35,7 +35,7 @@ static void pose_fn(SurviveObject *so, uint32_t timecode, SurvivePose *pose) { survive_default_raw_pose_process(so, timecode, pose); struct SurviveAsyncContext* actx = so->ctx->user_ptr; - int idx = so->user_ptr; + int idx = (int)so->user_ptr; actx->objects[idx].has_update = true; } static void lh_fn(SurviveContext *ctx, uint8_t lighthouse, SurvivePose *lighthouse_pose, @@ -46,7 +46,7 @@ static void lh_fn(SurviveContext *ctx, uint8_t lighthouse, SurvivePose *lighthou actx->objects[lighthouse].has_update = true; } -struct SurviveAsyncContext *survive_asyc_init(int argc, char *const *argv) { +struct SurviveAsyncContext *survive_async_init(int argc, char *const *argv) { SurviveContext* ctx = survive_init(argc, argv); if (ctx == 0) return 0; -- cgit v1.2.3 From 8992810b626e58e1dd1ed61b3b41f20db60dddf4 Mon Sep 17 00:00:00 2001 From: Justin Berger Date: Wed, 4 Apr 2018 00:50:05 -0600 Subject: Added basic documentation --- include/libsurvive/survive_api.h | 40 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/include/libsurvive/survive_api.h b/include/libsurvive/survive_api.h index aacd47a..52eca8d 100644 --- a/include/libsurvive/survive_api.h +++ b/include/libsurvive/survive_api.h @@ -8,22 +8,54 @@ extern "C" { struct SurviveAsyncContext; typedef struct SurviveAsyncContext SurviveAsyncContext; + /*** + * Initialize a new instance of an async context -- mirrors survive_init + * @return Pointer to the async context + */ SURVIVE_EXPORT SurviveAsyncContext *survive_async_init(int argc, char *const *argv); + + /** + * Close all devices and free all memory associated with the given context + */ SURVIVE_EXPORT void survive_async_close(SurviveAsyncContext* actx); + /** + * Start the background thread which processes images. + */ SURVIVE_EXPORT void survive_async_start_thread(SurviveAsyncContext* actx); - SURVIVE_EXPORT int survive_async_stop_thread(SurviveAsyncContext* actx); - SURVIVE_EXPORT bool survive_async_is_running(SurviveAsyncContext* actx); + + /** + * @return true iff the background thread is still running + */ + SURVIVE_EXPORT bool survive_async_is_running(SurviveAsyncContext *actx); struct SurviveAsyncObject; typedef struct SurviveAsyncObject SurviveAsyncObject; + /** + * Get the first known object. Note that the first n objects are the lighthouses; for however many you are + * configured for. + */ SURVIVE_EXPORT const SurviveAsyncObject* survive_async_get_first_tracked(SurviveAsyncContext* actx); + /** + * Get the next known object from a current one. + */ SURVIVE_EXPORT const SurviveAsyncObject* survive_async_get_next_tracked(SurviveAsyncContext* actx, const SurviveAsyncObject* curr); - SURVIVE_EXPORT const SurviveAsyncObject* survive_async_get_next_updated(SurviveAsyncContext* actx); + /** + * Gets the next object which has been updated since we last looked at it with this function + */ + SURVIVE_EXPORT const SurviveAsyncObject *survive_async_get_next_updated(SurviveAsyncContext *actx); + + /** + * Gets the pose of a given object + */ SURVIVE_EXPORT survive_timecode survive_async_object_get_latest_pose(const SurviveAsyncObject *sao, - SurvivePose *OUTPUT); + SurvivePose *pose); + + /** + * Gets the null terminated name of the object. + */ SURVIVE_EXPORT const char *survive_async_object_name(const SurviveAsyncObject *sao); #ifdef __cplusplus -- cgit v1.2.3 From 229a2cb44d1462200ffa14fe925cd91796e99989 Mon Sep 17 00:00:00 2001 From: Justin Berger Date: Wed, 4 Apr 2018 09:36:10 -0600 Subject: Dramatically reduced the scope of locking --- src/survive_api.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/survive_api.c b/src/survive_api.c index 2aaf31a..bb1f090 100644 --- a/src/survive_api.c +++ b/src/survive_api.c @@ -32,18 +32,23 @@ struct SurviveAsyncContext { }; static void pose_fn(SurviveObject *so, uint32_t timecode, SurvivePose *pose) { + struct SurviveAsyncContext *actx = so->ctx->user_ptr; + OGLockMutex(actx->poll_mutex); survive_default_raw_pose_process(so, timecode, pose); - struct SurviveAsyncContext* actx = so->ctx->user_ptr; int idx = (int)so->user_ptr; actx->objects[idx].has_update = true; + OGUnlockMutex(actx->poll_mutex); } static void lh_fn(SurviveContext *ctx, uint8_t lighthouse, SurvivePose *lighthouse_pose, SurvivePose *object_pose) { + struct SurviveAsyncContext *actx = ctx->user_ptr; + OGLockMutex(actx->poll_mutex); survive_default_lighthouse_pose_process(ctx, lighthouse, lighthouse_pose, object_pose); - struct SurviveAsyncContext* actx = ctx->user_ptr; actx->objects[lighthouse].has_update = true; + + OGUnlockMutex(actx->poll_mutex); } struct SurviveAsyncContext *survive_async_init(int argc, char *const *argv) { @@ -95,9 +100,7 @@ static inline void* __async_thread(void* _actx) { struct SurviveAsyncContext* actx = _actx; int error = 0; while (actx->running && error == 0) { - OGLockMutex(actx->poll_mutex); error = survive_poll(actx->ctx); - OGUnlockMutex(actx->poll_mutex); } actx->running = false; return (void*)error; -- cgit v1.2.3 From d438c5b16f42700c8ff541269759d6c585959729 Mon Sep 17 00:00:00 2001 From: Justin Berger Date: Wed, 4 Apr 2018 09:37:18 -0600 Subject: Fixed api demo --- api_example.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api_example.c b/api_example.c index f2d9bd6..515c4e6 100644 --- a/api_example.c +++ b/api_example.c @@ -4,7 +4,7 @@ #include int main(int argc, char **argv) { - SurviveAsyncContext *actx = survive_asyc_init(argc, argv); + SurviveAsyncContext *actx = survive_async_init(argc, argv); if (actx == 0) // implies -help or similiar return 0; -- cgit v1.2.3 From d6d310fdd13c11382f37faca6a0c20b361ae9c40 Mon Sep 17 00:00:00 2001 From: Justin Berger Date: Wed, 4 Apr 2018 10:42:51 -0600 Subject: Added python binding --- Makefile | 5 +-- bindings/python/Makefile | 7 ++++ bindings/python/example.py | 13 +++++++ bindings/python/libsurvive.py | 83 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 106 insertions(+), 2 deletions(-) create mode 100644 bindings/python/Makefile create mode 100644 bindings/python/example.py create mode 100644 bindings/python/libsurvive.py diff --git a/Makefile b/Makefile index 8493f18..7532dce 100644 --- a/Makefile +++ b/Makefile @@ -2,12 +2,13 @@ all : lib data_recorder test calibrate calibrate_client simple_pose_test CC?=gcc -CFLAGS:=-Iinclude/libsurvive -fPIC -g -O3 -Iredist -flto -DUSE_DOUBLE -std=gnu99 -rdynamic -llapacke -lcblas -lm #-fsanitize=address -fsanitize=undefined -Wall -Wno-unused-variable -Wno-switch -Wno-unused-but-set-variable -Wno-pointer-sign -Wno-parentheses + +CFLAGS:=-Iinclude/libsurvive -fPIC -g -O3 -Iredist -flto -DUSE_DOUBLE -std=gnu99 -rdynamic #-fsanitize=address -fsanitize=undefined -Wall -Wno-unused-variable -Wno-switch -Wno-unused-but-set-variable -Wno-pointer-sign -Wno-parentheses CFLAGS_RELEASE:=-Iinclude/libsurvive -fPIC -msse2 -ftree-vectorize -O3 -Iredist -flto -DUSE_DOUBLE -std=gnu99 -rdynamic -llapacke -lcblas -lm #LDFLAGS:=-L/usr/local/lib -lpthread -lusb-1.0 -lz -lm -flto -g -LDFLAGS:=-L/usr/local/lib -lpthread -lz -lm -flto -g +LDFLAGS:=-L/usr/local/lib -lpthread -lz -llapacke -lcblas -lm -flto -g #---------- # Platform specific changes to CFLAGS/LDFLAGS diff --git a/bindings/python/Makefile b/bindings/python/Makefile new file mode 100644 index 0000000..d3f846e --- /dev/null +++ b/bindings/python/Makefile @@ -0,0 +1,7 @@ +_libsurvive.so: ../../lib/libsurvive.so + cp ../../lib/libsurvive.so _libsurvive.so + +../../lib/libsurvive.so: .always + cd ../.. && make clean all + +.always: diff --git a/bindings/python/example.py b/bindings/python/example.py new file mode 100644 index 0000000..5454fbc --- /dev/null +++ b/bindings/python/example.py @@ -0,0 +1,13 @@ +import libsurvive +import sys + +actx = libsurvive.AsyncContext(sys.argv) + +for obj in actx.Objects(): + print(obj.Name()) + +while actx.Running(): + updated = actx.NextUpdated() + if updated: + print(updated.Name(), updated.Pose()) + diff --git a/bindings/python/libsurvive.py b/bindings/python/libsurvive.py new file mode 100644 index 0000000..1cf9b67 --- /dev/null +++ b/bindings/python/libsurvive.py @@ -0,0 +1,83 @@ +import ctypes + +_libsurvive = ctypes.CDLL('./_libsurvive.so') +LP_c_char = ctypes.POINTER(ctypes.c_char) +LP_LP_c_char = ctypes.POINTER(LP_c_char) + +_libsurvive.survive_async_init.argtypes = (ctypes.c_int, LP_LP_c_char) # argc, argv +_libsurvive.survive_async_init.restype = ctypes.c_void_p + +_libsurvive.survive_async_get_next_tracked.argtypes = [ctypes.c_void_p, ctypes.c_void_p] +_libsurvive.survive_async_get_next_tracked.restype = ctypes.c_void_p + +_libsurvive.survive_async_get_first_tracked.argtypes = [ctypes.c_void_p] +_libsurvive.survive_async_get_first_tracked.restype = ctypes.c_void_p + +_libsurvive.survive_async_get_next_updated.argtypes = [ctypes.c_void_p] +_libsurvive.survive_async_get_next_updated.restype = ctypes.c_void_p + +_libsurvive.survive_async_object_name.argtypes = [ ctypes.c_void_p ] +_libsurvive.survive_async_object_name.restype = ctypes.c_char_p + +_libsurvive.survive_async_is_running.argtypes = [ctypes.c_void_p] +_libsurvive.survive_async_is_running.restype = ctypes.c_bool + +_libsurvive.survive_async_start_thread.argtypes = [ctypes.c_void_p] +_libsurvive.survive_async_start_thread.restype = None + +class SurvivePose(ctypes.Structure): + _fields_ = [ + ('Pos', ctypes.c_double * 3), + ('Rot', ctypes.c_double * 4) + ] + def __repr__(self): + return '[{0} {1} {2}], [{3} {4} {5} {6}]'.format(self.Pos[0],self.Pos[1],self.Pos[2],self.Rot[0],self.Rot[1],self.Rot[2],self.Rot[3]) + + +_libsurvive.survive_async_object_get_latest_pose.argtypes = [ctypes.c_void_p, ctypes.POINTER(SurvivePose)] +_libsurvive.survive_async_object_get_latest_pose.restype = ctypes.c_uint + +class AsyncObject: + ptr = 0 + def __init__(self, ptr): + self.ptr = ptr + + def Name(self): + return _libsurvive.survive_async_object_name(self.ptr) + + def Pose(self): + pose = SurvivePose() + time = _libsurvive.survive_async_object_get_latest_pose(self.ptr, pose) + return (pose, time) + +class AsyncContext: + ptr = 0 + objects = [] + + def __init__(self, args): + argc = len(args) + argv = (LP_c_char * (argc + 1))() + for i, arg in enumerate(args): + enc_arg = arg.encode('utf-8') + argv[i] = ctypes.create_string_buffer(enc_arg) + self.ptr = _libsurvive.survive_async_init(argc, argv) + + self.objects = [] + curr = _libsurvive.survive_async_get_first_tracked(self.ptr); + while curr: + self.objects.append(AsyncObject(curr)) + curr = _libsurvive.survive_async_get_next_tracked(self.ptr, curr); + _libsurvive.survive_async_start_thread(self.ptr) + + def Objects(self): + return self.objects + + def Running(self): + return _libsurvive.survive_async_is_running(self.ptr) + + def NextUpdated(self): + ptr = _libsurvive.survive_async_get_next_updated(self.ptr) + if ptr: + return AsyncObject(ptr) + return None + -- cgit v1.2.3 From 9e1883922de980c01e60bde10c1e67261752afa6 Mon Sep 17 00:00:00 2001 From: Justin Berger Date: Thu, 5 Apr 2018 07:56:01 -0600 Subject: Fixed typo; naming suggestions --- api_example.c | 3 ++- include/libsurvive/survive_api.h | 10 +++++----- src/survive_api.c | 11 ++++++----- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/api_example.c b/api_example.c index 515c4e6..b0c9e4c 100644 --- a/api_example.c +++ b/api_example.c @@ -15,7 +15,8 @@ int main(int argc, char **argv) { SurvivePose pose; - for (const SurviveAsyncObject* it = survive_async_get_first_tracked(actx); it != 0; it = survive_async_get_next_tracked(actx, it)) { + for (const SurviveAsyncObject *it = survive_async_get_first_object(actx); it != 0; + it = survive_async_get_next_object(actx, it)) { uint32_t timecode = survive_async_object_get_latest_pose(it, &pose); printf("%s (%u): %f %f %f %f %f %f %f\n", survive_async_object_name(it), timecode, pose.Pos[0], pose.Pos[1], pose.Pos[2], pose.Rot[0], pose.Rot[1], pose.Rot[2], pose.Rot[3]); diff --git a/include/libsurvive/survive_api.h b/include/libsurvive/survive_api.h index 52eca8d..fc4ce2c 100644 --- a/include/libsurvive/survive_api.h +++ b/include/libsurvive/survive_api.h @@ -20,7 +20,7 @@ extern "C" { SURVIVE_EXPORT void survive_async_close(SurviveAsyncContext* actx); /** - * Start the background thread which processes images. + * Start the background thread which processes various inputs and produces deliverable data like position. */ SURVIVE_EXPORT void survive_async_start_thread(SurviveAsyncContext* actx); @@ -33,14 +33,14 @@ extern "C" { typedef struct SurviveAsyncObject SurviveAsyncObject; /** - * Get the first known object. Note that the first n objects are the lighthouses; for however many you are - * configured for. + * Get the first known object. Note that this also includes lighthouses */ - SURVIVE_EXPORT const SurviveAsyncObject* survive_async_get_first_tracked(SurviveAsyncContext* actx); + SURVIVE_EXPORT const SurviveAsyncObject *survive_async_get_first_object(SurviveAsyncContext *actx); /** * Get the next known object from a current one. */ - SURVIVE_EXPORT const SurviveAsyncObject* survive_async_get_next_tracked(SurviveAsyncContext* actx, const SurviveAsyncObject* curr); + SURVIVE_EXPORT const SurviveAsyncObject *survive_async_get_next_object(SurviveAsyncContext *actx, + const SurviveAsyncObject *curr); /** * Gets the next object which has been updated since we last looked at it with this function diff --git a/src/survive_api.c b/src/survive_api.c index bb1f090..e2c3d54 100644 --- a/src/survive_api.c +++ b/src/survive_api.c @@ -12,7 +12,7 @@ struct SurviveAsyncObject { } type; union { - int lighthosue; + int lighthouse; struct SurviveObject* so; } data; @@ -67,7 +67,7 @@ struct SurviveAsyncContext *survive_async_init(int argc, char *const *argv) { int i = 0; for (i = 0; i < ctx->activeLighthouses; i++) { struct SurviveAsyncObject* obj = &actx->objects[i]; - obj->data.lighthosue = i; + obj->data.lighthouse = i; obj->type = SurviveAsyncObject_LIGHTHOUSE; obj->actx = actx; obj->has_update = ctx->bsd[i].PositionSet; @@ -122,14 +122,15 @@ int survive_async_stop_thread(struct SurviveAsyncContext* actx) { return error; } -const struct SurviveAsyncObject* survive_async_get_next_tracked(struct SurviveAsyncContext* actx, const struct SurviveAsyncObject* curr) { +const struct SurviveAsyncObject *survive_async_get_next_object(struct SurviveAsyncContext *actx, + const struct SurviveAsyncObject *curr) { const struct SurviveAsyncObject* next = curr + 1; if (next >= actx->objects + actx->object_ct) return 0; return next; } -const struct SurviveAsyncObject* survive_async_get_first_tracked(struct SurviveAsyncContext* actx) { +const struct SurviveAsyncObject *survive_async_get_first_object(struct SurviveAsyncContext *actx) { return actx->objects; } @@ -150,7 +151,7 @@ uint32_t survive_async_object_get_latest_pose(const struct SurviveAsyncObject* s switch (sao->type) { case SurviveAsyncObject_LIGHTHOUSE: { if(pose) - *pose = sao->actx->ctx->bsd[sao->data.lighthosue].Pose; + *pose = sao->actx->ctx->bsd[sao->data.lighthouse].Pose; break; } case SurviveAsyncObject_OBJECT: -- cgit v1.2.3 From 0653df1da7364e75953eea85e92d23f2b41480be Mon Sep 17 00:00:00 2001 From: Justin Berger Date: Thu, 5 Apr 2018 08:39:25 -0600 Subject: Fixed naming in python binding --- bindings/python/libsurvive.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/bindings/python/libsurvive.py b/bindings/python/libsurvive.py index 1cf9b67..e88657a 100644 --- a/bindings/python/libsurvive.py +++ b/bindings/python/libsurvive.py @@ -7,11 +7,11 @@ LP_LP_c_char = ctypes.POINTER(LP_c_char) _libsurvive.survive_async_init.argtypes = (ctypes.c_int, LP_LP_c_char) # argc, argv _libsurvive.survive_async_init.restype = ctypes.c_void_p -_libsurvive.survive_async_get_next_tracked.argtypes = [ctypes.c_void_p, ctypes.c_void_p] -_libsurvive.survive_async_get_next_tracked.restype = ctypes.c_void_p +_libsurvive.survive_async_get_next_object.argtypes = [ctypes.c_void_p, ctypes.c_void_p] +_libsurvive.survive_async_get_next_object.restype = ctypes.c_void_p -_libsurvive.survive_async_get_first_tracked.argtypes = [ctypes.c_void_p] -_libsurvive.survive_async_get_first_tracked.restype = ctypes.c_void_p +_libsurvive.survive_async_get_first_object.argtypes = [ctypes.c_void_p] +_libsurvive.survive_async_get_first_object.restype = ctypes.c_void_p _libsurvive.survive_async_get_next_updated.argtypes = [ctypes.c_void_p] _libsurvive.survive_async_get_next_updated.restype = ctypes.c_void_p @@ -63,10 +63,10 @@ class AsyncContext: self.ptr = _libsurvive.survive_async_init(argc, argv) self.objects = [] - curr = _libsurvive.survive_async_get_first_tracked(self.ptr); + curr = _libsurvive.survive_async_get_first_object(self.ptr); while curr: self.objects.append(AsyncObject(curr)) - curr = _libsurvive.survive_async_get_next_tracked(self.ptr, curr); + curr = _libsurvive.survive_async_get_next_object(self.ptr, curr); _libsurvive.survive_async_start_thread(self.ptr) def Objects(self): -- cgit v1.2.3 From 30cfb87ec0d95e0cb8a671cf8f2327b4204927ed Mon Sep 17 00:00:00 2001 From: Justin Berger Date: Tue, 10 Apr 2018 23:44:36 -0600 Subject: Renamed api; fixed various warnings --- api_example.c | 25 +++++----- include/libsurvive/survive_api.h | 104 +++++++++++++++++++-------------------- src/survive_api.c | 98 +++++++++++++++++------------------- 3 files changed, 111 insertions(+), 116 deletions(-) diff --git a/api_example.c b/api_example.c index b0c9e4c..1f06740 100644 --- a/api_example.c +++ b/api_example.c @@ -4,31 +4,32 @@ #include int main(int argc, char **argv) { - SurviveAsyncContext *actx = survive_async_init(argc, argv); + SurviveSimpleContext *actx = survive_simple_init(argc, argv); if (actx == 0) // implies -help or similiar return 0; - survive_async_start_thread(actx); + survive_simple_start_thread(actx); - while (survive_async_is_running(actx)) { + while (survive_simple_is_running(actx)) { OGUSleep(30000); SurvivePose pose; - for (const SurviveAsyncObject *it = survive_async_get_first_object(actx); it != 0; - it = survive_async_get_next_object(actx, it)) { - uint32_t timecode = survive_async_object_get_latest_pose(it, &pose); - printf("%s (%u): %f %f %f %f %f %f %f\n", survive_async_object_name(it), timecode, - pose.Pos[0], pose.Pos[1], pose.Pos[2], pose.Rot[0], pose.Rot[1], pose.Rot[2], pose.Rot[3]); + for (const SurviveSimpleObject *it = survive_simple_get_first_object(actx); it != 0; + it = survive_simple_get_next_object(actx, it)) { + uint32_t timecode = survive_simple_object_get_latest_pose(it, &pose); + printf("%s (%u): %f %f %f %f %f %f %f\n", survive_simple_object_name(it), timecode, pose.Pos[0], + pose.Pos[1], pose.Pos[2], pose.Rot[0], pose.Rot[1], pose.Rot[2], pose.Rot[3]); } OGUSleep(30000); - for (const SurviveAsyncObject* it = survive_async_get_next_updated(actx); it != 0; it = survive_async_get_next_updated(actx)) { - printf("%s changed since last checked\n", survive_async_object_name(it)); + for (const SurviveSimpleObject *it = survive_simple_get_next_updated(actx); it != 0; + it = survive_simple_get_next_updated(actx)) { + printf("%s changed since last checked\n", survive_simple_object_name(it)); } } - - survive_async_close(actx); + + survive_simple_close(actx); return 0; } diff --git a/include/libsurvive/survive_api.h b/include/libsurvive/survive_api.h index fc4ce2c..64d1271 100644 --- a/include/libsurvive/survive_api.h +++ b/include/libsurvive/survive_api.h @@ -5,58 +5,58 @@ extern "C" { #endif - struct SurviveAsyncContext; - typedef struct SurviveAsyncContext SurviveAsyncContext; - - /*** - * Initialize a new instance of an async context -- mirrors survive_init - * @return Pointer to the async context - */ - SURVIVE_EXPORT SurviveAsyncContext *survive_async_init(int argc, char *const *argv); - - /** - * Close all devices and free all memory associated with the given context - */ - SURVIVE_EXPORT void survive_async_close(SurviveAsyncContext* actx); - - /** - * Start the background thread which processes various inputs and produces deliverable data like position. - */ - SURVIVE_EXPORT void survive_async_start_thread(SurviveAsyncContext* actx); - - /** - * @return true iff the background thread is still running - */ - SURVIVE_EXPORT bool survive_async_is_running(SurviveAsyncContext *actx); - - struct SurviveAsyncObject; - typedef struct SurviveAsyncObject SurviveAsyncObject; - - /** - * Get the first known object. Note that this also includes lighthouses - */ - SURVIVE_EXPORT const SurviveAsyncObject *survive_async_get_first_object(SurviveAsyncContext *actx); - /** - * Get the next known object from a current one. - */ - SURVIVE_EXPORT const SurviveAsyncObject *survive_async_get_next_object(SurviveAsyncContext *actx, - const SurviveAsyncObject *curr); - - /** - * Gets the next object which has been updated since we last looked at it with this function - */ - SURVIVE_EXPORT const SurviveAsyncObject *survive_async_get_next_updated(SurviveAsyncContext *actx); - - /** - * Gets the pose of a given object - */ - SURVIVE_EXPORT survive_timecode survive_async_object_get_latest_pose(const SurviveAsyncObject *sao, - SurvivePose *pose); - - /** - * Gets the null terminated name of the object. - */ - SURVIVE_EXPORT const char *survive_async_object_name(const SurviveAsyncObject *sao); +struct SurviveSimpleContext; +typedef struct SurviveSimpleContext SurviveSimpleContext; + +/*** + * Initialize a new instance of an simple context -- mirrors survive_init + * @return Pointer to the simple context + */ +SURVIVE_EXPORT SurviveSimpleContext *survive_simple_init(int argc, char *const *argv); + +/** + * Close all devices and free all memory associated with the given context + */ +SURVIVE_EXPORT void survive_simple_close(SurviveSimpleContext *actx); + +/** + * Start the background thread which processes various inputs and produces deliverable data like position. + */ +SURVIVE_EXPORT void survive_simple_start_thread(SurviveSimpleContext *actx); + +/** + * @return true iff the background thread is still running + */ +SURVIVE_EXPORT bool survive_simple_is_running(SurviveSimpleContext *actx); + +struct SurviveSimpleObject; +typedef struct SurviveSimpleObject SurviveSimpleObject; + +/** + * Get the first known object. Note that this also includes lighthouses + */ +SURVIVE_EXPORT const SurviveSimpleObject *survive_simple_get_first_object(SurviveSimpleContext *actx); +/** + * Get the next known object from a current one. + */ +SURVIVE_EXPORT const SurviveSimpleObject *survive_simple_get_next_object(SurviveSimpleContext *actx, + const SurviveSimpleObject *curr); + +/** + * Gets the next object which has been updated since we last looked at it with this function + */ +SURVIVE_EXPORT const SurviveSimpleObject *survive_simple_get_next_updated(SurviveSimpleContext *actx); + +/** + * Gets the pose of a given object + */ +SURVIVE_EXPORT survive_timecode survive_simple_object_get_latest_pose(const SurviveSimpleObject *sao, + SurvivePose *pose); + +/** + * Gets the null terminated name of the object. + */ +SURVIVE_EXPORT const char *survive_simple_object_name(const SurviveSimpleObject *sao); #ifdef __cplusplus } diff --git a/src/survive_api.c b/src/survive_api.c index e2c3d54..a39524b 100644 --- a/src/survive_api.c +++ b/src/survive_api.c @@ -3,13 +3,10 @@ #include "survive.h" #include "stdio.h" -struct SurviveAsyncObject { - struct SurviveAsyncContext* actx; - - enum SurviveAsyncObject_type { - SurviveAsyncObject_LIGHTHOUSE, - SurviveAsyncObject_OBJECT - } type; +struct SurviveSimpleObject { + struct SurviveSimpleContext *actx; + + enum SurviveSimpleObject_type { SurviveSimpleObject_LIGHTHOUSE, SurviveSimpleObject_OBJECT } type; union { int lighthouse; @@ -20,7 +17,7 @@ struct SurviveAsyncObject { bool has_update; }; -struct SurviveAsyncContext { +struct SurviveSimpleContext { SurviveContext* ctx; bool running; @@ -28,21 +25,21 @@ struct SurviveAsyncContext { og_mutex_t poll_mutex; size_t object_ct; - struct SurviveAsyncObject objects[]; + struct SurviveSimpleObject objects[]; }; static void pose_fn(SurviveObject *so, uint32_t timecode, SurvivePose *pose) { - struct SurviveAsyncContext *actx = so->ctx->user_ptr; + struct SurviveSimpleContext *actx = so->ctx->user_ptr; OGLockMutex(actx->poll_mutex); - survive_default_raw_pose_process(so, timecode, pose); + survive_default_raw_pose_process(so, timecode, pose); - int idx = (int)so->user_ptr; + intptr_t idx = (intptr_t)so->user_ptr; actx->objects[idx].has_update = true; OGUnlockMutex(actx->poll_mutex); } static void lh_fn(SurviveContext *ctx, uint8_t lighthouse, SurvivePose *lighthouse_pose, SurvivePose *object_pose) { - struct SurviveAsyncContext *actx = ctx->user_ptr; + struct SurviveSimpleContext *actx = ctx->user_ptr; OGLockMutex(actx->poll_mutex); survive_default_lighthouse_pose_process(ctx, lighthouse, lighthouse_pose, object_pose); @@ -51,7 +48,7 @@ static void lh_fn(SurviveContext *ctx, uint8_t lighthouse, SurvivePose *lighthou OGUnlockMutex(actx->poll_mutex); } -struct SurviveAsyncContext *survive_async_init(int argc, char *const *argv) { +struct SurviveSimpleContext *survive_simple_init(int argc, char *const *argv) { SurviveContext* ctx = survive_init(argc, argv); if (ctx == 0) return 0; @@ -59,25 +56,26 @@ struct SurviveAsyncContext *survive_async_init(int argc, char *const *argv) { survive_startup(ctx); int object_ct = ctx->activeLighthouses + ctx->objs_ct; - struct SurviveAsyncContext * actx = calloc(1, sizeof(struct SurviveAsyncContext) + sizeof(struct SurviveAsyncObject) * object_ct ); + struct SurviveSimpleContext *actx = + calloc(1, sizeof(struct SurviveSimpleContext) + sizeof(struct SurviveSimpleObject) * object_ct); actx->object_ct = object_ct; actx->ctx = ctx; actx->poll_mutex = OGCreateMutex(); ctx->user_ptr = actx; - int i = 0; + intptr_t i = 0; for (i = 0; i < ctx->activeLighthouses; i++) { - struct SurviveAsyncObject* obj = &actx->objects[i]; + struct SurviveSimpleObject *obj = &actx->objects[i]; obj->data.lighthouse = i; - obj->type = SurviveAsyncObject_LIGHTHOUSE; + obj->type = SurviveSimpleObject_LIGHTHOUSE; obj->actx = actx; obj->has_update = ctx->bsd[i].PositionSet; - snprintf(obj->name, 32, "LH%d", i); + snprintf(obj->name, 32, "LH%ld", i); } for (; i < object_ct; i++) { - struct SurviveAsyncObject* obj = &actx->objects[i]; + struct SurviveSimpleObject *obj = &actx->objects[i]; int so_idx = i - ctx->activeLighthouses; obj->data.so = ctx->objs[so_idx]; - obj->type = SurviveAsyncObject_OBJECT; + obj->type = SurviveSimpleObject_OBJECT; obj->actx = actx; obj->data.so->user_ptr = (void*)i; snprintf(obj->name, 32, "%s", obj->data.so->codename); @@ -88,53 +86,52 @@ struct SurviveAsyncContext *survive_async_init(int argc, char *const *argv) { return actx; } -void survive_async_close(struct SurviveAsyncContext* actx) { +int survive_simple_stop_thread(struct SurviveSimpleContext *actx) { + actx->running = false; + intptr_t error = (intptr_t)OGJoinThread(actx->thread); + if (error != 0) { + SurviveContext *ctx = actx->ctx; + SV_INFO("Warning: Loope exited with error %ld", error); + } + return error; +} + +void survive_simple_close(struct SurviveSimpleContext *actx) { if (actx->running) { - survive_async_stop_thread(actx); + survive_simple_stop_thread(actx); } survive_close(actx->ctx); } -static inline void* __async_thread(void* _actx) { - struct SurviveAsyncContext* actx = _actx; - int error = 0; +static inline void *__simple_thread(void *_actx) { + struct SurviveSimpleContext *actx = _actx; + intptr_t error = 0; while (actx->running && error == 0) { error = survive_poll(actx->ctx); } actx->running = false; return (void*)error; } -bool survive_async_is_running(struct SurviveAsyncContext* actx) { - return actx->running; -} -void survive_async_start_thread(struct SurviveAsyncContext* actx) { +bool survive_simple_is_running(struct SurviveSimpleContext *actx) { return actx->running; } +void survive_simple_start_thread(struct SurviveSimpleContext *actx) { actx->running = true; - actx->thread = OGCreateThread(__async_thread, actx); -} -int survive_async_stop_thread(struct SurviveAsyncContext* actx) { - actx->running = false; - int error = (int)OGJoinThread(actx->thread); - if (error != 0) { - SurviveContext* ctx = actx->ctx; - SV_INFO("Warning: Loope exited with error %d", error); - } - return error; + actx->thread = OGCreateThread(__simple_thread, actx); } -const struct SurviveAsyncObject *survive_async_get_next_object(struct SurviveAsyncContext *actx, - const struct SurviveAsyncObject *curr) { - const struct SurviveAsyncObject* next = curr + 1; +const struct SurviveSimpleObject *survive_simple_get_next_object(struct SurviveSimpleContext *actx, + const struct SurviveSimpleObject *curr) { + const struct SurviveSimpleObject *next = curr + 1; if (next >= actx->objects + actx->object_ct) return 0; return next; } -const struct SurviveAsyncObject *survive_async_get_first_object(struct SurviveAsyncContext *actx) { +const struct SurviveSimpleObject *survive_simple_get_first_object(struct SurviveSimpleContext *actx) { return actx->objects; } -const struct SurviveAsyncObject* survive_async_get_next_updated(struct SurviveAsyncContext* actx) { +const struct SurviveSimpleObject *survive_simple_get_next_updated(struct SurviveSimpleContext *actx) { for (int i = 0; i < actx->object_ct; i++) { if (actx->objects[i].has_update) { actx->objects[i].has_update = false; @@ -144,17 +141,17 @@ const struct SurviveAsyncObject* survive_async_get_next_updated(struct SurviveAs return 0; } -uint32_t survive_async_object_get_latest_pose(const struct SurviveAsyncObject* sao, SurvivePose* pose) { +uint32_t survive_simple_object_get_latest_pose(const struct SurviveSimpleObject *sao, SurvivePose *pose) { uint32_t timecode = 0; OGLockMutex(sao->actx->poll_mutex); switch (sao->type) { - case SurviveAsyncObject_LIGHTHOUSE: { + case SurviveSimpleObject_LIGHTHOUSE: { if(pose) *pose = sao->actx->ctx->bsd[sao->data.lighthouse].Pose; break; } - case SurviveAsyncObject_OBJECT: + case SurviveSimpleObject_OBJECT: if(pose) *pose = sao->data.so->OutPose; timecode = sao->data.so->OutPose_timecode; @@ -165,7 +162,4 @@ uint32_t survive_async_object_get_latest_pose(const struct SurviveAsyncObject* s return timecode; } -const char * survive_async_object_name(const SurviveAsyncObject * sao) -{ - return sao->name; -} +const char *survive_simple_object_name(const SurviveSimpleObject *sao) { return sao->name; } -- cgit v1.2.3 From 5f429662488533ff4f4384b678ae738244972cc6 Mon Sep 17 00:00:00 2001 From: Justin Berger Date: Tue, 10 Apr 2018 23:48:36 -0600 Subject: Updated naming of python binding --- bindings/python/example.py | 2 +- bindings/python/libsurvive.py | 56 +++++++++++++++++++++---------------------- 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/bindings/python/example.py b/bindings/python/example.py index 5454fbc..32d58de 100644 --- a/bindings/python/example.py +++ b/bindings/python/example.py @@ -1,7 +1,7 @@ import libsurvive import sys -actx = libsurvive.AsyncContext(sys.argv) +actx = libsurvive.SimpleContext(sys.argv) for obj in actx.Objects(): print(obj.Name()) diff --git a/bindings/python/libsurvive.py b/bindings/python/libsurvive.py index e88657a..653eb60 100644 --- a/bindings/python/libsurvive.py +++ b/bindings/python/libsurvive.py @@ -4,26 +4,26 @@ _libsurvive = ctypes.CDLL('./_libsurvive.so') LP_c_char = ctypes.POINTER(ctypes.c_char) LP_LP_c_char = ctypes.POINTER(LP_c_char) -_libsurvive.survive_async_init.argtypes = (ctypes.c_int, LP_LP_c_char) # argc, argv -_libsurvive.survive_async_init.restype = ctypes.c_void_p +_libsurvive.survive_simple_init.argtypes = (ctypes.c_int, LP_LP_c_char) # argc, argv +_libsurvive.survive_simple_init.restype = ctypes.c_void_p -_libsurvive.survive_async_get_next_object.argtypes = [ctypes.c_void_p, ctypes.c_void_p] -_libsurvive.survive_async_get_next_object.restype = ctypes.c_void_p +_libsurvive.survive_simple_get_next_object.argtypes = [ctypes.c_void_p, ctypes.c_void_p] +_libsurvive.survive_simple_get_next_object.restype = ctypes.c_void_p -_libsurvive.survive_async_get_first_object.argtypes = [ctypes.c_void_p] -_libsurvive.survive_async_get_first_object.restype = ctypes.c_void_p +_libsurvive.survive_simple_get_first_object.argtypes = [ctypes.c_void_p] +_libsurvive.survive_simple_get_first_object.restype = ctypes.c_void_p -_libsurvive.survive_async_get_next_updated.argtypes = [ctypes.c_void_p] -_libsurvive.survive_async_get_next_updated.restype = ctypes.c_void_p +_libsurvive.survive_simple_get_next_updated.argtypes = [ctypes.c_void_p] +_libsurvive.survive_simple_get_next_updated.restype = ctypes.c_void_p -_libsurvive.survive_async_object_name.argtypes = [ ctypes.c_void_p ] -_libsurvive.survive_async_object_name.restype = ctypes.c_char_p +_libsurvive.survive_simple_object_name.argtypes = [ ctypes.c_void_p ] +_libsurvive.survive_simple_object_name.restype = ctypes.c_char_p -_libsurvive.survive_async_is_running.argtypes = [ctypes.c_void_p] -_libsurvive.survive_async_is_running.restype = ctypes.c_bool +_libsurvive.survive_simple_is_running.argtypes = [ctypes.c_void_p] +_libsurvive.survive_simple_is_running.restype = ctypes.c_bool -_libsurvive.survive_async_start_thread.argtypes = [ctypes.c_void_p] -_libsurvive.survive_async_start_thread.restype = None +_libsurvive.survive_simple_start_thread.argtypes = [ctypes.c_void_p] +_libsurvive.survive_simple_start_thread.restype = None class SurvivePose(ctypes.Structure): _fields_ = [ @@ -34,23 +34,23 @@ class SurvivePose(ctypes.Structure): return '[{0} {1} {2}], [{3} {4} {5} {6}]'.format(self.Pos[0],self.Pos[1],self.Pos[2],self.Rot[0],self.Rot[1],self.Rot[2],self.Rot[3]) -_libsurvive.survive_async_object_get_latest_pose.argtypes = [ctypes.c_void_p, ctypes.POINTER(SurvivePose)] -_libsurvive.survive_async_object_get_latest_pose.restype = ctypes.c_uint +_libsurvive.survive_simple_object_get_latest_pose.argtypes = [ctypes.c_void_p, ctypes.POINTER(SurvivePose)] +_libsurvive.survive_simple_object_get_latest_pose.restype = ctypes.c_uint -class AsyncObject: +class SimpleObject: ptr = 0 def __init__(self, ptr): self.ptr = ptr def Name(self): - return _libsurvive.survive_async_object_name(self.ptr) + return _libsurvive.survive_simple_object_name(self.ptr) def Pose(self): pose = SurvivePose() - time = _libsurvive.survive_async_object_get_latest_pose(self.ptr, pose) + time = _libsurvive.survive_simple_object_get_latest_pose(self.ptr, pose) return (pose, time) -class AsyncContext: +class SimpleContext: ptr = 0 objects = [] @@ -60,24 +60,24 @@ class AsyncContext: for i, arg in enumerate(args): enc_arg = arg.encode('utf-8') argv[i] = ctypes.create_string_buffer(enc_arg) - self.ptr = _libsurvive.survive_async_init(argc, argv) + self.ptr = _libsurvive.survive_simple_init(argc, argv) self.objects = [] - curr = _libsurvive.survive_async_get_first_object(self.ptr); + curr = _libsurvive.survive_simple_get_first_object(self.ptr); while curr: - self.objects.append(AsyncObject(curr)) - curr = _libsurvive.survive_async_get_next_object(self.ptr, curr); - _libsurvive.survive_async_start_thread(self.ptr) + self.objects.append(SimpleObject(curr)) + curr = _libsurvive.survive_simple_get_next_object(self.ptr, curr); + _libsurvive.survive_simple_start_thread(self.ptr) def Objects(self): return self.objects def Running(self): - return _libsurvive.survive_async_is_running(self.ptr) + return _libsurvive.survive_simple_is_running(self.ptr) def NextUpdated(self): - ptr = _libsurvive.survive_async_get_next_updated(self.ptr) + ptr = _libsurvive.survive_simple_get_next_updated(self.ptr) if ptr: - return AsyncObject(ptr) + return SimpleObject(ptr) return None -- cgit v1.2.3