Create topic converter
This guide shows how to build a topic message converter that computes and plots the absolute value of acceleration data from a topic.
Setting up
In a Terminal window, cd
into the directory where your source code will live and run the following command:
npm init foxglove-extension@latest myExtensionName
This uses create-foxglove-extension
to create a myExtensionName
directory containing source code for an example message converter.
Registering a converter
The index.ts
file in your project's src
folder is the entry point for your extension source code. It must export an activate
function that accepts a single extensionContext
argument of type ExtensionContext
.
To register a message converter, we call registerMessageConverter
on the extensionContext
argument with the type topic
and several arguments to define the input and output.
import { MessageEvent } from "@foxglove/extension";
type MySignal = { acceleration: number };
export function activate(extensionContext: ExtensionContext) {
extensionContext.registerMessageConverter({
type: "topic",
inputTopics: ["/acceleration"],
outputTopic: "/acceleration/absolute",
schemaName: "AccelerationAbsolute",
schemaDescription: { value: "number" },
create: () => {
// create() returns a function that the app will call with a MessageEvent
// for every input message. The input MessageEvents are in log time order.
return (msgEvent) => {
const msg = msgEvent.message as MySignal;
return { value: Math.abs(msg.acceleration) };
};
},
});
}
Line-by-line explanation
Let's go through the lines above to explain what happens.
type: "topic"
This tells Foxglove that we're registering a topic message converter. Topic message converters use messages from one or more input topics to compute a new message on an output topic.
inputTopics: ["/acceleration"]
This tells Foxglove that we want to process incoming messages on the /acceleration
topic.
outputTopic: "/acceleration/absolute"
This tells Foxglove that we want to output messages to the /acceleration/absolute
topic.
The output topic is local to the app, it is not published back to a live connection or external system.
schemaName: "AccelerationAbsolute"
We've set the schema name for our output topic to AccelerationAbsolute
.
All topics have an associated schema name for the type of messages they contain. Since our topic is producing a new custom message type, we can pick any schema name we want.
For topics that produce custom messages, avoid schema names that conflict with existing schema names in your data source or well-known schema names.
schemaDescription: { value: "number" }
Here we define the actual schema for the output message. Our converter will output one field, named value in the new message and that field will be a number.
To power message path selection and autocomplete (i.e. in the plot panel series config or raw message panel), the app needs to know the shape of the messages you are creating.
create: () => { ... }
The create function initializes the converter. It is called by the app to create the converter when some panel subscribes to the output topic.
It should return a function that will be called with a MessageEvent
for every input message (from the input topics).
return (msgEvent) => { ... }
This function, returned by the create
function, is called with a MessageEvent
for every input message. It performs any computation and returns a new message matching the schema description. You can optionally return undefined to skip producing a message for the given input.
Testing
Once we've packaged and installed our extension, load any data source containing our custom /acceleration
topic and visualize them with the Plot panel by selecting the message path /acceleration/absolute.value
as the series to plot.
Message converters run on-demand only when the topic is subscribed to by a panel.