From 98e706ad8ff59c60117d30d3b4e1c33ed4e7895d Mon Sep 17 00:00:00 2001 From: Xuwznln <18435084+Xuwznln@users.noreply.github.com> Date: Mon, 26 Jan 2026 00:20:15 +0800 Subject: [PATCH] TestLatency Return Value Example & gitignore update --- .conda/scripts/post-link.bat | 9 ---- .conda/scripts/post-link.sh | 9 ---- .cursorignore | 26 ---------- .gitignore | 1 + unilabos/ros/nodes/presets/host_node.py | 64 +++++++++++++++++++++---- 5 files changed, 55 insertions(+), 54 deletions(-) delete mode 100644 .conda/scripts/post-link.bat delete mode 100644 .conda/scripts/post-link.sh delete mode 100644 .cursorignore diff --git a/.conda/scripts/post-link.bat b/.conda/scripts/post-link.bat deleted file mode 100644 index 352b78c..0000000 --- a/.conda/scripts/post-link.bat +++ /dev/null @@ -1,9 +0,0 @@ -@echo off -setlocal enabledelayedexpansion - -REM upgrade pip -"%PREFIX%\python.exe" -m pip install --upgrade pip - -REM install extra deps -"%PREFIX%\python.exe" -m pip install paho-mqtt opentrons_shared_data -"%PREFIX%\python.exe" -m pip install git+https://github.com/Xuwznln/pylabrobot.git diff --git a/.conda/scripts/post-link.sh b/.conda/scripts/post-link.sh deleted file mode 100644 index ef96f15..0000000 --- a/.conda/scripts/post-link.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/env bash -set -euxo pipefail - -# make sure pip is available -"$PREFIX/bin/python" -m pip install --upgrade pip - -# install extra deps -"$PREFIX/bin/python" -m pip install paho-mqtt opentrons_shared_data -"$PREFIX/bin/python" -m pip install git+https://github.com/Xuwznln/pylabrobot.git diff --git a/.cursorignore b/.cursorignore deleted file mode 100644 index 7b0d4f9..0000000 --- a/.cursorignore +++ /dev/null @@ -1,26 +0,0 @@ -.conda -# .github -.idea -# .vscode -output -pylabrobot_repo -recipes -scripts -service -temp -# unilabos/test -# unilabos/app/web -unilabos/device_mesh -unilabos_data -unilabos_msgs -unilabos.egg-info -CONTRIBUTORS -# LICENSE -MANIFEST.in -pyrightconfig.json -# README.md -# README_zh.md -setup.py -setup.cfg -.gitattrubutes -**/__pycache__ diff --git a/.gitignore b/.gitignore index 610be61..838331e 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ temp/ output/ unilabos_data/ pyrightconfig.json +.cursorignore ## Python # Byte-compiled / optimized / DLL files diff --git a/unilabos/ros/nodes/presets/host_node.py b/unilabos/ros/nodes/presets/host_node.py index 101476a..85ebf3a 100644 --- a/unilabos/ros/nodes/presets/host_node.py +++ b/unilabos/ros/nodes/presets/host_node.py @@ -5,7 +5,8 @@ import threading import time import traceback import uuid -from typing import TYPE_CHECKING, Optional, Dict, Any, List, ClassVar, Set, TypedDict, Union +from typing import TYPE_CHECKING, Optional, Dict, Any, List, ClassVar, Set, Union +from typing_extensions import TypedDict from action_msgs.msg import GoalStatus from geometry_msgs.msg import Point @@ -62,6 +63,17 @@ class TestResourceReturn(TypedDict): devices: List[DeviceSlot] +class TestLatencyReturn(TypedDict): + """test_latency方法的返回值类型""" + avg_rtt_ms: float + avg_time_diff_ms: float + max_time_error_ms: float + task_delay_ms: float + raw_delay_ms: float + test_count: int + status: str + + class HostNode(BaseROS2DeviceNode): """ 主机节点类,负责管理设备、资源和控制器 @@ -853,8 +865,13 @@ class HostNode(BaseROS2DeviceNode): # 适配后端的一些额外处理 return_value = return_info.get("return_value") if isinstance(return_value, dict): - unilabos_samples = return_info.get("unilabos_samples") - if isinstance(unilabos_samples, list): + unilabos_samples = return_value.pop("unilabos_samples", None) + if isinstance(unilabos_samples, list) and unilabos_samples: + self.lab_logger().info( + f"[Host Node] Job {job_id[:8]} returned {len(unilabos_samples)} sample(s): " + f"{[s.get('name', s.get('id', 'unknown')) if isinstance(s, dict) else str(s)[:20] for s in unilabos_samples[:5]]}" + f"{'...' if len(unilabos_samples) > 5 else ''}" + ) return_info["unilabos_samples"] = unilabos_samples suc = return_info.get("suc", False) if not suc: @@ -1326,10 +1343,20 @@ class HostNode(BaseROS2DeviceNode): self.lab_logger().debug(f"[Host Node-Resource] List parameters: {request}") return response - def test_latency(self): + def test_latency(self) -> TestLatencyReturn: """ 测试网络延迟的action实现 通过5次ping-pong机制校对时间误差并计算实际延迟 + + Returns: + TestLatencyReturn: 包含延迟测试结果的字典,包括: + - avg_rtt_ms: 平均往返时间(毫秒) + - avg_time_diff_ms: 平均时间差(毫秒) + - max_time_error_ms: 最大时间误差(毫秒) + - task_delay_ms: 实际任务延迟(毫秒),-1表示无法计算 + - raw_delay_ms: 原始时间差(毫秒),-1表示无法计算 + - test_count: 有效测试次数 + - status: 测试状态,"success"表示成功,"all_timeout"表示全部超时 """ import uuid as uuid_module @@ -1392,7 +1419,15 @@ class HostNode(BaseROS2DeviceNode): if not ping_results: self.lab_logger().error("❌ 所有ping-pong测试都失败了") - return {"status": "all_timeout"} + return { + "avg_rtt_ms": -1.0, + "avg_time_diff_ms": -1.0, + "max_time_error_ms": -1.0, + "task_delay_ms": -1.0, + "raw_delay_ms": -1.0, + "test_count": 0, + "status": "all_timeout", + } # 统计分析 rtts = [r["rtt_ms"] for r in ping_results] @@ -1400,7 +1435,7 @@ class HostNode(BaseROS2DeviceNode): avg_rtt_ms = sum(rtts) / len(rtts) avg_time_diff_ms = sum(time_diffs) / len(time_diffs) - max_time_diff_error_ms = max(abs(min(time_diffs)), abs(max(time_diffs))) + max_time_diff_error_ms: float = max(abs(min(time_diffs)), abs(max(time_diffs))) self.lab_logger().info("-" * 50) self.lab_logger().info("[测试统计]") @@ -1440,7 +1475,7 @@ class HostNode(BaseROS2DeviceNode): self.lab_logger().info("=" * 60) - return { + res: TestLatencyReturn = { "avg_rtt_ms": avg_rtt_ms, "avg_time_diff_ms": avg_time_diff_ms, "max_time_error_ms": max_time_diff_error_ms, @@ -1451,9 +1486,14 @@ class HostNode(BaseROS2DeviceNode): "test_count": len(ping_results), "status": "success", } + return res def test_resource( - self, resource: ResourceSlot = None, resources: List[ResourceSlot] = None, device: DeviceSlot = None, devices: List[DeviceSlot] = None + self, + resource: ResourceSlot = None, + resources: List[ResourceSlot] = None, + device: DeviceSlot = None, + devices: List[DeviceSlot] = None, ) -> TestResourceReturn: if resources is None: resources = [] @@ -1514,7 +1554,9 @@ class HostNode(BaseROS2DeviceNode): # 构建服务地址 srv_address = f"/srv{namespace}/s2c_resource_tree" - self.lab_logger().trace(f"[Host Node-Resource] Host -> {device_id} ResourceTree {action} operation started -------") + self.lab_logger().trace( + f"[Host Node-Resource] Host -> {device_id} ResourceTree {action} operation started -------" + ) # 创建服务客户端 sclient = self.create_client(SerialCommand, srv_address) @@ -1549,7 +1591,9 @@ class HostNode(BaseROS2DeviceNode): time.sleep(0.05) response = future.result() - self.lab_logger().trace(f"[Host Node-Resource] Host -> {device_id} ResourceTree {action} operation completed -------") + self.lab_logger().trace( + f"[Host Node-Resource] Host -> {device_id} ResourceTree {action} operation completed -------" + ) return True except Exception as e: