GUI Tool – Next Generation

I wanted to start a thread about the next generation of the GUI tool. As some might be aware the current version is encumbered by a GPL license in the Python binding for the QT GUI toolkit. Because one of the core features of UAVCAN is that “the specification and high quality reference implementations are open and free to use” we must find an alternative.

The current thinking (agreed upon at the recent Stockholm conference) is that we should start over using pyuavcan as the basis for the GUI but presenting this GUI as a JavaScript UI served from a local python process (e.g. Like Jupyter notebooks are served when run locally).

There are two important points to discuss in this thread:

1. What GUI toolkit should we use?

  • Angular?
  • React?
  • Ember?
  • ???

2. Is anyone in the community interested in taking on development of this GUI?

The current maintainers lack the time and expertise to take on a Javascript GUI while developing v1.

Here comes my personal wish list. Note that I intend to start working on an async-based rewrite of PyUAVCAN once the spec draft is finished.

Multi-node concurrent configuration tool

Many nodes, such as motor controllers, often require identical configuration to be shared across multiple devices. Shared configuration parameters are a subset of all parameters available on nodes; for example, uavcan.node_id will have to be unique, whereas motor_resistance are likely to be the same for all controllers.

Some parameters may have to be distributed across heterogeneous node sets, such as CAN bus bit rate.

The GUI tool should allow the user to batch-reconfigure an arbitrary set of nodes on the bus. Probably this should be arranged like some sort of table, where columns are nodes, and rows are configuration parameters:

Parameter name 12 42 123
param_a 1 2 <N/A>
param_b 12.34 -2.45 100500
param_c <N/A> 1, 2 2, 89

Parameter import/export

It should be possible to load/store configuration parameters to/from a node (or multiple nodes, as above) from/to file on disk.

Computational graph display with statistics

Quote from PR:

uavcan.node.GetPorts, uavcan.node.GetPortInfo, uavcan.node.GetPortStatistics - these data types provide a simple yet very powerful API that allows one to reconstruct the computational graph, collect the main communication metrics (input/output/errors) in real time, and verify that all nodes use compatible data types for communication with each other. Eventually, when the new GUI tool is around, it will be able to build things like this, showing the traffic intensity and transport errors in real time:

Bus monitor with logging

The existing bus monitor seems to have most of the required functionality. What is missing is the ability to log data (raw CAN frames with timestamps) to a file. For the file format, I suggest we use Popcop frame format, like HDLC – it is very simple, offers a transparent channel, and uses a strong CRC32C algorithm.

Logging to a file from the browser might be impossible though, so this functionality may need to be implemented on the server and controlled remotely from the browser with the ability to download the log file when completed.

Log file analysis

I haven’t given much thought to this idea yet, this is a highly complex feature which probably shouldn’t be implemented in the first edition of the tool. What follows is a highly disorganized collection of random ideas.

Ideally I would like to be able to load a frame dump file (which contains only timestamped CAN frames; or, well, not necessarily CAN, but we don’t support other protocols yet) recorded either by the tool itself or by a third-party hardware (which is why it is important to agree on a particular format beforehand), and let the tool perform an in-depth analysis of the state of the bus at any given moment in time, with a convenient overview of important events that were happening on the bus for the duration of the log file.

For example, suppose we have an hour long data dump from a black box flight recorder (which is stupid and all it does is just storing CAN frames on a flash disk with local monotonic timestamps). Having opened the recorded file, we should be able to see a brief event overview on a timeline, where important events are marked, such as: a new node appeared, a diagnostic message emitted, and so on, correlated with a bus load plot (so that we can see bus load abnormalities easily) and the system time (recovered from time sync messages correlated with the monotonic timestamps from the log file). There should be some kind of a cursor, which the user can slide across the timeline. Having positioned the cursor at a particular location, the user would get a sample of the current state of the bus at this exact moment of time: which nodes are online, what are their statuses, and so on. It should be possible to replay segments of the timeline to plot values and study the data exchanged over the bus during that segment. It should be possible to export parsed data from a particular subject to a CSV, or search for a particular data pattern on the bus (e.g. find the first occurence where abs(climb_rate) > 10). The tool should be able to automatically attempt to parse the entire data set and highlight sections where data could not be parsed, possibly indicating connectivity problems. Ideally it should be possible to correlate multiple dump files in the same analysis session, to support recordings from redundant transports. My wish list is very long but I perceive I should stop here.

At one point in the past I spent a lot of time working with the ROS logging system, you can find some info here for inspiration:


Supremely important for debugging. Nothing to add here, the feature is self-explanatory. I am generally okay with the plotter we have in the current GUI tool, except that its configuration interface is a bit clumsy and not so user-friendly, perhaps it could be improved.

Publishing tool

In the current GUI tool there is a “ESC panel”, which works, but it’s created for a very specific, narrow use case. I think it should be possible to create a generic alternative which would allow the user to publish arbitrary messages or invoke arbitrary services by providing a dynamically-constructed GUI based on the DSDL definition of the data type in use. That would be great to have, doesn’t seem very hard to implement.

Other features available in the current GUI tool

This includes the log viewer, dynamic node ID allocator, and the file server (the last two are implemented in PyUAVCAN). The file server is required for firmware updates.

I’d like to add:

Panel Framework

An API and mechanism for easily and dynamically adding custom UI panels to the gui. This allows system developers and vendors to provide highly specific controls for a given system/component.

It would also be interesting to define a way to associate a set of DSDL with a panel in a packaging format that would allow a vendor of, for example, a particular ESC to deliver the types and UI for their product using pypi or npm or something similar.

1 Like

So when shall we start this project? Looking forward to it.

The first step is to finish the specification:

Then we should update PyUAVCAN to make it compatible with the new spec (actually it will be a full rewrite):

When the above are done, we will be able to start working on the new GUI. Meanwhile we could use help with libcanard (which also requires update to UAVCAN v1.0).

1 Like

I think we can start on wireframes for the UI @pavel.kirienko?

You are right. I’m probably a bit too hung up on finishing the spec and the reference implementations; nothing is stopping us from starting with the GUI part and working out the general architecture. Who wants to spearhead this?

This is where I betray the fact that I have, in-fact, built a few user interfaces in my career. As such I have some experience working with information architects and UI designers and can pretend I learned something about those disciplines and volunteer do the wireframes. That said, If there are real creative types out there they should speak up now before I decide to make every user action require 10 mouse clicks and a scroll wheel.

1 Like

15 posts were split to a new topic: Deciding on the name (moved from #229)

Proposed Logo

I see a dog. What’s my diagnosis?

Random ideas galore. What if we turned the computational graph widget into an interactive graphical programming utility?

Suppose we introduced a convention (recommendation) that all ports with non-fixed ID can be configured via a configuration parameter (register) named in a particular way, e.g., uavcan.subj.motor_angvel – this example shows us a configuration parameter which sets the subject ID of a data link that carries the angular velocity of a certain motor; the part uavcan.subj. is dictated by the convention, and the suffix motor_angvel is defined by the user/vendor, it could be anything. The range of the parameter should be [0, 65536] (Natural32); the value 65536 is needed to represent an unconfigured subject ID.

Suppose we have a bus that contains seven nodes. The nodes have just been connected and powered on for the first time, the bus is non-functional yet. The graph widget shows us this:

Boring. The user picks up their computer mouse, clicks on the connection point labeled servo_angle_roll, and draws the mouse over to the first servo’s connection point labeled angle. The user lets go of the computer mouse, thereby having created a new subject. But wait, this new subject does not have a fixed subject ID, yet we need one.

A pop-up dialog saves the day: subject_id_of_new_link

Having specified the subject ID (let’s say 12), the user clicks OKAY. Yukon takes notice and issues two requests of type uavcan.register.Access to both of the involved nodes – the autopilot and the servo:

  • The request to the autopilot assigns the value 12 to the register uavcan.subj.servo_angle_roll.
  • The request to the servo assigns the value 12 to the register uavcan.subj.angle.

Done, the link is now created (although it may not be active yet, depending on whether the nodes require a restart for the parameter change to take effect).

If the user wanted to add yet another connection point to the same subject, the dialog box exercise wouldn’t have be repeated, because Yukon will be able to deduce that we’re connecting a new item to an already existing subject with a known subject ID.

Suppose that, having repeated the procedure a dozen of times, the user ended up with a satisfactory configuration:

The diagram is known to be incomplete and a bit misleading, because there always exist subjects with fixed port IDs that do not require a configuration. They are not shown in this demo. In the real widget they should probably appear as unchanging static links that can’t be disconnected or moved (they are static, after all).

Should the user desire to get rid of an unwanted connection, they would just disconnect an appropriate link, and Yukon will issue a request uavcan.register.Access with the value set to 65536.

It is assumed here that Yukon does not have any prior knowledge of the properties of the involved nodes; the information is deduced at runtime by evaluating the available registers; specifically, by matching all available register names against uavcan.subj.*.

An overly attentive reader would point out that we never once asked ourselves: “is it type safe?” Indeed, such blatant disregard of type safety is borderline illegal.

Unfortunately, the type introspection tools we have at our disposal (namely uavcan.node.port.GetInfo) operate at a level of abstraction that is too low to be useful in this setting. The core problem here is that the type information is attached to a port ID rather than a particular function available in the node. The important implications are:

  • Type introspection data is dependent on the port ID settings.
  • Type introspection can’t be performed until a port ID is assigned. Which in turn means that the correctness of a new subject link can’t be verified until the link is established.

What can we do about this? Raising the level of abstraction of the existing introspection API doesn’t seem like a decent idea because all options that come to mind so far seem extremely complex and implementers may be hesitant to support them. Another solution is to go the way of other protocols and introduce the optional concept of electronic datasheets, where the type information will be explicitly stated. The third solution is to further extend the register naming conventions by adding a new name pattern: uavcan.type.*, where the asterisk stands for the port name – e.g., uavcan.type.servo_angle_roll – the value contained in the register will be the name of the data type together with the major version number, like

Ultimately we may want to go both ways: introduce electronic datasheets at some point in the future, and also enrich introspection by specifying the register naming conventions (uavcan.subj.*, uavcan.type.*). The electronic datasheets are likely to be preferred in high-reliability settings where any extra logic that is not directly related to the end application implemented on the node is undesirable; the way of introspection is likely to be more useful for highly sophisticated setups involving many complex COTS nodes from different vendors (robotics, autonomous driving, etc.). This is is unlikely to appear in the spec before UAVCAN v1.1, but nobody is stopping us from implementing this logic in Yukon as a vendor-specific extension which is to be specified later.

Oh geez @pavel.kirienko, I’m getting flashbacks to directshow.

Oh wow. May I ask you to share a few words about that undertaking? I see that it is based on UAVCAN v0, which makes sense considering that I am yet to publish my rewrite of pyuavcan which is UAVCAN v1.0-compatible. Do you have migration to UAVCAN v1.0 on your short-term roadmap?

I have much more experience on frontend/backend/web stuff than C++ / I’m able to help much much more with this one!

I think that the best thing at this point in time (for web, at least) would be

  1. React
  2. Vue

(with that priority).
uavcan-web is extra nice; Having such a separation layer is a must for a portable UI. Edit: Api endpoint versioning could go in par with potential breaking changes in the spec.

In the end, it would not be hard to make some UI with any technology. The only thing that makes me wonder about implementation & technology details is

‘‘It would also be interesting to define a way to associate a set of DSDL with a panel in a packaging format that would allow a vendor of, for example, a particular ESC to deliver the types and UI for their product using pypi or npm or something similar.’’

Perhaps we can provide minumum-boilerplate starting project templates so anyone can use this.

PS. Some 2 extra name recommendations: uavcan shark / uavcan cat (inspired from wireshark / netcat)


This is great to hear! Us bit twiddlers have been looking for help from UI wranglers for awhile now. @Linjieqiang would you be willing to work with @Zarkopafilis to start Yukon as a Vue/Flask project?

I’d like to avoid React because Facebook and messed with the licensing in the past (I’m not sure if they changed it back to plain-vanilla MIT or if they still have the “we haz all your patenz” clause in it but I’d like to avoid it).

I’m cool with that. We can start by working out some endpoints and data contracts, then UI and backend can go sort of in parallel if we split the work up.

I’m away at Germany due to a family trip. I’ll be back at 21/Feb and after finishing the TxQueue PR (a very small fix and it should be ready), we can start iterating the agile way, without having a strict wireframe spec.

I guess we can start with some mockups too?

This is great to hear! I have one PR pending in Yukon (Paging @pavel.kirienko -> that lays out some very initial guidelines. Mostly I want to build a very modern GUI that avoids windows, dialogs, drop-down menus, and other dated interactions that nobody really likes. We should take our design cues from the web and IDEs that aren’t Eclipse (e.g. vscode and Atom both have a lot of nice interactions we could emulate).

I really don’t have time to contribute much to this effort other than help review and consult since my time for open-source work is dedicated to libuavcan these days but I’ll do what I can to get this started. It’s really very important to the ongoing success of uavcan.

We should also write down the final technology decisions in the Yukon readme. We did not consider an Electron based front-end if you have experience with that at all? Barring that I think Flask/Vu.js might be a good start for the front-end. What’s most important is to get a good interface layer between the core python toolset and any GUI we want to put on top of it.

Sorry, I hadn’t realized that it’s been waiting for my review. I normally ignore push notifications (maybe that’s because I push a lot), so in the future don’t hesitate to nudge me relentlessly if you need me to look at something. Sorry.

Crap. I love all that stuff. Can we at least keep a tiny command line hidden in there somewhere? :keyboard:

I should probably inform the public here that my pyuavcan rewrite is fully asynchronous and requires Python 3.6+ at the moment.

+1 for the command line. It needs to be decided whether it would be based on the interface layer (REST or whatever), or on newest pyuavcan.

We should have two “command-lines” actually. First: anything that you can do through the GUI you should be able to do through a command-line-only python script (i.e. we shall have feature parity between the GUI and either pyuavcan or an automation layer on top of pyuavcan). Second: we should have a “one-box” widget like vscode has via CMD+P that allows navigation using the keyboard.

Which re-raises the question: should this be an Electron application or even a VSCode extension?

1 Like