17#ifdef VRPN_USE_LIBNIFALCON
20#include "falcon/core/FalconDevice.h"
21#include "falcon/firmware/FalconFirmwareNovintSDK.h"
22#include "falcon/grip/FalconGripFourButton.h"
23#include "falcon/kinematic/FalconKinematicStamper.h"
24#include "falcon/util/FalconFirmwareBinaryNvent.h"
28#define FALCON_NUM_RETRIES 10
39typedef std::array<double, 3> d_vector;
42static d_vector operator+(
const d_vector &a,
const d_vector &b)
52static d_vector operator-(
const d_vector &a,
const d_vector &b)
62static double d_length(
const d_vector &a)
73static double timediff(
struct timeval t1,
struct timeval t2) {
74 return (t1.tv_usec - t2.tv_usec)*1.0 + 1000000.0 * (t1.tv_sec - t2.tv_sec);
79class vrpn_NovintFalcon_Device
82 vrpn_NovintFalcon_Device(
int flags)
86 m_falconDevice = NULL;
89 m_falconDevice =
new libnifalcon::FalconDevice;
90 m_falconDevice->setFalconFirmware<libnifalcon::FalconFirmwareNovintSDK>();
93 if (m_flags & KINE_STAMPER) {
94 m_falconDevice->setFalconKinematic<libnifalcon::FalconKinematicStamper>();
97 delete m_falconDevice;
99 fprintf(stderr,
"vrpn_NovintFalcon_Device::vrpn_NovintFalcon_Device(): delete failed\n");
106 if (m_flags & GRIP_FOURBUTTON) {
107 m_falconDevice->setFalconGrip<libnifalcon::FalconGripFourButton>();
110 delete m_falconDevice;
112 fprintf(stderr,
"vrpn_NovintFalcon_Device::vrpn_NovintFalcon_Device(): delete failed\n");
120 ~vrpn_NovintFalcon_Device() {
122 fprintf(stderr,
"Closing Falcon device %d.\n", m_flags & MASK_DEVICEIDX);
124 if (m_falconDevice) {
125 std::shared_ptr<libnifalcon::FalconFirmware> f;
126 f=m_falconDevice->getFalconFirmware();
128 f->setLEDStatus(libnifalcon::FalconFirmware::RED_LED |
129 libnifalcon::FalconFirmware::BLUE_LED |
130 libnifalcon::FalconFirmware::GREEN_LED);
131 for (
int i=0; !m_falconDevice->runIOLoop() && i < FALCON_NUM_RETRIES; ++i)
continue;
133 m_falconDevice->close();
136 delete m_falconDevice;
138 fprintf(stderr,
"vrpn_NovintFalcon_Device::~vrpn_NovintFalcon_Device(): delete failed\n");
151 m_falconDevice->getDeviceCount(count);
152 int devidx = m_flags & MASK_DEVICEIDX;
155 fprintf(stderr,
"Trying to open Falcon device %d/%d.\n", devidx, count);
157 if (devidx < count) {
158 if (!m_falconDevice->open(devidx)) {
159 fprintf(stderr,
"Cannot open falcon device %d - Lib Error Code: %d - Device Error Code: %d\n",
160 devidx, m_falconDevice->getErrorCode(), m_falconDevice->getFalconComm()->getDeviceErrorCode());
164 fprintf(stderr,
"Trying to open non-existing Novint Falcon device %d\n", devidx);
168 if (!m_falconDevice->isFirmwareLoaded()) {
170 fprintf(stderr,
"Loading Falcon Firmware\n");
174 for (i=0; i<FALCON_NUM_RETRIES; ++i) {
175 if(!m_falconDevice->getFalconFirmware()->loadFirmware(
true, libnifalcon::NOVINT_FALCON_NVENT_FIRMWARE_SIZE,
const_cast<uint8_t*
>(libnifalcon::NOVINT_FALCON_NVENT_FIRMWARE)))
177 fprintf(stderr,
"Firmware loading attempt %d failed.\n", i);
178 if(i==FALCON_NUM_RETRIES-1){
179 fprintf(stderr,
"Cannot load falcon device %d firmware - Device Error Code: %d - Comm Lib Error Code: %d\n",
180 devidx, m_falconDevice->getErrorCode(), m_falconDevice->getFalconComm()->getDeviceErrorCode());
185 fprintf(stderr,
"Falcon firmware successfully loaded.\n");
193 fprintf(stderr,
"Falcon Firmware already loaded.\n");
198 bool message =
false;
199 std::shared_ptr<libnifalcon::FalconFirmware> f;
200 f=m_falconDevice->getFalconFirmware();
201 for (i=0; !m_falconDevice->runIOLoop() && i < FALCON_NUM_RETRIES; ++i)
continue;
203 f->setHomingMode(
true);
204 for (i=0; !m_falconDevice->runIOLoop() && i < FALCON_NUM_RETRIES; ++i)
continue;
206 f->setLEDStatus(libnifalcon::FalconFirmware::RED_LED);
207 for (i=0; !m_falconDevice->runIOLoop() && i < FALCON_NUM_RETRIES; ++i)
continue;
209 fprintf(stderr,
"Falcon not currently calibrated. Move control all the way out then push straight all the way in.\n");
213 f->setLEDStatus(libnifalcon::FalconFirmware::BLUE_LED);
214 for (i=0; !m_falconDevice->runIOLoop() && i < FALCON_NUM_RETRIES; ++i)
continue;
216 fprintf(stderr,
"Falcon calibrated successfully.\n");
226 for (i=0; !m_falconDevice->runIOLoop() && i < FALCON_NUM_RETRIES; ++i)
continue;
227 d_vector pos = m_falconDevice->getPosition();
232 fprintf(stderr,
"Move control all the way out until led turns green to activate device.\n");
235 if (pos[2] > 0.170) {
236 f->setLEDStatus(libnifalcon::FalconFirmware::GREEN_LED);
237 for (i=0; !m_falconDevice->runIOLoop() && i < FALCON_NUM_RETRIES; ++i)
continue;
239 fprintf(stderr,
"Falcon activated successfully.\n");
248 bool get_status(vrpn_float64 *pos, vrpn_float64 *vel,
249 vrpn_float64 *quat, vrpn_float64 *vel_quat,
250 vrpn_float64 *vel_dt,
unsigned char *buttons) {
255 for (i=0; !m_falconDevice->runIOLoop() && i < FALCON_NUM_RETRIES; ++i)
continue;
256 if ( i == FALCON_NUM_RETRIES )
276 d_vector my_pos = m_falconDevice->getPosition();
277 const double convert_pos = 1.0;
278 pos[0] = convert_pos * my_pos[0];
279 pos[1] = convert_pos * my_pos[1];
280 pos[2] = convert_pos * (my_pos[2]-0.125);
282 fprintf(stderr,
"position %5.3f %5.3f %5.3f\n", pos[0],pos[1],pos[2]);
285 struct timeval current_time;
287 double deltat = timediff(current_time, m_oldtime);
290 vel[0] = convert_pos * (my_pos[0] - m_oldpos[0]) / deltat;
291 vel[1] = convert_pos * (my_pos[1] - m_oldpos[1]) / deltat;
292 vel[2] = convert_pos * (my_pos[2] - m_oldpos[2]) / deltat;
299 fprintf(stderr,
"velocity %5.3f %5.3f %5.3f\n", vel[0],vel[1],vel[2]);
302 m_oldtime.tv_sec = current_time.tv_sec;
303 m_oldtime.tv_usec = current_time.tv_usec;
307 unsigned int my_buttons = m_falconDevice->getFalconGrip()->getDigitalInputs();
308 if (m_flags & GRIP_FOURBUTTON) {
309 buttons[0] = (my_buttons & libnifalcon::FalconGripFourButton::CENTER_BUTTON) ? 1 : 0;
310 buttons[1] = (my_buttons & libnifalcon::FalconGripFourButton::PLUS_BUTTON) ? 1 : 0;
311 buttons[2] = (my_buttons & libnifalcon::FalconGripFourButton::MINUS_BUTTON) ? 1 : 0;
312 buttons[3] = (my_buttons & libnifalcon::FalconGripFourButton::FORWARD_BUTTON) ? 1 : 0;
318 bool set_force(
const d_vector &force) {
323 m_falconDevice->setForce(force);
324 if(!m_falconDevice->runIOLoop())
332 libnifalcon::FalconDevice *m_falconDevice;
334 struct timeval m_oldtime;
338 vrpn_NovintFalcon_Device() {};
340 vrpn_NovintFalcon_Device(
const vrpn_NovintFalcon_Device &dev) {};
346 MASK_DEVICEIDX = 0x000f,
347 KINE_STAMPER = 0x0010,
348 GRIP_FOURBUTTON = 0x0100
353class ForceFieldEffect
357 ForceFieldEffect() : m_active(false), m_time(0), m_cutoff(0.0), m_damping(0.9)
360 for (i=0; i < 3; i++) {
363 for (j=0; j < 3; j++) {
364 m_jacobian[i][j] = 0.0;
370 ~ForceFieldEffect() {}
374 void setForce(vrpn_float32 ori[3], vrpn_float32 frc[3], vrpn_float32 jac[3][3], vrpn_float32 rad) {
376 for (i=0; i < 3; i++) {
377 m_neworig[i] = ori[i];
378 m_newadd[i] = frc[i];
379 for (j=0; j < 3; j++) {
380 m_newjacob[i][j] = jac[i][j];
387 void setDamping(
double damp) {
392 virtual bool start() {
402 virtual void stop() {
407 virtual bool isActive()
const {
return m_active; }
410 d_vector calcForce(
const d_vector &pos) {
411 d_vector force, offset;
415 const double mix = 1.0 - m_damping;
417 for (i=0; i < 3; i++) {
418 m_origin[i] = m_damping*m_origin[i] + mix*m_neworig[i];
419 m_addforce[i] = m_damping*m_addforce[i] + mix*m_newadd[i];
420 for (j=0; j < 3; j++) {
421 m_jacobian[i][j] = m_damping*m_jacobian[i][j] + mix*m_newjacob[i][j];
424 m_cutoff = m_damping*m_cutoff + mix*m_newcut;
426 offset = pos - m_origin;
428 if (d_length(offset) > m_cutoff) {
440 for (i=0; i<3; ++i) {
441 for (j=0; j<3; ++j) {
442 force[i] += offset[j]*m_jacobian[i][j];
455 double m_jacobian[3][3];
459 double m_newjacob[3][3];
466 vrpn_Tracker_NovintFalcon *dev = (vrpn_Tracker_NovintFalcon *)userdata;
467 dev->update_forcefield_effect(p);
472class vrpn_NovintFalcon_ForceObjects {
474 vrpn_vector<ForceFieldEffect*> m_FFEffects;
483 vrpn_NovintFalcon_ForceObjects() {
484 m_curforce.fill(0.0);
488 ~vrpn_NovintFalcon_ForceObjects() {};
491 d_vector getObjForce(vrpn_float64 *pos, vrpn_float64 *vel) {
494 for (i=0; i<3; ++i) {
501 int nobj = m_FFEffects.
size();
502 for (i=0; i<nobj; ++i) {
503 m_curforce = m_curforce + m_FFEffects[i]->calcForce (m_curpos);
510vrpn_Tracker_NovintFalcon::vrpn_Tracker_NovintFalcon(
const char *name,
517 vrpn_ForceDevice(name, c), m_dev(NULL), m_obj(NULL), m_update_rate(1000.0), m_damp(0.9)
519 m_devflags=vrpn_NovintFalcon_Device::MASK_DEVICEIDX & devidx;
521 if (0 == strcmp(grip,
"4-button")) {
522 m_devflags |= vrpn_NovintFalcon_Device::GRIP_FOURBUTTON;
525 fprintf(stderr,
"WARNING: Unknown grip for Novint Falcon #%d: %s \n", devidx, grip);
532 if (0 == strcmp(kine,
"stamper")) {
533 m_devflags |= vrpn_NovintFalcon_Device::KINE_STAMPER;
535 fprintf(stderr,
"WARNING: Unknown kinematic model for Novint Falcon #%d: %s \n", devidx, kine);
542 vrpn_float64 val= atof(damp);
543 if (val >= 1.0 && val <= 10000.0) {
544 m_damp = 1.0 - 1.0/val;
546 fprintf(stderr,
"WARNING: Ignoring illegal force effect damping factor: %g \n", val);
551 if (register_autodeleted_handler(forcefield_message_id,
553 fprintf(stderr,
"vrpn_Tracker_NovintFalcon:can't register force handler\n");
560void vrpn_Tracker_NovintFalcon::clear_values()
563 if (m_devflags < 0)
return;
573 fprintf(stderr,
"vrpn_Tracker_NovintFalcon::clear_values(): delete failed\n");
577 try { m_obj =
new vrpn_NovintFalcon_ForceObjects; }
578 catch (...) { m_obj = NULL;
return; }
581 ForceFieldEffect *ffe;
582 try { ffe =
new ForceFieldEffect; }
583 catch (...) {
return; }
584 ffe->setDamping(m_damp);
586 m_obj->m_FFEffects.push_back(ffe);
589vrpn_Tracker_NovintFalcon::~vrpn_Tracker_NovintFalcon()
592 if (m_dev)
delete m_dev;
593 if (m_obj)
delete m_obj;
595 fprintf(stderr,
"vrpn_Tracker_NovintFalcon::~vrpn_Tracker_NovintFalcon(): delete failed\n");
600void vrpn_Tracker_NovintFalcon::reset()
604 if (m_devflags < 0)
return;
609 fprintf(stderr,
"Resetting the NovintFalcon #%d\n",
610 vrpn_NovintFalcon_Device::MASK_DEVICEIDX & m_devflags);
616 fprintf(stderr,
"vrpn_Tracker_NovintFalcon::reset(): delete failed\n");
621 try { m_dev =
new vrpn_NovintFalcon_Device(m_devflags); }
624 fprintf(stderr,
"Device constructor failed!\n");
631 if (!m_dev->init()) {
633 fprintf(stderr,
"Device init failed!\n");
639 fprintf(stderr,
"Reset Completed.\n");
643int vrpn_Tracker_NovintFalcon::get_report(
void)
649 if (m_dev->get_status(pos, vel, d_quat, vel_quat, &vel_quat_dt, buttons)) {
653 for (i=0; i < num_buttons; i++)
656 if (j == num_buttons) {
668 print_latest_report();
674void vrpn_Tracker_NovintFalcon::send_report(
void)
679 if (d_connection->pack_message(len, m_timestamp, position_m_id, d_sender_id, msgbuf,
683 if (d_connection->pack_message(len, m_timestamp, velocity_m_id, d_sender_id, msgbuf,
689void vrpn_Tracker_NovintFalcon::handle_forces(
void)
695 d_vector force= m_obj->getObjForce(pos,vel);
696 m_dev->set_force(force);
702 if (!m_obj)
return 1;
704 vrpn_float32 center[3];
705 vrpn_float32 force[3];
706 vrpn_float32 jacobian[3][3];
712 m_obj->m_FFEffects[0]->start();
713 m_obj->m_FFEffects[0]->setForce(center, force, jacobian, radius);
718void vrpn_Tracker_NovintFalcon::mainloop()
720 struct timeval current_time;
725 if ( timediff(current_time, m_timestamp) >= 1000000.0/m_update_rate) {
728 m_timestamp.tv_sec = current_time.tv_sec;
729 m_timestamp.tv_usec = current_time.tv_usec;
749 fprintf(stderr,
"NovintFalcon #%d , unknown status message: %d)\n",
750 vrpn_NovintFalcon_Device::MASK_DEVICEIDX & m_devflags, status);
vrpn_int32 d_sender_id
Sender ID registered with the connection.
Generic connection class not specific to the transport mechanism.
virtual int encode_to(char *buf)
virtual int encode_vel_to(char *buf)
This structure is what is passed to a vrpn_Connection message callback.
const vrpn_uint32 vrpn_CONNECTION_LOW_LATENCY
#define vrpn_gettimeofday
const int vrpn_TRACKER_FAIL
const int vrpn_TRACKER_RESETTING
const int vrpn_TRACKER_SYNCING
const int vrpn_TRACKER_PARTIAL
const int vrpn_TRACKER_AWAITING_STATION