fix: remove robot-side 250ms network disarm
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
TS1P 同构臂
|
||||
-> 工控机 xTELE tcp://127.0.0.1:5003
|
||||
-> OmniSocket KCP Hub 175.178.116.187:14049
|
||||
-> tg3_local_teleop(直接 OmniSocket Session;HBWALK / 错误 / 限位 / 失联门控)
|
||||
-> tg3_local_teleop(直接 OmniSocket Session;HBWALK / 错误 / 限位门控)
|
||||
-> /encoder_identical_joint(14 维 JointState)
|
||||
-> 厂家 freq_change_tg3_node(同步、滤波、200 Hz)
|
||||
-> /arm/cmd
|
||||
@@ -58,7 +58,7 @@ TS1P 同构臂
|
||||
只有以下条件全部满足才允许开始:机器人 `current_state` 和 `child_state` 均为
|
||||
`HBWALK`、状态为 `running`;同构臂数据新鲜;左右 CAN/伺服无错误;采样频率正常;
|
||||
启动瞬间的 14 个目标均在天工 3.0 文档限位内;没有检测到云端第二路同构臂命令。
|
||||
自定义关节目标限位仅对每个新 `session_id` 的 START 检查一次,采集/跟随过程中不再检查;失联、电机错误、
|
||||
自定义关节目标限位仅对每个新 `session_id` 的 START 检查一次,采集/跟随过程中不再检查;电机错误、
|
||||
HBWALK 状态等运行时保护仍持续检查。厂家 `freq_change_tg3_node` 原有的姿态同步、
|
||||
关节限位和碰撞保护保持不变。为启用二次开放文档规定的 HBWALK topic 行走,本机
|
||||
`xmigcs/config/dex_config.yaml` 的 HBWALK 速度许可已由全零改为当前 NAVIGATE 的上限;
|
||||
@@ -71,7 +71,7 @@ HBWALK 状态等运行时保护仍持续检查。厂家 `freq_change_tg3_node`
|
||||
|
||||
灵巧手仅在同一次长按武装后发布;以机器人真实手指位置为起点,并按每秒最多 400 个
|
||||
位置单位平滑跟随。BrainCo 状态 `0`(空闲)、`1`(运动)、`2`(接触/堵转或到限位)
|
||||
和 `3`(持续力)均为厂家定义的正常运行状态;仅状态失联、未知/非法状态、同构臂失联
|
||||
和 `3`(持续力)均为厂家定义的正常运行状态;仅状态失联、未知/非法状态
|
||||
或检测到另一命令源时,双臂和双手会一起解除武装并停止发布。停止遥操后灵巧手保持
|
||||
最后目标,双臂按原逻辑限速回 Home。BrainCo 驱动原有的电流、堵转和碰撞保护不作修改。
|
||||
匹配的 STOP、安全解除武装或服务退出都会清除右 B 指向手势的逻辑状态,但不会在
|
||||
@@ -130,10 +130,10 @@ systemctl --user stop tg3-local-teleop.service
|
||||
接收代理。若需回退到机器人与工控机的局域网直连,可把 `network.transport` 改成
|
||||
`zmq`;保留的 `iarm_endpoint` 为 `tcp://192.168.5.14:5003`。
|
||||
|
||||
遥操活动期间公网输入超过 `0.25 s` 未更新会立即解除武装并停止发布,同一会话不能自动
|
||||
重新武装;活动会话超过 `2 s` 仍无帧时才重建机器人 OmniSocket 进程。未 START 或收到
|
||||
STOP 后没有业务帧是正常待机,不触发反复重启。只有匹配的操作员 STOP 自动回 Home;
|
||||
意外断网只停控,不自动产生回位运动。
|
||||
机器人侧不再以 `0.25 s` 公网输入间隔解除武装。活动会话超过 `2 s` 仍无帧时重建机器人
|
||||
OmniSocket 进程;在此之前桥会保持最后一帧目标。未 START 或收到 STOP 后没有业务帧是
|
||||
正常待机,不触发反复重启。只有匹配的操作员 STOP 自动回 Home;意外断网不自动产生
|
||||
回位运动。
|
||||
|
||||
## 完整重启顺序
|
||||
|
||||
|
||||
@@ -11,14 +11,13 @@ omnisocket_max_packet_age_ms = 300.0
|
||||
# Active traffic resets this timer and is never interrupted by this refresh.
|
||||
omnisocket_idle_session_refresh_s = 30.0
|
||||
# The native session can remain blocked on an old connection after the public
|
||||
# Hub disappears. Publication stops at source_timeout_s; after this longer
|
||||
# interval the process exits and systemd creates a completely fresh session.
|
||||
# Hub disappears. An active session that receives no business frame for this
|
||||
# interval exits so systemd creates a completely fresh session.
|
||||
omnisocket_restart_after_stale_s = 2.0
|
||||
# Retained only as a direct-LAN fallback when transport is changed to "zmq".
|
||||
iarm_endpoint = "tcp://192.168.5.14:5003"
|
||||
expected_iarm_id = "IArm009027FA8190"
|
||||
expected_iarm_type = "TS1P"
|
||||
source_timeout_s = 0.25
|
||||
minimum_arm_frequency_hz = 30.0
|
||||
|
||||
[ros]
|
||||
|
||||
@@ -164,6 +164,69 @@ class RobotSessionGateTest(unittest.TestCase):
|
||||
valid["tg3_transport"]["protocol_version"] = 1
|
||||
self.assertIsNone(LocalTeleopBridge._teleop_session_info(valid))
|
||||
|
||||
def test_network_sample_age_is_not_a_runtime_disarm_gate(self) -> None:
|
||||
bridge = LocalTeleopBridge.__new__(LocalTeleopBridge)
|
||||
bridge.cfg = {
|
||||
"network": {
|
||||
"expected_iarm_id": "IArm-test",
|
||||
"expected_iarm_type": "TS1P",
|
||||
"minimum_arm_frequency_hz": 30.0,
|
||||
},
|
||||
"robot": {
|
||||
"arm_state_timeout_s": 0.25,
|
||||
"state_timeout_s": 1.0,
|
||||
"required_state": "HBWALK",
|
||||
"required_status": "running",
|
||||
},
|
||||
"control": {},
|
||||
}
|
||||
bridge.hands_enabled = False
|
||||
bridge.robot_arm_at = 100.0
|
||||
bridge.robot_arm_errors = [0] * 14
|
||||
bridge.rl_state_at = 100.0
|
||||
bridge.rl_state = {
|
||||
"current_state": "HBWALK",
|
||||
"child_state": "HBWALK",
|
||||
"status": "running",
|
||||
}
|
||||
bridge.foreign_source_seen = False
|
||||
bridge.foreign_hand_source_seen = False
|
||||
old_network_sample = ArmSnapshot(
|
||||
{
|
||||
"isomorphic_arm_id": "IArm-test",
|
||||
"isomorphic_arm_type": "TS1P",
|
||||
"servo_error": {"left": [0] * 7, "right": [0] * 7},
|
||||
"joycan_error": [0, 0],
|
||||
"freq": {"left": 80.0, "right": 80.0},
|
||||
},
|
||||
received_at=10.0,
|
||||
)
|
||||
|
||||
reasons = bridge._safety_reasons(
|
||||
100.0,
|
||||
old_network_sample,
|
||||
"",
|
||||
check_iarm_target=False,
|
||||
check_hands=False,
|
||||
check_hand_feedback=False,
|
||||
)
|
||||
self.assertEqual(reasons, [])
|
||||
|
||||
def test_two_second_omnisocket_restart_watchdog_remains(self) -> None:
|
||||
bridge = LocalTeleopBridge.__new__(LocalTeleopBridge)
|
||||
bridge.cfg = {
|
||||
"network": {
|
||||
"transport": "omnisocket",
|
||||
"omnisocket_restart_after_stale_s": 2.0,
|
||||
}
|
||||
}
|
||||
active = sample("f" * 32, 1, "active")
|
||||
self.assertIsNone(bridge._source_restart_reason(11.999, active))
|
||||
self.assertIn(
|
||||
"OmniSocket input stale",
|
||||
bridge._source_restart_reason(12.0, active),
|
||||
)
|
||||
|
||||
def test_locomotion_reacts_immediately_after_repress(self) -> None:
|
||||
bridge = LocalTeleopBridge.__new__(LocalTeleopBridge)
|
||||
bridge.locomotion_cfg = {
|
||||
|
||||
@@ -799,7 +799,6 @@ class LocalTeleopBridge(Node):
|
||||
# A server outage can leave the native OmniSocket recv call stuck in
|
||||
# an apparently connected session. Raising out of the ROS loop lets
|
||||
# systemd replace the whole process (and native session) cleanly.
|
||||
# The normal runtime gate above has already stopped publication.
|
||||
self.get_logger().error(restart_reason)
|
||||
raise RuntimeError(restart_reason)
|
||||
|
||||
@@ -1342,9 +1341,6 @@ class LocalTeleopBridge(Node):
|
||||
if check_iarm and sample is None:
|
||||
reasons.append(source_error or "no isomorphic-arm data")
|
||||
elif check_iarm:
|
||||
age = now - sample.received_at
|
||||
if age > float(net_cfg["source_timeout_s"]):
|
||||
reasons.append(f"isomorphic-arm data stale ({age:.3f}s)")
|
||||
data = sample.data
|
||||
expected_id = str(net_cfg.get("expected_iarm_id", ""))
|
||||
expected_type = str(net_cfg.get("expected_iarm_type", ""))
|
||||
@@ -1565,11 +1561,6 @@ class LocalTeleopBridge(Node):
|
||||
"omnisocket_restart_after_stale_s"
|
||||
),
|
||||
"iarm_connected": sample is not None,
|
||||
"iarm_stream_fresh": (
|
||||
sample is not None
|
||||
and now - sample.received_at
|
||||
<= float(self.cfg["network"]["source_timeout_s"])
|
||||
),
|
||||
"iarm_age_s": None if sample is None else round(now - sample.received_at, 4),
|
||||
"iarm_id": None if sample is None else sample.data.get("isomorphic_arm_id"),
|
||||
"iarm_frequency_hz": None if sample is None else sample.data.get("freq"),
|
||||
|
||||
Reference in New Issue
Block a user