Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
5b4f580
add 3d visualization
Apr 23, 2025
279c5ed
完成在main中启动设备可视化
Apr 23, 2025
6155ec2
完成TF发布
Apr 23, 2025
1e01eae
修改模型方向,在yaml中添加变换属性
Apr 25, 2025
bed9720
添加物料tf变化时,发送topic到前端
Apr 25, 2025
ff8b75b
添加关节发布节点与物料可视化节点进入unilab
Apr 27, 2025
bdf97be
使用json启动plr与3D模型仿真
Apr 29, 2025
8921bcd
完成启动OT并联动rviz
Apr 29, 2025
b7a16cd
add 3d visualization
Apr 23, 2025
2baa232
完成在main中启动设备可视化
Apr 23, 2025
0d24606
完成TF发布
Apr 23, 2025
2990e70
修改模型方向,在yaml中添加变换属性
Apr 25, 2025
111c3f4
添加物料tf变化时,发送topic到前端
Apr 25, 2025
d407423
添加关节发布节点与物料可视化节点进入unilab
Apr 27, 2025
49bb11b
使用json启动plr与3D模型仿真
Apr 29, 2025
dc197bf
完成启动OT并联动rviz
Apr 29, 2025
44c191f
Merge branch 'device_visualization' of https://github.com/q434343/Uni…
Apr 30, 2025
5212d2d
修复rviz位置问题,
Apr 30, 2025
9eb271f
Merge remote-tracking branch 'origin/dev' into fork/q434343/device_vi…
Xuwznln May 1, 2025
2b42808
fix: running logic
Xuwznln May 1, 2025
fa5db06
fix: running logic
Xuwznln May 1, 2025
78239ab
fix: missing ot
Xuwznln May 1, 2025
5668310
在main中直接初始化republisher和物料的mesh节点
May 1, 2025
80380d1
将joint_republisher和resource_mesh_manager添加进 main_slave_run.py中
May 2, 2025
d199fda
编写mesh添加action
May 6, 2025
3d607db
add action
May 6, 2025
8617b12
Merge remote-tracking branch 'upstream/dev' into device_visualization
May 6, 2025
b43f232
Merge remote-tracking branch 'origin/dev' into device_visualization
Xuwznln May 6, 2025
aad2359
fix
May 6, 2025
6d5ada0
Merge remote-tracking branch 'q434343/device_visualization' into devi…
Xuwznln May 6, 2025
5df304b
fix: browser on rviz
Xuwznln May 6, 2025
3d60cb3
fix: cloud bridge error fallback to local
Xuwznln May 6, 2025
6cdd8c1
fix: salve auto run rviz
Xuwznln May 6, 2025
c12c2a8
初始化两个plate
May 6, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9,590 changes: 9,590 additions & 0 deletions test/experiments/plr_test_converted.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion test/experiments/test_copy.json
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@
"position": {
"x": 10.87,
"y": 70.77,
"z": 10
"z": 9.47
},
"config": {
"type": "TipSpot",
Expand Down
4 changes: 3 additions & 1 deletion unilabos/app/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,9 @@ def _exit(signum, frame):
resource_visualization = ResourceVisualization(devices_and_resources, args_dict["resources_config"] ,enable_rviz=enable_rviz)
args_dict["resources_mesh_config"] = resource_visualization.resource_model
start_backend(**args_dict)
server_thread = threading.Thread(target=start_server, args=(not args_dict["disable_browser"],))
server_thread = threading.Thread(target=start_server, kwargs=dict(
open_browser=not args_dict["disable_browser"]
))
server_thread.start()
asyncio.set_event_loop(asyncio.new_event_loop())
resource_visualization.start()
Expand Down
Empty file.
18 changes: 10 additions & 8 deletions unilabos/device_mesh/resource_visalization.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,21 @@


class ResourceVisualization:
def __init__(self, device: dict, resource: list, enable_rviz: bool = True):
def __init__(self, device: dict, resource: dict, enable_rviz: bool = True):
"""初始化资源可视化类

该类用于将设备和资源的3D模型可视化展示。通过解析设备和资源的配置信息,
从注册表中获取对应的3D模型文件,并使用ROS2和RViz进行可视化。

Args:
device (dict): 设备配置字典,包含设备的类型、位置等信息
resource (list): 资源配置列表,包含资源的类型、位置等信息
resource (dict): 资源配置字典,包含资源的类型、位置等信息
registry (dict): 注册表字典,包含设备和资源类型的注册信息
enable_rviz (bool, optional): 是否启用RViz可视化. Defaults to True.
"""
self.launch_service = LaunchService()
self.launch_description = LaunchDescription()
self.resource_list = resource
self.resource_dict = resource
self.resource_model = {}
self.resource_type = ['deck', 'plate', 'container']
self.mesh_path = Path(__file__).parent.absolute()
Expand Down Expand Up @@ -64,18 +64,20 @@ def __init__(self, device: dict, resource: list, enable_rviz: bool = True):
self.resource_model[node['id']] = {
'mesh': f"{str(self.mesh_path)}/resources/{model_config['mesh']}",
'mesh_tf': model_config['mesh_tf']}
if model_config['children_mesh'] is not None:
self.resource_model[f"{node['id']}_"] = {
'mesh': f"{str(self.mesh_path)}/resources/{model_config['children_mesh']}",
'mesh_tf': model_config['children_mesh_tf']
}
if 'children_mesh' in model_config:
if model_config['children_mesh'] is not None:
self.resource_model[f"{node['id']}_"] = {
'mesh': f"{str(self.mesh_path)}/resources/{model_config['children_mesh']}",
'mesh_tf': model_config['children_mesh_tf']
}
elif model_config['type'] == 'device':
new_include = etree.SubElement(self.root, f"{{{xacro_uri}}}include")
new_include.set("filename", f"{str(self.mesh_path)}/devices/{model_config['mesh']}/macro_device.xacro")
new_dev = etree.SubElement(self.root, f"{{{xacro_uri}}}{model_config['mesh']}")
new_dev.set("parent_link", "world")
new_dev.set("mesh_path", str(self.mesh_path))
new_dev.set("device_name", node["id"]+"_")
new_dev.set("station_name", node["parent"]+'_')
new_dev.set("x",str(float(node["position"]["x"])/1000))
new_dev.set("y",str(float(node["position"]["y"])/1000))
new_dev.set("z",str(float(node["position"]["z"])/1000))
Expand Down
2 changes: 1 addition & 1 deletion unilabos/devices/ros_dev/liquid_handler_joint_publisher.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from rclpy.executors import MultiThreadedExecutor
from rclpy.action import ActionServer
from sensor_msgs.msg import JointState
from ilabos_msgs.action import SendCmd
from unilabos_msgs.action import SendCmd
from rclpy.action.server import ServerGoalHandle
from unilabos.ros.nodes.base_device_node import BaseROS2DeviceNode
from tf_transformations import quaternion_from_euler
Expand Down
4 changes: 4 additions & 0 deletions unilabos/registry/resources/opentrons/plates.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ nest_96_wellplate_2ml_deep:
class:
module: pylabrobot.resources.opentrons.plates:nest_96_wellplate_2ml_deep
type: pylabrobot
model:
type: resource
mesh: tecan_nested_tip_rack/meshes/plate.stl
mesh_tf: [0.064, 0.043, 0, -1.5708, 0, 1.5708]

nest_96_wellplate_200ul_flat:
description: Nest 96 wellplate 200ul flat
Expand Down
2 changes: 1 addition & 1 deletion unilabos/registry/resources/opentrons/tip_racks.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ opentrons_96_filtertiprack_1000ul:
mesh: tecan_nested_tip_rack/meshes/plate.stl
mesh_tf: [0.064, 0.043, 0, -1.5708, 0, 1.5708]
children_mesh: generic_labware_tube_10_75/meshes/0_base.stl
children_mesh_tf: [0.0018, 0.0018, 0, -1.5708,0, 0]
children_mesh_tf: [0.0085, 0.006, 0, -1.5708,0, 0]

opentrons_96_filtertiprack_20ul:
description: Opentrons 96 filtertiprack 20ul
Expand Down
11 changes: 7 additions & 4 deletions unilabos/resources/graphio.py
Original file line number Diff line number Diff line change
Expand Up @@ -394,14 +394,14 @@ def resource_ulab_to_plr_inner(resource: dict):
return resource_plr


def resource_plr_to_ulab(resource_plr: "ResourcePLR"):
def resource_plr_to_ulab(resource_plr: "ResourcePLR", parent_name: str = None):
def resource_plr_to_ulab_inner(d: dict, all_states: dict) -> dict:
r = {
"id": d["name"],
"name": d["name"],
"sample_id": None,
"children": [resource_plr_to_ulab_inner(child, all_states) for child in d["children"]],
"parent": d["parent_name"] if d["parent_name"] else None,
"parent": d["parent_name"] if d["parent_name"] else parent_name if parent_name else None,
"type": "device", # FIXME plr自带的type是python class name
"class": d.get("class", ""),
"position": (
Expand All @@ -417,6 +417,7 @@ def resource_plr_to_ulab_inner(d: dict, all_states: dict) -> dict:
d = resource_plr.serialize()
all_states = resource_plr.serialize_all_state()
r = resource_plr_to_ulab_inner(d, all_states)

return r


Expand Down Expand Up @@ -451,7 +452,8 @@ def initialize_resource(resource_config: dict, lab_registry: dict) -> list[dict]

if resource_class_config["type"] == "pylabrobot":
resource_plr = RESOURCE(name=resource_config["name"])
r = resource_plr_to_ulab(resource_plr=resource_plr)
r = resource_plr_to_ulab(resource_plr=resource_plr, parent_name=resource_config.get("parent", None))
# r = resource_plr_to_ulab(resource_plr=resource_plr)
if resource_config.get("position") is not None:
r["position"] = resource_config["position"]
r = tree_to_list([r])
Expand All @@ -475,8 +477,9 @@ def initialize_resources(resources_config) -> list[dict]:
"""

from unilabos.registry.registry import lab_registry

resources = []
for resource_config in resources_config:

resources.extend(initialize_resource(resource_config, lab_registry))

return resources
15 changes: 15 additions & 0 deletions unilabos/ros/main_slave_run.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,21 @@ def slave(
n = Node(f"slaveMachine_{BasicConfig.machine_name}", parameter_overrides=[])
executor.add_node(n)

if visual != "disable":
resource_mesh_manager = ResourceMeshManager(
resources_mesh_config,
resources_config,
resource_tracker= DeviceNodeResourceTracker(),
device_id = 'resource_mesh_manager',
)
joint_republisher = JointRepublisher(
'joint_republisher',
DeviceNodeResourceTracker()
)

executor.add_node(resource_mesh_manager)
executor.add_node(joint_republisher)

thread = threading.Thread(target=executor.spin, daemon=True, name="slave_executor_thread")
thread.start()

Expand Down
3 changes: 2 additions & 1 deletion unilabos/ros/nodes/presets/host_node.py
Original file line number Diff line number Diff line change
Expand Up @@ -643,7 +643,8 @@ def _resource_get_callback(self, request, response):
self.lab_logger().debug(f"[Host Node-Resource] Retrieved from bridge: {len(r)} resources")
except Exception as e:
self.lab_logger().error(f"[Host Node-Resource] Error retrieving from bridge: {str(e)}")
r = []
r = [resource for resource in self.resources_config if resource.get("id") == request.id]
self.lab_logger().warning(f"[Host Node-Resource] Retrieved from local: {len(r)} resources")
else:
# 本地物料服务,根据 id 查询物料
r = [resource for resource in self.resources_config if resource.get("id") == request.id]
Expand Down
Loading