VILLASframework
Modular co-simulation framework
Lab 10: The daemon

During the previous labs, we use the villas pipe, villas hook and villas signal tools connect simulators and process the exchanged simulation data. This approach is handy for small tests, development and training. However, more complex scenaries are unmanagable with this approach.

In this lab we introduce the VILLASnode daemon villas node which provides an easier way to setup complex scenarios. In addition, villas node benefits from lower latencies because we omit the standard input / output streams and the conversion of the samples in a human readable / line-based representation.

Note: We recommend the usage of the daemon for all real-time critical HIL simulations

The invocation of the daemon is pretty simple. Just pass the path to the configuration file as a paramteter:

$ villas node lab10_path_uni.conf

All VILLASnode tools can fetch their configuration file from remote locations (all protocols from libcurl are supported):

# From a web server
$ villas node https://villas.fein-aachen.org/doc/etc/lab3.conf
# From a Windows share (use single quotes!)
$ villas node 'smb://domain\user:passwd@example.com/share/file.conf'
# From a FTP server
$ villas node ftp://user:passwd@example.com/lab3.conf'
# Via SSH / SFTP
$ villas node sftp://user:passwd@example.com/etc/villas/node/lab3.conf

Example configurations

All of the following examples use the same set of nodes, which we define in the file lab10_nodes.conf:

1 hugepages = 200
2 
3 nodes = {
4  # Node names can be any alphanumeric value
5  rpi-1 = {
6  type = "socket"
7  layer = "udp"
8  format = "gtnet" # pre-built format to communicate in RTDS GTNET-SKT payload
9 
10  in = {
11  address = "*:12005" # villas node machine IP and port number
12 
13  signals = {
14  count = 8
15  type = "float"
16  }
17 
18  hooks = (
19  {
20  type = "stats"
21  warmup = 3000
22  }
23  )
24  },
25  out = {
26  address = "192.168.0.5:12005" # remote machine IP and port number
27  }
28  },
29  rpi-2 = {
30  type = "socket"
31  layer = "udp"
32  format = "gtnet" # pre-built format to communicate in RTDS GTNET-SKT payload
33 
34  in = {
35  address = "*:12006" # villas node machine IP and port number
36 
37  signals = {
38  count = 8
39  type = "float"
40  }
41 
42  hooks = (
43  {
44  type = "stats"
45  warmup = 3000
46  }
47  )
48  }
49  out = {
50  address = "192.168.0.6:12006" # remote machine IP and port number
51  }
52  },
53  rtds-1 = {
54  type = "socket"
55  layer = "udp"
56  format = "gtnet"
57 
58  in = {
59  address = "*:12083" # villas node machine IP and port number
60 
61  signals = {
62  count = 8
63  type = "float"
64  }
65 
66  hooks = (
67  {
68  type = "stats"
69  warmup = 3000
70  }
71  )
72  }
73  out = {
74  address = "192.168.0.4:12083" # remote machine IP and port number
75  }
76  }
77 }

Nodes for the following examples.

A unidirectional path

Todo: Please note, that currently each node must only used once as an input node. Using the same node as an input to multiple paths is not possible. Please consider using Loopback nodes as a workaround.

The configuration file lab10_uni_path.conf extends lab10_nodes.conf with a path section. This example reads samples from node rpi-1 and forwards them immediately to node rtds-1.

1 @include "lab10_nodes.conf"
2 
3 paths = (
4  {
5  in = [ "rpi-1" ],
6  out = [ "rtds-1" ]
7  }
8 )

A path with multiple destinations

A path can have multiple destinations by using an array for the out setting. This example reads samples from node rtds-1, duplicates them and forwards them immediately to nodes rpi-1 and rpi-2.

1 @include "lab10_nodes.conf"
2 
3 paths = (
4  {
5  in = [ "rtds-1" ],
6  out = [ "rpi-1", "rpi-2" ]
7  }
8 )

A path with a hook

Sometimes we want to filter and/or manipulate samples which are processes by a path. To do so, we can attach hook functions to a path. These hook functions are called for every batch of samples which is processed by the pass. This examples uses the print hook to display all forwarded samples on stdout of the console.

1 @include "lab10_nodes.conf"
2 
3 paths = (
4  {
5  in = [ "rpi-1" ],
6  out = [ "rtds-1" ],
7 
8  hooks = (
9  { type = "print", output = "stdout" }
10  )
11  }
12 )

A bidirectional path

In a last example we demonstrate a bi-directional path by using multiple entries in the paths section.

1 @include "lab10_nodes.conf"
2 
3 paths = (
4  # Each path dictionary corresponds to one way communnication
5  {
6  in = [ "rpi-1" ],
7  out = [ "rtds-1" ]
8  },
9  {
10  in = [ "rtds-1" ],
11  out = [ "rpi-1" ]
12  }
13 
14  # Alternatively, you can use a single path specification
15  # and set reverse = true
16  # Example:
17  # {
18  # in = [ "rpi-1" ],
19  # out = [ "rtds-1" ],
20  # reverse = true
21  # }
22 )

Go to [lab 11] =>(node-lab-11)