PanelExtensionContext
type PanelExtensionContext = object;
PanelExtensionContext 暴露了用于编写自定义面板的属性和方法。上下文提供了订阅消息、接收更新、配置面板设置以及将面板渲染到 UI 的方法。
registerPanel 中使用的 initPanel 函数接受一个 PanelExtensionContext 参数。该参数包含用于访问面板数据和渲染 UI 更新的属性和方法。initPanel 函数还可以返回一个可选的清理函数,当扩展的 panelElement 卸载时运行。
有关详细信息,请参阅创建自定义面板指南。
属性
panelElement
readonly panelElement: HTMLDivElement;
面板的根元素。将面板元素作为子元素添加到此元素下。
initialState
readonly initialState: unknown;
初始面板状态
layout
readonly layout: LayoutActions;
面板可以执行的与用户当前布局相关的操作。有关详细信息,请参阅 LayoutActions。
dataSourceProfile?
readonly optional dataSourceProfile: string;
标识正在播放的数据的语义,例如哪些主题或参数在语义上有意义,或者使用哪些规范化约定。这通常映射到机器人框架的简写标识符,如 "ros1"、"ros2" 或 "ulog"。有关详细信息,请参阅 MCAP profiles 概念。
onRender()?
optional onRender: (renderState, done) => void;
在面板初始化期间将此属性设置为函数。
可视化将在播放期间需要重新渲染面板时运行 context.onRender。该函数接受 renderState 和 done 回调作为参数。渲染事件频繁发生(60hz、30hz 等)。
注意:您的 onRender 函数必须在渲染后调用 done,以指示面板已准备好渲染下一组数据。done 调用的确切位置将因框架和不同扩展的逻辑而异。
context.onRender = (renderState, done) => {
// 使用 RenderState 中的字段渲染 UI 更新
// 当您已为此 renderState 渲染完所有 UI 时调用 done。
// 如果您的 UI 框架延迟渲染,请在渲染实际发生后调用 done。
done();
};
参数
| 参数 | 类型 |
|---|---|
| renderState | Immutable<RenderState> |
| done | () => void |
返回
void
subscribeMessageRange()?
optional subscribeMessageRange: (args) => () => void;
订阅以接收当前数据源的给定主题的整个时间范围的消息。
有关行为的详细信息,请参阅 SubscribeMessageRangeArgs。
注意:这不会读取实时源的消息,如 foxglove_bridge、rosbridge 或 ROS 1 原生连接。对于这些消息,您仍需要使用 context.subscribe() 和 watch("currentFrame")。
参数
| 参数 | 类型 |
|---|---|
| args | SubscribeMessageRangeArgs |
返回
Function
一个函数,将取消订阅主题,取消活动的异步迭代器,并防止再次调用 onNewRangeIterator。
返回
void
UNSTABLE_subscribeMessageRange()?
optional UNSTABLE_subscribeMessageRange: (args) => () => void;
参数
| 参数 | 类型 |
|---|---|
| args | SubscribeMessageRangeArgs |
返回
Function
返回
void
已弃用
已重命名为 subscribeMessageRange。请改用该方法。
方法
watch()
调用签名
watch(field): void
订阅渲染状态中此字段的更新。仅当此字段更改时才会调用渲染。
使用 context.watch 指示 RenderState 中的哪些字段(例如 currentFrame、currentTime、previewTime、parameters、topics)在包含的值更改时应触发面板重新渲染。
context.watch("topics");
context.watch("currentFrame");
context.watch("parameters");
context.watch("currentTime");
参数
| 参数 | 类型 |
|---|---|
| field | keyof RenderState |
返回
void
调用签名
watch(field): void
订阅渲染状态中此字段的更新。仅当此字段更改时才会调用渲染。
参数
| 参数 | 类型 |
|---|---|
| field | "allFrames" |
返回
void
已弃用
使用 allFrames 调用 watch 已弃用。请改用 PanelExtensionContext.subscribeMessageRange。
saveState()
saveState(state): void
使用 context.saveState 将任意对象作为持久化面板状态(也称为面板设置)保存在当前布局中。
context.initialState = undefined; // 面板的初始状态
context.saveState({ myNum: 2, myBool: false, myStr: "abc" });
参数
| 参数 | 类型 | 描述 |
|---|---|---|
| state | Partial<unknown> | 要保存的状态。此值应该是 JSON 可序列化的。 |
返回
void
setParameter()
setParameter(name, value): void
使用 context.setParameter 将参数 name 设置为任何有效的 value(即基本类型、日期、Uint8Array 以及包含这些值的数组或对象)。
context.setParameter("/param1", "value1");
参数
| 参数 | 类型 | 描述 |
|---|---|---|
| name | string | 要设置的参数的名称。 |
| value | ParameterValue | 参数的新值。 |
返回
void
setSharedPanelState()
setSharedPanelState(state): void
设置由调用此函数的同一类型面板共享的临时状态。这不会保存在布局中。
参数
| 参数 | 类型 |
|---|---|
| state | undefined | Record<string, unknown> |
返回
void
setVariable()
setVariable(name, value): void
使用 context.setVariable 将变量 name 设置为任何有效的变量 value。
context.setVariable("myVar", 55);
context.onRender = (renderState: RenderState, done) => {
// 从 renderState 读取变量值
const variableValues = renderState.variables;
const myVarValue = variableValues.myVar;
// 当您已为此 renderState 渲染完所有 UI 时调用 done。如果您的 UI 框架延迟渲染,请在渲染实际发生后调用 done。
done();
};
参数
| 参数 | 类型 | 描述 |
|---|---|---|
| name | string | 要设置的变量的名称。 |
| value | VariableValue | 变量的新值。 |
返回
void
setPreviewTime()
setPreviewTime(time): void
设置活动预览时间。将预览时间设置为 undefined 会清除预览时间。
参数
| 参数 | 类型 |
|---|---|
| time | undefined | number |
返回
void
seekPlayback()?
optional seekPlayback(time): void
将播放定位到给定时间。行为就像用户点击了播放栏进行定位一样。
参数
| 参数 | 类型 |
|---|---|
| time | number |
返回
void
subscribe()
subscribe(topic, options): () => void
使用 context.subscribe 订阅主题以接收消息。返回一个取消订阅函数,当不再需要消息时调用该函数。
const unsubscribe = context.subscribe("/my_topic", {
preload: true,
});
// 稍后取消订阅
unsubscribe();
参数
| 参数 | 类型 | 描述 |
|---|---|---|
| topic | string | 要订阅的主题名称。 |
| options | SubscribeOptions | undefined | 订阅选项。有关详细信息,请参阅 SubscribeOptions。 |
返回
Function
一个函数,调用时将取消订阅主题。
unsubscribeAll()
unsubscribeAll(): void
取消订阅所有主题。
context.unsubscribeAll();
返回
void
subscribeAppSettings()
subscribeAppSettings(): () => void
使用 context.subscribeAppSettings 订阅应用程序设置更新。返回一个取消订阅函数,当不再需要设置更新时调用该函数。
const unsubscribe = context.subscribeAppSettings();
// 稍后取消订阅
unsubscribe();
返回
Function
一个函数,调用时将取消订阅应用程序设置更新。
advertise()?
optional advertise(topic, datatype, options): void
使用 context.advertise 在主题上发布消息。这必须在使用 context.publish 发布消息之前调用。
context.advertise("/my_topic", "std_msgs/String");
参数
| 参数 | 类型 | 描述 |
|---|---|---|
| topic | string | 要发布消息的主题名称。 |
| schemaName | string | 已发布消息将遵循的模式名称。 |
| options | Record<string, unknown> | 传递给当前数据源的选项,用于附加配置。 |
返回
void
unadvertise()?
optional unadvertise(topic): void
指示您不再想在此主题上发布。
context.unadvertise("/my_image_topic");
如果当前数据源不支持发布,此属性可能为 undefined。
参数
| 参数 | 类型 |
|---|---|
| topic | string |
返回
void
publish()?
optional publish(topic, message): void
使用 context.publish 在之前发布的主题上发布消息。(您必须先调用 advertise 来发布主题,然后才能发布。)如果主题未发布或以其他方式格式不正确,该函数将抛出错误。
context.advertise("/my_color_topic", "std_msgs/ColorRGBA");
context.publish("/my_color_topic", { r: 0, g: 1, b: 0, a: 1 });
如果当前数据源不支持发布,此属性可能为 undefined。
参数
| 参数 | 类型 | 描述 |
|---|---|---|
| topic | string | 要发布消息的主题名称 |
| message | unknown | 要发布的消息 |
返回
void
callService()?
optional callService(service, request): Promise<unknown>
使用 context.callService 向指定的 service 发送服务调用,并带有请求负载。
context.callService("my_service", { foo: "bar" });
如果当前数据源不支持服务,此属性可能为 undefined。
参数
| 参数 | 类型 | 描述 |
|---|---|---|
| service | string | 要调用的服务名称 |
| request | unknown | 服务调用的请求负载 |
返回
Promise<unknown>
一个 Promise,当结果可用时解析,或在出错时拒绝
updatePanelSettingsEditor()
updatePanelSettingsEditor(settings): void
在面板的 PanelExtensionContext 实例上调用 updatePanelSettingsEditor 方法,以定义或更新其设置。
const panelSettings: SettingsTree = {
nodes: { ... },
actionHandler: (action: SettingsTreeAction) => { ... }
};
context.updatePanelSettingsEditor(panelSettings);
settings 参数必须是有效的 SettingsTree,并包含 2 个必需的属性 – nodes 和 actionHandler:
nodes- 层次结构,其中每个节点可以包含输入字段、显示字段,甚至其他节点actionHandler- 当用户与设置 UI 交互时调用的函数;包含处理交互和更新面板或设置树的逻辑
它还可以包含以下可选属性:
enableFilter– 设置是否应显示过滤器控件focusedPath– 要滚动到的节点(临时一次性效果)
下面的示例树在 General 部分内有一个 title 文本输入字段,以及一个 actionHandler 来响应 title 字段的更新。
const panelSettings: SettingsTree = {
nodes: {
general: {
label: "General",
fields: {
title: {
label: "Title",
input: "string",
// `panelTitle` 指的是扩展面板配置中的值
value: panelTitle,
},
},
},
},
actionHandler: (action: SettingsTreeAction) => {
switch (action.action) {
case "perform-node-action":
// 处理用户在设置树中为节点定义的操作
break;
case "update":
if (action.payload.path[0] === "general" && action.payload.path[1] === "title") {
// 读取 action.payload.value 获取新的面板标题值
panelTitle = action.payload.value;
// 相应地更新面板状态
}
break;
}
},
}
context.updatePanelSettingsEditor(panelSettings);
SettingsTreeAction
SettingsTreeAction 描述了当用户与其字段交互时设置 UI 应如何更新。
每个 SettingsTreeAction 都有一个带有 path 的 payload,指向要更新的设置字段(例如 ["general", "title"])。
update 操作对应于用户为字段设置新值(例如 "My new title")。
特殊节点属性
有两个特殊的 SettingsTreeNode 属性,label 和 visibility。您为 label 指定的值将控制设置编辑器中显示的标签。如果您将 renamable 节点属性设置为 true,用户可以编辑节点 label – 您将收到一个 update 的 SettingsTreeAction,路径以 label 结尾。
此外,如果您为节点的 visibility 指定布尔值,则设置编辑器将提供一个按钮来切换节点的可见性,并且您将收到一个 update 操作,路径以 visibility 作为最终元素。
有关如何使用这些特殊属性的示例,请查看面板设置示例扩展。
输入类型
除了上面示例中的 string 输入类型外,面板 API 还为扩展面板输入字段提供了多种类型。
每种输入类型都有不同的属性,您可以配置:
autocompletebooleanrgbrgbagradientmessagepathselectstringtogglevec3vec2
参数
| 参数 | 类型 | 描述 |
|---|---|---|
| settings | { actionHandler: (action) => void; enableFilter: boolean; focusedPath: readonly string[]; nodes: {}; } | - |
| settings.actionHandler | (action) => void | 处理由 UI 发起的设置树上的所有操作的处理程序。 |
| settings.enableFilter? | boolean | 如果设置编辑器应显示过滤器控件,则为 true。 |
| settings.focusedPath? | readonly string[] | 设置这将具有一次性效果,滚动编辑器到路径处的节点并高亮显示它。这是一个临时效果,因此不需要随后取消设置。 |
| settings.nodes | 设置树根节点。对这些的更新将自动反映在编辑器 UI 中。 |
返回
void
setDefaultPanelTitle()
setDefaultPanelTitle(defaultTitle): void
使用 context.setDefaultPanelTitle 覆盖面板的默认标题。用户始终可以通过手动编辑来覆盖默认标题。如果未设置覆盖或默认标题,面板将仅显示其类型(例如 "Image")。
// 覆盖默认面板标题
context.setDefaultPanelTitle(`Plot of ${config.topicName}`);
参数
| 参数 | 类型 |
|---|---|
| defaultTitle | undefined | string |
返回
void