Fw 0.4.1 / why does odrive instance takes 30s to be created?

i will try on ubuntu soon.

It seems creating an odrive instance takes 30sec instead of an expected nearly instantaneous durations.

Why ?

output

C:\Users\user\Desktop\odrive>python test.py
duration: 30.70100000000093  <== this is the problem
voltage: 12.4757080078125
serial: 59765331406903
fw: 0.4.1.1
hw: 3.5
variant: 48

script

import time
import odrive
t0 = time.monotonic()
odrv0 = odrive.find_any()
t1 = time.monotonic()
print("duration: "+str(t1-t0))
voltage = odrv0.vbus_voltage
print("voltage: "+str(voltage))
serial = str(odrv0.serial_number)
print("serial: "+serial)
fw = str(odrv0.fw_version_major) + "." + str(odrv0.fw_version_minor) + "." + str(odrv0.fw_version_revision) + "." + str(odrv0.fw_version_unreleased)
print("fw: "+fw)
hw = str(odrv0.hw_version_major) + "." + str(odrv0.hw_version_minor) 
print("hw: "+hw)
variant = str(odrv0.hw_version_variant)
print("variant: "+variant)

i just tested on a raspberry pi 3 model b+ (install is a breeze! great work!)

I started the script twice, there it takes 7 sec. It’s much better but honnestly it kinda sucks. I connected the odrive to a Tattu 3S battery (dont think it’s related but i prefer to mention it)

root@raspberrypi:/home/pi/Desktop/odrive2# python3 test.py 
duration: 7.605438955000864  <== much better but still disappointing
voltage: 12.184863090515137
serial: 59765331406903
fw: 0.4.1.1
hw: 3.5
variant: 48
^CException ignored in: <module 'threading' from '/usr/lib/python3.5/threading.py'>
Traceback (most recent call last):
  File "/usr/lib/python3.5/threading.py", line 1288, in _shutdown
    t.join()
  File "/usr/lib/python3.5/threading.py", line 1054, in join
    self._wait_for_tstate_lock()
  File "/usr/lib/python3.5/threading.py", line 1070, in _wait_for_tstate_lock
    elif lock.acquire(block, timeout):
KeyboardInterrupt
root@raspberrypi:/home/pi/Desktop/odrive2# python3 test.py 
duration: 7.657688958999643
voltage: 12.184863090515137
serial: 59765331406903
fw: 0.4.1.1
hw: 3.5
variant: 48
^CException ignored in: <module 'threading' from '/usr/lib/python3.5/threading.py'>
Traceback (most recent call last):
  File "/usr/lib/python3.5/threading.py", line 1288, in _shutdown
    t.join()
  File "/usr/lib/python3.5/threading.py", line 1054, in join
    self._wait_for_tstate_lock()
  File "/usr/lib/python3.5/threading.py", line 1070, in _wait_for_tstate_lock
    elif lock.acquire(block, timeout):
KeyboardInterrupt
root@raspberrypi:/home/pi/Desktop/odrive2# uname -a
Linux raspberrypi 4.9.80-v7+ #1098 SMP Fri Mar 9 19:11:42 GMT 2018 armv7l GNU/Linux
root@raspberrypi:/home/pi/Desktop/odrive2# cat /etc/os-release 
PRETTY_NAME="Raspbian GNU/Linux 9 (stretch)"
NAME="Raspbian GNU/Linux"
VERSION_ID="9"
VERSION="9 (stretch)"
ID=raspbian
ID_LIKE=debian
HOME_URL="http://www.raspbian.org/"
SUPPORT_URL="http://www.raspbian.org/RaspbianForums"
BUG_REPORT_URL="http://www.raspbian.org/RaspbianBugs"
root@raspberrypi:/home/pi/Desktop/odrive2# 

I will try to reboot the pi just in case and will report here if i observe a difference.

nope. rebooting does not change anything.
I tried using the usb:0001:0008 argument with
odrv0 = odrive.find_any(path="usb:0001:0008")
(what lsusb -v shows up for odrive (InterBiometrics), it stays to about 7 seconds.
(and i did try a another non existing usb path and then it never connects to odrive as expected. so the path argument does something)

i tried with odrivetool, even though I could not measure it, it feels like the same delay. I had same behavior with odrivetool on win7.

it seems to me something waits for a given timeout to happen ?

hope that helps. Basically i can’t work with a 30sec to wait between executions. I must be doing something wrong. I did not have this behavior with the odrive 3.2/3.0 boards.

why is it that find_any is so long ?
surely there must be something wrong

It takes 5-10s for me. The reason it takes a while is that the Python reads the entire protocol dictionary in a fairly inefficient way from the ODrive when it connects. I think 7s is acceptable, and is what most people see. We can look at adding a cache for the protocol descriptor and sending just the hash to check that the cache matches.

The interesting question is why it takes 30s on your one machine. Can you describe if there is anything different about that particular machine?

it’s a corporate win7 64bits machine. i have no clue of it’s particularities. a kaspersky antivus maybe? i’ll try to deactivate it.
do you have a usb monitoring software for windows to suggest (like wireshark usb on linux), so that i know what happens ok the wire. i feel helpless in windows.
worse case scenario, i’ll drop windows.

i think the cache/hash thing is a good idea.

I picked up another win7 64 corporate machine (a dell).
I observe 5.6 sec
i guess i’ll just live with this PC for now.
it would be great if you could implement the cache thing so that redownloading the entire structure of param/functions when not changed is not performed.

It’d be great to have faster startup time. The current 9 second pause makes testing tedious. I’m considering rearchitecting to have a long-running daemon process just for the odrive communication, but this adds a complicated moving part I’ve been able to avoid in all the rest of my system.

I think saving the JSON to a cache file on the machine and verifying it with the CRC only from the ODrive would be the most direct way to improve the speed in a straightforward manner.

back on odrive those days. this time on a frenshly installed ubuntu 18.
i observe some 9sec… it makes dev/testing really tedious, especially considering that it’s a regression compared to older firmware revisions :confused:

another solution for very same issue (fw/sw need to be compatible) I have seen implemented successfully
0. make fw version api long term

  1. starts with checking fw
  2. if client lib runs on a firmware version that is not compatible with software, refuse to communicate

if it’s possible to downgrade the firmware (*) => then i consider this behavior acceptable if not plain desirable. it would then make the need to main a local json useless since pip install would basically provide it

(*) this is for the case when i purchase an odrive board in 1 year from now and do not want the hassle of changing my own software to match odrive latest features

BlackMagic does it for its products and it’s just great.

The delay you are experiencing is caused by the client side software (odrivetool), not the firmware. If you write your own code you can skip this step if you would rather cache the configuration.

can u please point me where in https://github.com/madcowswe/ODrive/tree/master/tools/odrive i should be starting to hack things?

Here is my crack at it. I first create a USB connection. I then try to read the JSON object from a cache file. If that fails, I fall back to reading it from the odrive and writing the cache file. I probably need to invalidate the cache eventually, but I don’t know how to know it needs to be done. Maybe with the firmware version?

Edit: Using this cache, it takes about a second to connect from my laptop and about 2 seconds to connect on a Raspberry Pi.

3 Likes