Front Page › Forums › Programming Issues › Help Using The Device Log Example
- This topic has 23 replies, 2 voices, and was last updated 4 years, 8 months ago by npevange.
-
AuthorPosts
-
April 25, 2019 at 6:08 pm #740827npevangeParticipant
I would like to create a program that reads in the values outputted by the Device Log Example and then gives them to a Python Program that we can use to process the data, etc. But I am having trouble finding how the data is stored using that example.
Ideally, I would want the python program to get the new data as it is updated by the haptic.April 26, 2019 at 7:25 am #740839MarkusKeymasterDid you find the file outputted by DeviceLog.x3d?
IIRC it would end up in the working directory used when starting the application.
The documentation for the field logBinary should tell you what you need to know to understand how things are logged.April 26, 2019 at 6:04 pm #740851npevangeParticipantHi Markus,
Thanks for the quick reply. Yes I was able to find where that file is saved into the directory. But I guess what I was also wondering is if there is a way to have the data go directly into python using the python node or if I would need to read in the file to python after it is created.If I do have to take the file output and read it into python do I just need to use a split function to separate it based on the spaces or is there a different way that you suggest.
Thank you,
April 26, 2019 at 9:02 pm #740852npevangeParticipantAlso I noticed that If I use the Device Log and choose all for the outputs there are 10 headers, but 28 values returned, Is there a detailed list that divides those 28 values into the correct categories. I didn’t see anything about it in the other documentation.
Thank you,
May 3, 2019 at 6:21 am #740972MarkusKeymasterHello,
You will have to take the reroute through reading a file, there is not way to get it directly into python.
The only information about this is in the header documentation for the field logBinary and logData. In the logBinary description it lists each of the data entries for each of the headers. In the logData info it lists which field it corresponds to (i.e. indirectly it lists the type for each data entry). Positions are 3 values and orientations are 4.
https://www.h3dapi.org/uploads/api/H3DAPI_2.4/doc/H3DAPI/html/classH3D_1_1DeviceLog.html#a8e32b8dbcbda9c5285640fe57d5baa4eAlso, did you see we have a new release of h3d?
May 3, 2019 at 7:38 pm #741022npevangeParticipantHi Markus,
Thanks for the info. A few more things. We are using a phantom device and we were wondering if it has its own clock that we can use to time sync the data or would we have to use one through the PCI card or some other means. Are there any examples I can look at on how to do this? Also for the data that we get out of it, are the position 3 values (x,y,z) in order? And what do the position values represent? When I looked at the position each timepoint said [1 0 0 0]. Lastly, I noticed that the force data was mostly 0 as well. Is this data only collected when the haptic is set up to provide a force such as using the spring example?Thank you,
NathanMay 6, 2019 at 5:49 am #741075MarkusKeymasterHello,
I do not know whether the phantom device has its own internal clock. That information should be in the OpenHaptics SDK documentation which you should have gotten with your installation of OpenHaptics.
The position values are as described in the corresponding field in H3DHapticsDevice. They should be in x,y,z using H3DAPIs coordinate system (right hand coordinate system, x to the right and y up).
You can log both the calibrated position and the raw position.
Here is a short run on my system of the H3DAPI/examples/DeviceLog.x3d example in which logging is done at 1 Hz.TIME POSITION ORIENTATION VELOCITY BUTTONS FORCE TORQUE RAW_POSITION RAW_ORIENTATION RAW_VELOCITY RAW_FORCE RAW_TORQUE TIMESTAMP 0.00000 0.01784 -0.15474 -0.06591 -0.79984 -0.09942 0.59193 1.23000 -0.00002 -0.00103 -0.00030 0 0.00000 0.00000 0.00000 0.00000 0.00000 -0.00000 0.00892 -0.07737 -0.03295 -0.79984 -0.09942 0.59193 1.23000 -0.00001 -0.00051 -0.00015 0.00000 0.00000 0.00000 0.00000 0.00000 -0.00000 1557121307.14506 1.00048 -0.15094 0.08434 -0.02928 -0.81565 0.28188 0.50522 1.23054 -0.36086 0.87366 0.22553 0 0.00000 0.00000 0.00000 0.00000 -0.00000 -0.00000 -0.07547 0.04217 -0.01464 -0.81565 0.28188 0.50522 1.23054 -0.18043 0.43683 0.11277 0.00000 0.00000 0.00000 0.00000 -0.00000 -0.00000 1557121308.14533 2.00093 -0.07273 -0.02099 -0.03264 0.07701 -0.05516 0.99550 0.92230 -0.18497 0.25902 0.05477 0 0.00000 0.00000 0.00000 0.00000 0.00000 -0.00000 -0.03637 -0.01049 -0.01632 0.07701 -0.05516 0.99550 0.92230 -0.09249 0.12951 0.02738 0.00000 0.00000 0.00000 0.00000 0.00000 -0.00000 1557121309.14579 3.00155 0.01687 0.04173 -0.06170 0.57819 0.66692 -0.47002 3.95755 -0.02113 -0.02553 -0.02736 0 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00843 0.02086 -0.03085 0.57819 0.66692 -0.47002 3.95755 -0.01057 -0.01277 -0.01368 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 1557121310.14643
Position and orientation give out values just fine in my case.
All the zero values except the first one are either the buttons or force and torque.May 6, 2019 at 9:51 pm #741106npevangeParticipantHi Markus,
I meant to ask what the orientation values represent as well. Those (orientation) were the values that were giving us [1 0 0 0], at each timepoint. Are these related to (x,y,z,?) as well? Also do you know what we can do to fix this? Is it a calibration issue or would we need to look into the Open Haptics or ask 3D systems why this might be happening? Could it be an installation issue?Thank you,
NathanMay 7, 2019 at 12:40 pm #741115MarkusKeymasterHello,
Sorry I did not get that.
Orientation values are axis, angle. The first three values represent an axis (x,y,z) and the fourth is the angle around that axis in radians. It is basically this representation.
https://en.wikipedia.org/wiki/Axis–angle_representationI am surprised it gives you 1 0 0 0 because that would either be default or it can not read the values properly for some reason. I assume you are using a device which has 6-dof input (i.e. actually has rotation).
If the calibration works fine with rotation I can not see why it would not work fine in your case, maybe some mismatch in OpenHaptics version.
June 20, 2019 at 11:06 pm #747317npevangeParticipantHi Markus,
Those tips worked well, but we had some follow up questions. I have been trying to incorporate a python script that will wait for a signal then start the device log but have been having a few problems. When I initially had the script running a while loop that was checking for the signal but it seemed like that would cause the H3DViewer to not respond and it also wouldnt pick up the signal when it was sent. Do you have any ideas how I can incorporate this loop so that it wont cause errors with H3D.Thanks,
NathanJune 24, 2019 at 5:37 am #747318MarkusKeymasterHello Nathan,
You could try using the traverseSG function that can be defined in a python script and will be called once per graphics loop.
Section 4.3.1. of the h3dapi manual
https://www.h3dapi.org/uploads/api/H3DAPI_2.4/doc/H3D%20API%20Manual.pdf
I think this will be the easiest way.Or you could use the threading module of python.
https://docs.python.org/2.7/library/threading.html?highlight=threading#module-threadingCheers,
MarkusJune 26, 2019 at 7:58 pm #747319npevangeParticipantHi Markus,
I am a bit familiar with threading so I was planning to try using both that and the traverseSG(). However, since our task requires some specific timings to be known I was wondering if there was a way I could have H3D send the time that it starts the deviceLog to python. I had briefly tested some routes, but I wasn’t sure if it had a time module similar to python that I might be able to use.Second, is there a function or call I can do to stop the DeviceLog at a certain point while still having the H3D running? Or do I have to close H3D to stop the scene. I saw there was also some mention of
Third, I was wondering about the order that H3D will initialize the scene. I was assuming that it would start the scene and go down the list of whatever I have in that node. However while I was testing it, it seemed like it would start the python script first( I was using initialize() and traverseSG()) and then it would start the DeviceLog and other parts of the H3D node after python.
Is there a reference to the logic that it uses that I could look at.Thank you,
NathanJune 27, 2019 at 10:13 am #747320MarkusKeymasterHello,
The DeviceLog is implemented as a HAPIForceEffect which means the following:
1. The graphics node DeviceLogs traverseSG function is reached. It creates a HAPIForceEffect called DeviceLog and attach it to the TraverseInfo. The log file is opened here.
2. Later in the graphics loop the collected force effects are set up to be synced with the haptic loop.
3. The haptic loop is done, and reaches a “transfer new force effects” state.
4. The haptics loop reaches the place where forces are calculated of all the force effects in this loop. This is when logging finally starts.So it really depends on what you mean with “get a signal when logging starts”. By default fields should not be set from a different thread than the main one (graphics thread). If it is sufficient that you know when the force effect is queued up for being transferred then you could just modify H3DAPI::DeviceLog::traverseSG to set a field for you.
If you need to know this later somewhere you need to create a thread safe variant of the field (there might be a couple of templates for this) that could notify you in python and setup an autoupdate field that handles some signal triggering.
Either make these modifications in H3DAPI directly or create your own library in a similar fashion to for example H3DPhysics and just create a subclass to DeviceLog for this.You could stop the device log by just using the “close” field of the DeviceLog node. Set that field to true and the file it writes to will be closed and no more logging will be done.
When parsing the files initialize of all the nodes in the tree is called.
Then traverseSG is called and it will simply traverse the tree starting from the top node and traversing depth first. So if your PythonScript is listed before the DeviceLog in the tree hierarchy (or if it is a child of the PythonScript) it will reach traverseSG of the PythonScript before DeviceLog.June 27, 2019 at 7:08 pm #747321npevangeParticipantHi Markus,
When I said get a signal, what I really wanted was to know if I could generate a timestamp at the time that the logging starts so that we can compare it to a separate start timestamp to line up the haptic data with other video data. (Do you have example code of something like this or examples to look at?)Also when you mention the H3DAPI::DeviceLog::traverseSG, I can modify that by using the following below::
def traverseSG():
my python code here
Or do I also have to set it up in my H3D script?Also for closing the DeviceLog as you mentioned, how do I reference that “close” field. I tried to define a close value in the DeviceLog in H3D but I was given an error:
Loading C:\H3D\H3DAPI\examples\TestingCloseDeviceLog.x3d
Warning: Couldn’t find field named “close” in DeviceLog node (C:\H3D\H3DAPI\examples\TestingCloseDeviceLog.x3d line 21)Here is a sample of the code I was trying to run, let me know if you see anything that I should change.(Note: these codes were just to test the close functionality that you mentioned, I had planned to integrate it later into my main code). Also I noticed that the indentation is off when I copy it but it won’t let me change it to the proper indentation if it is difficult to read let me know and I can email you a copy of the scripts:
H3D:<DeviceLog DEF = 'DL' url='testing.csv' frequency='2000' deviceIndex='0' logBinary='false' logData='ALL' close='true' /> <PythonScript DEF="PS" url="C:\Python27\x3dtestGETNODE.py"/> <ROUTE fromNode="PS" fromField="closedevlog" toNode="DL" toField="close"/>
Python:
from H3DInterface import * import winsound import time def initialize(): global counter, devlog print('init') counter = 0 devlog = True def traverseSG(): global counter, devlog, start counter = counter + 1 if counter == 1: start = time.time() elif counter > 1 and devlog == True: timer = time.time() - start if timer > 10 and timer < 11: print('close') devlog = False closedevlog = closeDevLog() elif devlog == False: print('done') time.sleep(1) devlog = True class closeDevLog( SFBool): def update(self): global devlog print('update') close = False if return close global devlog devlog = False closedevlog = closeDevLog()
June 28, 2019 at 5:59 am #747323MarkusKeymasterHello,
The device log can log both the relative time and the absolute time, the last number when logging all data should be an absolute time stamp.:
TIME POSITION ORIENTATION VELOCITY BUTTONS FORCE TORQUE RAW_POSITION RAW_ORIENTATION RAW_VELOCITY RAW_FORCE RAW_TORQUE TIMESTAMP 0.00000 -0.00206 -0.15372 -0.07293 -0.82016 -0.57191 0.01606 1.62600 0.00000 0.00000 0.00000 0 0.00000 0.00000 0.00000 -0.00000 0.00000 0.00000 -0.00103 -0.07686 -0.03646 -0.82016 -0.57191 0.01606 1.62600 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 -0.00000 0.00000 0.00000 1557121628.20370
For traverseSG, yes it is enough to just put that function in the file that your PythonScript x3d node statement refers to through the url field.
Are you using the latest H3D 2.4 release? or an earlier version? Close might be a new field, if you use an earlier version download the latest.
I can not run the code you posted mostly because I can not figure out the indentation.
There is a “code” tag for posts. I am testing it now and we will see if it works 🙂 -
AuthorPosts
- You must be logged in to reply to this topic.