Segfault when enabling sensor fusion

I've been having issues with the bluetooth connection cutting out when streaming euler angles from a MetaMotionR using the pymetawear library (hardware is the Pi & dongle from mbientlab store). In order to isolate this issue, I've stripped down to just the C bindings provided by mbientlab. At this point, I have the following code, which I think is about as simple as it gets, and is based on the stream_acc.py example.

from mbientlab.metawear import MetaWear, libmetawear
from mbientlab.metawear.cbindings import SensorFusionData, SensorFusionMode, FnVoid_VoidP_DataP
from mbientlab.warble import WarbleException
from threading import Event
from time import sleep

count = 0
e = Event()
def handle_notification(ctx, data):
    global count
    print("notification {0}".format(count))
    count += 1
    if count > 1000:
        e.set()

addr = 'DE:42:E0:1D:1A:43'
data_source = SensorFusionData.EULER_ANGLE
max_connect_attempts = 5

for attempt in range(max_connect_attempts):
    try:
        print('connection attempt: {}'.format(attempt + 1))
        device = MetaWear(addr, hci_mac='hci1')
        device.connect()
    except WarbleException as err:
        print('reattempting after warble exception: {}'.format(err))
        sleep(1)
    else:
        break
else:
    print("couldn't connect to device")
    quit()

try:    
    print('setting mode')
    libmetawear.mbl_mw_sensor_fusion_set_mode(device.board, SensorFusionMode.NDOF)

    print('writing config')
    libmetawear.mbl_mw_sensor_fusion_write_config(device.board)

    print('getting signal')
    processor = libmetawear.mbl_mw_sensor_fusion_get_data_signal(device.board, data_source)

    print('subscribing')
    libmetawear.mbl_mw_datasignal_subscribe(processor, None, FnVoid_VoidP_DataP(handle_notification))

    print('enabling')
    libmetawear.mbl_mw_sensor_fusion_enable_data(device.board, data_source)

    print('starting')
    libmetawear.mbl_mw_sensor_fusion_start(device.board) # Line that causes segfault

    e.wait()

except RuntimeError as err:
    print(err)

finally:
    print('stopping')
    libmetawear.mbl_mw_sensor_fusion_stop(device.board)

    print('disabling')
    libmetawear.mbl_mw_sensor_fusion_clear_enabled_mask(device.board)

    print('unsubscribing')
    libmetawear.mbl_mw_datasignal_unsubscribe(processor)

    print('disconnecting')
    libmetawear.mbl_mw_debug_disconnect(device.board)

If I don't comment out the 'start' line, then I get a segfault, however while monitoring the data in btmon, I can see data start streaming. If I then comment out that line and rerun this code, I get the desired functionality. The connection is made, I get 1000 notifications, and then the device is shutdown properly. If I then run this again (without uncommenting the start command), I get up to the point where I wait for notifications, but of course none come because I have not started the stream. This is a reproducible issue on the device I've been using, and I've also verified that it occurs on a different device. Is there something I'm missing here about how to properly start these devices?

Comments

  • Oh interesting. I haven't used ctypes all that much, so that likely would've taken me forever to find, thanks.

    For anyone looking at this afterwards, all I had to do was change:

    libmetawear.mbl_mw_datasignal_subscribe(processor, None, FnVoid_VoidP_DataP(handle_notification))
    

    to:

    wrapped_handler = FnVoid_VoidP_DataP(handle_notification)
    libmetawear.mbl_mw_datasignal_subscribe(processor, None, wrapped_handler)
    

    I know this was a ctypes thing and not an 'mbientlab code' thing, but it probably wouldn't hurt to stick a comment with either that link or an explanation about why the handler is being wrapped on a separate line in one of python examples on your repo.

  • @gwenger said:
    I know this was a ctypes thing and not an 'mbientlab code' thing, but it probably wouldn't hurt to stick a comment with either that link or an explanation about why the handler is being wrapped on a separate line in one of python examples on your repo.

    All example Python code in the tutorial does this, like the stream_acc.py example you said you based your script on.

  • Yes I know, I was just suggesting sticking a comment along with it in at least one of the examples to explain why it was being done that way. Even just that link you posted above one of the instances would help someone realize "ok yep I need to keep these two lines as is."

Sign In or Register to comment.