vrecko
virtual reality framework
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
PHANToM_Device.h
Go to the documentation of this file.
1 #ifndef PHANTOM_H
2 #define PHANTOM_H
3 
4 
5 #ifndef COMPILE_PHANTOM_DEVICE
6  #include "PHANToM_compile.inc"
7 #endif
8 
9 
10 #ifdef COMPILE_PHANTOM_DEVICE
11 
12 #include <vrecko/IOPins.h>
13 #include <vrecko/Ability.h>
14 #include <vrecko/Device.h>
15 #include <vrecko/EventDispatcher.h>
16 #include <vrecko/MTLock.h>
17 #include <helpers/DynamicArray.h>
18 
19 #include <HD/hd.h>
20 #include <HDU/hduVector.h>
21 #include <HDU/hduError.h>
22 
23 #include <osg/Matrix>
24 
25 namespace vreckoDP_PHANToM {
26 
27 class DP_EXPORT PHANToMFilter;
28 
29 typedef struct {
30  osg::Vec3 position;
31  osg::Matrix orientation;
32  osg::Vec3 velocity;
33  osg::Vec3 acceleration;
34  HDint nCurrentButtons;
35  HDint nLastButtons;
36 
37 // If Phantom is relative to the camera, then the following variables hold different values than the [position] and [orientation]
38 // (the untransformed ones)
39  osg::Vec3 absolutePosition;
40  osg::Matrix absoluteOrientation;
41 } PHANToMSTATE;
42 
43 
44 struct PHANTOM_HELD_OBJECT {
45  unsigned long objectID;
46  osg::Matrix transform; // sub-transform of this particular object from the center of gravity/rotation (of the whole group of held objects)
47 
48  PHANTOM_HELD_OBJECT & operator= (const PHANTOM_HELD_OBJECT & other) {
49  objectID = other.objectID;
50  transform = other.transform;
51  return *this;
52  }
53 
54 };
55 
56 typedef DynamicArray<PHANTOM_HELD_OBJECT> PHANTOM_HELD_OBJECTS_ARRAY;
57 
58 
59 class DP_EXPORT PHANToM : public vrecko::Device {
60  public:
61  PHANToM(void);
62 // PHANToM(int freq);
63  ~PHANToM();
64 
65  virtual bool loadXMLParameters(XERCES_CPP_NAMESPACE_QUALIFIER DOMNode *);
66 
67  virtual void preInitialize(void);
68  virtual void postInitialize(void);
69 
70  void processEvent(const std::string &input_name, void *value);
71 
72  virtual int openDevice(void);
73  int closeDevice(void);
74  int calibrateDevice(void);
75 
76  void update(void);
77 
78  // filters
79  void addFilter(PHANToMFilter* newFilter);
80  // filter is added to the correct position using its priority.
81  // If there is already a filter with the same priority, it will be added after that.
82 
83  void removeFilter(unsigned int);
84  void removeFilter(PHANToMFilter*);
85 // std::vector<PHANToMFilter*> &getAdditionalFilterVector(void) {return filter;}
86  void applyFilters(PHANToMSTATE &pState, osg::Vec3 &temp_force, osg::Vec3 &temp_torque);
87 
88  void resetFilters(void);
89  // All filter will return to the initial state - useful for example after grabbing a new object
90  // WARNING: The caller must acquire call acquireMainLock()/releaseMainLock() (i.e. filters don't have to - it's already done)
91 
92  bool isForceApplied() { return !bDontApplyForce; }
93 
94  inline void acquireMainLock() { filterVectorLock.lock(); }
95  inline void releaseMainLock() { filterVectorLock.unlock(); }
96 
97  void setHeldObjects(PHANTOM_HELD_OBJECTS_ARRAY * newHeldObjects);
98  // [newHeldObjects] might be NULL, the object list is copied, so the caller may deallocate the memory.
99  // WARNING: Whoever calls this must also call acquireMainLock()/releaseMainLock(),
100  // i.e. filters doesn't need to lock it, but callers from outside the Phantom thread MUST OBTAIN THE LOCK !
101  // WARNING 2: Inside the lock, the resetFilters() SHOULD ALSO BE CALLED !
102 
103  PHANTOM_HELD_OBJECTS_ARRAY * getHeldObjects(bool *bIsDefault = NULL);
104  // WARNING: Whoever calls this must also call acquireMainLock()/releaseMainLock(),
105  // i.e. filters doesn't need to lock it, but callers from outside the Phantom thread MUST OBTAIN THE LOCK
106  // WARNING 2: Only the pointer is returned, so you have to process the returned information (or copy it elsewhere)
107  // BEFORE releasing the lock.
108  // if [bIsDefault] is not NULL, it will receive whether the returned array are the default held objects or not.
109 
110  inline PHANTOM_HELD_OBJECTS_ARRAY * getDefaultHeldObjects(void) { return &defaultHeldObjects; }
111  // And again:
112  // WARNING: Whoever calls this must also call acquireMainLock()/releaseMainLock(),
113  // i.e. filters doesn't need to lock it, but callers from outside the Phantom thread MUST OBTAIN THE LOCK
114  // WARNING 2: Only the pointer is returned, so you have to process the returned information (or copy it elsewhere)
115  // BEFORE releasing the lock.
116 
117  // For shared use in filters, should be used after setting/getting the held objects
118  // inside the same acquireMainLock()/releaseMainLock() sequence
119  inline const osg::Matrix &getHeldObjectsTransform() const { return heldObjectsTransform; }
120  inline void setHeldObjectsTransform(osg::Matrix const &newTransform) { heldObjectsTransform = newTransform; }
121  // The transformation should not include the scaling, just rotation and translation
122 
123  void setLastPhantomTrans(osg::Matrix &newMat);
124  // Set the last phantom transformation.
125  // For use in methods outside of this class. Will use the [lastPhantomTransLock] automatically.
126  void getLastPhantomTrans(osg::Matrix *outMat);
127  // Get the last phantom transformation.
128  // For use in methods outside of this class. Will use the [lastPhantomTransLock] automatically.
129 
130 
131  void setCollisionOccurred(bool bNewValue) { bCollisionOccurred = bNewValue; }
132  bool getCollisionOccurred() { return bCollisionOccurred; }
133 
134 
135  float workspace_scale;
136  bool bRelativeToCamera;
137  float fCameraOffset;
138  bool bVisualizeAxes; // requires objects with IDs 999804, 999805 and 999806
139 
140  vrecko::MTLock avatarDataLock;
141  bool avatarPosModifiedByUs; // [avatarDataLock] must be used before accessing the variable
142  // were the variables below modified by this class or Phantom filters?
143  // i.e. should we set the avatar pos on the next update instead of reading it.
144  osg::Vec3 avatarPos; // [avatarDataLock] must be used before accessing the variable
145  osg::Vec3 avatarLookAt; // normalized. [avatarDataLock] must be used before accessing the variable
146  osg::Vec3 avatarUp; // normalized. [avatarDataLock] must be used before accessing the variable
147 
148  bool bInitializeHeldObjectsTransform;
149  // Initial condition, because the Device is created BEFORE the Scene creation.
150  // Therefore the objects' transformations have to be queried in the first update() or similarly.
151 
152  bool stopMotion(bool state);
153  bool bStopMotion;
154 
155  protected:
156  HHD hHD;
157  HDSchedulerHandle hHSCallback;
158  osg::Vec3 position, velocity;
159  osg::Matrix orientation, transform;
160  bool button_state;
161  vrecko::EventDispatcher *pEventDispatcher;
162  bool last_button_state;
163 
164  bool bDeviceOpened;
165 
166  bool bDontApplyForce;
167  // A "debug" switch to disable the force.
168  // The force is still calculated, but the results are thrown away.
169 
170  // additional filters
171  std::vector<PHANToMFilter*> filters;
172  vrecko::MTLock filterVectorLock;
173 
174  osg::Matrix heldObjectsTransform;
175  // The transformation should not include the scaling, just rotation and translation
176  PHANTOM_HELD_OBJECTS_ARRAY heldObjects;
177  PHANTOM_HELD_OBJECTS_ARRAY defaultHeldObjects;
178  // (Operated by setHeldObjects()/getHeldObjects())
179  // The list of objects which the user holds in their hand AND
180  // the list of objects which are used as a backup when the user "doesn't hold" anything (so typically we can display a hand)
181 
182 
183  bool bCollisionOccurred; // has collision occurred _in this frame_
184 
185 
186  vrecko::MTLock lastPhantomTransLock;
187  osg::Matrix lastPhantomTrans;
188  // Last phantom transformation, use the [lastPhantomTransLock] for access or getLastPhantomTrans() method.
189  // For use in the methods outside this class, filters receive the position/rotation automatically.
190 
191 
192  void readHeldObjectsFromXML( XERCES_CPP_NAMESPACE_QUALIFIER DOMNode * tmpNode, PHANTOM_HELD_OBJECTS_ARRAY* defaultHeldObjects );
193 
194  virtual int processNotification(BaseClass *sender, unsigned long notificationType,
195  void *notificationData);
196 
198  DECLARE_OUTPUT(Orientation, vrecko::MessageQuat);
199  DECLARE_OUTPUT(Button, vrecko::MessageBool);
200 };
201 
202 
203 class DP_EXPORT PHANToMFilter : public vrecko::Ability {
204  public:
205  PHANToMFilter(const char* abName) : Ability(abName), filter_enabled(true), bIsAfterReset(true), bActiveAfterReset(true), resetTime(0) {};
206  //~PHANToMFilter() {}; -> no default constructor -> force to name the Ability
207 
208  virtual void apply(PHANToMSTATE &pState, osg::Vec3 &force, osg::Vec3 &torque) {};
209 
210  void enableFilter(void) {filter_enabled = true;}
211  void disableFilter(void) {filter_enabled = false;}
212  bool isFilterEnabled(void) {return filter_enabled;}
213 
214  inline bool isAfterReset(void) { return bIsAfterReset; }
215  inline void setIsAfterReset(bool bNewAfterReset) { bIsAfterReset = bNewAfterReset; if (bNewAfterReset) { resetTime = osg::Timer::instance()->tick(); } }
216  inline osg::Timer_t getResetTime() { return resetTime; }
217 
218  inline bool isActiveFirstTime() { return bActiveAfterReset; }
219  inline void setActiveAfterReset(bool bNewActiveAfterReset) { bActiveAfterReset = bNewActiveAfterReset; }
220 
221 // inline int getFilterPriority() { return iFilterPriority; }
222 // void setFilterPriorty(int newPriority) { iFilterPriority = newPriority; } // Note: This will NOT reorder the filters (i.e. it must be done before adding the filter to the phantom filter "stack")
223 
224  protected:
225  bool filter_enabled;
226  bool bIsAfterReset;
227  // Is this the FIRST time the filter would be applied (if the [bActiveAfterReset] is "true")?
228  // (Managed automatically by the PHANToM device plugin through our setIsAfterReset() method.)
229  // Use isAfterReset() to get the value.
230  bool bActiveAfterReset;
231  // Is the filter executed in the first run?
232  // (Managed automatically by the PHANToM device plugin through our setActiveAfterReset() method.)
233  // Use isActiveFirstTime() to get the value.
234  osg::Timer_t resetTime;
235 // int iFilterPriority;
236  // The default priority is 0.
237 };
238 
239 }
240 
241 #endif //COMPILE_PHANTOM_DEVICE
242 
243 #endif //PHANTOM_H
244