Matt's Blog

Labview dataflow programming in Erlang

Tue Nov 28 21:09:38 EST 2006

Labview is a commonly used language for setting up experiments. It has a number of nice features:

  • programs are written in a graphical programming language, ie by moving icons around a diagram to create a schematic representation of the experiment
  • program execution is data-flow oriented, ie each icon has a number of inputs and outputs, and only outputs data once all of its inputs have received data. This seems a natural way of modelling signal processing tasks.

Erlang is a language where concurrency is the main consideration. The Erlang virtual machine can create independent lightweight processes at very little cost, with the processes communicating via message passing to unique process identifiers (PIDs).
Here I am going to consider the problem of programming Labview-like data-flow oriented programming in Erlang.

A Virtual Instrument (VI) is represented in Labview as an icon having a certain number of input and output terminals, and some function that connects the input to the output. I think that this can be represented in Erlang by a process each input, output and the main function (or manager), as described below.

The input processes consist of server loops that know the PID of the main function. When an input process receives data it sends it on to the main function and then enters another state where it waits for the main function wo tell it to continue. During this "wait state" any incoming data messages are left in the process data queue.

The output processes store a list of processes connected to the output, and forward any incoming messages to these "subscribers" when the main function outputs data.

The manager is aware of the PIDs of all of the inputs and outputs, and indeed creates them on intialisation. Other processes connect to the inputs and outputs by sending a message to the manager process, eg connect(device1,input1,device2,output1) (much like the Qt slots and stubs GUI callback model). Connecting to an input involves the manager telling the input what PID to listen to data from and telling the subscriber the PID of the input. Connecting to the output just involves telling the output the PID of the subscriber. When the program is running the manager keeps a list of inputs that it has not received data from. When this list is empty the manager calculates the function that it represents and passes the results to the output processes. It then unlocks the input processes and waits for more data.

Model this in a domain specific language eg

% Define an adder
define adder (in: x,y; out: z){
  input number x
  input number y
  output number z=x+y}

% Define a data source
define rand (out: x) {
  output number x=(random:float 0.0 1.0)

% Create the adder and data sources
create a1 {adder}
create r1 {rand}
create r2 {rand}

% Connect everything together
connect r1.x adder.x
connect r2.x adder.y
connect adder.z stdout

I want to be able to compile something similar to the above into a set of Erlang programs. It feels to me that each VI should be represented by a separate OTP application, since this is about the only abstraction mechanism present in Erlang (applications can contain other applications but processes can't contain other processes). But I don't know enough about OTP to be sure about this.

Short term goals:

  • write a simple data source that outputs a random number to another PID. Connect this to stdout or another window.
  • write a simple data sink that receives input. Perhaps create a graphical window to represent the state of this data sink.
  • Tie the source and the sink together.
  • Wrap a while loop around the two processes somehow. This will depend on how the data source is represented, the while loop could just be another process that tells the data source to generate a new value periodically.

Other thoughts:

  • my device descriptions above remind me of the ADA language
  • the circuit description language in Chapter 3 of SICP (the wizard book) could also be a useful starting point

[code] [erlang]


code (31)

erlang (6)
ideas (24)
lisp (1)
me (14)
notes (6)
ocaml (4)
physics (46)
qo (7)
unix (6)
vim (3)