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


#1

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)

ODrive doesn't show up in odrivetool
#2

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.


#3

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.


#4

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


#5

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?


#6

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.


#7

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.


#8

I suppose I don’t see much benefit in having to CRC the JSON interface upon each connection. SInce the interface is essentially bound to the firmware major/minor/variant, I think it makes sense to just ship the JSON interface definition with the client side during release - especially now that the code generation is in place.

Alternatively, skip the whole JSON part and have the code generator spit out actual code rather than an object representing the interface.

I can appreciate the idea of dynamically discovering endpoints and the client never really having to know the firmware version, but I think in practice it’s not especially useful beyond an interactive CLI sort of situation a la odrivetool; especially with significant breaking changes to the API that a client library can’t hide behind its abstractions.

Mind you this is from the perspective of a dev currently neck deep in the whole shebang and not privy to any future plans where this dynamicism may underpin the entire feature. I had planned (still do) to associate an archived endpoints.json/CRC16 with firmware fw_version_major/minor/variant and bypass the fetch of endpoint 0 altogether.

edit: I’ve noticed also a few TODO/FIX notes citing small packet sizes as well. As it stands, 32 bytes is the max packet size from endpoint 0 - 2 bytes of which are the sequence number, so we’re talking about 30 characters per sequential round-trip until receiving the entire 18,000 characters for a total of about 600 request/response pairs. USB performance is going to play a large role in the instantiation time, I think.