Developing in MPA (Modal Pipe Architecture)
Before reading this page, see The Modal Pipe Architecture page!
This page will discuss VOXL’s software architecture in more detail, providing critical knowledge for any developer that would like to make custom applications for ROS.
If you would simply like to use ROS on VOXL, see the page on Custom ROS Applications.
Working examples for the patterns on this page are cataloged on the Example Code page.
Overview
Every MPA service follows the same pattern: subscribe to input pipes with the libmodal_pipe client API, process data, and publish results through the server API. The best way to learn it is:
- Read the libmodal_pipe page for the core concepts (servers, clients, sinks, the info file, and message types).
- Build and run the hello examples from the libmodal-pipe examples directory inside voxl-cross.
- Start your own service from the voxl-cross-template project, which ships the build scaffolding, packaging, and a working pipe client/server skeleton.
The Pattern in Code
The whole architecture reduces to two calls. A server creates a named pipe and writes to it. Condensed from modal-hello-server.c:
pipe_info_t info = {
.name = PIPE_NAME,
.location = PIPE_LOCATION,
.type = "text",
.server_name = SERVER_NAME,
.size_bytes = MODAL_PIPE_DEFAULT_PIPE_SIZE};
if(pipe_server_create(SERVER_CH, info, flags)) return -1;
while(main_running){
pipe_server_write(SERVER_CH, str, len+1);
usleep(1000000/frequency_hz);
}
A client subscribes with a callback. Condensed from modal-hello-client.c:
// called whenever the simple helper has data for us to process
static void _simple_cb(int ch, char* data, int bytes, __attribute__((unused)) void* context)
{
printf("received %d bytes on channel %d: %s\n", bytes, ch, data);
}
pipe_client_set_simple_helper_cb(CLIENT_CH, _simple_cb, NULL);
pipe_client_open(CLIENT_CH, PIPE_NAME, CLIENT_NAME, CLIENT_FLAG_EN_SIMPLE_HELPER, PIPE_READ_BUF_SIZE);
Every service and inspect tool in the SDK is an elaboration of this pattern with different message types.