kuavo-humanoid-sdk-ws 1.1.6b858__tar.gz → 1.1.6b1125__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {kuavo_humanoid_sdk_ws-1.1.6b858 → kuavo_humanoid_sdk_ws-1.1.6b1125}/PKG-INFO +1 -1
- {kuavo_humanoid_sdk_ws-1.1.6b858 → kuavo_humanoid_sdk_ws-1.1.6b1125}/kuavo_humanoid_sdk/interfaces/data_types.py +22 -0
- {kuavo_humanoid_sdk_ws-1.1.6b858 → kuavo_humanoid_sdk_ws-1.1.6b1125}/kuavo_humanoid_sdk/kuavo/__init__.py +2 -2
- {kuavo_humanoid_sdk_ws-1.1.6b858 → kuavo_humanoid_sdk_ws-1.1.6b1125}/kuavo_humanoid_sdk/kuavo/core/audio.py +1 -1
- {kuavo_humanoid_sdk_ws-1.1.6b858 → kuavo_humanoid_sdk_ws-1.1.6b1125}/kuavo_humanoid_sdk/kuavo/core/ros/audio.py +3 -4
- {kuavo_humanoid_sdk_ws-1.1.6b858 → kuavo_humanoid_sdk_ws-1.1.6b1125}/kuavo_humanoid_sdk/kuavo/core/ros/state.py +6 -6
- kuavo_humanoid_sdk_ws-1.1.6b1125/kuavo_humanoid_sdk/kuavo/core/ros/tools.py +196 -0
- kuavo_humanoid_sdk_ws-1.1.6b1125/kuavo_humanoid_sdk/kuavo/core/ros/vision.py +280 -0
- {kuavo_humanoid_sdk_ws-1.1.6b858 → kuavo_humanoid_sdk_ws-1.1.6b1125}/kuavo_humanoid_sdk/kuavo/robot_audio.py +1 -1
- kuavo_humanoid_sdk_ws-1.1.6b1125/kuavo_humanoid_sdk/kuavo/robot_tool.py +58 -0
- kuavo_humanoid_sdk_ws-1.1.6b1125/kuavo_humanoid_sdk/kuavo/robot_vision.py +82 -0
- {kuavo_humanoid_sdk_ws-1.1.6b858 → kuavo_humanoid_sdk_ws-1.1.6b1125}/kuavo_humanoid_sdk_ws.egg-info/PKG-INFO +1 -1
- {kuavo_humanoid_sdk_ws-1.1.6b858 → kuavo_humanoid_sdk_ws-1.1.6b1125}/kuavo_humanoid_sdk_ws.egg-info/SOURCES.txt +4 -0
- {kuavo_humanoid_sdk_ws-1.1.6b858 → kuavo_humanoid_sdk_ws-1.1.6b1125}/setup.py +1 -1
- {kuavo_humanoid_sdk_ws-1.1.6b858 → kuavo_humanoid_sdk_ws-1.1.6b1125}/README.md +0 -0
- {kuavo_humanoid_sdk_ws-1.1.6b858 → kuavo_humanoid_sdk_ws-1.1.6b1125}/kuavo_humanoid_sdk/__init__.py +0 -0
- {kuavo_humanoid_sdk_ws-1.1.6b858 → kuavo_humanoid_sdk_ws-1.1.6b1125}/kuavo_humanoid_sdk/common/logger.py +0 -0
- {kuavo_humanoid_sdk_ws-1.1.6b858 → kuavo_humanoid_sdk_ws-1.1.6b1125}/kuavo_humanoid_sdk/common/websocket_kuavo_sdk.py +0 -0
- {kuavo_humanoid_sdk_ws-1.1.6b858 → kuavo_humanoid_sdk_ws-1.1.6b1125}/kuavo_humanoid_sdk/interfaces/__init__.py +0 -0
- {kuavo_humanoid_sdk_ws-1.1.6b858 → kuavo_humanoid_sdk_ws-1.1.6b1125}/kuavo_humanoid_sdk/interfaces/end_effector.py +0 -0
- {kuavo_humanoid_sdk_ws-1.1.6b858 → kuavo_humanoid_sdk_ws-1.1.6b1125}/kuavo_humanoid_sdk/interfaces/robot.py +0 -0
- {kuavo_humanoid_sdk_ws-1.1.6b858 → kuavo_humanoid_sdk_ws-1.1.6b1125}/kuavo_humanoid_sdk/interfaces/robot_info.py +0 -0
- {kuavo_humanoid_sdk_ws-1.1.6b858 → kuavo_humanoid_sdk_ws-1.1.6b1125}/kuavo_humanoid_sdk/kuavo/core/core.py +0 -0
- {kuavo_humanoid_sdk_ws-1.1.6b858 → kuavo_humanoid_sdk_ws-1.1.6b1125}/kuavo_humanoid_sdk/kuavo/core/dex_hand_control.py +0 -0
- {kuavo_humanoid_sdk_ws-1.1.6b858 → kuavo_humanoid_sdk_ws-1.1.6b1125}/kuavo_humanoid_sdk/kuavo/core/leju_claw_control.py +0 -0
- {kuavo_humanoid_sdk_ws-1.1.6b858 → kuavo_humanoid_sdk_ws-1.1.6b1125}/kuavo_humanoid_sdk/kuavo/core/ros/control.py +0 -0
- {kuavo_humanoid_sdk_ws-1.1.6b858 → kuavo_humanoid_sdk_ws-1.1.6b1125}/kuavo_humanoid_sdk/kuavo/core/ros/observation.py +0 -0
- {kuavo_humanoid_sdk_ws-1.1.6b858 → kuavo_humanoid_sdk_ws-1.1.6b1125}/kuavo_humanoid_sdk/kuavo/core/ros/param.py +0 -0
- {kuavo_humanoid_sdk_ws-1.1.6b858 → kuavo_humanoid_sdk_ws-1.1.6b1125}/kuavo_humanoid_sdk/kuavo/core/ros/sat_utils.py +0 -0
- {kuavo_humanoid_sdk_ws-1.1.6b858 → kuavo_humanoid_sdk_ws-1.1.6b1125}/kuavo_humanoid_sdk/kuavo/core/ros_env.py +0 -0
- {kuavo_humanoid_sdk_ws-1.1.6b858 → kuavo_humanoid_sdk_ws-1.1.6b1125}/kuavo_humanoid_sdk/kuavo/dexterous_hand.py +0 -0
- {kuavo_humanoid_sdk_ws-1.1.6b858 → kuavo_humanoid_sdk_ws-1.1.6b1125}/kuavo_humanoid_sdk/kuavo/leju_claw.py +0 -0
- {kuavo_humanoid_sdk_ws-1.1.6b858 → kuavo_humanoid_sdk_ws-1.1.6b1125}/kuavo_humanoid_sdk/kuavo/robot.py +0 -0
- {kuavo_humanoid_sdk_ws-1.1.6b858 → kuavo_humanoid_sdk_ws-1.1.6b1125}/kuavo_humanoid_sdk/kuavo/robot_arm.py +0 -0
- {kuavo_humanoid_sdk_ws-1.1.6b858 → kuavo_humanoid_sdk_ws-1.1.6b1125}/kuavo_humanoid_sdk/kuavo/robot_head.py +0 -0
- {kuavo_humanoid_sdk_ws-1.1.6b858 → kuavo_humanoid_sdk_ws-1.1.6b1125}/kuavo_humanoid_sdk/kuavo/robot_info.py +0 -0
- {kuavo_humanoid_sdk_ws-1.1.6b858 → kuavo_humanoid_sdk_ws-1.1.6b1125}/kuavo_humanoid_sdk/kuavo/robot_observation.py +0 -0
- {kuavo_humanoid_sdk_ws-1.1.6b858 → kuavo_humanoid_sdk_ws-1.1.6b1125}/kuavo_humanoid_sdk/kuavo/robot_state.py +0 -0
- {kuavo_humanoid_sdk_ws-1.1.6b858 → kuavo_humanoid_sdk_ws-1.1.6b1125}/kuavo_humanoid_sdk/kuavo_strategy/__init__.py +0 -0
- {kuavo_humanoid_sdk_ws-1.1.6b858 → kuavo_humanoid_sdk_ws-1.1.6b1125}/kuavo_humanoid_sdk/kuavo_strategy/grasp_box/grasp_box_strategy.py +0 -0
- {kuavo_humanoid_sdk_ws-1.1.6b858 → kuavo_humanoid_sdk_ws-1.1.6b1125}/kuavo_humanoid_sdk/kuavo_strategy/kuavo_strategy.py +0 -0
- {kuavo_humanoid_sdk_ws-1.1.6b858 → kuavo_humanoid_sdk_ws-1.1.6b1125}/kuavo_humanoid_sdk/msg/__init__.py +0 -0
- {kuavo_humanoid_sdk_ws-1.1.6b858 → kuavo_humanoid_sdk_ws-1.1.6b1125}/kuavo_humanoid_sdk_ws.egg-info/dependency_links.txt +0 -0
- {kuavo_humanoid_sdk_ws-1.1.6b858 → kuavo_humanoid_sdk_ws-1.1.6b1125}/kuavo_humanoid_sdk_ws.egg-info/requires.txt +0 -0
- {kuavo_humanoid_sdk_ws-1.1.6b858 → kuavo_humanoid_sdk_ws-1.1.6b1125}/kuavo_humanoid_sdk_ws.egg-info/top_level.txt +0 -0
- {kuavo_humanoid_sdk_ws-1.1.6b858 → kuavo_humanoid_sdk_ws-1.1.6b1125}/setup.cfg +0 -0
|
@@ -269,3 +269,25 @@ class KuavoTwist:
|
|
|
269
269
|
"""
|
|
270
270
|
linear: Tuple[float, float, float]
|
|
271
271
|
angular: Tuple[float, float, float]
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
@dataclass
|
|
276
|
+
class AprilTagDetection:
|
|
277
|
+
"""表示AprilTag检测结果的数据类"""
|
|
278
|
+
|
|
279
|
+
@dataclass
|
|
280
|
+
class Point:
|
|
281
|
+
x: float
|
|
282
|
+
y: float
|
|
283
|
+
z: float
|
|
284
|
+
|
|
285
|
+
@dataclass
|
|
286
|
+
class Quaternion:
|
|
287
|
+
x: float
|
|
288
|
+
y: float
|
|
289
|
+
z: float
|
|
290
|
+
w: float
|
|
291
|
+
|
|
292
|
+
position: Point
|
|
293
|
+
orientation: Quaternion
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
from .robot import KuavoSDK, KuavoRobot
|
|
2
2
|
from .robot_info import KuavoRobotInfo
|
|
3
3
|
from .robot_state import KuavoRobotState
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
from .robot_vision import KuavoRobotVision
|
|
5
|
+
from .robot_tool import KuavoRobotTools
|
|
6
6
|
from .robot_arm import KuavoRobotArm
|
|
7
7
|
from .robot_head import KuavoRobotHead
|
|
8
8
|
from .robot_audio import KuavoRobotAudio
|
|
@@ -12,7 +12,7 @@ class KuavoRobotAudioCore:
|
|
|
12
12
|
def __init__(self):
|
|
13
13
|
self.robot_audio = AudioWebsocket()
|
|
14
14
|
|
|
15
|
-
def play_audio(self, music_number: str, volume:
|
|
15
|
+
def play_audio(self, music_number: str, volume: int = 100, speed: float = 1.0) -> bool:
|
|
16
16
|
"""
|
|
17
17
|
play music
|
|
18
18
|
"""
|
|
@@ -16,7 +16,7 @@ class AudioWebsocket:
|
|
|
16
16
|
self._audio_stop_publisher = roslibpy.Topic(websocket.client, 'stop_music', 'std_msgs/Bool')
|
|
17
17
|
self._audio_stop_publisher.advertise()
|
|
18
18
|
|
|
19
|
-
def play_audio(self, file_name: str, volume:
|
|
19
|
+
def play_audio(self, file_name: str, volume: int = 100, speed: float = 1.0) -> bool:
|
|
20
20
|
"""Play the specified audio file through WebSocket.
|
|
21
21
|
|
|
22
22
|
Args:
|
|
@@ -31,11 +31,10 @@ class AudioWebsocket:
|
|
|
31
31
|
websocket = WebSocketKuavoSDK()
|
|
32
32
|
service = roslibpy.Service(websocket.client, 'play_music', 'kuavo_msgs/playmusic')
|
|
33
33
|
|
|
34
|
-
volume = min(max(volume, 0),
|
|
34
|
+
volume = min(max(volume, 0), 100)
|
|
35
35
|
request = {
|
|
36
36
|
"music_number": file_name,
|
|
37
|
-
"volume": volume
|
|
38
|
-
"speed": speed
|
|
37
|
+
"volume": volume
|
|
39
38
|
}
|
|
40
39
|
|
|
41
40
|
response = service.call(request)
|
|
@@ -133,14 +133,14 @@ class KuavoRobotStateCoreWebsocket:
|
|
|
133
133
|
angular = (0.0, 0.0, 0.0)
|
|
134
134
|
)
|
|
135
135
|
self._eef_state = (EndEffectorState(
|
|
136
|
-
position = [0.0] * 12 if kuavo_info['end_effector_type'].startswith('qiangnao') else [0.0] * 2,
|
|
137
|
-
velocity = [0.0] * 12 if kuavo_info['end_effector_type'].startswith('qiangnao') else [0.0] * 2,
|
|
138
|
-
effort = [0.0] * 12 if kuavo_info['end_effector_type'].startswith('qiangnao') else [0.0] * 2,
|
|
136
|
+
position = [0.0] * 12 if kuavo_info['end_effector_type'] is not None and kuavo_info['end_effector_type'].startswith('qiangnao') else [0.0] * 2,
|
|
137
|
+
velocity = [0.0] * 12 if kuavo_info['end_effector_type'] is not None and kuavo_info['end_effector_type'].startswith('qiangnao') else [0.0] * 2,
|
|
138
|
+
effort = [0.0] * 12 if kuavo_info['end_effector_type'] is not None and kuavo_info['end_effector_type'].startswith('qiangnao') else [0.0] * 2,
|
|
139
139
|
state=EndEffectorState.GraspingState.UNKNOWN
|
|
140
140
|
), EndEffectorState(
|
|
141
|
-
position = [0.0] * 12 if kuavo_info['end_effector_type'].startswith('qiangnao') else [0.0] * 2,
|
|
142
|
-
velocity = [0.0] * 12 if kuavo_info['end_effector_type'].startswith('qiangnao') else [0.0] * 2,
|
|
143
|
-
effort = [0.0] * 12 if kuavo_info['end_effector_type'].startswith('qiangnao') else [0.0] * 2,
|
|
141
|
+
position = [0.0] * 12 if kuavo_info['end_effector_type'] is not None and kuavo_info['end_effector_type'].startswith('qiangnao') else [0.0] * 2,
|
|
142
|
+
velocity = [0.0] * 12 if kuavo_info['end_effector_type'] is not None and kuavo_info['end_effector_type'].startswith('qiangnao') else [0.0] * 2,
|
|
143
|
+
effort = [0.0] * 12 if kuavo_info['end_effector_type'] is not None and kuavo_info['end_effector_type'].startswith('qiangnao') else [0.0] * 2,
|
|
144
144
|
state=EndEffectorState.GraspingState.UNKNOWN
|
|
145
145
|
))
|
|
146
146
|
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
#! /usr/bin/env python3
|
|
2
|
+
# coding: utf-8
|
|
3
|
+
|
|
4
|
+
import copy
|
|
5
|
+
import time
|
|
6
|
+
import numpy as np
|
|
7
|
+
from typing import Tuple, Union
|
|
8
|
+
from kuavo_humanoid_sdk.common.logger import SDKLogger
|
|
9
|
+
from transforms3d import euler, quaternions
|
|
10
|
+
import roslibpy
|
|
11
|
+
from kuavo_humanoid_sdk.common.websocket_kuavo_sdk import WebSocketKuavoSDK
|
|
12
|
+
from kuavo_humanoid_sdk.interfaces.data_types import (PoseQuaternion, HomogeneousMatrix)
|
|
13
|
+
from kuavo_humanoid_sdk.kuavo.core.ros.param import make_robot_param, EndEffectorType
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class KuavoRobotToolsCoreWebsocket:
|
|
17
|
+
"""Provides core ROS tools for Kuavo humanoid robot transformations.
|
|
18
|
+
|
|
19
|
+
Attributes:
|
|
20
|
+
tf_service (roslibpy.Service): Service proxy for tf2_web_republisher
|
|
21
|
+
_transform_cache (dict): Cache for storing recent transforms
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
def __init__(self):
|
|
25
|
+
"""Initializes TF2 web republisher service proxy."""
|
|
26
|
+
if not hasattr(self, '_initialized'):
|
|
27
|
+
try:
|
|
28
|
+
# Initialize WebSocket connection
|
|
29
|
+
self.websocket = WebSocketKuavoSDK()
|
|
30
|
+
|
|
31
|
+
# Initialize TF2 web republisher service
|
|
32
|
+
self.tf_service = roslibpy.Service(
|
|
33
|
+
self.websocket.client,
|
|
34
|
+
'/republish_tfs',
|
|
35
|
+
'kuavo_msgs/RepublishTFs'
|
|
36
|
+
)
|
|
37
|
+
self._transform_cache = {}
|
|
38
|
+
self._initialized = True
|
|
39
|
+
except Exception as e:
|
|
40
|
+
SDKLogger.error(f"Failed to initialize tf2_web_republisher: {str(e)}")
|
|
41
|
+
SDKLogger.error("Please make sure tf2_web_republisher node is running")
|
|
42
|
+
raise
|
|
43
|
+
|
|
44
|
+
def _get_tf_tree_transform(self, target_frame: str, source_frame: str,
|
|
45
|
+
time_=0.0, timeout=5.0,
|
|
46
|
+
return_type: str = "pose_quaternion") -> Union[PoseQuaternion, HomogeneousMatrix, None]:
|
|
47
|
+
"""Gets transform between coordinate frames using tf2_web_republisher.
|
|
48
|
+
|
|
49
|
+
Args:
|
|
50
|
+
target_frame (str): Target coordinate frame name
|
|
51
|
+
source_frame (str): Source coordinate frame name
|
|
52
|
+
time (float, optional): Time of transform. Defaults to 0.0.
|
|
53
|
+
timeout (float, optional): Wait timeout in seconds. Defaults to 5.0.
|
|
54
|
+
return_type (str, optional): Return data format. Options:
|
|
55
|
+
"pose_quaternion", "homogeneous". Defaults to "pose_quaternion".
|
|
56
|
+
|
|
57
|
+
Returns:
|
|
58
|
+
Union[PoseQuaternion, HomogeneousMatrix, None]: Requested transform data
|
|
59
|
+
or None if failed
|
|
60
|
+
"""
|
|
61
|
+
try:
|
|
62
|
+
|
|
63
|
+
# 调用服务
|
|
64
|
+
request = {
|
|
65
|
+
'source_frames': [source_frame],
|
|
66
|
+
'target_frame': target_frame,
|
|
67
|
+
'angular_thres': 0.01,
|
|
68
|
+
'trans_thres': 0.01,
|
|
69
|
+
'rate': 10.0,
|
|
70
|
+
'timeout': {'secs': int(timeout), 'nsecs': int((timeout % 1) * 1e9)}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
response = self.tf_service.call(request)
|
|
74
|
+
if response['status'] == -1:
|
|
75
|
+
SDKLogger.error(f"{source_frame} or {target_frame} not exist")
|
|
76
|
+
return None
|
|
77
|
+
|
|
78
|
+
# 检查话题是否发布
|
|
79
|
+
topic_list = self.websocket.client.get_topics()
|
|
80
|
+
if response['topic_name'] not in topic_list:
|
|
81
|
+
SDKLogger.error(f"Topic {response['topic_name']} not published")
|
|
82
|
+
return None
|
|
83
|
+
|
|
84
|
+
# 创建订阅者
|
|
85
|
+
transform_received = False
|
|
86
|
+
transform_data = None
|
|
87
|
+
|
|
88
|
+
def transform_callback(msg):
|
|
89
|
+
nonlocal transform_received, transform_data
|
|
90
|
+
transform_received = True
|
|
91
|
+
transform_data = msg
|
|
92
|
+
|
|
93
|
+
sub = roslibpy.Topic(self.websocket.client, response['topic_name'], 'kuavo_msgs/TFArray')
|
|
94
|
+
sub.subscribe(transform_callback)
|
|
95
|
+
|
|
96
|
+
# 等待接收数据
|
|
97
|
+
start_time = time.time()
|
|
98
|
+
while not transform_received and (time.time() - start_time) < timeout:
|
|
99
|
+
time.sleep(0.1)
|
|
100
|
+
|
|
101
|
+
# 取消订阅
|
|
102
|
+
sub.unsubscribe()
|
|
103
|
+
|
|
104
|
+
if not transform_received:
|
|
105
|
+
SDKLogger.error("No transform data received")
|
|
106
|
+
return None
|
|
107
|
+
|
|
108
|
+
# 从TFArray中获取对应的变换
|
|
109
|
+
for tf_msg in transform_data['transforms']:
|
|
110
|
+
if tf_msg['header']['frame_id'] == target_frame and tf_msg['child_frame_id'] == source_frame:
|
|
111
|
+
return self._parse_transform(tf_msg['transform'], return_type)
|
|
112
|
+
|
|
113
|
+
SDKLogger.error(f"No matching transform found in TFArray")
|
|
114
|
+
return None
|
|
115
|
+
|
|
116
|
+
except Exception as e:
|
|
117
|
+
SDKLogger.error(f"Transform error: {str(e)}")
|
|
118
|
+
return None
|
|
119
|
+
|
|
120
|
+
def _parse_transform(self, transform, return_type: str) -> Union[PoseQuaternion, HomogeneousMatrix, None]:
|
|
121
|
+
"""Parses transform data to specified format.
|
|
122
|
+
|
|
123
|
+
Args:
|
|
124
|
+
transform (dict): Input transform data
|
|
125
|
+
return_type (str): Output format type. Valid values:
|
|
126
|
+
"pose_quaternion", "homogeneous"
|
|
127
|
+
|
|
128
|
+
Returns:
|
|
129
|
+
Union[PoseQuaternion, HomogeneousMatrix, None]: Parsed transform data
|
|
130
|
+
in requested format, or None if invalid input
|
|
131
|
+
"""
|
|
132
|
+
if return_type == "pose_quaternion":
|
|
133
|
+
return PoseQuaternion(
|
|
134
|
+
position=(transform['translation']['x'],
|
|
135
|
+
transform['translation']['y'],
|
|
136
|
+
transform['translation']['z']),
|
|
137
|
+
orientation=(transform['rotation']['x'],
|
|
138
|
+
transform['rotation']['y'],
|
|
139
|
+
transform['rotation']['z'],
|
|
140
|
+
transform['rotation']['w'])
|
|
141
|
+
)
|
|
142
|
+
elif return_type == "homogeneous":
|
|
143
|
+
return HomogeneousMatrix(
|
|
144
|
+
matrix=self._transform_to_homogeneous(transform)
|
|
145
|
+
)
|
|
146
|
+
else:
|
|
147
|
+
SDKLogger.warn(f"Invalid return_type: {return_type}, using default(pose_quaternion)")
|
|
148
|
+
return self._parse_transform(transform, "pose_quaternion")
|
|
149
|
+
|
|
150
|
+
def _transform_to_homogeneous(self, transform) -> np.ndarray:
|
|
151
|
+
"""Converts transform dict to homogeneous matrix.
|
|
152
|
+
|
|
153
|
+
Args:
|
|
154
|
+
transform (dict): Input transform message
|
|
155
|
+
|
|
156
|
+
Returns:
|
|
157
|
+
np.ndarray: 4x4 homogeneous transformation matrix (numpy.float32)
|
|
158
|
+
"""
|
|
159
|
+
# 四元数转旋转矩阵
|
|
160
|
+
rotation = [
|
|
161
|
+
transform['rotation']['x'],
|
|
162
|
+
transform['rotation']['y'],
|
|
163
|
+
transform['rotation']['z'],
|
|
164
|
+
transform['rotation']['w']
|
|
165
|
+
]
|
|
166
|
+
|
|
167
|
+
# Convert quaternion to rotation matrix using transforms3d
|
|
168
|
+
rot_matrix = np.eye(4)
|
|
169
|
+
rot_matrix[:3,:3] = quaternions.quat2mat([rotation[3], rotation[0], rotation[1], rotation[2]])
|
|
170
|
+
|
|
171
|
+
# 设置平移分量
|
|
172
|
+
translation = [
|
|
173
|
+
transform['translation']['x'],
|
|
174
|
+
transform['translation']['y'],
|
|
175
|
+
transform['translation']['z']
|
|
176
|
+
]
|
|
177
|
+
rot_matrix[:3, 3] = translation
|
|
178
|
+
|
|
179
|
+
return rot_matrix.astype(np.float32) # 确保矩阵数据类型一致
|
|
180
|
+
|
|
181
|
+
# if __name__ == "__main__":
|
|
182
|
+
# robot_tools = KuavoRobotToolsCore()
|
|
183
|
+
# time.sleep(0.1)
|
|
184
|
+
# # 获取位姿信息
|
|
185
|
+
# pose = robot_tools._get_tf_tree_transform("odom", "base_link", return_type="pose_quaternion")
|
|
186
|
+
# print(f"Position: {pose.position}")
|
|
187
|
+
# print(f"Orientation: {pose.orientation}")
|
|
188
|
+
|
|
189
|
+
# # 获取齐次矩阵
|
|
190
|
+
# homogeneous = robot_tools._get_tf_tree_transform("odom", "base_link", return_type="homogeneous")
|
|
191
|
+
# print(f"Transformation matrix:\n{homogeneous.matrix}")
|
|
192
|
+
|
|
193
|
+
# # 矩阵运算示例
|
|
194
|
+
# transform_matrix = homogeneous.matrix
|
|
195
|
+
# inverse_matrix = np.linalg.inv(transform_matrix) # 求逆变换
|
|
196
|
+
# print(f"Inverse matrix:\n{inverse_matrix}")
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
#! /usr/bin/env python3
|
|
2
|
+
# coding: utf-8
|
|
3
|
+
|
|
4
|
+
import copy
|
|
5
|
+
import time
|
|
6
|
+
import numpy as np
|
|
7
|
+
from collections import deque
|
|
8
|
+
from typing import Tuple, Optional
|
|
9
|
+
from transforms3d import quaternions, euler
|
|
10
|
+
|
|
11
|
+
from kuavo_humanoid_sdk.kuavo.core.ros.param import make_robot_param, EndEffectorType
|
|
12
|
+
from kuavo_humanoid_sdk.common.logger import SDKLogger
|
|
13
|
+
from kuavo_humanoid_sdk.interfaces.data_types import (AprilTagData, AprilTagDetection)
|
|
14
|
+
import roslibpy
|
|
15
|
+
from kuavo_humanoid_sdk.common.websocket_kuavo_sdk import WebSocketKuavoSDK
|
|
16
|
+
|
|
17
|
+
class KuavoRobotVisionCoreWebsocket:
|
|
18
|
+
"""Handles vision-related data processing for Kuavo humanoid robot.
|
|
19
|
+
|
|
20
|
+
Attributes:
|
|
21
|
+
tf_client (roslibpy.Topic): TF client for coordinate transformations
|
|
22
|
+
tf_publisher (roslibpy.Topic): TF publisher for broadcasting transforms
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
def __init__(self):
|
|
26
|
+
"""Initializes vision system components including TF and AprilTag subscribers."""
|
|
27
|
+
if not hasattr(self, '_initialized'):
|
|
28
|
+
# Initialize WebSocket connection
|
|
29
|
+
self.websocket = WebSocketKuavoSDK()
|
|
30
|
+
|
|
31
|
+
# Initialize AprilTag subscribers
|
|
32
|
+
self._apriltag_data_camera_sub = roslibpy.Topic(
|
|
33
|
+
self.websocket.client,
|
|
34
|
+
'/tag_detections',
|
|
35
|
+
'apriltag_ros/AprilTagDetectionArray'
|
|
36
|
+
)
|
|
37
|
+
self._apriltag_data_camera_sub.subscribe(self._apriltag_data_callback_camera)
|
|
38
|
+
|
|
39
|
+
self._apriltag_data_base_sub = roslibpy.Topic(
|
|
40
|
+
self.websocket.client,
|
|
41
|
+
'/robot_tag_info',
|
|
42
|
+
'apriltag_ros/AprilTagDetectionArray'
|
|
43
|
+
)
|
|
44
|
+
self._apriltag_data_base_sub.subscribe(self._apriltag_data_callback_base)
|
|
45
|
+
|
|
46
|
+
self._apriltag_data_odom_sub = roslibpy.Topic(
|
|
47
|
+
self.websocket.client,
|
|
48
|
+
'/robot_tag_info_odom',
|
|
49
|
+
'apriltag_ros/AprilTagDetectionArray'
|
|
50
|
+
)
|
|
51
|
+
self._apriltag_data_odom_sub.subscribe(self._apriltag_data_callback_odom)
|
|
52
|
+
|
|
53
|
+
# Initialize data structures
|
|
54
|
+
self._apriltag_data_from_camera = AprilTagData(
|
|
55
|
+
id = [],
|
|
56
|
+
size = [],
|
|
57
|
+
pose = []
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
self._apriltag_data_from_base = AprilTagData(
|
|
61
|
+
id = [],
|
|
62
|
+
size = [],
|
|
63
|
+
pose = []
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
self._apriltag_data_from_odom = AprilTagData(
|
|
67
|
+
id = [],
|
|
68
|
+
size = [],
|
|
69
|
+
pose = []
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
self._initialized = True
|
|
73
|
+
|
|
74
|
+
def _tf_callback(self, msg):
|
|
75
|
+
"""Callback for TF messages.
|
|
76
|
+
|
|
77
|
+
Args:
|
|
78
|
+
msg: TF message containing transforms
|
|
79
|
+
"""
|
|
80
|
+
for transform in msg['transforms']:
|
|
81
|
+
key = (transform['header']['frame_id'], transform['child_frame_id'])
|
|
82
|
+
self._transforms[key] = transform
|
|
83
|
+
|
|
84
|
+
def _apriltag_data_callback_camera(self, data):
|
|
85
|
+
"""Callback for processing AprilTag detections from camera.
|
|
86
|
+
|
|
87
|
+
Args:
|
|
88
|
+
data (dict): Raw detection data from camera
|
|
89
|
+
"""
|
|
90
|
+
# 清空之前的数据
|
|
91
|
+
self._apriltag_data_from_camera.id = []
|
|
92
|
+
self._apriltag_data_from_camera.size = []
|
|
93
|
+
self._apriltag_data_from_camera.pose = []
|
|
94
|
+
|
|
95
|
+
# 处理每个标签检测
|
|
96
|
+
for detection in data['detections']:
|
|
97
|
+
# 添加ID
|
|
98
|
+
for id in detection['id']:
|
|
99
|
+
self._apriltag_data_from_camera.id.append(id)
|
|
100
|
+
|
|
101
|
+
# 添加尺寸
|
|
102
|
+
if detection.get('size') and len(detection['size']) > 0:
|
|
103
|
+
self._apriltag_data_from_camera.size.append(detection['size'][0])
|
|
104
|
+
else:
|
|
105
|
+
self._apriltag_data_from_camera.size.append(0.0)
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
# Convert pose dict to AprilTagDetection
|
|
109
|
+
pose_dict = detection['pose']['pose']['pose']
|
|
110
|
+
|
|
111
|
+
tag_detection = AprilTagDetection(
|
|
112
|
+
position=AprilTagDetection.Point(
|
|
113
|
+
x=float(pose_dict['position']['x']),
|
|
114
|
+
y=float(pose_dict['position']['y']),
|
|
115
|
+
z=float(pose_dict['position']['z'])
|
|
116
|
+
),
|
|
117
|
+
orientation=AprilTagDetection.Quaternion(
|
|
118
|
+
x=float(pose_dict['orientation']['x']),
|
|
119
|
+
y=float(pose_dict['orientation']['y']),
|
|
120
|
+
z=float(pose_dict['orientation']['z']),
|
|
121
|
+
w=float(pose_dict['orientation']['w'])
|
|
122
|
+
))
|
|
123
|
+
# 添加姿态
|
|
124
|
+
self._apriltag_data_from_camera.pose.append(tag_detection)
|
|
125
|
+
|
|
126
|
+
def _apriltag_data_callback_base(self, data):
|
|
127
|
+
"""Callback for processing AprilTag detections from base link.
|
|
128
|
+
|
|
129
|
+
Args:
|
|
130
|
+
data (dict): Raw detection data from base frame
|
|
131
|
+
"""
|
|
132
|
+
# 清空之前的数据
|
|
133
|
+
self._apriltag_data_from_base.id = []
|
|
134
|
+
self._apriltag_data_from_base.size = []
|
|
135
|
+
self._apriltag_data_from_base.pose = []
|
|
136
|
+
|
|
137
|
+
# 处理每个标签检测
|
|
138
|
+
for detection in data['detections']:
|
|
139
|
+
# 添加ID
|
|
140
|
+
for id in detection['id']:
|
|
141
|
+
self._apriltag_data_from_base.id.append(id)
|
|
142
|
+
|
|
143
|
+
# 添加尺寸
|
|
144
|
+
if detection.get('size') and len(detection['size']) > 0:
|
|
145
|
+
self._apriltag_data_from_base.size.append(detection['size'][0])
|
|
146
|
+
else:
|
|
147
|
+
self._apriltag_data_from_base.size.append(0.0)
|
|
148
|
+
|
|
149
|
+
# Convert pose dict to AprilTagDetection
|
|
150
|
+
pose_dict = detection['pose']['pose']['pose']
|
|
151
|
+
|
|
152
|
+
tag_detection = AprilTagDetection(
|
|
153
|
+
position=AprilTagDetection.Point(
|
|
154
|
+
x=float(pose_dict['position']['x']),
|
|
155
|
+
y=float(pose_dict['position']['y']),
|
|
156
|
+
z=float(pose_dict['position']['z'])
|
|
157
|
+
),
|
|
158
|
+
orientation=AprilTagDetection.Quaternion(
|
|
159
|
+
x=float(pose_dict['orientation']['x']),
|
|
160
|
+
y=float(pose_dict['orientation']['y']),
|
|
161
|
+
z=float(pose_dict['orientation']['z']),
|
|
162
|
+
w=float(pose_dict['orientation']['w'])
|
|
163
|
+
))
|
|
164
|
+
|
|
165
|
+
# 添加姿态
|
|
166
|
+
self._apriltag_data_from_base.pose.append(tag_detection)
|
|
167
|
+
|
|
168
|
+
def _apriltag_data_callback_odom(self, data):
|
|
169
|
+
"""Callback for processing AprilTag detections from odom frame.
|
|
170
|
+
|
|
171
|
+
Args:
|
|
172
|
+
data (dict): Raw detection data from odom frame
|
|
173
|
+
"""
|
|
174
|
+
# 清空之前的数据
|
|
175
|
+
self._apriltag_data_from_odom.id = []
|
|
176
|
+
self._apriltag_data_from_odom.size = []
|
|
177
|
+
self._apriltag_data_from_odom.pose = []
|
|
178
|
+
|
|
179
|
+
# 处理每个标签检测
|
|
180
|
+
for detection in data['detections']:
|
|
181
|
+
# 添加ID
|
|
182
|
+
for id in detection['id']:
|
|
183
|
+
self._apriltag_data_from_odom.id.append(id)
|
|
184
|
+
|
|
185
|
+
# 添加尺寸
|
|
186
|
+
if detection.get('size') and len(detection['size']) > 0:
|
|
187
|
+
self._apriltag_data_from_odom.size.append(detection['size'][0])
|
|
188
|
+
else:
|
|
189
|
+
self._apriltag_data_from_odom.size.append(0.0)
|
|
190
|
+
|
|
191
|
+
# Convert pose dict to AprilTagDetection
|
|
192
|
+
pose_dict = detection['pose']['pose']['pose']
|
|
193
|
+
|
|
194
|
+
tag_detection = AprilTagDetection(
|
|
195
|
+
position=AprilTagDetection.Point(
|
|
196
|
+
x=float(pose_dict['position']['x']),
|
|
197
|
+
y=float(pose_dict['position']['y']),
|
|
198
|
+
z=float(pose_dict['position']['z'])
|
|
199
|
+
),
|
|
200
|
+
orientation=AprilTagDetection.Quaternion(
|
|
201
|
+
x=float(pose_dict['orientation']['x']),
|
|
202
|
+
y=float(pose_dict['orientation']['y']),
|
|
203
|
+
z=float(pose_dict['orientation']['z']),
|
|
204
|
+
w=float(pose_dict['orientation']['w'])
|
|
205
|
+
))
|
|
206
|
+
|
|
207
|
+
# 添加姿态
|
|
208
|
+
self._apriltag_data_from_odom.pose.append(tag_detection)
|
|
209
|
+
|
|
210
|
+
@property
|
|
211
|
+
def apriltag_data_from_camera(self) -> AprilTagData:
|
|
212
|
+
"""AprilTag detection data in camera coordinate frame.
|
|
213
|
+
|
|
214
|
+
Returns:
|
|
215
|
+
AprilTagData: Contains lists of tag IDs, sizes and poses
|
|
216
|
+
"""
|
|
217
|
+
return self._apriltag_data_from_camera
|
|
218
|
+
|
|
219
|
+
@property
|
|
220
|
+
def apriltag_data_from_base(self) -> AprilTagData:
|
|
221
|
+
"""AprilTag detection data in base_link coordinate frame.
|
|
222
|
+
|
|
223
|
+
Returns:
|
|
224
|
+
AprilTagData: Contains lists of tag IDs, sizes and poses
|
|
225
|
+
"""
|
|
226
|
+
return self._apriltag_data_from_base
|
|
227
|
+
|
|
228
|
+
@property
|
|
229
|
+
def apriltag_data_from_odom(self) -> AprilTagData:
|
|
230
|
+
"""AprilTag detection data in odom coordinate frame.
|
|
231
|
+
|
|
232
|
+
Returns:
|
|
233
|
+
AprilTagData: Contains lists of tag IDs, sizes and transformed poses
|
|
234
|
+
"""
|
|
235
|
+
return self._apriltag_data_from_odom
|
|
236
|
+
|
|
237
|
+
def _get_data_by_id(self, target_id: int, data_source: str = "base") -> Optional[dict]:
|
|
238
|
+
"""Retrieves AprilTag data by specific ID from selected source.
|
|
239
|
+
|
|
240
|
+
Args:
|
|
241
|
+
target_id (int): AprilTag ID to search for
|
|
242
|
+
data_source (str): Data source selector, valid options:
|
|
243
|
+
"camera", "base", "odom"
|
|
244
|
+
|
|
245
|
+
Returns:
|
|
246
|
+
Optional[dict]: Dictionary containing 'sizes' and 'poses' lists if found,
|
|
247
|
+
None if no matching data
|
|
248
|
+
"""
|
|
249
|
+
data_map = {
|
|
250
|
+
"camera": self._apriltag_data_from_camera,
|
|
251
|
+
"base": self._apriltag_data_from_base,
|
|
252
|
+
"odom": self._apriltag_data_from_odom
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
if data_source not in data_map:
|
|
256
|
+
raise ValueError(f"Invalid data source: {data_source}")
|
|
257
|
+
|
|
258
|
+
data = data_map[data_source]
|
|
259
|
+
|
|
260
|
+
# 查找匹配的ID
|
|
261
|
+
try:
|
|
262
|
+
idx = data.id.index(target_id)
|
|
263
|
+
return {
|
|
264
|
+
'sizes': [data.size[idx]],
|
|
265
|
+
'poses': [data.pose[idx]]
|
|
266
|
+
}
|
|
267
|
+
except ValueError:
|
|
268
|
+
return None
|
|
269
|
+
|
|
270
|
+
# if __name__ == "__main__":
|
|
271
|
+
|
|
272
|
+
# kuavo_robot_vision_core = KuavoRobotVisionCoreWebsocket()
|
|
273
|
+
# time.sleep(5)
|
|
274
|
+
# print("apriltag_data_from_camera:")
|
|
275
|
+
# print(kuavo_robot_vision_core.apriltag_data_from_camera)
|
|
276
|
+
# print("apriltag_data_from_base:")
|
|
277
|
+
# print(kuavo_robot_vision_core.apriltag_data_from_base)
|
|
278
|
+
# print("apriltag_data_from_odom:")
|
|
279
|
+
# print(kuavo_robot_vision_core.apriltag_data_from_odom)
|
|
280
|
+
# rospy.spin()
|
|
@@ -12,7 +12,7 @@ class KuavoRobotAudio:
|
|
|
12
12
|
"""Initialize the audio system."""
|
|
13
13
|
self.audio = KuavoRobotAudioCore()
|
|
14
14
|
|
|
15
|
-
def play_audio(self, file_name: str, volume:
|
|
15
|
+
def play_audio(self, file_name: str, volume: int = 100, speed: float = 1.0) -> bool:
|
|
16
16
|
"""Play the specified audio file.
|
|
17
17
|
|
|
18
18
|
Args:
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# coding: utf-8
|
|
3
|
+
import math
|
|
4
|
+
from kuavo_humanoid_sdk.common.logger import SDKLogger
|
|
5
|
+
from kuavo_humanoid_sdk.interfaces.data_types import (PoseQuaternion, HomogeneousMatrix)
|
|
6
|
+
from kuavo_humanoid_sdk.kuavo.core.ros.tools import KuavoRobotToolsCoreWebsocket
|
|
7
|
+
from typing import Union
|
|
8
|
+
|
|
9
|
+
class KuavoRobotTools:
|
|
10
|
+
"""机器人工具类,提供坐标系转换接口。
|
|
11
|
+
|
|
12
|
+
该类封装了不同机器人坐标系之间的坐标变换查询功能,支持多种返回数据格式。
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
def __init__(self):
|
|
16
|
+
self.tools_core = KuavoRobotToolsCoreWebsocket()
|
|
17
|
+
|
|
18
|
+
def get_tf_transform(self, target_frame: str, source_frame: str,
|
|
19
|
+
return_type: str = "pose_quaternion") -> Union[PoseQuaternion, HomogeneousMatrix, None]:
|
|
20
|
+
"""获取指定坐标系之间的变换。
|
|
21
|
+
|
|
22
|
+
Args:
|
|
23
|
+
target_frame (str): 目标坐标系名称
|
|
24
|
+
source_frame (str): 源坐标系名称
|
|
25
|
+
return_type (str, optional): 返回数据格式类型。有效值: \n
|
|
26
|
+
- "pose_quaternion" : 四元数姿态格式, \n
|
|
27
|
+
- "homogeneous" : 齐次矩阵格式。默认为"pose_quaternion"。\n
|
|
28
|
+
|
|
29
|
+
Returns:
|
|
30
|
+
Union[PoseQuaternion, HomogeneousMatrix, None]:
|
|
31
|
+
指定格式的变换数据,如果失败则返回None
|
|
32
|
+
|
|
33
|
+
Raises:
|
|
34
|
+
ValueError: 如果提供了无效的 return_type
|
|
35
|
+
"""
|
|
36
|
+
return self.tools_core._get_tf_tree_transform(target_frame, source_frame, return_type=return_type)
|
|
37
|
+
|
|
38
|
+
def get_base_to_odom(self, return_type: str = "pose_quaternion") -> Union[PoseQuaternion, HomogeneousMatrix, None]:
|
|
39
|
+
"""获取从base_link到odom坐标系的变换。
|
|
40
|
+
|
|
41
|
+
Args:
|
|
42
|
+
return_type (str, optional): 返回格式类型。与get_tf_transform相同,默认为"pose_quaternion"。
|
|
43
|
+
|
|
44
|
+
Returns:
|
|
45
|
+
Union[PoseQuaternion, HomogeneousMatrix, None]: 变换数据或 None
|
|
46
|
+
"""
|
|
47
|
+
return self.get_tf_transform("odom", "base_link", return_type)
|
|
48
|
+
|
|
49
|
+
def get_camera_to_base(self, return_type: str = "homogeneous") -> Union[PoseQuaternion, HomogeneousMatrix, None]:
|
|
50
|
+
"""获取从camera_link到base_link坐标系的变换。
|
|
51
|
+
|
|
52
|
+
Args:
|
|
53
|
+
return_type (str, optional): 返回格式类型。与get_tf_transform相同,默认为"homogeneous"。
|
|
54
|
+
|
|
55
|
+
Returns:
|
|
56
|
+
Union[PoseQuaternion, HomogeneousMatrix, None]: 变换数据或None
|
|
57
|
+
"""
|
|
58
|
+
return self.get_tf_transform("base_link", "camera_link", return_type)
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# coding: utf-8
|
|
3
|
+
import math
|
|
4
|
+
from kuavo_humanoid_sdk.common.logger import SDKLogger
|
|
5
|
+
from kuavo_humanoid_sdk.interfaces.data_types import (AprilTagData)
|
|
6
|
+
from kuavo_humanoid_sdk.kuavo.core.ros.vision import KuavoRobotVisionCoreWebsocket
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class KuavoRobotVision:
|
|
10
|
+
"""Kuavo机器人视觉系统接口。
|
|
11
|
+
|
|
12
|
+
提供从不同坐标系获取AprilTag检测数据的接口。
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
def __init__(self, robot_type: str = "kuavo"):
|
|
16
|
+
"""初始化视觉系统。
|
|
17
|
+
|
|
18
|
+
Args:
|
|
19
|
+
robot_type (str, optional): 机器人类型标识符。默认为"kuavo"
|
|
20
|
+
"""
|
|
21
|
+
if not hasattr(self, '_initialized'):
|
|
22
|
+
self._vision_core = KuavoRobotVisionCoreWebsocket()
|
|
23
|
+
|
|
24
|
+
def get_data_by_id(self, target_id: int, data_source: str = "base") -> dict:
|
|
25
|
+
"""获取指定ID的AprilTag检测数据。
|
|
26
|
+
|
|
27
|
+
Args:
|
|
28
|
+
target_id (int): 要检索的AprilTag ID
|
|
29
|
+
data_source (str, optional): 数据源坐标系。可以是"base"、"camera"或"odom"。默认为"base"。
|
|
30
|
+
|
|
31
|
+
Returns:
|
|
32
|
+
dict: 包含位置、方向和元数据的检测数据
|
|
33
|
+
"""
|
|
34
|
+
return self._vision_core._get_data_by_id(target_id, data_source)
|
|
35
|
+
|
|
36
|
+
def get_data_by_id_from_camera(self, target_id: int) -> dict:
|
|
37
|
+
"""从相机坐标系获取AprilTag数据。
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
target_id (int): 要检索的AprilTag ID
|
|
41
|
+
|
|
42
|
+
Returns:
|
|
43
|
+
dict: 包含位置、方向和元数据的检测数据。参见 :meth:`get_data_by_id` 的返回格式说明。
|
|
44
|
+
"""
|
|
45
|
+
return self._vision_core._get_data_by_id(target_id, "camera")
|
|
46
|
+
|
|
47
|
+
def get_data_by_id_from_base(self, target_id: int) -> dict:
|
|
48
|
+
"""从基座坐标系获取AprilTag数据。
|
|
49
|
+
|
|
50
|
+
Args:
|
|
51
|
+
target_id (int): 要检索的AprilTag ID
|
|
52
|
+
|
|
53
|
+
Returns:
|
|
54
|
+
dict: 包含位置、方向和元数据的检测数据。参见 :meth:`get_data_by_id` 的返回格式说明。
|
|
55
|
+
"""
|
|
56
|
+
return self._vision_core._get_data_by_id(target_id, "base")
|
|
57
|
+
|
|
58
|
+
def get_data_by_id_from_odom(self, target_id: int) -> dict:
|
|
59
|
+
"""从里程计坐标系获取AprilTag数据。
|
|
60
|
+
|
|
61
|
+
Args:
|
|
62
|
+
target_id (int): 要检索的AprilTag ID
|
|
63
|
+
|
|
64
|
+
Returns:
|
|
65
|
+
dict: 包含位置、方向和元数据的检测数据。参见 :meth:`get_data_by_id` 的返回格式说明。
|
|
66
|
+
"""
|
|
67
|
+
return self._vision_core._get_data_by_id(target_id, "odom")
|
|
68
|
+
|
|
69
|
+
@property
|
|
70
|
+
def apriltag_data_from_camera(self) -> AprilTagData:
|
|
71
|
+
"""AprilTagData: 相机坐标系中检测到的所有AprilTag(属性)"""
|
|
72
|
+
return self._vision_core.apriltag_data_from_camera
|
|
73
|
+
|
|
74
|
+
@property
|
|
75
|
+
def apriltag_data_from_base(self) -> AprilTagData:
|
|
76
|
+
"""AprilTagData: 基座坐标系中检测到的所有AprilTag(属性)"""
|
|
77
|
+
return self._vision_core.apriltag_data_from_base
|
|
78
|
+
|
|
79
|
+
@property
|
|
80
|
+
def apriltag_data_from_odom(self) -> AprilTagData:
|
|
81
|
+
"""AprilTagData: 里程计坐标系中检测到的所有AprilTag(属性)"""
|
|
82
|
+
return self._vision_core.apriltag_data_from_odom
|
|
@@ -18,6 +18,8 @@ kuavo_humanoid_sdk/kuavo/robot_head.py
|
|
|
18
18
|
kuavo_humanoid_sdk/kuavo/robot_info.py
|
|
19
19
|
kuavo_humanoid_sdk/kuavo/robot_observation.py
|
|
20
20
|
kuavo_humanoid_sdk/kuavo/robot_state.py
|
|
21
|
+
kuavo_humanoid_sdk/kuavo/robot_tool.py
|
|
22
|
+
kuavo_humanoid_sdk/kuavo/robot_vision.py
|
|
21
23
|
kuavo_humanoid_sdk/kuavo/core/audio.py
|
|
22
24
|
kuavo_humanoid_sdk/kuavo/core/core.py
|
|
23
25
|
kuavo_humanoid_sdk/kuavo/core/dex_hand_control.py
|
|
@@ -29,6 +31,8 @@ kuavo_humanoid_sdk/kuavo/core/ros/observation.py
|
|
|
29
31
|
kuavo_humanoid_sdk/kuavo/core/ros/param.py
|
|
30
32
|
kuavo_humanoid_sdk/kuavo/core/ros/sat_utils.py
|
|
31
33
|
kuavo_humanoid_sdk/kuavo/core/ros/state.py
|
|
34
|
+
kuavo_humanoid_sdk/kuavo/core/ros/tools.py
|
|
35
|
+
kuavo_humanoid_sdk/kuavo/core/ros/vision.py
|
|
32
36
|
kuavo_humanoid_sdk/kuavo_strategy/__init__.py
|
|
33
37
|
kuavo_humanoid_sdk/kuavo_strategy/kuavo_strategy.py
|
|
34
38
|
kuavo_humanoid_sdk/kuavo_strategy/grasp_box/grasp_box_strategy.py
|
|
File without changes
|
{kuavo_humanoid_sdk_ws-1.1.6b858 → kuavo_humanoid_sdk_ws-1.1.6b1125}/kuavo_humanoid_sdk/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|