Skip to main content

Message path syntax

Use message path syntax throughout Foxglove to drill down to the exact information you want to inspect in your data.

Topics and fields

Reference this sample message for the /my_models topic:

{
"total": 4,
"objects": [
{ "width": 10, "height": 20 },
{ "width": 15, "height": 30 },
{ "width": 20, "height": 40 },
{ "width": 25, "height": 50 }
]
}

Specify the topic name to display all messages for that topic:

/my_models =>
{
total: 4,
objects: [
{ width: 10, height: 20 },
{ width: 15, height: 30 },
{ width: 20, height: 40 },
{ width: 25, height: 50 }
]
}

To access nested fields, first specify the topic, then use dot notation . to drill down into a nested field:

/my_models.total => 4

Typing in a message path input field will display a list of matching autocomplete options. Any topics or nested fields that contain the input text will be included in this list.

autocomplete options

Indexing into an array

Index into an array with bracket notation:

/my_models.objects[1].width => 15
/my_models.objects[-1].width => 25

Slices

Reference this sample message for the /my_options topic:

{
"colors": [
{ "r": 10, "g": 20, "b": 100 },
{ "r": 15, "g": 30, "b": 50 },
{ "r": 20, "g": 40, "b": 20 },
{ "r": 25, "g": 50, "b": 70 },
{ "r": 30, "g": 60, "b": 90 }
],
"numbers": [3, 5, 7, 9, 10]
}

Slices will return an array of values:

/my_options.colors[1:2] => [{ r: 15, g: 30, b: 50 }, { r: 20, g: 40, b: 20 }]
/my_options.numbers[-2:-1] => [9, 10]

Using dot notation after an array of objects will map through to access each element's nested field:

/my_options.colors[1:3].r => [15, 20, 25]
/my_options.colors[:].g => [20, 30, 40, 50, 60]

Using variables to slice

Slice on a variable by prepending each variable name with a $. For example, setting my_start_idx to 3 and my_end_idx to 4:

/my_options.colors[$my_start_idx:$my_end_idx] => [{ r: 25, g: 50, b: 70 }, { r: 30, g: 60, b: 90 }]
/my_options.colors[$my_start_idx:$my_end_idx].b => [70, 90]

/my_options.numbers[$my_start_idx:$my_end_idx] => [9, 10]

Filters

Reference these sample messages for the /my_books topic:

// message 1
{
stats: {
pages: 100,
author: "Beatrice Potter"
},
readers: [
{ id: 1, name: "Ashley", isCurrentlyReading: true },
{ id: 2, name: "Baron", isCurrentlyReading: false },
{ id: 3, name: "Charlie", isCurrentlyReading: true }
]
}

// message 2
{
stats: {
pages: 210,
author: 'Tommy "Two Gun" Simon'
},
readers: [
{ id: 4, name: "Dana", isCurrentlyReading: true },
{ id: 5, name: "Ethan", isCurrentlyReading: false },
{ id: 6, name: "Frank", isCurrentlyReading: false }
]
}

Filter messages based on their fields’ boolean, number, or string values. The following comparison operators are supported: ==, !=, <, <=, >, >=.

Create filters in message path syntax using curly brackets. Messages that don't match the filter will be skipped entirely:

/my_books{stats.pages>200} =>
{
stats: {
pages: 210,
author: 'Tommy "Two Gun" Simon'
}
}

/my_books{stats.pages==100}.author => "Beatrice Potter"

/my_books{stats.pages==500} => // no value returned

Filtering on nested fields

You can also filter on a message’s nested field values using a combination of slices and filters:

/my_books.readers[:]{isCurrentlyReading==true}.name =>
["Ashley", "Charlie"] // message 1
["Dana"] // message 2

Using variables to filter

In addition to filtering on primitive values, you can filter on variables. Setting variable my_id to 1:

/my_books.readers[:]{id==$my_id} =>
{ id: 1, name: "Ashley", isCurrentlyReading: true } // message 1
// No value returned for message 2

Using multiple filters

When you apply multiple filters, only messages that satisfy all filters will be returned (i.e. an AND expression):

/my_books.readers[:]{id==1}{isCurrentlyReading==true}.name =>
"Ashley" // message 1
// No value returned for message 2

/my_books.readers[:]{id==1}{isCurrentlyReading==false}.name =>
// No value returned for message 1
// No value returned for message 2

/my_books.readers[:]{id==5}{isCurrentlyReading==false}.name =>
// No value returned for message 1
"Ethan" // message 2

Other considerations

Escaping quotation marks in strings is not supported, but you can use single or double quotes, which allows you to express most strings:

/my_books{stats.author=='Tommy "Two Gun" Simon'}.readers[:].name =>

// No value returned for message 1
["Dana", "Ethan", "Frank"] // message 2

Enum names in filters

For fields with enum types, you can filter using the enum name instead of the numeric value:

/my_topic{status==MOVING}    // filters where status field equals the MOVING enum value
/my_topic{status==2} // equivalent numeric filter

Enum names are unquoted bare words. They are case-sensitive and must match the enum definition exactly. If the name doesn't match any defined enum value, the filter matches nothing.

For boolean fields, the parser recognizes true and false as boolean values:

/my_topic.readers[:]{isActive==true}.name

The parser does not treat quoted strings as enum names. Use unquoted identifiers for enums and quoted strings for string comparisons:

/my_topic{status==OK}        // enum name, resolved to numeric value
/my_topic{name=="OK"} // string comparison

Variables cannot be used outside of slicing and filtering in message paths.

Message path functions

Some panels support appending a message path function suffix to transform the final value returned by a path.

Use .@functionname syntax, with an optional operand for functions that accept one:

/imu.linear_acceleration.x.@abs
/wheel.speed.@mul(3.6)
/imu.linear_acceleration.@norm

Some functions operate on structured values and can return either a converted struct or a specific field.

For quaternion and RPY/Euler conversion, use:

/odom.orientation.@rpy
/odom.orientation.@rpy.yaw
/odometry.euler.@quat
/odometry.euler.@quat.w
  • .@rpy converts a quaternion object (x, y, z, w) to roll/pitch/yaw (radians). Uses XYZ Euler order (intrinsic rotations: first around X-axis/roll, then Y-axis/pitch, then Z-axis/yaw).
  • .@quat converts an RPY object (roll, pitch, yaw, in radians) to a quaternion. Inverse of .@rpy using the same XYZ Euler convention.
  • Append a field access (for example, .yaw or .w) when you need a scalar numeric result.

For the current list of supported functions and compatibility notes, see the Plot panel docs.