Viper Quadcopter

It works :rocket: :heart: !

But another issue whose source I don’t quite understand …

$ pyuavcan dsdl-gen-pkg https://github.com/UAVCAN/public_regulated_data_types/archive/master.zip dsdl_src/my_project
Error: RuntimeError: test saturated was already defined.

Can you please re-run the command with -vv and post the output here?

Sure. Here’s the data gathered via

pyuavcan -vv dsdl-gen-pkg https://github.com/UAVCAN/public_regulated_data_types/archive/master.zip dsdl_src/my_project 2> pyuavcan.errlog

pyuavcan.errlog (69.7 KB)

It’s a version mismatch that was just fixed in https://github.com/UAVCAN/pyuavcan/pull/111. Sorry. As we are still working on Nunavut and PyUAVCAN, occasionally things go out of sync causing problems of this kind. Can you please install the latest master of PyUAVCAN? Just clone the repo and run pip install . from its root directory. I think that should get you sorted out. I will be releasing a new version soon.

No worries :wink: Unfortunately it’s still not quite cutting it.

Doing this …

git clone https://github.com/UAVCAN/pyuavcan
cd pyuavcan
python3.8 -m pip install .

… results in …

Processing /home/alex/projects/tools/pyuavcan
Collecting pydsdl~=1.4 (from pyuavcan==1.1.0.dev0)
  Using cached https://files.pythonhosted.org/packages/cf/46/89811eab172932d89e247c6c5b8ebb0fb595005cdefb57ceb0edafdd78a4/pydsdl-1.4.2-py3-none-any.whl
Collecting numpy~=1.16 (from pyuavcan==1.1.0.dev0)
  Using cached https://files.pythonhosted.org/packages/cf/5d/e8198f11dd73a91f7bde15ca88a2b78913fa2b416ae2dc2a6aeafcf4c63d/numpy-1.18.4-cp38-cp38-manylinux1_x86_64.whl
Collecting nunavut==0.2.3 (from pyuavcan==1.1.0.dev0)
  Using cached https://files.pythonhosted.org/packages/dc/53/d956f3833c419e6685d4f736d2dfaf41bc31b8e08b8753b249f8c71ded0c/nunavut-0.2.3-24-py3-none-any.whl
Collecting setuptools (from nunavut==0.2.3->pyuavcan==1.1.0.dev0)
  Using cached https://files.pythonhosted.org/packages/2c/c5/0d38afb961f83e0d51f319f7dc166195ebabc1ea3cb20a10a77f500f7156/setuptools-46.4.0-py3-none-any.whl
Installing collected packages: pydsdl, numpy, setuptools, nunavut, pyuavcan
  Running setup.py install for pyuavcan ... done
Successfully installed numpy-1.18.4 nunavut-0.2.4 pydsdl-1.4.2 pyuavcan-1.1.0.dev0 setuptools-46.4.0

When running …

pyuavcan -vv dsdl-gen-pkg https://github.com/UAVCAN/public_regulated_data_types/archive/master.zip dsdl_src/my_project 2> pyuavcan.errlog2

… I get another error:
pyuavcan.errlog2 (79.3 KB)

Since your commit is about pinning nunavut to 0.2.3 I’m wondering if I have a unclean build setup since it obviously uses 0.2.4 again.

Successfully installed numpy-1.18.4 nunavut-0.2.4 pydsdl-1.4.2 pyuavcan-1.1.0.dev0 setuptools-46.4.0

EDIT: For the record …

pyuavcan$ git log -n 1
commit 5463c0df6522885e87605db168a016d1a1d94541 (HEAD -> master, origin/master, origin/HEAD)
Merge: 5752640 2598d07
Author: Pavel Kirienko <pavel.kirienko@gmail.com>
Date:   Tue May 26 15:59:47 2020 +0300

    Merge pull request #111 from jxltom/patch-1
    
    Update pydsdl as requirement to 1.4

Please run pip install nunavut==0.2.3 or just remove it and reinstall pyuavcan again (Nunavut will be pulled in automatically as a dependency).

Installation:

$ python3.8 -m pip install .
...
Collecting nunavut==0.2.3 (from pyuavcan==1.1.0.dev0)
  Using cached https://files.pythonhosted.org/packages/dc/53/d956f3833c419e6685d4f736d2dfaf41bc31b8e08b8753b249f8c71ded0c/nunavut-0.2.3-24-py3-none-any.whl
...
Installing collected packages: pydsdl, numpy, setuptools, nunavut, pyuavcan
  Running setup.py install for pyuavcan ... done
Successfully installed numpy-1.18.4 nunavut-0.2.3 pydsdl-1.4.2 pyuavcan-1.1.0.dev0 setuptools-46.4.0

Show nunavut version just to be safe:

$ python3.8 -m pip show nunavut
Name: nunavut
Version: 0.2.3
Summary: Generate code from DSDL using Jinja2 templates.
...

Running pyuavcan still generates an error (same as reported here):

pyuavcan -vv dsdl-gen-pkg https://github.com/UAVCAN/public_regulated_data_types/archive/master.zip dsdl_src/my_project 2> pyuavcan.errlog3

pyuavcan.errlog3 (79.3 KB)

Ah. Your root namespace directory dsdl_src/my_project does not appear to contain any DSDL source files. Maybe you forgot to specify version numbers? It should be like Foo.1.0.uavcan instead of Foo.uavcan.

The error message is absolutely unclear and it’s a bug. If you could confirm the above I am going to file it as such on GitHub.

Good morning :wave:

Yes I can in fact confirm that dsdl_src/myproject is empty. Also I don’t want to use any custom UAVCAN types, I just wanted to print a heartbeat on vcan0 via

$ pyuavcan pub 32085.Heartbeat.1.0 '{uptime:0xDEADBEEF, health:HEALTH_NOMINAL, mode:MODE_OPERATIONAL}'
Error: RuntimeError: Subsystem factory 'NodeFactory' for command 'publish' has failed: No module named 'uavcan'

Alas, it didn’t work either so I thought the command listed above the publish command in the crash course is necessary.

It failed because you didn’t generate the types. For that, you just need to run this:

pyuavcan dsdl-gen-pkg https://github.com/UAVCAN/public_regulated_data_types/archive/master.zip

Naturally, if you don’t have any custom types then you shouldn’t ask the generator to generate code for them.

Thank you for pointing this out. Obviously that’s not obvious for a first time user and the error message wasn’t very beneficial either. Now that I’ve generated types for UAVCAN only …

user@dir$ ls uavcan/
diagnostic  file  __init__.py  internet  metatransport  node  pnp  primitive  register  si  time

… I’ve attemted to publish a basic message using a basic example available within the pyuavcan documentation.

user@dir$ pyuavcan publish uavcan.diagnostic.Record.1.0 '{"text": "Hello world!"}'
Error: RuntimeError: Subsystem factory 'NodeFactory' for command 'publish' has failed: No module named 'uavcan'

For sure that error means something to your, for me it’s utterly meaningless :wink:

The tool is behaving as intended. The root cause is that the directory that contains the generated package is not listed as the Python import look-up path. This is mentioned in the documentation if you look at pyuavcan dsdl-gen-pkg --help:

--output OUTPUT, -O OUTPUT
Path to the directory where the generated packages will be stored.
If not specified, defaults to the current working directory.
Existing packages will be overwritten entirely.
                 
The destination directory should be in PYTHONPATH to use the generated
packages

You can fix it like this, if you use bash/sh:

export PYTHONPATH=/your/directory:$PYTHONPATH

The problem with the bad error message is registered at https://github.com/UAVCAN/pydsdl/issues/41

Hi :wave: Thank you very much for providing this bit of information (it works now, after another final piece has been dealt with - details below).

Please don’t take this the wrong way - people don’t read the documentation. Even if its as good as yours and I can tell that you’ve put a lot of effort into it. Also error messages should provide some clue about what has gone wrong, I’m not going to look up the offending Python line causing a runtime error, even if the code is open-source. Tools, code and their usage needs to be as much as possible self-evident.

That being said, even after adding the director to $PYTHONPATH I had the following error

pyuavcan publish uavcan.diagnostic.Record.1.0 '{"text": "Hello world!"}' --tr='CAN(can.media.socketcan.SocketCANMedia("vcan0",8),59)'
Error: RuntimeError: Subsystem factory 'NodeFactory' for command 'publish' has failed: No module named 'serial'

Quite annoying, because I don’t need serial at all. Fixed by

python3.8 -m pip install pyserial

EDIT: Adding documentation of success case

sudo modprobe vcan
sudo ip link add dev vcan0 type vcan
sudo ip link set up vcan0
candump -decaxta vcan0
 (1591276745.132963)  vcan0  TX - -  107D553B   [8]  00 00 00 00 00 A3 03 E0   '........'
 (1591276745.133101)  vcan0  TX - -  107FF83B   [8]  00 00 00 00 00 00 00 A0   '........'
 (1591276745.133181)  vcan0  TX - -  107FF83B   [8]  00 0C 48 65 6C 6C 6F 00   '..Hello.'
 (1591276745.133221)  vcan0  TX - -  107FF83B   [8]  20 77 6F 72 6C 64 21 20   ' world! '
 (1591276745.133292)  vcan0  TX - -  107FF83B   [3]  00 F5 40                  '..@'
 (1591276746.135043)  vcan0  TX - -  107D553B   [8]  01 00 00 00 00 A3 03 E1   '........'

Next question arises … I’m trying my hand at generating a heartbeat message:

$ pyuavcan publish 32085.Heartbeat.1.0 '{uptime: 1337}' --tr='CAN(can.media.socketcan.SocketCANMedia("vcan0",8),59)'
Error: ValueError: Malformed data spec: '32085.Heartbeat.1.0

Now I’ve got not idea from where this error is coming from, if I extent the command like that to encompass all entries of 32085.Heartbeat.1.0.uavcan it fails all the same.

$ pyuavcan publish 32085.Heartbeat.1.0 '{uptime: 1337, health: HEALTH_CAUTION, mode: MODE_MAINTAINANCE}' --tr='CAN(can.media.socketcan.SocketCANMedia("vcan0",8),59)'
Error: ValueError: Malformed data spec: '32085.Heartbeat.1.0'

:man_shrugging:

You found a bug! :tada: Congratulations, I registered it on the bug tracker. Thank you.

The correct syntax is as follows:

pyuavcan publish 32085.uavcan.node.Heartbeat.1.0 '{uptime: 1337}' --tr='CAN(can.media.socketcan.SocketCANMedia("vcan0",8),59)'

Your example didn’t work because you did not provide the full data type name. It should be 32085.uavcan.node.Heartbeat.1.0, not 32085.Heartbeat.1.0. The error message, again, could be better, I agree.

Your feedback is very important. There is a new ticket here: https://github.com/UAVCAN/pyuavcan/issues/115. I am not sure if it’s even possible to build a self-documenting command-line interface due to the limited number of interaction scenarios offered by the command line. If you have a radical idea of how to improve the usability, please share; for now, I will focus on merely improving the error messages.

Thank you very much for your prompt reply :heart: I’m not really setting out to find any bugs, it just that I really don’t like Python very much and therefore have very little on my system (lately I did sudo apt-get purge python* in a Python rage fit which left me amongst other things without a window manager - thank god such inconveniences can be recovered from by reinstalling the window manager from bash :wink: ).

Let’s get back to the subject at hand, I tried to use the “health” field too and stumbled onto the next blocker. Do I have to prefix the message type somehow?

pyuavcan publish 32085.uavcan.node.Heartbeat.1.0 '{uptime: 1337, health: HEALTH_CAUTION}' --tr='CAN(can.media.socketcan.SocketCANMedia("vcan0",8),59)'
Error: ValueError: invalid literal for int() with base 10: 'HEALTH_CAUTION'

Another question that came up: Which node-id is chosen for publishing this message and can I manually set it? I’ve found the folder

node-id-59

within

~/.uavcan/pyuavcan/v1.1/output-transfer-id-maps

. Does that mean that node id 59 (decimal?) was used for my last successful heartbeat transfer?

Nope, the problem is that primitive representations do not allow you to reference constants. You should just use literal 2 instead of HEALTH_CAUTION. It is, indeed, inconvenient, but I am not sure how to approach it best and this issue is so far down the list that it’s not even tracked on the bug tracker.

--transport EXPRESSION, --tr EXPRESSION
...
Observe that the node-ID for the local node is to be configured here as well,
because per the UAVCAN architecture, this is a transport-layer property.
If desired, a usable node-ID value can be automatically found using the
command "pick-node-id"; read its help for usage information (it's useful for
various automation scripts and similar tasks).
...

Don’t get me wrong – I don’t mind answering your questions; in fact, they offer extremely valuable insights about the user’s perception of what we’re building, but I am concerned that you might be spending more of your time on this than you really have to.

You set the node-ID yourself in the string CAN(can.media.socketcan.SocketCANMedia("vcan0",8),59). See 59 at the end of it? You can see the full parameter specs in the docs or you can just execute pyuavcan show-transport to read the same docs in the command line locally.

You appear to be unaware of the fact that every invocation of CLI that instantiates a non-anonymous node will be publishing the heartbeat automatically. Just letting you know because I predict that next you will be asking why is your heartbeat published twice :wink: If you want to override the fields of that auto heartbeat you can use --heartbeat-fields.

If you have any ideas about how to make the life of the user easier (aside from improving error messages), please share. The CLI toolset does seem a bit convoluted and it could be possible to make it more approachable without requiring the user to dig through the docs for hours. Maybe.

Actually I was not going to ask that question because I read in fact the whole UAVCAN v1 crash course entry where this aspect is mentioned :wink: But yes, I fully admit guilty to the trial-and-error approach when it comes to reading documentation :blush:

Actually I’ve got a couple of suggestions to make the CLI tool easier to use.

  1. As a user using the pyuavcan publish feature I’m interested first and foremost in publishing UAVCAN data on various transport layers. That’s why my focus is on setting up the message and not configuring the transportlayer which additionally is appended at the end of a already very long bash entry (alternatively it’s in front but the manipulation of the message is at the end, also undesirable). This is actually the reason why I was unable to make the connection of the 59 node id with the 59 at the end of the --tr string - it was simply lost to my eye focus because of the awful long bash line.
  2. As a typical user I’m not going to change my transport layer 3 times a day. Probably I’ll change it never. Therefore it might be worth considering to introduce “state” to the pyuavcan CLI tool which allows to permanently configure the desired transport layer. (pyuavcan config --gobal transport=CAN). It’s probably only you as the UAVCAN devs that need to change between various transport layers on a regular basis.
  3. The transport layer configuration is done via a string. I daresay that’s unusal for the typical bash user. They(we) are used to having identifiers before the parameter which give some hint as what it is that we are configuring. E.g.
--tr=[CAN|Serial|...]
--tr=CAN [can0|vcan0|can1|...] -can-mtu-=[8|64] -can-id=(0-127)

Thank you. I think 1 and 2 are sensible points and I just registered this issue here: https://github.com/UAVCAN/pyuavcan/issues/117

Not sure about the specialized options though. I implemented this approach early in the development process but it is quite messy because you have to keep these options aware and in sync with the transport implementations, it’s just too much work to maintain reliably. I think if we made the environment variables as described in the linked issue it would solve the problem ultimately because I suppose you would just stash the config away in your ~/.bashrc and never look at it again.