feat: set right-B point gesture hold to one second

This commit is contained in:
LengedZhao
2026-08-08 16:38:49 +08:00
parent 29030c0b25
commit 6bf610295b
8 changed files with 27 additions and 27 deletions

View File

@@ -40,8 +40,8 @@ TOML 解析检查。若还要核对外置 OmniSocketGo 版本,可设置任务
稳定松开,再重新长按 3 秒。pending 和活动会话都不会自动重试或自动恢复。 稳定松开,再重新长按 3 秒。pending 和活动会话都不会自动重试或自动恢复。
- 右 C + 左摇杆上下:HBWALK 前进/后退。 - 右 C + 左摇杆上下:HBWALK 前进/后退。
- 左 Z + 右摇杆左右:HBWALK 原地转向。 - 左 Z + 右摇杆左右:HBWALK 原地转向。
- 右 B 连续 3 秒:右手进入厂商“单食指”姿态;松开至少 0.5 秒后再次连续 - 右 B 连续 1 秒:右手进入厂商“单食指”姿态;松开至少 0.5 秒后再次连续
3 秒退出。手指动作继续受 `400 units/s` 限速。 1 秒退出。手指动作继续受 `400 units/s` 限速。
## 迁移前必须修改 ## 迁移前必须修改

View File

@@ -397,8 +397,8 @@ omnisocket_server = "203.0.113.10:15000"
5. 松开两个扳机,长按左 Z + 右 C 3 秒启动; 5. 松开两个扳机,长按左 Z + 右 C 3 秒启动;
6. 先做小幅单关节跟随,再逐渐扩大动作; 6. 先做小幅单关节跟随,再逐渐扩大动作;
7. 分别小幅扣左右扳机,验证双手方向、范围和限速; 7. 分别小幅扣左右扳机,验证双手方向、范围和限速;
8. 保持右摇杆回中,连续长按右 B 3 秒,确认右手以 `400 units/s` 限速进入厂商 8. 保持右摇杆回中,连续长按右 B 1 秒,确认右手以 `400 units/s` 限速进入厂商
“单食指”姿态;松开至少 0.5 秒后再次长按 3 秒,确认退出并恢复正常右手跟随; “单食指”姿态;松开至少 0.5 秒后再次长按 1 秒,确认退出并恢复正常右手跟随;
9. 先停止并确认 `armed=false`,按飞书指南逐个选择其他手势组合键;检查 EAI 9. 先停止并确认 `armed=false`,按飞书指南逐个选择其他手势组合键;检查 EAI
`status.json` 的 `command_frames_accepted` 增长,并在 EAI 本机 5001 抓帧确认处理后的 `status.json` 的 `command_frames_accepted` 增长,并在 EAI 本机 5001 抓帧确认处理后的
`hand.position` 为六维数组;待机不会构包,`command_hand_merges` 此时不应增长; `hand.position` 为六维数组;待机不会构包,`command_hand_merges` 此时不应增长;

View File

@@ -43,8 +43,8 @@ TS1P 同构臂
- 同构臂当前的一维手部开合量以机器人实测默认打开姿态为 0 端点,并按厂家 xTELE 的 - 同构臂当前的一维手部开合量以机器人实测默认打开姿态为 0 端点,并按厂家 xTELE 的
BrainCoRevo2 保守“常规”抓握姿态作为 1 端点映射到六电机; BrainCoRevo2 保守“常规”抓握姿态作为 1 端点映射到六电机;
若 xTELE 后续直接输出六维归一化位置,会自动使用六维位置。 若 xTELE 后续直接输出六维归一化位置,会自动使用六维位置。
- 右手指向手势:遥操已启动且灵巧手反馈健康时,连续长按右 `B` 3 秒开启;松开 - 右手指向手势:遥操已启动且灵巧手反馈健康时,连续长按右 `B` 1 秒开启;松开
至少 `0.5 s` 后,再连续长按右 `B` 3 秒关闭。首次启动和每个新遥操会话都必须先 至少 `0.5 s` 后,再连续长按右 `B` 1 秒关闭。首次启动和每个新遥操会话都必须先
稳定松开 B,保持同一次按压不会反复切换。计时未满、中途松开、输入畸形或反馈 稳定松开 B,保持同一次按压不会反复切换。计时未满、中途松开、输入畸形或反馈
中断均不触发;计时期间冻结右手最后一条命令,左手和双臂仍照常跟随。 中断均不触发;计时期间冻结右手最后一条命令,左手和双臂仍照常跟随。
- 指向只覆盖右手。目标采用工控机 xTELE `GestureController` 的 BrainCoRevo2 第 2 号 - 指向只覆盖右手。目标采用工控机 xTELE `GestureController` 的 BrainCoRevo2 第 2 号

View File

@@ -111,12 +111,12 @@ closed_normalized = [0.9, 0.5, 0.45, 0.52, 0.52, 0.45]
# Right B owns a robot-side, release-guarded pointing gesture while a teleop # Right B owns a robot-side, release-guarded pointing gesture while a teleop
# session is armed. Both activation and deactivation require one continuous # session is armed. Both activation and deactivation require one continuous
# 3-second hold, separated by at least 0.5 seconds of stable release. A new # 1-second hold, separated by at least 0.5 seconds of stable release. A new
# session is always release-locked. The pose is xTELE GestureController's # session is always release-locked. The pose is xTELE GestureController's
# BrainCoRevo2 gesture 2 ("single index finger"), state 0, in motor order: # BrainCoRevo2 gesture 2 ("single index finger"), state 0, in motor order:
# thumb bend, thumb rotation, index, middle, ring, little. # thumb bend, thumb rotation, index, middle, ring, little.
right_b_point_gesture_enabled = true right_b_point_gesture_enabled = true
right_b_point_gesture_hold_seconds = 3.0 right_b_point_gesture_hold_seconds = 1.0
right_b_point_gesture_release_seconds = 0.5 right_b_point_gesture_release_seconds = 0.5
right_b_point_pose_normalized = [0.2, 0.688, 0.0, 0.98, 0.98, 0.98] right_b_point_pose_normalized = [0.2, 0.688, 0.0, 0.98, 0.98, 0.98]

View File

@@ -16,7 +16,7 @@ POINT_POSE = [0.2, 0.688, 0.0, 0.98, 0.98, 0.98]
class GestureToggleTest(unittest.TestCase): class GestureToggleTest(unittest.TestCase):
def setUp(self) -> None: def setUp(self) -> None:
self.gesture = GestureToggle(hold_seconds=3.0, release_seconds=0.5) self.gesture = GestureToggle(hold_seconds=1.0, release_seconds=0.5)
self.gesture.new_session() self.gesture.new_session()
def stable_release(self, started_at: float) -> float: def stable_release(self, started_at: float) -> float:
@@ -44,7 +44,7 @@ class GestureToggleTest(unittest.TestCase):
self.assertFalse(self.gesture.active) self.assertFalse(self.gesture.active)
self.assertTrue(self.gesture.freeze_right_hand) self.assertTrue(self.gesture.freeze_right_hand)
def test_continuous_three_second_holds_toggle_once_each(self) -> None: def test_continuous_one_second_holds_toggle_once_each(self) -> None:
released_at = self.stable_release(0.0) released_at = self.stable_release(0.0)
self.assertFalse( self.assertFalse(
self.gesture.update( self.gesture.update(
@@ -56,7 +56,7 @@ class GestureToggleTest(unittest.TestCase):
) )
self.assertFalse( self.assertFalse(
self.gesture.update( self.gesture.update(
released_at + 3.0, released_at + 1.0,
armed=True, armed=True,
input_healthy=True, input_healthy=True,
pressed=True, pressed=True,
@@ -64,7 +64,7 @@ class GestureToggleTest(unittest.TestCase):
) )
self.assertTrue( self.assertTrue(
self.gesture.update( self.gesture.update(
released_at + 3.01, released_at + 1.01,
armed=True, armed=True,
input_healthy=True, input_healthy=True,
pressed=True, pressed=True,
@@ -93,7 +93,7 @@ class GestureToggleTest(unittest.TestCase):
) )
self.assertTrue( self.assertTrue(
self.gesture.update( self.gesture.update(
second_release + 3.02, second_release + 1.02,
armed=True, armed=True,
input_healthy=True, input_healthy=True,
pressed=True, pressed=True,
@@ -115,7 +115,7 @@ class GestureToggleTest(unittest.TestCase):
self.assertEqual(self.gesture.state, "holding_start") self.assertEqual(self.gesture.state, "holding_start")
self.gesture.update( self.gesture.update(
released_at + 2.0, released_at + 0.8,
armed=True, armed=True,
input_healthy=True, input_healthy=True,
pressed=False, pressed=False,
@@ -124,14 +124,14 @@ class GestureToggleTest(unittest.TestCase):
self.assertTrue(self.gesture.require_release) self.assertTrue(self.gesture.require_release)
self.assertTrue(self.gesture.freeze_right_hand) self.assertTrue(self.gesture.freeze_right_hand)
self.gesture.update( self.gesture.update(
released_at + 2.49, released_at + 1.29,
armed=True, armed=True,
input_healthy=True, input_healthy=True,
pressed=False, pressed=False,
) )
self.assertTrue(self.gesture.require_release) self.assertTrue(self.gesture.require_release)
self.gesture.update( self.gesture.update(
released_at + 2.5, released_at + 1.3,
armed=True, armed=True,
input_healthy=True, input_healthy=True,
pressed=False, pressed=False,
@@ -148,7 +148,7 @@ class GestureToggleTest(unittest.TestCase):
pressed=True, pressed=True,
) )
self.gesture.update( self.gesture.update(
released_at + 2.99, released_at + 0.99,
armed=True, armed=True,
input_healthy=True, input_healthy=True,
pressed=None, pressed=None,
@@ -156,7 +156,7 @@ class GestureToggleTest(unittest.TestCase):
self.assertTrue(self.gesture.require_release) self.assertTrue(self.gesture.require_release)
self.assertIsNone(self.gesture.hold_started_at) self.assertIsNone(self.gesture.hold_started_at)
released_at = self.stable_release(released_at + 3.0) released_at = self.stable_release(released_at + 1.0)
self.gesture.update( self.gesture.update(
released_at + 0.01, released_at + 0.01,
armed=True, armed=True,
@@ -164,7 +164,7 @@ class GestureToggleTest(unittest.TestCase):
pressed=True, pressed=True,
) )
self.gesture.update( self.gesture.update(
released_at + 2.99, released_at + 0.99,
armed=True, armed=True,
input_healthy=False, input_healthy=False,
pressed=True, pressed=True,
@@ -183,14 +183,14 @@ class GestureToggleTest(unittest.TestCase):
) )
self.assertTrue( self.assertTrue(
self.gesture.update( self.gesture.update(
released_at + 3.02, released_at + 1.02,
armed=True, armed=True,
input_healthy=True, input_healthy=True,
pressed=True, pressed=True,
) )
) )
self.gesture.update( self.gesture.update(
released_at + 3.03, released_at + 1.03,
armed=True, armed=True,
input_healthy=False, input_healthy=False,
pressed=True, pressed=True,
@@ -207,7 +207,7 @@ class GestureToggleTest(unittest.TestCase):
pressed=True, pressed=True,
) )
self.gesture.update( self.gesture.update(
released_at + 3.02, released_at + 1.02,
armed=True, armed=True,
input_healthy=True, input_healthy=True,
pressed=True, pressed=True,
@@ -215,7 +215,7 @@ class GestureToggleTest(unittest.TestCase):
self.assertTrue(self.gesture.active) self.assertTrue(self.gesture.active)
self.assertFalse( self.assertFalse(
self.gesture.update( self.gesture.update(
released_at + 3.03, released_at + 1.03,
armed=False, armed=False,
input_healthy=True, input_healthy=True,
pressed=True, pressed=True,

View File

@@ -406,7 +406,7 @@ class LocalTeleopBridge(Node):
) )
self.right_point_gesture = GestureToggle( self.right_point_gesture = GestureToggle(
hold_seconds=float( hold_seconds=float(
self.hands_cfg.get("right_b_point_gesture_hold_seconds", 3.0) self.hands_cfg.get("right_b_point_gesture_hold_seconds", 1.0)
), ),
release_seconds=float( release_seconds=float(
self.hands_cfg.get("right_b_point_gesture_release_seconds", 0.5) self.hands_cfg.get("right_b_point_gesture_release_seconds", 0.5)

View File

@@ -23,7 +23,7 @@ xTELE 已处理的标量或六维 BrainCoRevo2 目标。5002 的界面事件和
右侧原始按键顺序是 `A/B/C`。按住右 `B` 时,sender 仍合并 5001 的左手 右侧原始按键顺序是 `A/B/C`。按住右 `B` 时,sender 仍合并 5001 的左手
目标,但保留 5003 的原始右手开合量,不用 xTELE 处理后的右手目标覆盖。 目标,但保留 5003 的原始右手开合量,不用 xTELE 处理后的右手目标覆盖。
这样右 B 的自定义长按手势还未满 3 秒时,原厂 B 处理不会让右手提前动作。 这样右 B 的自定义长按手势还未满 1 秒时,原厂 B 处理不会让右手提前动作。
松开 B 并连续稳定释放 `0.5 s` 后,还要等新鲜 5001 右手目标连续至少 `0.25 s` 松开 B 并连续稳定释放 `0.5 s` 后,还要等新鲜 5001 右手目标连续至少 `0.25 s`
恢复到按键前基线或当前 5003 原始开合量,才恢复双侧合并;无法确认时持续使用原始 恢复到按键前基线或当前 5003 原始开合量,才恢复双侧合并;无法确认时持续使用原始
右手值,防止释放沿后的锁存/延迟目标漏入。 右手值,防止释放沿后的锁存/延迟目标漏入。

View File

@@ -87,7 +87,7 @@ class XteleSender:
self.connect_result: tuple[int, Session | None, str] | None = None self.connect_result: tuple[int, Session | None, str] | None = None
# Keep xTELE's processed right-hand stream isolated for the complete # Keep xTELE's processed right-hand stream isolated for the complete
# right-B press and stable-release transaction. The robot runs the # right-B press and stable-release transaction. The robot runs the
# authoritative three-second gesture toggle from the raw B state. # authoritative one-second gesture toggle from the raw B state.
self.right_b_merge_suppressed = False self.right_b_merge_suppressed = False
self.right_b_release_started_at: float | None = None self.right_b_release_started_at: float | None = None
self.right_b_recovery_started_at: float | None = None self.right_b_recovery_started_at: float | None = None
@@ -521,7 +521,7 @@ class XteleSender:
return copy.deepcopy(processed_position), ("left", "right") return copy.deepcopy(processed_position), ("left", "right")
# While right B is held, xTELE may emit its own right-hand gesture # While right B is held, xTELE may emit its own right-hand gesture
# before our separate three-second B latch fires on the robot. Keep # before our separate one-second B latch fires on the robot. Keep
# the authoritative raw 5003 right-hand value, but allow an unrelated # the authoritative raw 5003 right-hand value, but allow an unrelated
# processed left-hand target to pass through. # processed left-hand target to pass through.
if not isinstance(raw_position, dict) or "right" not in raw_position: if not isinstance(raw_position, dict) or "right" not in raw_position: