Main Page Namespace List Class Hierarchy Alphabetical List Compound List File List Namespace Members Compound Members File Members Related Pages

P_VRPNFeedback.C

Go to the documentation of this file.
00001 /***************************************************************************
00002 *cr 
00003 *cr (C) Copyright 1995-2019 The Board of Trustees of the 
00004 *cr University of Illinois 
00005 *cr All Rights Reserved 
00006 *cr 
00007 ***************************************************************************/
00008 
00009 /***************************************************************************
00010 * RCS INFORMATION:
00011 *
00012 * $RCSfile: P_VRPNFeedback.C,v $
00013 * $Author: johns $ $Locker: $ $State: Exp $
00014 * $Revision: 1.35 $ $Date: 2019年01月17日 21:21:01 $
00015 *
00016 ***************************************************************************
00017 * DESCRIPTION:
00018 * This is Paul's new Tracker code -- pgrayson@ks.uiuc.edu
00019 *
00020 *
00021 ***************************************************************************/
00022 
00023 #if defined(VMDVRPN)
00024 
00025 #include "P_VRPNFeedback.h"
00026 #include "utilities.h"
00027 
00028 #include <stdlib.h>
00029 #include <string.h>
00030 #include <math.h> // for sqrt()
00031 
00032 VRPNFeedback::VRPNFeedback() {
00033 fdv = NULL;
00034 }
00035 
00036 int VRPNFeedback::do_start(const SensorConfig *config) {
00037 if (fdv) return 0;
00038 if (!config->have_one_sensor()) return 0;
00039 char myUSL[100];
00040 config->make_vrpn_address(myUSL);
00041 fdv = new vrpn_ForceDevice_Remote(myUSL);
00042 set_maxforce(config->getmaxforce());
00043 
00044 // 
00045 // XXX we wish this worked, but apparently not implemented.
00046 // Have haptic device interpolate the force field between 
00047 // updates. This would help eliminate jerky updates.
00048 // fdv->setRecoveryTime(10); // make haptic constraint update smoother,
00049 // // by stepping N times between points...
00050 forceoff();
00051 return 1;
00052 }
00053 
00054 VRPNFeedback::~VRPNFeedback() {
00055 forceoff();
00056 // if(fdv) delete fdv; // XXX VRPN has broken destructors
00057 }
00058 
00059 void VRPNFeedback::update() {
00060 if(!alive()) return;
00061 // fdv->mainloop();
00062 }
00063 
00064 void VRPNFeedback::addconstraint(float k, const float *location) {
00065 int i;
00066 for(i=0;i<3;i++) {
00067 // the jacobian is k*I
00068 jac[i][i] -= k;
00069 
00070 // there is a force due to offset from the origin
00071 F[i] += k*location[i];
00072 }
00073 }
00074 
00075 void VRPNFeedback::addforcefield(const float *origin, const float *force,
00076 const float *jacobian) {
00077 int i;
00078 for(i=0;i<3;i++) {
00079 F[i] += force[i];
00080 
00081 // force due to the offset
00082 F[i] -= origin[0] * jacobian[0+3*i]
00083 + origin[1] * jacobian[1+3*i]
00084 + origin[2] * jacobian[2+3*i];
00085 }
00086 
00087 for(i=0;i<9;i++) jac[i/3][i%3] += jacobian[i];
00088 
00089 }
00090 
00091 void VRPNFeedback::sendforce(const float *initial_pos) {
00092 float disp[3],Finitial[3],Fmag;
00093 float origin[3]={0,0,0};
00094 
00095 if (!fdv) return;
00096 vec_sub(disp,initial_pos,origin);
00097 Finitial[0] = dot_prod(jac[0],disp);
00098 Finitial[1] = dot_prod(jac[1],disp);
00099 Finitial[2] = dot_prod(jac[2],disp);
00100 vec_add(Finitial,F,Finitial);
00101 
00102 Fmag=norm(Finitial);
00103 if(Fmag>=maxforce && maxforce>=0) { // send a constant force
00104 float newjac[3][3];
00105 float newFinitial[3];
00106 int i, j;
00107 
00108 vec_scale(newFinitial,maxforce/Fmag,Finitial); // scale the force
00109 for(i=0; i<3; i++) { // now fix up the jacobian
00110 for(j=0; j<3; j++) {
00111 float FJj = Finitial[0]*jac[0][j] +
00112 Finitial[1]*jac[1][j] +
00113 Finitial[2]*jac[2][j];
00114 newjac[i][j] = jac[i][j] - Finitial[i]*FJj/(Fmag*Fmag);
00115 }
00116 }
00117 for(i=0; i<3; i++) { // scale the jacobian
00118 vec_scale(newjac[i],maxforce/Fmag,newjac[i]);
00119 }
00120 
00121 vec_copy(origin,initial_pos); // use the point as an origin
00122 fdv->sendForceField(origin, newFinitial, newjac, 1000); // send the force
00123 }
00124 else {
00125 // send the requested force
00126 fdv->sendForceField(origin, F, jac, 1000);
00127 }
00128 }
00129 
00130 inline float sqr(float x) {
00131 return x*x;
00132 }
00133 
00134 void VRPNFeedback::addplaneconstraint(float k, const float *point,
00135 const float *thenormal) {
00136 int i,j;
00137 float jacobian[9], normal[3], force[3]={0,0,0}, len=0;
00138 
00139 for(i=0;i<3;i++) len += sqr(thenormal[i]); // normalize the normal
00140 len = sqrtf(len);
00141 for(i=0;i<3;i++) normal[i] = thenormal[i]/len;
00142 
00143 /* the part of a vector V that is normal to the plane is given by
00144 N*(V.N) (when V is a coordinate vector this is very simple)
00145 And (dFx/dx, dFy/dx, dFz/dx) = N*(i.N) for a plane! */
00146 for(i=0;i<3;i++) { // V = ith basis vector
00147 for(j=0;j<3;j++) // jth component of N
00148 jacobian[i+j*3] = -k * normal[j] * normal[i];
00149 }
00150 addforcefield(point,force,jacobian);
00151 }
00152 
00153 inline void VRPNFeedback::zeroforce() {
00154 int i,j;
00155 for(i=0;i<3;i++) {
00156 F[i]=0;
00157 for(j=0;j<3;j++) jac[i][j]=0;
00158 }
00159 }
00160 
00161 inline void VRPNFeedback::forceoff() {
00162 zeroforce();
00163 if(fdv) fdv->stopForceField();
00164 }
00165 
00166 #endif
00167 

Generated on Wed Nov 19 02:47:04 2025 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002

AltStyle によって変換されたページ (->オリジナル) /