Introduction
Extend Foxglove's capabilities with custom extensions to better support your team's unique workflows. Build bespoke panels, convert custom messages to Foxglove-supported schemas, and alias topic names for easy visualization.
Once you've developed and installed your extension, you can open your app settings to display all available and installed extensions.
Custom panels
While Foxglove offers a suite of built-in panels for robotics data visualization and debugging, many users have domain-specific needs that our out-of-the-box offering does not address.
Custom panel extensions allow you to build an entire panel. Custom panels can subscribe to messages on various topics, advertise and publish, and display the message information in whatever form is most relevant for your workflow.
Custom panels are ideal when your visualization or interaction needs are bespoke and not easily solved via one of the built-in panels.
Links and resources
Message converters
Message converter extensions allow you to convert messages from one schema to another. By transforming messages to adhere to Foxglove-supported schemas, you can inspect them using Foxglove's built-in visualization features. For example, you can use a message converter to convert your custom GPS messages into foxglove.LocationFix
messages for visualization in the Map panel.
NOTE: Message converters run on-demand only when the topic is subscribed to by a panel.
Links and resources
- Guide: Create message converter
- Write a message converter extension (Map panel)
- Write a message converter extension (3D panel)
Topic aliases
Topic alias extensions allow you to alias topics in your data source to new topics. Foxglove panels can subscribe to both the aliased topics and the original data source's topics.
Writing an extension
You can write extensions in JavaScript or Typescript and package them into .foxe
files. You can distribute these files privately to your Foxglove organization or publicly via our registry - installing extensions via the registry is only supported on the desktop app. A single extension can include multiple panels or converters.
Foxglove provides a set of starter templates and commands in the create-foxglove-extension
package to simplify authoring an extension.
Requirements:
To set up your extension project, navigate to the directory where you'll want your source code to live and run the following command in a Terminal window:
npm init foxglove-extension@latest my-extension-name
This will set up an extension directory structure. The entrypoint of your extension is the index.ts
file.
The entrypoint script MUST export a single activate
function which accepts a single ExtensionContext
argument.
Custom panels
export function activate(extensionContext: ExtensionContext) {
// your extension code will decide which methods to call on the extensionContext
// Here's an example which registers a new panel:
extensionContext.registerPanel({ name: "example-panel", initPanel: initExamplePanel });
}
Message converters
export function activate(extensionContext: ExtensionContext) {
// Register a new message converter:
extensionContext.registerMessageConverter({
fromSchemaName: "sensors.MyGps",
toSchemaName: "foxglove.LocationFix",
converter: (inputMessage) => {
// logic to turn sensors.MyGps messages into foxglove.LocationFix messages
},
});
}
Topic aliases
The registerTopicAliases
function accepts an argument with two fields – topics
with the data source's original topics and globalVariables
with the current layout's variables – and returns a list of aliased topics:
import { ExtensionContext } from "@foxglove/extension";
export function activate(extensionContext: ExtensionContext): void {
// Register a topic alias function that takes the current list of datasource topics and
// global variables and outputs a list of topic aliases.
extensionContext.registerTopicAliases((args) => {
// Use args.topics if you want to access the list of available topics in your data source.
const { globalVariables } = args;
// Output a list of aliased topics, in this case influenced by the current value of
// the global variable `camera`.
const camera = globalVariables["camera"] ?? "FRONT";
return [
{ sourceTopicName: `/CAM_${camera}/image_rect_compressed`, name: `/selected_camera_image` },
{ sourceTopicName: "/imu", name: "/aliased_imu" },
{ sourceTopicName: "/odom", name: "/aliased_odom" },
];
});
}
This registerTopicAliases
function is rerun whenever the data source's original topics or the current layout's global variables change.