quarc_udp_multiagent_agent1_demo.mdl
quarc_udp_multiagent_agent2_demo.mdl; quarc_udp_multiagent_agent3_demo.mdl
Open these models

QUARC UDP Multi-Agent Demo

This example consists of three Simulink models. It demonstrates how to use the Basic Communications blockset from the QUARC Targets Library to implement a set of multiple cooperating agents which communicate with each other using UDP broadcasting. In this particular example, each agent exchanges information with all the other agents at the same time. The clients may be run on the local machine or on remote hosts. For general information on the Basic Communications feature of QUARC, you can refer to the Basic Communications section. Be sure to investigate the Important Considerations section below to understand the design considerations that went into this demonstration.

UDP Agent #1 Demo Simulink Diagram

UDP Agent #2 Demo Simulink Diagram

UDP Agent #3 Demo Simulink Diagram

Configuring the Demonstration

This demonstration can be run with all three models running on the local host, or it can be run with each agent running on a different target on the same network. Refer to the appropriate section below for the desired configuration. Quanser recommends trying the demonstration on the local host first before attempting to run the agents on remote targets, because firewall considerations become relevant when communicating with remote targets.

Running on Local Host

To run the demonstration on the local Windows host no configuration should be required. The defaults should work.

Running on Remote Hosts

To run an agent on a remote target, some configuration is required. Specifically:

The steps outlined below assume that the remote targets are the same platform as the local host. If not then a different configuration must be activated in Model Explorer to correspond to the type of target running on each remote target.

To modify the model URI of an agent so that the agent model is run on the desired remote target, open the Configuration Parameters dialog by selecting Configuration Parameters... from the Simulation menu, or by pressing Ctrl+E. Then navigate to the Code Generation/Interface pane in the Select treeview.

Agent Configuration Parameters dialog

In the MEX-file arguments field, append the model URI of the remote target in single quotes. Be sure to separate the model URI from the model arguments with a comma. For example, if the remote machine is called "remhost", then a suitable model URI is "tcpip://remhost:17001" and the MEX-file arguments would look like:

            '-w -d %d -uri %u','tcpip://remhost:17001'
        

For more information on model URIs and running QUARC models on remote targets, please refer to the Specifying a Model and/or Target URI page in the QUARC documentation. For a general discussion of model URIs, refer to Real-Time Code - the Model URI section of the Communicating with the Target documentation.

Configure the model URI of each agent model that is to be run on a remote target. Don't forget the firewall exceptions for UDP port 18000 and TCP ports 17000 and 17001.

Demonstration

Select Build from the QUARC menu of the diagram, or press Ctrl+B while each of the diagrams is the active window. A great deal of output will appear in the Diagnostic Viewer about the progress of the build. If you cannot see the Diagnostic Viewer, you can open it by selecting View/Diagnostic Viewer from the menu of the diagram, or clicking on the View Diagnostics hyperlink at the bottom of the diagram. If you have MATLAB R2013b or earlier then the output will appear in the MATLAB Command Window.

Double-click on the "Agent #1 Data", "Agent #2 Data" and "Agent #3 Data" Scopes in the quarc_udp_multiagent_agent1_demo.mdl, quarc_udp_multiagent_agent2_demo.mdl and quarc_udp_multiagent_agent3_demo.mdl models to open their Scopes.

Click on the Connect to Target button or select Connect to Target from the Simulation menu of the quarc_udp_multiagent_agent1_demo.mdl diagram to connect to the Agent #1 model.

Start the Agent #1 model by clicking on the Run button or selecting Run from the Simulation menu of the diagrams. The Start item of the QUARC menu may also be used to both connect and start the model in one operation.

At this point, only Agent #1 is running. No other agents are executing. However, the "Agent #1 Data" plot shows the sine wave transmitted by Agent #1. Unlike the "QUARC UDP Server Demo", in this example each agent receives its own data! Because the Stream Server block is operating in UDP broadcast mode, each datagram it sends gets broadcast to the whole network and received by every server listening on the port - including the server which sent the datagram in the first place. The logic for the models must account for this behaviour when UDP broadcast is used.

Agent #1 Data scope when Agent #1 running Agent #2 Data scope when Agent #2 not running Agent #3 Data scope when Agent #3 not running

Now start the Agent #2 and Agent #3 models.

A sine wave of amplitude 4 will be displayed in the "Agent #1 Data" Scope of all the agents. A sawtooth wave will appear for the "Agent #2 Data" Scopes and a square wave will plot on the "Agent #3 Data" Scopes of all agents.

Agent #1 Data Scope with sine wave of amplitude 4 Agent #2 Data Scope with Sawtooth Wave of Amplitude 4 Agent #3 Data Scope with Square Wave of Amplitude 4

Click on the Stop button or select Stop from the Simulation menu of the diagram to stop each model. The Stop item of the QUARC menu may also be used.

Important Considerations

A number of important decisions were made in designing this demonstration to ensure that communications with multiple agents operated correctly. This section deals with the important factors that were considered and drove the implementation of this example. It will also highlight changes from the default settings that were required.

Use of Stream Server block for Agents

Unlike the QUARC UDP Server Demo, this example uses the Stream Server block in all the models instead of the Stream Client block. At first, this implementation appears very counter-intuitive.

However, the reasoning is actually not that complicated. Each model broadcasts UDP datagrams to the network using a special broadcast address. They do not communicate using the IP address of each target. However, UDP clients only receive datagrams sent to their IP address and port. Thus, using a Stream Client would not allow the client to receive any datagrams from the server because the broadcast address would not match the IP address and port of the client socket.

By using a Stream Server block in each model, each agent can receive any datagrams sent to the same port, regardless whether the IP address is a broadcast address or not. Thus, the Stream Server block in each model can receive the data broadcast by the other agents.

Each Stream Server is also configured to broadcast its datagrams to all the models on the network. As a result, by using a Stream Server block in each model, the agents can both send data to and receive data from every other agent.

Peer Setting on the Server URI

The URI of the Stream Server block in each agent's model has an additional option that is not part of the default settings. The peer option has been changed from the default to the value broadcast.

Stream Server configuration dialog

When the peer option is set to broadcast the UDP protocol allows datagrams from any other agent to be received by the server. The default value of this option is one, which only accepts datagrams from the first agent to communicate with the server. The default is one because it is assumed that the most common paradigm is only two models communicating.

With the peer option set to broadcast, the UDP server sends a special type of datagram when transmitting data that is broadcast to every computer on the network. Using UDP broadcast is an efficient way for an agent to communicate with the other agents because it does not have to transmit a separate datagram for each agent.

Blocking I/O for the Stream Server

The default setting for the Implementation parameter of the Stream Server block in the model is Use blocking I/O in a separate thread. Unlike the QUARC UDP Server Demo, this default does not need to be changed because client starvation cannot occur in UDP broadcast mode. Agents cannot be starved for data because each agent broadcasts every datagram to every other agent. The non-blocking I/O implementation could be used as well.

Decimating the Data

All three models run at the same sampling rate. Let the sampling rate be Ts. The Stream Server is receiving data from the othe two agents at the same time, as well as from itself. If all agents were sending data at the sampling rate Ts then each agent would be receiving three UDP datagrams every sampling instant: one from each agent (including itself). However, the Stream Server block is only reading one datagram at a time from the stream. It can only read one datagram every Ts seconds, not three. If all the agents were sending data every Ts seconds then the Stream Server block would not be able to keep up with the data.

To avoid overwhelming the Stream Server with data, each agent decimates the data it sends to the others. This decimation is accomplished using a Pulse Generator block connected to the en input of the Stream Server blocks.

Pulse Generator

The Pulse Generator is configured to produce a pulse every N sampling instants, where N is the number of agents. In this case there are three agents, so N is 3, and the Pulse Generator produces a pulse every third sampling instant. Notice that this decimation is different from the QUARC UDP Server Demo.

As a result, the agents are sending data every N*Ts seconds and each agent receives a datagram every Ts seconds on average. The Stream Server block is not overwhelmed with data.

A natural question is why the Stream Server block should only process one datagram at a time. Why not configure it to receive N datagrams at a time, and then the N agents will not need to decimate their data? The problem with this solution is that not all agents may be running. For example, if the user stops one of the agents then the other agents will no longer be receiving N datagrams each sampling instant. Hence, it will have to wait for another sampling instant before it has a full N datagrams and can output anything from its rcv port. Since it is not uncommon for an agent not to be running, particularly when the topology is started up or shut down, this situation will occur and is not ideal. It can however be detected by monitoring the new output of the Stream Server block.

Another possible alternative is to place the Stream Server block in a For Iterator Subsystem which executes N times and have it only transmit on the first iteration (so it doesn't send itself and every other agent N datagrams). The loop could be aborted if the new output was false. This solution may effectively resolve the decimation issue but was not attempted for this example because of the added complexity.

Agent Identifiers

The Stream Server block does not provide any mechanism for knowing the IP address associated with each datagram received since it is a generic Stream block used for any communications protocol. As a result, the agents cannot use the IP address to distinguish between the data sent from the other agents. In reality, an IP address is an inconvenient quantity anyways, as IP addresses are often dynamically assigned by DHCP.

To enable each model to associate each datagram with a particular agent, an identifier value was added to the data sent by each agent.

Agent identifier

The above figure shows the agent identifier being muxed into the data sent to the other agents. Each agent uses this identifier to route the agent's data to its own Scope via a Demultiplexer block. The Demultiplexer block acts like a digital demultiplexer and routes its input signal to one of N outputs based on the selection input. The agent identifier is passed to the selection input to route the data received to the appropriate plot. Note that the agent identifiers transmitted are zero-based to correspond with the selection input of the Demultiplexer block.

Agent demultiplexing

Running the example on a different target

To run the example on a different target, refer to the instructions on the Running QUARC Examples on Remote Targets page.