You should always use libphantom, additionally, you may use phlib, which uses libphantom itself, so that you may not bother with it.
Libphantom is a basic (and simple) interface between phantom, kernel and the user process. Realize, that there is no other way to do so in this version (version for 2.6 linux) of phantom.
libph-test.c as an basic example of libphantom usage follows:
#include <fcntl.h> #include <stdio.h> #include <unistd.h> #include <linux/types.h> #include <sys/time.h> #include <time.h> #include <libphantom.h> #define print2(args...) fprintf(stderr, args) //#define SPHERE #define N 64 static unsigned long frequency = 1000; static float center[3]; static const double radius = 0.05; static const float stiffness = 1000.0 / 2.0; #ifdef SPHERE static void object(struct phantom_info *p, float force[]) /* sphere */ { float x = p->actual.pos[0] - center[0]; float y = p->actual.pos[1] - center[1]; float z = p->actual.pos[2] - center[2]; float n = x * x + y * y + z * z; if (n <= radius * radius) { double d = (n > 0.0001) ? (radius / sqrt(n) - 1) * stiffness : 10; force[0] = x * d; force[1] = y * d; force[2] = z * d; } else force[0] = force[1] = force[2] = 0.0; } #else static void object(struct phantom_info *p, float force[]) /* plane */ { const float A = 0; const float B = 0; const float C = 1; const float D = -0.0; /* select X m above zero */ float delta = A * p->actual.pos[0] + B * p->actual.pos[1] + C * p->actual.pos[2] + D; if (delta > 0) { force[0] = force[1] = force[2] = 0; } else { /* we want opposite force depending on the depth you are inside the sphere */ delta = -delta * stiffness; force[0] = A * delta; force[1] = B * delta; force[2] = C * delta; } } #endif static inline unsigned int print_rate(unsigned int i) { return !(i % 10); } static void test(struct phantom_device *dev) { struct phantom_info *p; unsigned int i, tm, maxtm; unsigned long it = 0; double speed[2*N], a[N]; float force[3]; tm = 0; maxtm = 1; memset(a, 0, sizeof(a)); p = phm_switch(dev); memset(&p->force, 0, sizeof(p->force)); phm_wait(dev); p = phm_switch(dev); /* get actual phantom position and set center */ center[0] = center[1] = center[2] = 0.0; memset(speed, 0, sizeof(speed)); dev->iterations = 1; for (i = 1; (!(dev->status & PHM_ERROR) && i < frequency * 15) ; i++) { /* wait for new data */ phm_wait(dev); it++; p = phm_switch(dev); object(p, force); phm_force_clamp_max(force, PHM_DEFAULT_MAX_FORCE); memcpy(p->force, force, sizeof(force)); if (print_rate(i)) { printf("force: %f %f %f\n", p->force[0], p->force[1], p->force[2]); } if (tm > maxtm) maxtm = tm; if (print_rate(i)) { printf("pos: %f %f %f\n", p->actual.pos[0], p->actual.pos[1], p->actual.pos[2]); /* printf("ang: %f %f %f\n", p->actual.alpha, p->actual.beta, p->actual.gamma); */ } } printf("Iterations: %lu global iterations: %lu diff: %lu\n", it, dev->iterations, dev->iterations - it); printf("Forces: %f %f %f \n", p->force[0], p->force[1], p->force[2]); } int main(int argc, char **argv) { struct phantom_device *dev; char *devname = "/dev/phantom0"; switch (argc) { case 2: devname = argv[1]; case 1: break; default: print2("Bad arguments count!\n"); goto err; } printf("devname: %s\n", devname); dev = phm_open(devname); if (dev == NULL) { print2("Can't open phantom!\n"); goto err; } if (phm_reset(dev)) { /* this sould never happen :) */ print2("Can't reset phantom!\n"); goto err_stop; } if (phm_start(dev, 0)) { print2("Can't start phantom!\n"); goto err_stop; } test(dev); phm_stop(dev); return 0; err_stop: phm_stop(dev); err: return 1; }
Note the phm_reset() call. You may omit it, but in that case, be sure, that you've involved ph-reset binary (which does the job for you). It is necessary to reset phantom at least once before using.
Note, that phm_stop() is called even if phm_start() was not called in the case of phm_reset() failure. This approach is OK.