vrpn (empty) → 0.2.0.0
raw patch · 7 files changed
+869/−0 lines, 7 filesdep +basesetup-changed
Dependencies added: base
Files
- LICENSE +20/−0
- ReadMe.md +44/−0
- Setup.hs +2/−0
- src/Main.hs +51/−0
- src/Network/VRPN.hs +501/−0
- src/vrpn.cpp +208/−0
- vrpn.cabal +43/−0
+ LICENSE view
@@ -0,0 +1,20 @@+Copyright (c) 2015 Brian W Bush++Permission is hereby granted, free of charge, to any person obtaining+a copy of this software and associated documentation files (the+"Software"), to deal in the Software without restriction, including+without limitation the rights to use, copy, modify, merge, publish,+distribute, sublicense, and/or sell copies of the Software, and to+permit persons to whom the Software is furnished to do so, subject to+the following conditions:++The above copyright notice and this permission notice shall be included+in all copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ ReadMe.md view
@@ -0,0 +1,44 @@+Bindings for VRPN+=================++This package contains bindings to VRPN, <<https://github.com/vrpn/vrpn/wiki>> and is loosely modeled on the code in <<https://github.com/vrpn/vrpn/blob/master/client_src/vrpn_print_devices.C>>. This has been tested using VRPN 07.30 on Linux. It requires the VRPN C++ header files.++Please report issues at <<https://bwbush.atlassian.net/projects/HVRPN/issues/>>.+++Skeletal example illustrating the use of VRPN bindings+------------------------------------------------------++```haskell+data ButtonType = LeftButton | RightButton+ deriving (Enum, Eq, Show)++main :: IO ()+main =+ do+ putStrLn "Press the left button to exit."+ done <- newEmptyMVar+ let+ -- A remote button that signals completion when the left button is released.+ button :: Device Int ButtonType Double+ button =+ Button "spacenav0@localhost"+ $ Just+ $ \time button state ->+ do+ print (time, button, state)+ if button == LeftButton && not state+ then void $ tryPutMVar done ()+ else return ()+ -- An analog device.+ analog :: Device Int Int Int Double+ analog = Analog "spacenav0@localhost"+ $ Just+ $ curry print+ -- Open the remote devices.+ devices <- sequence [openDevice button, openDevice analog]+ -- Loop until a signal to complete is received.+ mainLoops (not <$> isEmptyMVar done) 10 devices+ -- Close the remote devices.+ mapM_ closeDevice devices+```
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ src/Main.hs view
@@ -0,0 +1,51 @@+{-|+Module : Main+Copyright : (c) 2015 Brian W Bush+License : MIT+Maintainer : Brian W Bush <consult@brianwbush.info>+Stability : Stable+Portability : Portable++Simple VRPN client.+-}+++module Main (+ main+) where+++import Network.VRPN (Device(..), closeDevice, mainLoops, openDevice)+import System.Environment (getArgs)+import System.IO (hFlush, stdout)+++-- | Action for a simple VRPN client.+main :: IO ()+main =+ do+ names <- getArgs+ let+ out s = putStrLn s >> hFlush stdout+ devices :: [Device Int Int Int Double]+ devices =+ concat+ [+ [+ Tracker name+ (Just $ \t s p o -> out $ show t ++ ", sensor " ++ show s ++ ", position " ++ show p ++ ", orientation " ++ show o)+ (Just $ \t s v o d -> out $ show t ++ ", sensor " ++ show s ++ ", velocity " ++ show v ++ ", orientation " ++ show o ++ ", delta " ++ show d)+ (Just $ \t s a o d -> out $ show t ++ ", sensor " ++ show s ++ ", acceleration " ++ show a ++ ", orientation " ++ show o ++ ", delta " ++ show d)+ , Button name+ (Just $ \t b p -> out $ show t ++ ", button " ++ show b ++ ", pressed " ++ show p)+ , Analog name+ (Just $ \t v -> out $ show t ++ ", analog " ++ show v)+ , Dial name+ (Just $ \t d c -> out $ show t ++ ", dial " ++ show d ++ ", change " ++ show c)+ ]+ |+ name <- names+ ]+ remotes <- mapM openDevice devices+ mainLoops (return False) (10 :: Double) remotes+ mapM_ closeDevice remotes
+ src/Network/VRPN.hs view
@@ -0,0 +1,501 @@+{-|+Module : Network.VRPN+Copyright : (c) 2015 Brian W Bush+License : MIT+Maintainer : Brian W Bush <consult@brianwbush.info>+Stability : Stable+Portability : Portable++Bindings to VRPN, \<<https://github.com/vrpn/vrpn/wiki>\>, and is loosely modeled on the code in \<<https://github.com/vrpn/vrpn/blob/master/client_src/vrpn_print_devices.C>\>. This has been tested using VRPN 07.30 on Linux. It requires the VRPN C++ header files.++Here is a simple example that illustrates the use of this module:++@+data ButtonType = LeftButton | RightButton+ deriving (Enum, Eq, Show)++main :: IO ()+main =+ do+ putStrLn "Press the left button to exit."+ done <- newEmptyMVar+ let+ -- A remote button that signals completion when the left button is released.+ button :: Device Int ButtonType Double+ button =+ Button "spacenav0@localhost"+ $ Just+ $ \time button state ->+ do+ print (time, button, state)+ if button == LeftButton && not state+ then void $ tryPutMVar done ()+ else return ()+ -- An analog device.+ analog :: Device Int Int Int Double+ analog = Analog "spacenav0@localhost"+ $ Just+ $ curry print+ -- Open the remote devices.+ devices <- sequence [openDevice button, openDevice analog]+ -- Loop until a signal to complete is received.+ mainLoops (not <$> isEmptyMVar done) 10 devices+ -- Close the remote devices.+ mapM_ closeDevice devices+@+-}+++{-# LANGUAGE ForeignFunctionInterface #-}+{-# LANGUAGE RecordWildCards #-}+++module Network.VRPN (+-- * Devices+ Device(..)+, RemoteDevice+-- * Callbacks+, PositionCallback+, VelocityCallback+, AccelerationCallback+, ButtonCallback+, AnalogCallback+, DialCallback+, ExitCallback+-- * Operations on devices+, openDevice+, closeDevice+, mainLoop+, mainLoops+-- * Time+, TimeVal(..)+, sleep+) where+++import Control.Monad (unless)+import Foreign.C.String (CString, withCString) +import Foreign.C.Types (CDouble(..), CInt(..), CLong(..))+import Foreign.Concurrent (newForeignPtr)+import Foreign.Marshal.Array (peekArray)+import Foreign.ForeignPtr (ForeignPtr, finalizeForeignPtr, withForeignPtr)+import Foreign.Ptr (FunPtr, Ptr, freeHaskellFunPtr, nullFunPtr)+++-- | A VRPN device.+data Device s b d a =+ -- | A tracker.+ Tracker+ {+ device :: String -- ^ The device name.+ , positionCallback :: Maybe (PositionCallback s a) -- ^ The position callback.+ , velocityCallback :: Maybe (VelocityCallback s a) -- ^ The velocity callback.+ , accelerationCallback :: Maybe (AccelerationCallback s a) -- ^ The acceleration callback.+ }+ -- | A button.+ | Button+ {+ device :: String -- ^ The device name.+ , buttonCallback :: Maybe (ButtonCallback b) -- ^ The button callback.+ }+ -- | An analog device.+ | Analog+ {+ device :: String -- ^ The device name.+ , analogCallback :: Maybe (AnalogCallback a) -- ^ The analog callback.+ }+ -- | A dial.+ | Dial+ {+ device :: String -- ^ The device name.+ , dialCallback :: Maybe (DialCallback d a) -- ^ The dial callback.+ }+++-- | Timestamps in seconds and fractions of a section.+data TimeVal =+ TimeVal+ {+ timeSeconds :: Int -- ^ The seconds.+ , timeMicroSeconds :: Int -- ^ The microseconds.+ }+ deriving (Eq, Ord, Read, Show)+++-- | Callback for position information.+type PositionCallback s a = TimeVal -- ^ The timestamp.+ -> s -- ^ Which sensor is reporting.+ -> (a, a, a) -- ^ The position vector.+ -> (a, a, a, a) -- ^ The orientation quaternion.+ -> IO () -- ^ The action performed by the callback.+++-- | Callback for position information.+type PositionCallback' = CLong -- ^ Seconds of the timestamp.+ -> CLong -- ^ Microseconds of the timestamp.+ -> CInt -- ^ Which sensor is reporting.+ -> CDouble -- ^ 1st component of the position vector.+ -> CDouble -- ^ 2nd component of the position vector.+ -> CDouble -- ^ 3rd component of the position vector.+ -> CDouble -- ^ 1st component of the orientation quaternion.+ -> CDouble -- ^ 2nd component of the orientation quaternion.+ -> CDouble -- ^ 3rd component of the orientation quaternion.+ -> CDouble -- ^ 4th component of the orientation quaternion.+ -> IO () -- ^ The action performed by the callback.++-- | Wrap a position callback.+foreign import ccall "wrapper"+ wrapPositionCallback :: PositionCallback' -> IO (FunPtr PositionCallback')+++-- | Make a position callback suitable for FFI.+makePositionCallback :: (Enum s, RealFloat a)+ => PositionCallback s a -- ^ The callback.+ -> PositionCallback' -- ^ An equivalent FFI callback.+makePositionCallback callback seconds microseconds sensor px py pz ox oy oz ow =+ callback+ (TimeVal (fromEnum seconds) (fromEnum microseconds))+ (toEnum $ fromEnum sensor)+ (realToFrac px, realToFrac py, realToFrac pz)+ (realToFrac ox, realToFrac oy, realToFrac oz, realToFrac ow)+++-- | Callback for velocity information.+type VelocityCallback s a = TimeVal -- ^ The timestamp.+ -> s -- ^ Which sensor is reporting.+ -> (a, a, a) -- ^ The velocity vector.+ -> (a, a, a, a) -- ^ The future orientation quaternion.+ -> a -- ^ Delta time for the future orientation quaternion, in seconds.+ -> IO () -- ^ The action performed by the callback.+++-- | Callback for velocity information.+type VelocityCallback' = CLong -- ^ Seconds of the timestamp.+ -> CLong -- ^ Microseconds of the timestamp.+ -> CInt -- ^ Which sensor is reporting.+ -> CDouble -- ^ 1st component of the velocity vector.+ -> CDouble -- ^ 2nd component of the velocity vector.+ -> CDouble -- ^ 3rd component of the velocity vector.+ -> CDouble -- ^ 1st component of the future orientation quaternion.+ -> CDouble -- ^ 2nd component of the future orientation quaternion.+ -> CDouble -- ^ 3rd component of the future orientation quaternion.+ -> CDouble -- ^ 4th component of the future orientation quaternion.+ -> CDouble -- ^ Delta time for the future orientation quaternion, in seconds.+ -> IO () -- ^ The action performed by the callback.+++-- | Wrap a velocity callback.+foreign import ccall "wrapper"+ wrapVelocityCallback :: VelocityCallback' -> IO (FunPtr VelocityCallback')+++-- | Make a velocity callback suitable for FFI.+makeVelocityCallback :: (Enum s, RealFloat a)+ => VelocityCallback s a -- ^ The callback.+ -> VelocityCallback' -- ^ An equivalent FFI callback.+makeVelocityCallback callback seconds microseconds sensor vx vy vz ox oy oz ow dt =+ callback+ (TimeVal (fromEnum seconds) (fromEnum microseconds))+ (toEnum $ fromEnum sensor)+ (realToFrac vx, realToFrac vy, realToFrac vz)+ (realToFrac ox, realToFrac oy, realToFrac oz, realToFrac ow)+ (realToFrac dt)+++-- | Callback for acceleration information.+type AccelerationCallback s a = TimeVal -- ^ The timestamp.+ -> s -- ^ Which sensor is reporting.+ -> (a, a, a) -- ^ The acceleration vector.+ -> (a, a, a, a) -- ^ The acceleration orientation quaternion.+ -> a -- ^ Delta time for the acceleration quaternion, in seconds.+ -> IO () -- ^ The action performed by the callback.+++-- | Callback for acceleration information.+type AccelerationCallback' = CLong -- ^ Seconds of the timestamp.+ -> CLong -- ^ Microseconds of the timestamp.+ -> CInt -- ^ Which sensor is reporting.+ -> CDouble -- ^ 1st component of the acceleration vector.+ -> CDouble -- ^ 2nd component of the acceleration vector.+ -> CDouble -- ^ 3rd component of the acceleration vector.+ -> CDouble -- ^ 1st component of the acceleration quaternion.+ -> CDouble -- ^ 2nd component of the acceleration quaternion.+ -> CDouble -- ^ 3rd component of the acceleration quaternion.+ -> CDouble -- ^ 4th component of the acceleration quaternion.+ -> CDouble -- ^ Delta time for the acceleration quaternion, in seconds.+ -> IO () -- ^ The action performed by the callback.+++-- | Wrap an acceleration callback.+foreign import ccall "wrapper"+ wrapAccelerationCallback :: AccelerationCallback' -> IO (FunPtr AccelerationCallback')+++-- | Make an acceleration callback suitable for FFI.+makeAccelerationCallback :: (Enum s, RealFloat a)+ => AccelerationCallback s a -- ^ The callback.+ -> AccelerationCallback' -- ^ An equivalent FFI callback.+makeAccelerationCallback callback seconds microseconds sensor ax ay az ox oy oz ow dt =+ callback+ (TimeVal (fromEnum seconds) (fromEnum microseconds))+ (toEnum $ fromEnum sensor)+ (realToFrac ax, realToFrac ay, realToFrac az)+ (realToFrac ox, realToFrac oy, realToFrac oz, realToFrac ow)+ (realToFrac dt)+++-- | Callback for button information.+type ButtonCallback b = TimeVal -- ^ The timestamp.+ -> b -- ^ Which button was pressed, counting from 0.+ -> Bool -- ^ Whether the button is pressed.+ -> IO () -- ^ The action performed by the callback.+++-- | Callback for button information.+type ButtonCallback' = CLong -- ^ Seconds of the timestamp.+ -> CLong -- ^ Microseconds of the timestamp.+ -> CInt -- ^ Which button was pressed, counting from 0.+ -> CInt -- ^ The button state (0 = off, 1 = on).+ -> IO () -- ^ The action performed by the callback.+++-- | Wrap a button callback.+foreign import ccall "wrapper"+ wrapButtonCallback :: ButtonCallback' -> IO (FunPtr ButtonCallback')+++-- | Make a button callback suitable for FFI.+makeButtonCallback :: Enum b+ => ButtonCallback b -- ^ The callback.+ -> ButtonCallback' -- ^ An equivalent FFI callback.+makeButtonCallback callback seconds microseconds button state =+ callback+ (TimeVal (fromEnum seconds) (fromEnum microseconds))+ (toEnum $ fromEnum button)+ (state /= 0)+++-- | Callback for analog information.+type AnalogCallback a = TimeVal -- ^ The timestamp.+ -> [a] -- ^ The analog values.+ -> IO () -- ^ The action performed by the callback.+++-- | Callback for analog information.+type AnalogCallback' = CLong -- ^ Seconds of the timestamp.+ -> CLong -- ^ Microseconds of the timestamp.+ -> CInt -- ^ The number of values.+ -> Ptr CDouble -- ^ The analog values.+ -> IO () -- ^ The action performed by the callback.+++-- | Wrap an analog callback.+foreign import ccall "wrapper"+ wrapAnalogCallback :: AnalogCallback' -> IO (FunPtr AnalogCallback')+++-- | Make an analog callback suitable for FFI.+makeAnalogCallback :: RealFloat a+ => AnalogCallback a -- ^ The callback.+ -> AnalogCallback' -- ^ An equivalent FFI callback.+makeAnalogCallback callback seconds microseconds n ptr =+ do+ values <- peekArray (fromEnum n) ptr+ callback+ (TimeVal (fromEnum seconds) (fromEnum microseconds))+ (map realToFrac values)+++-- | Callback for dial information.+type DialCallback d a = TimeVal -- ^ The timestamp.+ -> d -- ^ Which dial changed.+ -> a -- ^ The fraction of a revolution it changed.+ -> IO () -- ^ The action performed by the callback.+++-- | Callback for dial information.+type DialCallback' = CLong -- ^ Seconds of the timestamp.+ -> CLong -- ^ Microseconds of the timestamp.+ -> CInt -- ^ Which dial changed.+ -> CDouble -- ^ The fraction of a revolution it changed.+ -> IO () -- ^ The action performed by the callback.+++-- | Wrap a dial callback.+foreign import ccall "wrapper"+ wrapDialCallback :: DialCallback' -> IO (FunPtr DialCallback')+++-- | Make an analog callback suitable for FFI.+makeDialCallback :: (Enum d, RealFloat a)+ => DialCallback d a -- ^ The callback.+ -> DialCallback' -- ^ An equivalent FFI callback.+makeDialCallback callback seconds microseconds dial value =+ callback+ (TimeVal (fromEnum seconds) (fromEnum microseconds))+ (toEnum $ fromEnum dial)+ (realToFrac value)+++-- | Callback for exiting the main loop.+type ExitCallback = IO Bool -- ^ An action indicate whether to exit the main loop.+++-- | A remote object.+data Remote+++-- | Construct a remote tracker.+foreign import ccall "makeTracker"+ makeTracker :: CString -> FunPtr PositionCallback' -> FunPtr VelocityCallback' -> FunPtr AccelerationCallback' -> IO (Ptr Remote)+++-- | Run the main loop of a remote tracker.+foreign import ccall "mainloopTracker"+ mainloopTracker :: Ptr Remote -> IO ()+++-- | Destroy a remote tracker.+foreign import ccall "deleteTracker"+ deleteTracker :: Ptr Remote -> IO ()+++-- | Construct a remote button.+foreign import ccall "makeButton"+ makeButton :: CString -> FunPtr ButtonCallback' -> IO (Ptr Remote)+++-- | Run the main loop of a remote button.+foreign import ccall "mainloopButton"+ mainloopButton :: Ptr Remote -> IO ()+++-- | Destory a remote button.+foreign import ccall "deleteButton"+ deleteButton :: Ptr Remote -> IO ()+++-- | Construct a remote analog.+foreign import ccall "makeAnalog"+ makeAnalog :: CString -> FunPtr AnalogCallback' -> IO (Ptr Remote)+++-- | Run the main loop of a remote analog.+foreign import ccall "mainloopAnalog"+ mainloopAnalog :: Ptr Remote -> IO ()+++-- | Destroy a remote analog.+foreign import ccall "deleteAnalog"+ deleteAnalog :: Ptr Remote -> IO ()+++-- | Construction a remote dial.+foreign import ccall "makeDial"+ makeDial :: CString -> FunPtr DialCallback' -> IO (Ptr Remote)+++-- | Run the main loop of a remote dial.+foreign import ccall "mainloopDial"+ mainloopDial :: Ptr Remote -> IO ()+++-- | Destory a remote dial.+foreign import ccall "deleteDial"+ deleteDial :: Ptr Remote -> IO ()+++-- | Sleep for the specified milliseconds.+foreign import ccall "vrpnSleep"+ vrpnSleep :: CDouble -> IO ()+++-- | Sleep for the specified amount of time.+sleep :: RealFloat a => a -- ^ The number of milliseconds.+ -> IO () -- ^ An action to sleep the specified amount of time+sleep = vrpnSleep . realToFrac+++-- | A remote VRPN device.+newtype RemoteDevice = RemoteDevice (ForeignPtr Remote, ForeignPtr Remote -> IO ())+++-- | Open a remote VRPN device.+openDevice :: (Enum s, Enum b, Enum d, RealFloat a)+ => Device s b d a -- ^ The device.+ -> IO RemoteDevice -- ^ An action for opening the device.+openDevice Tracker{..} =+ do+ positionCallback' <- maybe (return nullFunPtr) (wrapPositionCallback . makePositionCallback ) positionCallback+ velocityCallback' <- maybe (return nullFunPtr) (wrapVelocityCallback . makeVelocityCallback ) velocityCallback+ accelerationCallback' <- maybe (return nullFunPtr) (wrapAccelerationCallback . makeAccelerationCallback) accelerationCallback+ ptr <-+ withCString device $ \device' ->+ makeTracker device' positionCallback' velocityCallback' accelerationCallback'+ ptr' <-+ newForeignPtr ptr $ do+ deleteTracker ptr+ freeHaskellFunPtr positionCallback'+ freeHaskellFunPtr velocityCallback'+ freeHaskellFunPtr accelerationCallback'+ return $ RemoteDevice (ptr', flip withForeignPtr mainloopTracker)+openDevice Button{..} =+ do+ buttonCallback' <- maybe (return nullFunPtr) (wrapButtonCallback . makeButtonCallback) buttonCallback+ ptr <-+ withCString device $ \device' ->+ makeButton device' buttonCallback'+ ptr' <-+ newForeignPtr ptr $ do+ deleteButton ptr+ freeHaskellFunPtr buttonCallback'+ return $ RemoteDevice (ptr', flip withForeignPtr mainloopButton)+openDevice Analog{..} =+ do+ analogCallback' <- maybe (return nullFunPtr) (wrapAnalogCallback . makeAnalogCallback) analogCallback+ ptr <-+ withCString device $ \device' ->+ makeAnalog device' analogCallback'+ ptr' <-+ newForeignPtr ptr $ do+ deleteAnalog ptr+ freeHaskellFunPtr analogCallback'+ return $ RemoteDevice (ptr', flip withForeignPtr mainloopAnalog)+openDevice Dial{..} =+ do+ dialCallback' <- maybe (return nullFunPtr) (wrapDialCallback . makeDialCallback) dialCallback+ ptr <-+ withCString device $ \device' ->+ makeDial device' dialCallback'+ ptr' <-+ newForeignPtr ptr $ do+ deleteDial ptr+ freeHaskellFunPtr dialCallback'+ return $ RemoteDevice (ptr', flip withForeignPtr mainloopDial)+++-- | Close a remote device.+closeDevice :: RemoteDevice -- ^ The device.+ -> IO () -- ^ An action for closing the device.+closeDevice (RemoteDevice (device, _)) = finalizeForeignPtr device+++-- | Run the main loop of a device *once*.+mainLoop :: RemoteDevice -- ^ The device.+ -> IO () -- ^ An action for running the main loop of the device *once*.+mainLoop (RemoteDevice (device, mainloopDevice)) = mainloopDevice device+++-- | Run the main loops of devices *repeatedly*.+mainLoops :: RealFloat a+ => ExitCallback -- ^ Callback for exiting the loop.+ -> a -- ^ The number of milliseconds to idle after each device's main loop is run once.+ -> [RemoteDevice] -- ^ The devices.+ -> IO () -- ^ An action for running the main loops *repeatedly*.+mainLoops exitCallback milliseconds devices =+ do+ mapM_ mainLoop devices+ sleep milliseconds+ exit <- exitCallback+ unless exit+ $ mainLoops exitCallback milliseconds devices
+ src/vrpn.cpp view
@@ -0,0 +1,208 @@+#include <stdio.h>+#include <stdlib.h>+#include <vrpn_Analog.h>+#include <vrpn_Dial.h>+#include <vrpn_Button.h>+#include <vrpn_Tracker.h>+++typedef void (PositionCallback)(long, long, int, double, double, double, double, double, double, double);+++void VRPN_CALLBACK handle_tracker_pos_quat(void *callback, const vrpn_TRACKERCB tracker)+{+ ((PositionCallback*) callback)(+ tracker.msg_time.tv_sec+ , tracker.msg_time.tv_usec+ , tracker.sensor+ , tracker.pos[0]+ , tracker.pos[1]+ , tracker.pos[2]+ , tracker.quat[0]+ , tracker.quat[1]+ , tracker.quat[2]+ , tracker.quat[3]+ );+}+++typedef void (VelocityCallback)(long, long, int, double, double, double, double, double, double, double, double);+++void VRPN_CALLBACK handle_tracker_vel(void *callback, const vrpn_TRACKERVELCB tracker)+{+ ((VelocityCallback*) callback)(+ tracker.msg_time.tv_sec+ , tracker.msg_time.tv_usec+ , tracker.sensor+ , tracker.vel[0]+ , tracker.vel[1]+ , tracker.vel[2]+ , tracker.vel_quat[0]+ , tracker.vel_quat[1]+ , tracker.vel_quat[2]+ , tracker.vel_quat[3]+ , tracker.vel_quat_dt+ );+}+++typedef void (AccelerationCallback)(long, long, int, double, double, double, double, double, double, double, double);+++void VRPN_CALLBACK handle_tracker_acc(void *callback, const vrpn_TRACKERACCCB tracker)+{+ ((AccelerationCallback*) callback)(+ tracker.msg_time.tv_sec+ , tracker.msg_time.tv_usec+ , tracker.sensor+ , tracker.acc[0]+ , tracker.acc[1]+ , tracker.acc[2]+ , tracker.acc_quat[0]+ , tracker.acc_quat[1]+ , tracker.acc_quat[2]+ , tracker.acc_quat[3]+ , tracker.acc_quat_dt+ );+}+++typedef void (ButtonCallback)(long, long, int, int);+++void VRPN_CALLBACK handle_button(void *callback, const vrpn_BUTTONCB button)+{+ ((ButtonCallback*) callback)(+ button.msg_time.tv_sec+ , button.msg_time.tv_usec+ , button.button+ , button.state+ );+}+++typedef void (AnalogCallback)(long, long, int, const double*);+++void VRPN_CALLBACK handle_analog (void *callback, const vrpn_ANALOGCB analog)+{+ ((AnalogCallback*) callback)(+ analog.msg_time.tv_sec+ , analog.msg_time.tv_usec+ , analog.num_channel+ , analog.channel+ );+}+++typedef void (DialCallback)(long, long, int, double);+++void VRPN_CALLBACK handle_dial(void *callback, const vrpn_DIALCB dial)+{+ ((DialCallback*) callback)(+ dial.msg_time.tv_sec+ , dial.msg_time.tv_usec+ , dial.dial+ , dial.change+ );+}+++extern "C" vrpn_Tracker_Remote* makeTracker(char* device, PositionCallback positionCallback, VelocityCallback velocityCallback, AccelerationCallback accelerationCallback)+{+ vrpn_Tracker_Remote* tracker = new vrpn_Tracker_Remote(device);+ if (tracker && positionCallback)+ tracker->register_change_handler((void*) positionCallback, handle_tracker_pos_quat);+ if (tracker && velocityCallback)+ tracker->register_change_handler((void*) velocityCallback, handle_tracker_vel);+ if (tracker && accelerationCallback)+ tracker->register_change_handler((void*) accelerationCallback, handle_tracker_acc);+ return tracker;+}+++extern "C" void mainloopTracker(vrpn_Tracker_Remote* tracker)+{+ if (tracker)+ tracker->mainloop();+}+++extern "C" void deleteTracker(vrpn_Tracker_Remote* tracker)+{+ delete tracker;+}+++extern "C" vrpn_Button_Remote* makeButton(char* device, ButtonCallback buttonCallback)+{+ vrpn_Button_Remote* button = new vrpn_Button_Remote(device);+ if (button && buttonCallback)+ button->register_change_handler((void*) buttonCallback, handle_button);+ return button;+}+++extern "C" void mainloopButton(vrpn_Button_Remote* button)+{+ if (button)+ button->mainloop();+}+++extern "C" void deleteButton(vrpn_Button_Remote* button)+{+ delete button;+}+++extern "C" vrpn_Analog_Remote* makeAnalog(char* device, AnalogCallback analogCallback)+{+ vrpn_Analog_Remote* analog = new vrpn_Analog_Remote(device);+ if (analog && analogCallback)+ analog->register_change_handler((void*) analogCallback, handle_analog);+ return analog;+} +++extern "C" void mainloopAnalog(vrpn_Analog_Remote* analog)+{+ if (analog)+ analog->mainloop();+}+++extern "C" void deleteAnalog(vrpn_Analog_Remote* analog)+{+ delete analog;+}+++extern "C" vrpn_Dial_Remote* makeDial(char* device, DialCallback dialCallback)+{+ vrpn_Dial_Remote* dial = new vrpn_Dial_Remote(device);+ if (dial && dialCallback)+ dial->register_change_handler((void*) dialCallback, handle_dial);+ return dial;+}+++extern "C" void mainloopDial(vrpn_Dial_Remote* dial)+{+ if (dial)+ dial->mainloop();+}+++extern "C" void deleteDial(vrpn_Dial_Remote* dial)+{+ delete dial;+}+++extern "C" void vrpnSleep(long t)+{+ vrpn_SleepMsecs(t);+}
+ vrpn.cabal view
@@ -0,0 +1,43 @@+name: vrpn+version: 0.2.0.0+synopsis: Bindings to VRPN.+description: See \<<https://github.com/vrpn/vrpn/wiki>\> for information on VRPN. This has been tested using VRPN 07.30 on Linux.+license: MIT+license-file: LICENSE+author: Brian W Bush <consult@brianwbush.info>+maintainer: Brian W Bush <consult@brianwbush.info>+copyright: (c) 2015 Brian W Bush+category: Network+build-type: Simple+cabal-version: >= 1.10+homepage: https://bitbucket.org/bwbush/vrpn+bug-reports: https://bwbush.atlassian.net/projects/HVRPN/issues/+package-url: https://bitbucket.org/bwbush/vrpn/vrp-0.2.0.0.tar.gz++extra-source-files: ReadMe.md++source-repository head+ type: git+ location: https://bwbush@bitbucket.org/bwbush/vrpn.git+ +library+ exposed-modules: Network.VRPN+ build-depends: base >= 4.8.1 && < 5+ hs-source-dirs: src+ ghc-options: -Wall+ default-language: Haskell2010+ C-sources: src/vrpn.cpp+ include-dirs: /usr/local/include+ extra-lib-dirs: /usr/local/lib+ extra-libraries: vrpn stdc++++executable test-vrpn+ main-is: Main.hs+ build-depends: base+ hs-source-dirs: src+ ghc-options: -Wall+ default-language: Haskell2010+ C-sources: src/vrpn.cpp+ include-dirs: /usr/local/include+ extra-lib-dirs: /usr/local/lib+ extra-libraries: vrpn stdc++