Skip to content

Commit 9854ed8

Browse files
committed
fix ros2 future
print all logs to file fix resource dict dump error
1 parent 52544a2 commit 9854ed8

7 files changed

Lines changed: 43 additions & 32 deletions

File tree

unilabos/app/communication.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ def get_client(cls, protocol: Optional[str] = None) -> BaseCommunicationClient:
141141
"""
142142
if cls._client_cache is None:
143143
cls._client_cache = cls.create_client(protocol)
144-
logger.info(f"[CommunicationFactory] Created {type(cls._client_cache).__name__} client")
144+
logger.trace(f"[CommunicationFactory] Created {type(cls._client_cache).__name__} client")
145145

146146
return cls._client_cache
147147

unilabos/app/ws_client.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -389,7 +389,7 @@ def start(self) -> None:
389389
self.is_running = True
390390
self.thread = threading.Thread(target=self._run, daemon=True, name="MessageProcessor")
391391
self.thread.start()
392-
logger.info("[MessageProcessor] Started")
392+
logger.trace("[MessageProcessor] Started")
393393

394394
def stop(self) -> None:
395395
"""停止消息处理线程"""
@@ -939,7 +939,7 @@ def __init__(self, device_manager: DeviceActionManager, message_processor: Messa
939939
# 事件通知机制
940940
self.queue_update_event = threading.Event()
941941

942-
logger.info("[QueueProcessor] Initialized")
942+
logger.trace("[QueueProcessor] Initialized")
943943

944944
def set_websocket_client(self, websocket_client: "WebSocketClient"):
945945
"""设置WebSocket客户端引用"""
@@ -954,7 +954,7 @@ def start(self) -> None:
954954
self.is_running = True
955955
self.thread = threading.Thread(target=self._run, daemon=True, name="QueueProcessor")
956956
self.thread.start()
957-
logger.info("[QueueProcessor] Started")
957+
logger.trace("[QueueProcessor] Started")
958958

959959
def stop(self) -> None:
960960
"""停止队列处理线程"""

unilabos/resources/graphio.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ def canonicalize_nodes_data(
9797

9898
for node in nodes:
9999
try:
100-
print_status(f"DeviceId: {node['id']}, Class: {node['class']}", "info")
100+
# print_status(f"DeviceId: {node['id']}, Class: {node['class']}", "info")
101101
# 使用标准化方法
102102
resource_instance = ResourceDictInstance.get_resource_instance_from_dict(node)
103103
known_nodes[node["id"]] = resource_instance

unilabos/ros/nodes/base_device_node.py

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -582,7 +582,7 @@ async def update_resource(self, resources: List["ResourcePLR"]):
582582
except Exception as e:
583583
self.lab_logger().error(f"更新资源uuid失败: {e}")
584584
self.lab_logger().error(traceback.format_exc())
585-
self.lab_logger().debug(f"资源更新结果: {response}")
585+
self.lab_logger().trace(f"资源更新结果: {response}")
586586

587587
async def get_resource(self, resources_uuid: List[str], with_children: bool = True) -> ResourceTreeSet:
588588
"""
@@ -1164,43 +1164,43 @@ def ACTION(**kwargs):
11641164
execution_error = traceback.format_exc()
11651165
break
11661166

1167-
##### self.lab_logger().info(f"准备执行: {action_kwargs}, 函数: {ACTION.__name__}")
11681167
time_start = time.time()
11691168
time_overall = 100
11701169
future = None
11711170
if not error_skip:
11721171
# 将阻塞操作放入线程池执行
11731172
if asyncio.iscoroutinefunction(ACTION):
11741173
try:
1175-
##### self.lab_logger().info(f"异步执行动作 {ACTION}")
1176-
future = ROS2DeviceNode.run_async_func(ACTION, trace_error=False, **action_kwargs)
1177-
1178-
def _handle_future_exception(fut):
1174+
self.lab_logger().trace(f"异步执行动作 {ACTION}")
1175+
def _handle_future_exception(fut: Future):
11791176
nonlocal execution_error, execution_success, action_return_value
11801177
try:
11811178
action_return_value = fut.result()
1179+
if isinstance(action_return_value, BaseException):
1180+
raise action_return_value
11821181
execution_success = True
1183-
except Exception as e:
1182+
except Exception as _:
11841183
execution_error = traceback.format_exc()
11851184
error(
11861185
f"异步任务 {ACTION.__name__} 报错了\n{traceback.format_exc()}\n原始输入:{action_kwargs}"
11871186
)
11881187

1188+
future = ROS2DeviceNode.run_async_func(ACTION, trace_error=False, **action_kwargs)
11891189
future.add_done_callback(_handle_future_exception)
11901190
except Exception as e:
11911191
execution_error = traceback.format_exc()
11921192
execution_success = False
11931193
self.lab_logger().error(f"创建异步任务失败: {traceback.format_exc()}")
11941194
else:
1195-
##### self.lab_logger().info(f"同步执行动作 {ACTION}")
1195+
self.lab_logger().trace(f"同步执行动作 {ACTION}")
11961196
future = self._executor.submit(ACTION, **action_kwargs)
11971197

1198-
def _handle_future_exception(fut):
1198+
def _handle_future_exception(fut: Future):
11991199
nonlocal execution_error, execution_success, action_return_value
12001200
try:
12011201
action_return_value = fut.result()
12021202
execution_success = True
1203-
except Exception as e:
1203+
except Exception as _:
12041204
execution_error = traceback.format_exc()
12051205
error(
12061206
f"同步任务 {ACTION.__name__} 报错了\n{traceback.format_exc()}\n原始输入:{action_kwargs}"
@@ -1305,7 +1305,7 @@ def _handle_future_exception(fut):
13051305
get_result_info_str(execution_error, execution_success, action_return_value),
13061306
)
13071307

1308-
##### self.lab_logger().info(f"动作 {action_name} 完成并返回结果")
1308+
self.lab_logger().trace(f"动作 {action_name} 完成并返回结果")
13091309
return result_msg
13101310

13111311
return execute_callback
@@ -1540,17 +1540,29 @@ class ROS2DeviceNode:
15401540
这个类封装了设备类实例和ROS2节点的功能,提供ROS2接口。
15411541
它不继承设备类,而是通过代理模式访问设备类的属性和方法。
15421542
"""
1543+
@staticmethod
1544+
async def safe_task_wrapper(trace_callback, func, **kwargs):
1545+
try:
1546+
if callable(trace_callback):
1547+
trace_callback(await func(**kwargs))
1548+
return await func(**kwargs)
1549+
except Exception as e:
1550+
if callable(trace_callback):
1551+
trace_callback(e)
1552+
return e
15431553

15441554
@classmethod
1545-
def run_async_func(cls, func, trace_error=True, **kwargs) -> Task:
1546-
def _handle_future_exception(fut):
1555+
def run_async_func(cls, func, trace_error=True, inner_trace_callback=None, **kwargs) -> Task:
1556+
def _handle_future_exception(fut: Future):
15471557
try:
1548-
fut.result()
1558+
ret = fut.result()
1559+
if isinstance(ret, BaseException):
1560+
raise ret
15491561
except Exception as e:
1550-
error(f"异步任务 {func.__name__} 报错了")
1562+
error(f"异步任务 {func.__name__} 获取结果失败")
15511563
error(traceback.format_exc())
15521564

1553-
future = rclpy.get_global_executor().create_task(func(**kwargs))
1565+
future = rclpy.get_global_executor().create_task(ROS2DeviceNode.safe_task_wrapper(inner_trace_callback, func, **kwargs))
15541566
if trace_error:
15551567
future.add_done_callback(_handle_future_exception)
15561568
return future

unilabos/ros/nodes/presets/host_node.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -718,7 +718,7 @@ def send_goal(
718718
feedback_callback=lambda feedback_msg: self.feedback_callback(item, action_id, feedback_msg),
719719
goal_uuid=goal_uuid_obj,
720720
)
721-
future.add_done_callback(lambda future: self.goal_response_callback(item, action_id, future))
721+
future.add_done_callback(lambda f: self.goal_response_callback(item, action_id, f))
722722

723723
def goal_response_callback(self, item: "QueueItem", action_id: str, future) -> None:
724724
"""目标响应回调"""
@@ -729,9 +729,11 @@ def goal_response_callback(self, item: "QueueItem", action_id: str, future) -> N
729729

730730
self.lab_logger().info(f"[Host Node] Goal {action_id} ({item.job_id}) accepted")
731731
self._goals[item.job_id] = goal_handle
732-
goal_handle.get_result_async().add_done_callback(
733-
lambda future: self.get_result_callback(item, action_id, future)
732+
goal_future = goal_handle.get_result_async()
733+
goal_future.add_done_callback(
734+
lambda f: self.get_result_callback(item, action_id, f)
734735
)
736+
goal_future.result()
735737

736738
def feedback_callback(self, item: "QueueItem", action_id: str, feedback_msg) -> None:
737739
"""反馈回调"""

unilabos/ros/nodes/resource_tracker.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ def get_plr_nested_dict(self) -> Dict[str, Any]:
155155
res_dict = self.res_content.model_dump(by_alias=True)
156156
res_dict["children"] = {child.res_content.id: child.get_plr_nested_dict() for child in self.children}
157157
res_dict["parent"] = self.res_content.parent_instance_name
158-
res_dict["position"] = self.res_content.position.position.model_dump()
158+
res_dict["position"] = self.res_content.pose.position.model_dump()
159159
del res_dict["pose"]
160160
return res_dict
161161

unilabos/utils/log.py

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -162,8 +162,9 @@ def configure_logger(loglevel=None, working_dir=None):
162162
"""
163163
# 获取根日志记录器
164164
root_logger = logging.getLogger()
165-
165+
root_logger.setLevel(TRACE_LEVEL)
166166
# 设置日志级别
167+
numeric_level = logging.DEBUG
167168
if loglevel is not None:
168169
if isinstance(loglevel, str):
169170
# 将字符串转换为logging级别
@@ -173,20 +174,16 @@ def configure_logger(loglevel=None, working_dir=None):
173174
numeric_level = getattr(logging, loglevel.upper(), None)
174175
if not isinstance(numeric_level, int):
175176
print(f"警告: 无效的日志级别 '{loglevel}',使用默认级别 DEBUG")
176-
numeric_level = logging.DEBUG
177177
else:
178178
numeric_level = loglevel
179-
root_logger.setLevel(numeric_level)
180-
else:
181-
root_logger.setLevel(logging.DEBUG) # 默认级别
182179

183180
# 移除已存在的处理器
184181
for handler in root_logger.handlers[:]:
185182
root_logger.removeHandler(handler)
186183

187184
# 创建控制台处理器
188185
console_handler = logging.StreamHandler()
189-
console_handler.setLevel(root_logger.level) # 使用与根记录器相同的级别
186+
console_handler.setLevel(numeric_level) # 使用与根记录器相同的级别
190187

191188
# 使用自定义的颜色格式化器
192189
color_formatter = ColoredFormatter()
@@ -206,7 +203,7 @@ def configure_logger(loglevel=None, working_dir=None):
206203

207204
# 创建文件处理器
208205
file_handler = logging.FileHandler(log_filepath, encoding="utf-8")
209-
file_handler.setLevel(root_logger.level)
206+
file_handler.setLevel(TRACE_LEVEL)
210207

211208
# 使用不带颜色的格式化器
212209
file_formatter = ColoredFormatter(use_colors=False)

0 commit comments

Comments
 (0)