xsens / xsens_dot_server

32 stars 24 forks source link

Only getting data in "Orientation Quaternion" mode, no other modes #11

Open aero-man opened 4 years ago

aero-man commented 4 years ago

Hello,

I have a Python script that is successfully getting data from a single sensor. However, no matter which setting I write to the Control Characteristic, I appear to only be getting data in "Orientation Quaternion" mode. No matter which mode I specify at the end of my byte string (for example, b'\x01\x01\x02' for "Extended (Quaternion)" mode), the data I get in the notifications is not 36 bytes as expected, but only 20 bytes. After converting the 20 bytes that I do get to numbers, it looks like I get a timestamp (uint32) and 4 chunks of quaternion data (each a 32-bit float for quaternion W, X, Y, and Z). When I write my enable message b'\x01\x01\x02' to the Control Characteristic, I also read it back to ensure that it was written properly, and it does read b'\x01\x01\x02' like I expect.

Another source of confusion is that when I get a notification with some sensor data, the notification says it was sent from handle 39 (the handle for the medium payload length characteristic), and yet the data I am getting is supposed to be sent from the short payload length characteristic, which should have a handle of 43.

Is there another step to enabling these sensors and setting the measurement mode that I am missing? My current understanding is outlined in Issue #7 and is copied below:

  1. Scan for the sensor (can skip this if you already know the Bluetooth address)
  2. Connect to the sensor using the Bluetooth address found via scanning
  3. Subscribe to the Measurement Characteristic by writing an enable message to that characteristic's CCCD, which is at integer handle + 1 (e.g. if the characteristic's handle is 39, write to its CCCD at handle 40) (There are two measurement characteristics to choose from for Xsens DOTs, depending on whether your measurement type is a short or medium payload)
  4. Write an enable message to the Control Characteristic
  5. Add a delegate to your sensor to start listening for notifications from the sensor
  6. Run a loop to listen for notifications and do something with the data received. (The example below just prints it.)

Thanks for your help.

aero-man commented 4 years ago

This may actually be an issue with how I am processing the buffers my script receives. Will report back tomorrow if I still need assistance.

aero-man commented 4 years ago

Update: confirmed that I am only getting 20-byte notifications, regardless of what my script does with that data.

fancycww commented 4 years ago

@aero-man Hi, This project is using nodejs. I'm not familiar with Python, but I think it's similar to write data to Bluetooth. After successful writing, data notifications will be received. Does Python divide the data into multiple pieces? Thanks.

freddijkstra commented 4 years ago

When Python informs the application of each received notification packet, then it is to be expected that the data-size is 20-bytes as that is the size of the user data in a notification packet. It would be strange however since the stack should stitch the larger notifications together as one data-block.

aero-man commented 4 years ago

Thanks @fancycww and @freddijkstra for the tips. I will investigate again how Python and Bluepy are breaking up the data.

aero-man commented 4 years ago

Here are ten lines of sensor data that I am getting from a single sensor. Though I set the sensor to "Extended (Quaternion)" mode, which should be 40 bytes, I am only getting 20 bytes. It does not appear that the script is dividing the DOT notification into two separate 20-byte notifications, since each line has a legitimate timestamp in the expected order. If every other line was actually the second 20-byte chunk of the overall notification, I'd expect the timestamp to be some accelerometer or gyro value that got accidentally interpreted as a timestamp and thus be something very different from 29873xxxxx and so on.

[(2987388214, 0.6987149, 0.00213826, 0.00411566, -0.7153855)]
[(2987404881, 0.6987097, 0.00213495, 0.00412598, -0.71539044)]
[(2987421548, 0.69870615, 0.00214881, 0.00411967, -0.71539396)]
[(2987438215, 0.6987045, 0.00214634, 0.00412696, -0.7153956)]
[(2987454882, 0.6987034, 0.00213842, 0.00412312, -0.71539664)]
[(2987471549, 0.6987081, 0.00214344, 0.00411941, -0.715392)]
[(2987488216, 0.6987105, 0.00214916, 0.00412804, -0.7153896)]
[(2987504883, 0.6987047, 0.00214807, 0.00411882, -0.7153953)]
[(2987521550, 0.69870716, 0.00215218, 0.00411918, -0.7153929)]
[(2987538217, 0.69870716, 0.00215312, 0.00412477, -0.7153929)]

Thanks again.

FrederikPetri commented 4 years ago

@aero-man Hi, Very useful python script #7 , thanks for sharing! Can you explain how you convert the raw sensor data you print in the example code to timestamp and quaternions?

aero-man commented 4 years ago

I'm still trying to debug this issue. Still only getting 20 bytes of data. Looking at the underlying code in Bluepy.

Do you guys know what the Bluetooth packet looks like when it leaves the sensor. Is there any documentation available on this? I'm having Bluepy print out what it gets from the sensors, and each packet looks like this: rsp=$ntfy\x1ehnd=h27\x1ed=b4479A0E3A1FDA53C3DA7633FACF2E9BE7723DCBA\n Is this what it is supposed to look like? Trying to rule out whether this is a problem with how Bluepy is parsing the data.

Thanks.

aero-man commented 4 years ago

@FrederikPetri I am using Numpy.

import numpy as np
...
data_type = np.dtype([('timestamp', np.uint32), ('quat_w', np.float32), ('quat_x', np.float32),
                       ('quat_y', np.float32), ('quat_z', np.float32)])
human_readable_data = np.frombuffer(data, dtype=data_type)

This code lives in the callback function handleNotification(cHandle, data) that's part of Bluepy