外观
遥测系统(Telemetry)使用指南
Telemetry 类常见方法表格
| 方法 | 作用 | 备注注意项 |
|---|---|---|
| addData(String key, Object value) | 添加一个键值对数据项到遥测显示 | 返回 Item 对象,支持链式调用 |
| addData(String key, String format, Object... args) | 使用格式化字符串添加键值对数据 | 支持类似 printf 的格式化字符串 |
| addLine() | 添加一个空行 | 返回 Line 对象,支持链式调用 addData |
| addLine(String lineCaption) | 添加带有标题的行 | 返回 Line 对象,支持链式调用 |
| update() | 将累积的遥测数据发送到驾驶站显示 | 每次添加数据后必须调用才能显示 |
| clear() | 清除非保留的常规遥测数据 | 不会清除日志数据和已设置为保留的数据 |
| clearAll() | 清除所有常规遥测数据,包括保留项 | 不会清除日志数据 |
| removeItem(Item item) | 移除特定的数据项 | 删除由 addData 返回的 Item 对象 |
| removeLine(Line line) | 移除特定的行 | 删除由 addLine 返回的 Line 对象 |
| setAutoClear(boolean autoClear) | 设置更新时是否自动清除数据 | 默认为 true,每次 update 前清除数据 |
| isAutoClear() | 检查是否启用了自动清除 | 返回布尔值 |
| setMsTransmissionInterval(int msInterval) | 设置遥测数据传输的最小时间间隔 | 默认值为 250ms (4Hz) |
| getMsTransmissionInterval() | 获取当前遥测数据传输间隔 | 返回毫秒值 |
| log() | 获取日志管理器对象 | 返回 Log 对象,可访问日志相关方法 |
| log().add(String message) | 添加日志消息 | 日志消息在 update 后不会被清除 |
| log().clear() | 清除所有日志消息 | 只清除日志数据,不影响普通数据 |
| log().setCapacity(int capacity) | 设置日志最大容量(行数) | 超出容量时,最旧的日志会被移除 |
| log().setDisplayOrder(DisplayOrder displayOrder) | 设置日志显示顺序 | 可选 NEWEST_FIRST 或 OLDEST_FIRST |
| addAction(Runnable action) | 添加在遥测间隔到期时要执行的操作 | 用于创建定时执行的操作 |
| speak(String text) | 通过文本到语音功能播放消息 | 立即执行,不需要调用 update 方法 |
| speak(String text, String languageCode, String countryCode) | 使用特定语言和地区播放文本 | 如 zh-CN 表示中文(中国),en-US 表示英文(美国) |
什么是遥测系统 (Telemetry)?
遥测系统是 FTC 机器人程序中非常重要的调试和信息显示工具。它允许您的机器人程序向驾驶站应用程序发送文本和数据,这些信息会显示在手机或平板电脑屏幕上,帮助您:
- 调试程序中的问题
- 显示传感器读数和电机状态
- 追踪程序执行流程
- 向驾驶员提供重要信息
简单来说,遥测系统就像是机器人和人类之间的"聊天窗口",让机器人可以告诉您它正在做什么、发现了什么、遇到了什么问题。
基本用法
1. 添加和显示数据
最基本的遥测操作是添加数据并更新显示:
java
// 添加简单文本消息
telemetry.addData("状态", "初始化完成");
// 添加带数值的消息
telemetry.addData("电机功率", 0.75);
// 添加带格式化数值的消息
telemetry.addData("电池电压", "%.1f 伏特", 12.5);
// 更新显示(发送数据到驾驶站)
telemetry.update();1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
要记住的重要一点:必须调用 telemetry.update() 才能将数据发送到驾驶站显示。
2. 覆盖与累加
关于数据添加和清除机制的重要说明:
- 调用
addData()时,数据会被添加到遥测缓冲区,不会自动覆盖同名键的数据 - 只有在调用
telemetry.update()时,系统才会根据setAutoClear设置决定是否清除数据 - 默认情况下(
setAutoClear(true)),调用update()会清除之前的所有控制消息,然后发送新数据 - 当设置
setAutoClear(false)时,调用update()不会清除之前的控制消息,新旧数据会一起显示
java
// 默认行为(setAutoClear为true)
telemetry.addData("状态", "初始化中");
telemetry.update(); // 显示"状态: 初始化中"
telemetry.addData("状态", "初始化完成");
telemetry.update(); // 清除之前数据,只显示"状态: 初始化完成"
// 设置为不自动清除
telemetry.setAutoClear(false);
telemetry.addData("状态", "初始化中");
telemetry.update(); // 显示"状态: 初始化中"
telemetry.addData("状态", "初始化完成");
telemetry.update(); // 同时显示"状态: 初始化中"和"状态: 初始化完成"1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
需要注意的是,addData()方法会返回 Item 类型对象,这使得您可以进行链式调用:
java
// 链式调用多个addData方法
telemetry.addData("电机状态", "运行中").addData("速度", "50%");1
2
2
记住:无论自动清除设置如何,日志消息(通过log().add()添加的)始终会保留,除非明确调用telemetry.log().clear()或达到日志容量上限。
3. 多行数据
您可以使用以下方式添加多条相关信息:
java
// 方法1:使用换行符
telemetry.addData("信息", "第一行\n第二行");
// 方法2:使用链式调用
telemetry.addLine("机器人状态")
.addData("电机", "运行中")
.addData("伺服", "就位");
// 方法3:直接链式调用addData
telemetry.addData("机器人状态", "正常")
.addData("电机", "运行中")
.addData("伺服", "就位");1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
4. addLine 与 addData 的区别
addLine 和 addData 的主要区别:
addData是用于添加键值对的方法(如 "速度: 50")addLine是创建一个新行,可以作为多个相关数据的"标题"addLine返回一个可以继续添加数据的对象,支持链式调用addData返回 Item 类型,也支持链式调用,可以连续添加多条数据
示例对比:
java
// 使用addData链式调用
telemetry.addData("机器人状态", "正常")
.addData("电机", "0.5")
.addData("舵机", "0.7");
// 使用addLine链式调用
telemetry.addLine("驱动系统\n")
.addData("左电机", "0.5")
.addData("右电机", "0.6");1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
显示效果对比:
// addData链式调用效果
机器人状态: 正常
电机: 0.5
舵机: 0.7
// addLine链式调用效果
驱动系统
左电机: 0.5|右电机: 0.61
2
3
4
5
6
7
8
2
3
4
5
6
7
8
注意:默认情况下每次调用telemetry.update()前会清除之前的所有常规遥测数据(如果setAutoClear(true))。
高级功能
1. 延迟评估(提高性能)
如果某些数据计算成本较高(如传感器读数),可以使用函数延迟计算:
java
// 仅在实际需要发送数据时才计算电池电压(遥测传输是被限制的,以减少带宽使用)
telemetry.addData("电压", new Func<Double>() {
@Override public Double value() {
return getBatteryVoltage(); // 这个方法只在需要时调用
}
});1
2
3
4
5
6
2
3
4
5
6
延迟评估的原理解释
延迟评估的原理是:只在实际需要显示数据时才进行计算,而不是每次调用 addData 时就计算。
new Func<Double>() { ... } 是创建一个匿名函数对象的语法,这个语法看起来复杂,但可以简单理解为:
- 创建一个"任务包",里面包含了计算数据的方法
- 遥测系统会在真正需要显示数据时,才"打开包裹"执行里面的方法
@Override public Double value()表示重写原有的value方法return getBatteryVoltage();是实际获取数据的代码- 整个过程类似于"懒加载",只在必要时才执行耗时操作
这对于获取传感器数据、进行复杂计算或耗时操作特别有用,可以提高程序效率。
遥测系统"打开包裹"(即执行延迟评估函数)的确切时机是由 FTC SDK 内部实现决定的,这个过程对开发者是透明的,但有几个关键时刻会触发这个行为:
- 当调用 telemetry.update()时:这是最主要的触发点。当您调用 update()方法时,遥测系统会遍历所有添加的数据项,对于那些使用 Func 对象(延迟评估)的项目,它会在此时调用其 value()方法获取实际值。
- 传输数据到驾驶站前:系统在实际将数据发送到驾驶站显示之前,会确保所有需要的值都已计算完成。
为什么延迟评估能提高效率 ?
- 如果您在一个循环中多次添加相同的数据项,但只在循环结束时调用一次 update(),那么耗时的计算只会在真正需要展示数据时执行一次,而不是每次添加数据时都计算。
2. 日志功能
遥测系统还提供日志功能,可以保存历史消息:
java
// 添加日志消息
telemetry.log().add("机器人启动");
telemetry.log().add("发现障碍物");
// 设置日志容量(保存多少行)
telemetry.log().setCapacity(10);
// 设置显示顺序(最新的在前还是最老的在前)
telemetry.log().setDisplayOrder(Telemetry.Log.DisplayOrder.NEWEST_FIRST);1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
普通 addData 与 log().add() 的区别
addData 和 log().add() 的主要区别:
数据持久性:
addData:显示当前状态,每次 update 后会被新数据覆盖log().add():保存历史记录,新消息会追加而不是覆盖旧消息
显示方式:
addData:显示在主遥测区域,通常显示实时状态log().add():显示在日志区域(通常在主区域下方),记录历史事件
适用场景:
addData:适合显示实时变化的数据(如电机功率、位置)log().add():适合记录事件发生(如"已完成导航"、"检测到障碍物")
简单来说,addData 就像仪表盘,显示当前状态;而 log().add() 就像行车记录仪,记录发生过的事件。
3. 清除数据
清除之前添加的所有数据:
java
telemetry.clear();1
clear() 与 clearAll() 的区别
clear() 和 clearAll() 的区别:
clear():只清除通过addData或addLine添加的非保留常规遥测数据(即未设置setRetained(true)的项目)clearAll():清除所有常规遥测数据(包括保留项目)以及所有动作(actions),但不会清除日志数据
重要的是要明白,无论是clear()还是clearAll(),都不会清除通过log().add()添加的日志数据。日志数据只会在以下情况被清除:
- 调用
telemetry.log().clear() - 日志数据达到了通过
log().setCapacity()设置的容量上限,此时最旧的日志会被自动移除
如果您想保留日志记录但刷新实时数据,使用 clear();如果想完全重置所有常规遥测数据(包括保留项目),使用 clearAll()。
4. 消息持久性
控制遥测数据在调用update()方法时是否自动清除:
java
// 设置为不自动清除(新旧消息会一起显示)
telemetry.setAutoClear(false);
// 恢复默认行为(每次update前自动清除)
telemetry.setAutoClear(true);1
2
3
4
5
2
3
4
5
自动清除机制解释
自动清除机制(setAutoClear)只影响通过 addData 和 addLine 添加的常规遥测数据,不影响日志(即通过 log().add() 添加的数据)。
- 当
setAutoClear(true)时(默认行为):每次调用update()前会先清除之前添加的所有常规数据 - 当
setAutoClear(false)时:调用update()时不会清除之前的数据,新添加的数据会与之前的数据一起显示
重要的是要理解,数据清除是在update()方法调用时发生的,而不是在添加新数据时。只有调用update(),数据才会实际发送到驾驶站显示。
日志数据(通过 log().add() 添加的)始终是累积的,无论自动清除设置如何,只受 log().setCapacity() 限制,且只能通过telemetry.log().clear()显式清除。
5. 保持某些数据始终显示
java
// 关闭自动清除
telemetry.setAutoClear(false);
// 仅清除不再需要的数据
telemetry.clear(); // 默认只清除非保留数据
// 或者使用removeItem/removeLine方法精确移除特定数据
Item tempData = telemetry.addData("临时信息", "将被移除");
telemetry.removeItem(tempData); // 只移除这一项数据1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
6. 格式化数字
java
// 显示两位小数
telemetry.addData("精确值", "%.2f", 3.14159);
// 显示科学计数法
telemetry.addData("大数", "%.2e", 1234567.89);1
2
3
4
5
2
3
4
5
7. 使用语音功能 (speak 方法)
Telemetry 提供了 speak 方法,可以让驾驶站设备通过语音播报重要信息,让驾驶员不必始终盯着屏幕查看状态。
java
// 基本用法 - 使用默认语言朗读文本
telemetry.speak("Robot initialized");
// 指定语言和地区进行朗读
telemetry.speak("Ready to start", "en", "US"); // 英文(美国)
telemetry.speak("Commencer la mission", "fr", "FR"); // 法语(法国)1
2
3
4
5
6
2
3
4
5
6
speak 方法与 addData 的区别
- 执行机制不同:
speak()方法会立即发送语音请求到驾驶站,不需要调用update()addData()添加的数据必须通过update()才能发送到驾驶站显示
- 使用场景不同:
speak()适合传达需要驾驶员立即注意的重要信息addData()适合显示需要持续监控的状态信息
speak 方法使用技巧
添加延时:在连续调用多个
speak()方法时,应添加适当延时javatelemetry.speak("Object detected"); sleep(2000); // 等待语音完成 telemetry.speak("Starting navigation");1
2
3语言和地区代码:
- 语言代码(languageCode):使用 ISO 639 标准的双字母代码
- "zh" - 中文
- "en" - 英文
- "ja" - 日语
- "ko" - 韩语
- 国家/地区代码(countryCode):使用 ISO 3166 标准的双字母代码
- "CN" - 中国
- "US" - 美国
- "GB" - 英国
- "JP" - 日本
- 语言代码(languageCode):使用 ISO 639 标准的双字母代码
在 Driver Hub 上启用 TTS 功能:
- 在 Driver Hub 上打开 FTC Driver Station 应用
- 点击右上角的三点菜单(⋮)
- 在菜单中选择 Settings (设置)
- 将 Sound 选项设置为 ON
适度使用:
- 避免频繁使用语音功能,以免干扰驾驶员
- 优先用于关键状态变化和警告信息
- 保持语音提示简短明了
示例:使用 speak 方法的完整示例
java
@TeleOp(name="语音提示演示")
public class SpeakDemo extends LinearOpMode {
@Override
public void runOpMode() {
// 初始化提示
telemetry.speak("Robot initialized");
telemetry.addData("Status", "Initialized");
telemetry.update();
waitForStart();
// 开始提示
telemetry.speak("Starting operation", "en", "US");
while (opModeIsActive()) {
// 检测障碍物示例
if (isObstacleDetected()) {
telemetry.speak("Warning, obstacle detected");
sleep(2000); // 给语音足够的播放时间
}
// 正常遥测数据更新
telemetry.addData("Motor Power", motorPower);
telemetry.update();
}
}
private boolean isObstacleDetected() {
// 假设的障碍物检测逻辑
return false;
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
8. 移除特定遥测数据 (removeItem 和 removeLine 方法)
Telemetry 提供了两个方法来移除已添加但尚未发送的特定遥测数据:
java
// 保存addData返回的Item引用
Item motorItem = telemetry.addData("Motor Power", 0.5);
Item servoItem = telemetry.addData("Servo Position", 0.3);
// 稍后移除特定数据项
telemetry.removeItem(motorItem); // 只移除电机功率数据
// 保存addLine返回的Line引用
Line statusLine = telemetry.addLine("Status")
.addData("Mode", "AUTO")
.addData("Task", "Navigation");
// 稍后移除整行
telemetry.removeLine(statusLine); // 移除整个状态行及其所有数据1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
removeItem 和 removeLine 的应用场景
动态管理显示信息:
- 在不同阶段显示不同信息,移除不再相关的数据
- 在保持
setAutoClear(false)的同时,选择性地移除特定数据
条件显示:
- 只在特定条件下显示某些信息
- 例如:只在检测到障碍物时显示障碍物信息,其余时间移除此信息
优化显示空间:
- 在屏幕空间有限时,移除暂时不重要的信息
- 优先显示当前阶段最关键的数据
removeItem/removeLine 与 clear 的区别
removeItem/removeLine:精确移除特定的数据项或行,其他数据保持不变clear():移除所有非保留数据clearAll():移除所有数据,包括保留项
注意事项
- 引用保存:必须保存
addData或addLine返回的引用,才能稍后移除 - 立即生效:移除操作立即生效,但只有调用
update()后才会在驾驶站更新显示 - 替代方法:如果不需要保留引用,可以考虑使用条件性的
addData来控制显示内容
9. 控制遥测数据刷新频率
setMsTransmissionInterval(int msInterval)方法用于设置遥测数据传输的最小时间间隔,影响数据刷新频率。
java
// 设置更新频率为每秒10次(100毫秒)
telemetry.setMsTransmissionInterval(100);
// 设置更新频率为每秒2次(500毫秒)
telemetry.setMsTransmissionInterval(500);1
2
3
4
5
2
3
4
5
setMsTransmissionInterval 与 update 的关系
setMsTransmissionInterval和update()方法的关系是:
最小间隔限制:
setMsTransmissionInterval设置的是数据发送的最小时间间隔- 即使您频繁调用
update(),系统也不会超过这个频率发送数据 - 默认值为 250 毫秒(4Hz),即每秒最多发送 4 次数据
实际更新机制:
- 当您调用
update()时,系统会检查距离上次发送数据是否已超过设定的间隔 - 如果间隔不足,虽然
update()会执行(准备数据),但不会实际发送数据 - 只有当时间间隔满足条件时,数据才会发送到驾驶站
- 当您调用
实际刷新频率: 实际数据刷新频率 = min(update 调用频率, msInterval)
示例:
java
// 设置最小间隔为100毫秒
telemetry.setMsTransmissionInterval(100);
// 情况1:每50毫秒调用一次update
while (opModeIsActive()) {
updateSensorData();
telemetry.update(); // 实际上每100毫秒才会发送一次
sleep(50);
}
// 情况2:每200毫秒调用一次update
while (opModeIsActive()) {
updateSensorData();
telemetry.update(); // 每次调用都会发送,因为已超过最小间隔
sleep(200);
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
应用场景
- 调试场景:设置较短间隔(50-100ms)获取更实时的反馈
- 比赛场景:使用较长间隔(250-500ms)减轻通信负担
- 传感器监控:根据传感器更新频率调整最小间隔
实用场景
1. 传感器调试
java
// 显示颜色传感器值
telemetry.addData("颜色", "R:%d G:%d B:%d",
colorSensor.red(), colorSensor.green(), colorSensor.blue());
// 显示距离传感器值
telemetry.addData("距离", "%.1f 厘米", distanceSensor.getDistance(DistanceUnit.CM));1
2
3
4
5
6
2
3
4
5
6
2. 状态机调试
java
telemetry.addData("当前状态", currentState.toString());
telemetry.addData("计时器", "%.1f 秒", stateTimer.seconds());1
2
2
3. 自动驾驶进度
java
telemetry.addData("任务", "正在导航到标记");
telemetry.addData("完成度", "%d%%", (int)(progress * 100));1
2
2
总结
遥测系统是连接机器人和人类操作者的桥梁,有效使用它可以:
- 加速调试过程
- 提高驾驶员对机器人状态的了解
- 帮助追踪复杂程序的执行流程
- 诊断传感器和电机问题
从简单的文本消息开始,逐步添加更复杂的数据显示,很快您就能掌握这个强大工具的各种用法!
