Debugging Guide

In this section, we'll cover some debugging suggestions that can help track down the source of issues in an app.

Tracing Broken and Orphaned Blocks

Pictorus is constantly re-evaluating your diagram to see what it can generate code for, and what it cannot. You can highlight issues by clicking the blue exclamation mark in the bottom-right. It will highlight any Broken (blocks with bad parameters or missing inputs) in red, and any Orphaned blocks (blocks affected by a Broken block) in orange.

broken and orphaned blocks

In the example above, we could see that the Product block was broken, since multiplication requires two inputs. By attaching another signal to it, the issue is resolved and the App compiles. By removing an input to the Sum block, new issues are reported and we can quickly identify them.

Error Messages

Certain blocks also have specific checks that run before an app can be compiled. If there is an issue that causes these checks to fail, a build error message will appear in red at the top of the canvas. We can see an example of this below, where a matrix multiplication block sees an error in the sizes of its input matrices. Errors will usually show the block name and size to help identify the source of the issue. Resizing the second input with a Vector Reshape block clears the error in this example.

Build error messages

Build errors will appear in the debugging terminal rather than as a banner in the canvas when the terminal is viewable. Below we see that the matrix sizing error is also logged in the debug terminal.

Terminal error

Errors that happen when an app is running will also appear at the top of the canvas and in the debug. Some examples of these errors include a device going offline or a protocol being configured incorrectly. For instance, here we see an error for a nonexistent serial port on a Raspberry Pi:

Runtime error

Sizing and Execution Order Hints

When an app is successfully compiled, Pictorus can also display information about the flow of data in an app. Specifically, users can see the order of execution of blocks as well as the size of the output for each block. After the app builds successfully, click the blue exclamation mark (!) in the bottom left of the UI to display block flow information. The execution order (#n) and size (m,n) will appear above each block, as outlined in orange below:

Sizing and execution order

Debugging Apps on a Device

General hardware debugging guidance

Before digging into our on-hardware debugging features, here is a quick reminder to consider some general hardware debugging steps when an app does not run as expected:

  • Check your wiring. Double check that your pins, ports, and connections match those configured in your diagram.

  • Check the documentation. Devices often have nuanced bootup/configuration sequences, or odd timing steps that must be executed precisely before the device will communicate properly.

  • Check all required protocols are enabled. Some protocols on some devices (like I2C on RaspberryPi) have to be manually enabled within the OS. Check if that is the case.

  • Does it work with a trusted Python script (or any other tool)? Many device manufacturers publish simple scripts online that can verify a device is working properly.

  • When in doubt, power-cycle! The old reliable medicine for a misbehaving computer.

For devices which are online but behaving oddly, consider the following software debugging steps:

Viewing App Logs

After SSHing into your device. You should be able to see logs from the app and device manager using journalctl.

  • To see all logs: journalctl -u pictorus
  • To see recent log output in real time journalctl -u pictorus -f

These logs may reveal some telling errors, especially if the app is crashing or failing to initialize properly.

Running the app manually

You can also run an app outside of the device manager and manually pass in flags to make debugging easier.

  1. First make sure that the app is not running to avoid any resource conflicts.
    • You can do this by pausing the app from the UI, or by running sudo systemctl stop pictorus to kill the device manager and any associated processes. If you kill the app manager, make sure to start it when you're finished: sudo systemctl start pictorus.
  2. You can now run the installed app manually by running sudo /root/.pictorus/device_manager/apps/pictorus_managed_app

Debug logging

You can add the flag LOG_LEVEL=debug to print out extra information, including the value of each block at every time step. Warning: This generates a lot of verbose output, and can affect the performance of apps.

  • sudo LOG_LEVEL=debug /root/.pictorus/device_manager/apps/pictorus_managed_app

Recording data to a CSV

You can have the app output block values to a CSV file by setting APP_DATA_LOG_RATE_HZ=<rate_hz>, where the specified number is the maximum rate in Hz that the data will be logged. Data will be output to a file named diagram_output.csv in your current directory.

  • sudo APP_DATA_LOG_RATE_HZ=1 /root/.pictorus/device_manager/apps/pictorus_managed_app
  • This will only record data from blocks connected to a diagram output (such as plots or network/file IO blocks), so you will need to connect any blocks you're interested in to a Plot block.

Overriding block parameters

You can override parameters for any block in the diagram using environment variables. This can be done by locating the block ID (found in the lower right-hand corner of a block's setting panel),

Block ID

and then appending the name of the param you want to override. For instance: if I wanted to set the Amplitude of a block with ID = sinewave_123 to 42, I would add the flag SINEWAVE_123_AMPLITUDE=42 (note this must be all caps!) to the run command.

  • sudo SINEWAVE_123_AMPLITUDE=42 /root/.pictorus/device_manager/apps/pictorus_managed_app

Environment variables

There are other environment variables your App will respond to. Below is a list of them:

  • APP_DATA_LOG_RATE_HZ (default = 0): Sets the rate, in hertz (times per second), at which output data is logged to file. If the rate is 0 (as it is by default), no data output file will be created. An App cannot publish faster than its fundamental update rate (specified in browser).
  • APP_RUN_PATH (default = ""): The run path sets the local path where any assets generated by the app (i.e. the data log) will be stored.
  • APP_TRANSMIT_ENABLED (default = True): Enables/Disables any communication with hardware and protocols. When running in Simulation mode, for example, this prevents apps from attempting to communicate with non-existent hardware.
  • APP_PUBLISH_SOCKET (default = ""): Sets the UDP socket for communication with the Pictorus Device Manager.
  • LOG_LEVEL (default = INFO): Sets the logging level. Options are currently INFO and DEBUG. Info level shows very little logging, but will capture any major failure messages. Debug level dumps every single block’s value at every single time step. Use with caution!