kuavo-humanoid-sdk 1.1.2a922__py3-none-any.whl → 1.1.3a1226__py3-none-any.whl
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.
Potentially problematic release.
This version of kuavo-humanoid-sdk might be problematic. Click here for more details.
- kuavo_humanoid_sdk/common/global_config.py +15 -0
- kuavo_humanoid_sdk/common/websocket_kuavo_sdk.py +23 -0
- kuavo_humanoid_sdk/interfaces/data_types.py +46 -0
- kuavo_humanoid_sdk/kuavo/__init__.py +3 -0
- kuavo_humanoid_sdk/kuavo/core/audio.py +33 -0
- kuavo_humanoid_sdk/kuavo/core/core.py +16 -6
- kuavo_humanoid_sdk/kuavo/core/ros/audio.py +87 -0
- kuavo_humanoid_sdk/kuavo/core/ros/control.py +645 -19
- kuavo_humanoid_sdk/kuavo/core/ros/param.py +142 -4
- kuavo_humanoid_sdk/kuavo/core/ros/state.py +329 -15
- kuavo_humanoid_sdk/kuavo/core/ros/tools.py +149 -0
- kuavo_humanoid_sdk/kuavo/core/ros/vision.py +272 -0
- kuavo_humanoid_sdk/kuavo/core/ros_env.py +229 -1
- kuavo_humanoid_sdk/kuavo/dexterous_hand.py +6 -2
- kuavo_humanoid_sdk/kuavo/leju_claw.py +6 -2
- kuavo_humanoid_sdk/kuavo/robot.py +43 -22
- kuavo_humanoid_sdk/kuavo/robot_audio.py +39 -0
- kuavo_humanoid_sdk/kuavo/robot_info.py +7 -2
- kuavo_humanoid_sdk/kuavo/robot_state.py +6 -2
- kuavo_humanoid_sdk/kuavo/robot_tool.py +62 -0
- kuavo_humanoid_sdk/kuavo/robot_vision.py +87 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_AprilTagDetection.py +306 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_AprilTagDetectionArray.py +437 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/msg/__init__.py +9 -0
- kuavo_humanoid_sdk/msg/{motion_capture_ik → kuavo_msgs}/msg/_armHandPose.py +2 -2
- kuavo_humanoid_sdk/msg/{motion_capture_ik → kuavo_msgs}/msg/_handPose.py +2 -2
- kuavo_humanoid_sdk/msg/{motion_capture_ik → kuavo_msgs}/msg/_ikSolveError.py +13 -13
- kuavo_humanoid_sdk/msg/{motion_capture_ik → kuavo_msgs}/msg/_ikSolveParam.py +2 -2
- kuavo_humanoid_sdk/msg/{motion_capture_ik → kuavo_msgs}/msg/_robotArmQVVD.py +2 -2
- kuavo_humanoid_sdk/msg/{motion_capture_ik → kuavo_msgs}/msg/_twoArmHandPose.py +13 -13
- kuavo_humanoid_sdk/msg/{motion_capture_ik → kuavo_msgs}/msg/_twoArmHandPoseCmd.py +15 -15
- kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_SpeechSynthesis.py +270 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/srv/__init__.py +5 -0
- kuavo_humanoid_sdk/msg/{motion_capture_ik → kuavo_msgs}/srv/_changeArmCtrlModeKuavo.py +5 -5
- kuavo_humanoid_sdk/msg/{motion_capture_ik → kuavo_msgs}/srv/_fkSrv.py +13 -13
- kuavo_humanoid_sdk/msg/{motion_capture_ik/srv/_changeArmCtrlMode.py → kuavo_msgs/srv/_playmusic.py} +97 -98
- kuavo_humanoid_sdk/msg/{motion_capture_ik → kuavo_msgs}/srv/_twoArmHandPoseCmdSrv.py +23 -23
- {kuavo_humanoid_sdk-1.1.2a922.dist-info → kuavo_humanoid_sdk-1.1.3a1226.dist-info}/METADATA +2 -1
- {kuavo_humanoid_sdk-1.1.2a922.dist-info → kuavo_humanoid_sdk-1.1.3a1226.dist-info}/RECORD +41 -33
- kuavo_humanoid_sdk/msg/motion_capture_ik/msg/__init__.py +0 -9
- kuavo_humanoid_sdk/msg/motion_capture_ik/msg/_headBodyPose.py +0 -145
- kuavo_humanoid_sdk/msg/motion_capture_ik/msg/_robotHandPosition.py +0 -225
- kuavo_humanoid_sdk/msg/motion_capture_ik/srv/__init__.py +0 -4
- {kuavo_humanoid_sdk-1.1.2a922.dist-info → kuavo_humanoid_sdk-1.1.3a1226.dist-info}/WHEEL +0 -0
- {kuavo_humanoid_sdk-1.1.2a922.dist-info → kuavo_humanoid_sdk-1.1.3a1226.dist-info}/top_level.txt +0 -0
|
@@ -5,13 +5,17 @@ from typing import Tuple
|
|
|
5
5
|
from kuavo_humanoid_sdk.interfaces.end_effector import EndEffector
|
|
6
6
|
from kuavo_humanoid_sdk.interfaces.data_types import EndEffectorSide, EndEffectorState
|
|
7
7
|
from kuavo_humanoid_sdk.kuavo.core.leju_claw_control import LejuClawControl
|
|
8
|
-
from kuavo_humanoid_sdk.kuavo.core.ros.state import KuavoRobotStateCore
|
|
8
|
+
from kuavo_humanoid_sdk.kuavo.core.ros.state import KuavoRobotStateCore, KuavoRobotStateCoreWebsocket
|
|
9
|
+
from kuavo_humanoid_sdk.common.global_config import GlobalConfig
|
|
9
10
|
|
|
10
11
|
class LejuClaw(EndEffector):
|
|
11
12
|
def __init__(self):
|
|
12
13
|
super().__init__(joint_names=['left_claw', 'right_claw'])
|
|
13
14
|
self.leju_claw_control = LejuClawControl()
|
|
14
|
-
|
|
15
|
+
if GlobalConfig.use_websocket:
|
|
16
|
+
self._rb_state = KuavoRobotStateCoreWebsocket()
|
|
17
|
+
else:
|
|
18
|
+
self._rb_state = KuavoRobotStateCore()
|
|
15
19
|
|
|
16
20
|
def control(self, target_positions: list, target_velocities:list=None, target_torques: list=None)->bool:
|
|
17
21
|
"""Control the claws to grip.
|
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
2
|
# coding: utf-8
|
|
3
|
-
from kuavo_humanoid_sdk.
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
from kuavo_humanoid_sdk.common.logger import SDKLogger, disable_sdk_logging
|
|
3
|
+
from kuavo_humanoid_sdk.common.global_config import GlobalConfig
|
|
4
|
+
|
|
5
|
+
from kuavo_humanoid_sdk.kuavo.core.ros_env import KuavoROSEnv, KuavoROSEnvWebsocket
|
|
6
|
+
from kuavo_humanoid_sdk.interfaces.robot import RobotBase
|
|
7
|
+
from kuavo_humanoid_sdk.common.logger import SDKLogger, disable_sdk_logging
|
|
8
|
+
from kuavo_humanoid_sdk.interfaces.data_types import KuavoPose, KuavoIKParams
|
|
9
|
+
from kuavo_humanoid_sdk.kuavo.core.core import KuavoRobotCore
|
|
10
|
+
|
|
11
|
+
from typing import Tuple
|
|
12
|
+
from kuavo_humanoid_sdk.kuavo.robot_info import KuavoRobotInfo
|
|
13
|
+
from kuavo_humanoid_sdk.kuavo.robot_arm import KuavoRobotArm
|
|
14
|
+
from kuavo_humanoid_sdk.kuavo.robot_head import KuavoRobotHead
|
|
16
15
|
|
|
17
16
|
"""
|
|
18
17
|
Kuavo SDK - Python Interface for Kuavo Robot Control
|
|
@@ -45,19 +44,30 @@ class KuavoSDK:
|
|
|
45
44
|
pass
|
|
46
45
|
|
|
47
46
|
@staticmethod
|
|
48
|
-
def Init(options:int=Options.Normal, log_level: str = "INFO"
|
|
47
|
+
def Init(options:int=Options.Normal, log_level: str = "INFO",
|
|
48
|
+
websocket_mode: bool = False, websocket_host='127.0.0.1', websocket_port=9090, websocket_timeout=5)-> bool:
|
|
49
49
|
"""Initialize the SDK.
|
|
50
|
-
|
|
51
50
|
Args:
|
|
52
51
|
log_level (str): The logging level to use. Can be "ERROR", "WARN", "INFO", "DEBUG".
|
|
53
52
|
Defaults to "INFO".
|
|
54
|
-
|
|
53
|
+
websocket_mode (bool): Whether to use websocket mode for ROS communication. If True,
|
|
54
|
+
the SDK will connect to ROS through websocket instead of direct ROS connection.
|
|
55
|
+
Defaults to False.
|
|
56
|
+
websocket_host (str): The host address of the rosbridge websocket server when using
|
|
57
|
+
websocket mode. Defaults to "127.0.0.1".
|
|
58
|
+
websocket_port (int): The port number of the rosbridge websocket server when using
|
|
59
|
+
websocket mode. Defaults to 9090.
|
|
60
|
+
websocket_timeout (int): The timeout for the websocket connection. Defaults to 5.
|
|
55
61
|
Returns:
|
|
56
62
|
bool: True if initialization is successful, False otherwise.
|
|
57
63
|
|
|
58
64
|
Raises:
|
|
59
65
|
RuntimeError: If the initialization fails.
|
|
60
66
|
"""
|
|
67
|
+
GlobalConfig.use_websocket = websocket_mode
|
|
68
|
+
GlobalConfig.websocket_host = websocket_host
|
|
69
|
+
GlobalConfig.websocket_port = websocket_port
|
|
70
|
+
GlobalConfig.websocket_timeout = websocket_timeout
|
|
61
71
|
SDKLogger.setLevel(log_level.upper())
|
|
62
72
|
# Initialize core components, connect ROS Topics...
|
|
63
73
|
kuavo_core = KuavoRobotCore()
|
|
@@ -65,12 +75,18 @@ class KuavoSDK:
|
|
|
65
75
|
debug = True
|
|
66
76
|
else:
|
|
67
77
|
debug = False
|
|
68
|
-
|
|
69
78
|
# Check if IK option is enabled
|
|
70
|
-
if
|
|
71
|
-
if
|
|
72
|
-
|
|
73
|
-
|
|
79
|
+
if GlobalConfig.use_websocket:
|
|
80
|
+
if options & KuavoSDK.Options.WithIK:
|
|
81
|
+
if not KuavoROSEnvWebsocket.check_rosnode_exists('/arms_ik_node'):
|
|
82
|
+
print("\033[31m\nError:WithIK option is enabled but ik_node is not running, please run `roslaunch motion_capture_ik ik_node.launch`\033[0m")
|
|
83
|
+
exit(1)
|
|
84
|
+
else:
|
|
85
|
+
if options & KuavoSDK.Options.WithIK:
|
|
86
|
+
if not KuavoROSEnv.check_rosnode_exists('/arms_ik_node'):
|
|
87
|
+
print("\033[31m\nError:WithIK option is enabled but ik_node is not running, please run `roslaunch motion_capture_ik ik_node.launch`\033[0m")
|
|
88
|
+
exit(1)
|
|
89
|
+
|
|
74
90
|
|
|
75
91
|
if not kuavo_core.initialize(debug=debug):
|
|
76
92
|
SDKLogger.error("[SDK] Failed to initialize core components.")
|
|
@@ -86,11 +102,16 @@ class KuavoSDK:
|
|
|
86
102
|
class KuavoRobot(RobotBase):
|
|
87
103
|
def __init__(self):
|
|
88
104
|
super().__init__(robot_type="kuavo")
|
|
105
|
+
|
|
106
|
+
if not GlobalConfig.use_websocket:
|
|
107
|
+
kuavo_ros_env = KuavoROSEnv()
|
|
108
|
+
if not kuavo_ros_env.Init():
|
|
109
|
+
raise RuntimeError("Failed to initialize ROS environment")
|
|
110
|
+
|
|
89
111
|
self._robot_info = KuavoRobotInfo()
|
|
90
112
|
self._robot_arm = KuavoRobotArm()
|
|
91
113
|
self._robot_head = KuavoRobotHead()
|
|
92
114
|
self._kuavo_core = KuavoRobotCore()
|
|
93
|
-
|
|
94
115
|
def stance(self)->bool:
|
|
95
116
|
"""Put the robot into 'stance' mode.
|
|
96
117
|
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# coding: utf-8
|
|
3
|
+
from kuavo_humanoid_sdk.kuavo.core.audio import KuavoRobotAudioCore
|
|
4
|
+
|
|
5
|
+
class KuavoRobotAudio:
|
|
6
|
+
"""Audio system interface for controlling audio playback functionality of Kuavo humanoid robot.
|
|
7
|
+
|
|
8
|
+
Provides functionality to play music files.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
def __init__(self):
|
|
12
|
+
"""Initialize the audio system."""
|
|
13
|
+
self.audio = KuavoRobotAudioCore()
|
|
14
|
+
|
|
15
|
+
def play_audio(self, file_name: str, volume: float = 0.5, speed: float = 1.0) -> bool:
|
|
16
|
+
"""Play the specified audio file.
|
|
17
|
+
|
|
18
|
+
Args:
|
|
19
|
+
file_name (str): Name of the audio file to play
|
|
20
|
+
|
|
21
|
+
Returns:
|
|
22
|
+
bool: True if the play request was successfully sent, False otherwise
|
|
23
|
+
"""
|
|
24
|
+
return self.audio.play_audio(file_name, volume, speed)
|
|
25
|
+
|
|
26
|
+
def stop_music(self):
|
|
27
|
+
"""Stop the currently playing audio."""
|
|
28
|
+
return self.audio.stop_music()
|
|
29
|
+
|
|
30
|
+
def text_to_speech(self, text: str, volume: float = 0.5) -> bool:
|
|
31
|
+
"""Synthesize and play the specified text.
|
|
32
|
+
|
|
33
|
+
Args:
|
|
34
|
+
text (str): Text to be played
|
|
35
|
+
|
|
36
|
+
Returns:
|
|
37
|
+
bool: True if the play request was successfully sent, False otherwise
|
|
38
|
+
"""
|
|
39
|
+
return self.audio.text_to_speech(text, volume)
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
# coding: utf-8
|
|
3
3
|
from typing import Tuple
|
|
4
4
|
from kuavo_humanoid_sdk.interfaces.robot_info import RobotInfoBase
|
|
5
|
-
from kuavo_humanoid_sdk.kuavo.core.ros.param import RosParameter, make_robot_param
|
|
5
|
+
from kuavo_humanoid_sdk.kuavo.core.ros.param import RosParameter, RosParamWebsocket, make_robot_param
|
|
6
|
+
from kuavo_humanoid_sdk.common.global_config import GlobalConfig
|
|
6
7
|
|
|
7
8
|
class KuavoRobotInfo(RobotInfoBase):
|
|
8
9
|
def __init__(self, robot_type: str = "kuavo"):
|
|
@@ -10,7 +11,11 @@ class KuavoRobotInfo(RobotInfoBase):
|
|
|
10
11
|
|
|
11
12
|
# Load robot parameters from ROS parameter server
|
|
12
13
|
kuavo_ros_param = make_robot_param()
|
|
13
|
-
|
|
14
|
+
if GlobalConfig.use_websocket:
|
|
15
|
+
self._ros_param = RosParamWebsocket()
|
|
16
|
+
else:
|
|
17
|
+
self._ros_param = RosParameter()
|
|
18
|
+
|
|
14
19
|
self._robot_version = kuavo_ros_param['robot_version']
|
|
15
20
|
self._end_effector_type = kuavo_ros_param['end_effector_type']
|
|
16
21
|
self._arm_joint_dof = kuavo_ros_param['arm_dof']
|
|
@@ -4,11 +4,15 @@ import time
|
|
|
4
4
|
from typing import Tuple
|
|
5
5
|
from kuavo_humanoid_sdk.interfaces.data_types import (
|
|
6
6
|
KuavoImuData, KuavoJointData, KuavoOdometry, KuavoArmCtrlMode,EndEffectorState)
|
|
7
|
-
from kuavo_humanoid_sdk.kuavo.core.ros.state import KuavoRobotStateCore
|
|
7
|
+
from kuavo_humanoid_sdk.kuavo.core.ros.state import KuavoRobotStateCore, KuavoRobotStateCoreWebsocket
|
|
8
|
+
from kuavo_humanoid_sdk.common.global_config import GlobalConfig
|
|
8
9
|
|
|
9
10
|
class KuavoRobotState:
|
|
10
11
|
def __init__(self, robot_type: str = "kuavo"):
|
|
11
|
-
|
|
12
|
+
if GlobalConfig.use_websocket:
|
|
13
|
+
self._rs_core = KuavoRobotStateCoreWebsocket()
|
|
14
|
+
else:
|
|
15
|
+
self._rs_core = KuavoRobotStateCore()
|
|
12
16
|
|
|
13
17
|
@property
|
|
14
18
|
def imu_data(self) -> KuavoImuData:
|
|
@@ -0,0 +1,62 @@
|
|
|
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 KuavoRobotToolsCore
|
|
7
|
+
from typing import Union
|
|
8
|
+
|
|
9
|
+
class KuavoRobotTools:
|
|
10
|
+
"""Robot tools class providing coordinate frame transformation interfaces.
|
|
11
|
+
|
|
12
|
+
This class encapsulates coordinate transformation queries between different robot frames,
|
|
13
|
+
supporting multiple return data formats.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
def __init__(self):
|
|
17
|
+
"""Initialize robot tools instance."""
|
|
18
|
+
self.tools_core = KuavoRobotToolsCore()
|
|
19
|
+
|
|
20
|
+
def get_tf_transform(self, target_frame: str, source_frame: str,
|
|
21
|
+
return_type: str = "pose_quaternion") -> Union[PoseQuaternion, HomogeneousMatrix, None]:
|
|
22
|
+
"""Get transformation between specified coordinate frames.
|
|
23
|
+
|
|
24
|
+
Args:
|
|
25
|
+
target_frame (str): Name of target coordinate frame
|
|
26
|
+
source_frame (str): Name of source coordinate frame
|
|
27
|
+
return_type (str, optional): Return data format type. Valid values:
|
|
28
|
+
"pose_quaternion" - quaternion pose format,
|
|
29
|
+
"homogeneous" - homogeneous matrix format. Defaults to "pose_quaternion".
|
|
30
|
+
|
|
31
|
+
Returns:
|
|
32
|
+
Union[PoseQuaternion, HomogeneousMatrix, None]:
|
|
33
|
+
Transformation data in specified format, or None if failed
|
|
34
|
+
|
|
35
|
+
Raises:
|
|
36
|
+
ValueError: If invalid return_type is provided
|
|
37
|
+
"""
|
|
38
|
+
return self.tools_core._get_tf_tree_transform(target_frame, source_frame, return_type=return_type)
|
|
39
|
+
|
|
40
|
+
def get_base_to_odom(self, return_type: str = "pose_quaternion") -> Union[PoseQuaternion, HomogeneousMatrix, None]:
|
|
41
|
+
"""Get transformation from base_link to odom frame.
|
|
42
|
+
|
|
43
|
+
Args:
|
|
44
|
+
return_type (str, optional): Return format type. Same as get_tf_transform.
|
|
45
|
+
Defaults to "pose_quaternion".
|
|
46
|
+
|
|
47
|
+
Returns:
|
|
48
|
+
Union[PoseQuaternion, HomogeneousMatrix, None]: Transformation data or None
|
|
49
|
+
"""
|
|
50
|
+
return self.get_tf_transform("odom", "base_link", return_type)
|
|
51
|
+
|
|
52
|
+
def get_camera_to_base(self, return_type: str = "homogeneous") -> Union[PoseQuaternion, HomogeneousMatrix, None]:
|
|
53
|
+
"""Get transformation from camera_link to base_link frame.
|
|
54
|
+
|
|
55
|
+
Args:
|
|
56
|
+
return_type (str, optional): Return format type. Same as get_tf_transform.
|
|
57
|
+
Defaults to "homogeneous".
|
|
58
|
+
|
|
59
|
+
Returns:
|
|
60
|
+
Union[PoseQuaternion, HomogeneousMatrix, None]: Transformation data or None
|
|
61
|
+
"""
|
|
62
|
+
return self.get_tf_transform("base_link", "camera_link", return_type)
|
|
@@ -0,0 +1,87 @@
|
|
|
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 KuavoRobotVisionCore
|
|
7
|
+
|
|
8
|
+
from apriltag_ros.msg import AprilTagDetectionArray
|
|
9
|
+
|
|
10
|
+
class KuavoRobotVision:
|
|
11
|
+
"""Vision system interface for Kuavo humanoid robot.
|
|
12
|
+
|
|
13
|
+
Provides access to AprilTag detection data from different coordinate frames.
|
|
14
|
+
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
def __init__(self, robot_type: str = "kuavo"):
|
|
18
|
+
"""Initialize the vision system.
|
|
19
|
+
|
|
20
|
+
Args:
|
|
21
|
+
robot_type (str, optional): Robot type identifier. Defaults to "kuavo".
|
|
22
|
+
"""
|
|
23
|
+
if not hasattr(self, '_initialized'):
|
|
24
|
+
self._vision_core = KuavoRobotVisionCore()
|
|
25
|
+
|
|
26
|
+
def get_data_by_id(self, target_id: int, data_source: str = "base") -> dict:
|
|
27
|
+
"""Get AprilTag detection data for a specific ID from specified source.
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
target_id (int): AprilTag ID to retrieve
|
|
31
|
+
data_source (str, optional): Data source frame. Can be "base", "camera",
|
|
32
|
+
or "odom". Defaults to "base".
|
|
33
|
+
|
|
34
|
+
Returns:
|
|
35
|
+
dict: Detection data containing position, orientation and metadata
|
|
36
|
+
"""
|
|
37
|
+
return self._vision_core._get_data_by_id(target_id, data_source)
|
|
38
|
+
|
|
39
|
+
def get_data_by_id_from_camera(self, target_id: int) -> dict:
|
|
40
|
+
"""Get AprilTag data from camera coordinate frame.
|
|
41
|
+
|
|
42
|
+
Args:
|
|
43
|
+
target_id (int): AprilTag ID to retrieve
|
|
44
|
+
|
|
45
|
+
Returns:
|
|
46
|
+
dict: See get_data_by_id() for return format
|
|
47
|
+
"""
|
|
48
|
+
return self._vision_core._get_data_by_id(target_id, "camera")
|
|
49
|
+
|
|
50
|
+
def get_data_by_id_from_base(self, target_id: int) -> dict:
|
|
51
|
+
"""Get AprilTag data from base coordinate frame.
|
|
52
|
+
|
|
53
|
+
Args:
|
|
54
|
+
target_id (int): AprilTag ID to retrieve
|
|
55
|
+
|
|
56
|
+
Returns:
|
|
57
|
+
dict: See get_data_by_id() for return format
|
|
58
|
+
"""
|
|
59
|
+
return self._vision_core._get_data_by_id(target_id, "base")
|
|
60
|
+
|
|
61
|
+
def get_data_by_id_from_odom(self, target_id: int) -> dict:
|
|
62
|
+
"""Get AprilTag data from odom coordinate frame.
|
|
63
|
+
|
|
64
|
+
Args:
|
|
65
|
+
target_id (int): AprilTag ID to retrieve
|
|
66
|
+
|
|
67
|
+
Returns:
|
|
68
|
+
dict: See get_data_by_id() for return format
|
|
69
|
+
"""
|
|
70
|
+
return self._vision_core._get_data_by_id(target_id, "odom")
|
|
71
|
+
|
|
72
|
+
@property
|
|
73
|
+
def apriltag_data_from_camera(self) -> AprilTagData:
|
|
74
|
+
"""AprilTagData: All detected AprilTags in camera frame (property)"""
|
|
75
|
+
return self._vision_core.apriltag_data_from_camera
|
|
76
|
+
|
|
77
|
+
@property
|
|
78
|
+
def apriltag_data_from_base(self) -> AprilTagData:
|
|
79
|
+
"""AprilTagData: All detected AprilTags in camera frame (property)"""
|
|
80
|
+
return self._vision_core.apriltag_data_from_base
|
|
81
|
+
|
|
82
|
+
@property
|
|
83
|
+
def apriltag_data_from_odom(self) -> AprilTagData:
|
|
84
|
+
"""AprilTagData: All detected AprilTags in camera frame (property)"""
|
|
85
|
+
return self._vision_core.apriltag_data_from_odom
|
|
86
|
+
|
|
87
|
+
|
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
# This Python file uses the following encoding: utf-8
|
|
2
|
+
"""autogenerated by genpy from kuavo_msgs/AprilTagDetection.msg. Do not edit."""
|
|
3
|
+
import codecs
|
|
4
|
+
import sys
|
|
5
|
+
python3 = True if sys.hexversion > 0x03000000 else False
|
|
6
|
+
import genpy
|
|
7
|
+
import struct
|
|
8
|
+
|
|
9
|
+
import geometry_msgs.msg
|
|
10
|
+
import std_msgs.msg
|
|
11
|
+
|
|
12
|
+
class AprilTagDetection(genpy.Message):
|
|
13
|
+
_md5sum = "090173a6e2b6c8fd96ce000fe9378b4e"
|
|
14
|
+
_type = "kuavo_msgs/AprilTagDetection"
|
|
15
|
+
_has_header = False # flag to mark the presence of a Header object
|
|
16
|
+
_full_text = """# Tag ID(s). If a standalone tag, this is a vector of size 1. If a tag bundle,
|
|
17
|
+
# this is a vector containing the IDs of each tag in the bundle.
|
|
18
|
+
int32[] id
|
|
19
|
+
|
|
20
|
+
# Tag size(s). If a standalone tag, this is a vector of size 1. If a tag bundle,
|
|
21
|
+
# this is a vector containing the sizes of each tag in the bundle, in the same
|
|
22
|
+
# order as the IDs above.
|
|
23
|
+
float64[] size
|
|
24
|
+
|
|
25
|
+
# Pose in the camera frame, obtained from homography transform. If a standalone
|
|
26
|
+
# tag, the homography is from the four tag corners. If a tag bundle, the
|
|
27
|
+
# homography is from at least the four corners of one member tag and at most the
|
|
28
|
+
# four corners of all member tags.
|
|
29
|
+
geometry_msgs/PoseWithCovarianceStamped pose
|
|
30
|
+
================================================================================
|
|
31
|
+
MSG: geometry_msgs/PoseWithCovarianceStamped
|
|
32
|
+
# This expresses an estimated pose with a reference coordinate frame and timestamp
|
|
33
|
+
|
|
34
|
+
Header header
|
|
35
|
+
PoseWithCovariance pose
|
|
36
|
+
|
|
37
|
+
================================================================================
|
|
38
|
+
MSG: std_msgs/Header
|
|
39
|
+
# Standard metadata for higher-level stamped data types.
|
|
40
|
+
# This is generally used to communicate timestamped data
|
|
41
|
+
# in a particular coordinate frame.
|
|
42
|
+
#
|
|
43
|
+
# sequence ID: consecutively increasing ID
|
|
44
|
+
uint32 seq
|
|
45
|
+
#Two-integer timestamp that is expressed as:
|
|
46
|
+
# * stamp.sec: seconds (stamp_secs) since epoch (in Python the variable is called 'secs')
|
|
47
|
+
# * stamp.nsec: nanoseconds since stamp_secs (in Python the variable is called 'nsecs')
|
|
48
|
+
# time-handling sugar is provided by the client library
|
|
49
|
+
time stamp
|
|
50
|
+
#Frame this data is associated with
|
|
51
|
+
string frame_id
|
|
52
|
+
|
|
53
|
+
================================================================================
|
|
54
|
+
MSG: geometry_msgs/PoseWithCovariance
|
|
55
|
+
# This represents a pose in free space with uncertainty.
|
|
56
|
+
|
|
57
|
+
Pose pose
|
|
58
|
+
|
|
59
|
+
# Row-major representation of the 6x6 covariance matrix
|
|
60
|
+
# The orientation parameters use a fixed-axis representation.
|
|
61
|
+
# In order, the parameters are:
|
|
62
|
+
# (x, y, z, rotation about X axis, rotation about Y axis, rotation about Z axis)
|
|
63
|
+
float64[36] covariance
|
|
64
|
+
|
|
65
|
+
================================================================================
|
|
66
|
+
MSG: geometry_msgs/Pose
|
|
67
|
+
# A representation of pose in free space, composed of position and orientation.
|
|
68
|
+
Point position
|
|
69
|
+
Quaternion orientation
|
|
70
|
+
|
|
71
|
+
================================================================================
|
|
72
|
+
MSG: geometry_msgs/Point
|
|
73
|
+
# This contains the position of a point in free space
|
|
74
|
+
float64 x
|
|
75
|
+
float64 y
|
|
76
|
+
float64 z
|
|
77
|
+
|
|
78
|
+
================================================================================
|
|
79
|
+
MSG: geometry_msgs/Quaternion
|
|
80
|
+
# This represents an orientation in free space in quaternion form.
|
|
81
|
+
|
|
82
|
+
float64 x
|
|
83
|
+
float64 y
|
|
84
|
+
float64 z
|
|
85
|
+
float64 w
|
|
86
|
+
"""
|
|
87
|
+
__slots__ = ['id','size','pose']
|
|
88
|
+
_slot_types = ['int32[]','float64[]','geometry_msgs/PoseWithCovarianceStamped']
|
|
89
|
+
|
|
90
|
+
def __init__(self, *args, **kwds):
|
|
91
|
+
"""
|
|
92
|
+
Constructor. Any message fields that are implicitly/explicitly
|
|
93
|
+
set to None will be assigned a default value. The recommend
|
|
94
|
+
use is keyword arguments as this is more robust to future message
|
|
95
|
+
changes. You cannot mix in-order arguments and keyword arguments.
|
|
96
|
+
|
|
97
|
+
The available fields are:
|
|
98
|
+
id,size,pose
|
|
99
|
+
|
|
100
|
+
:param args: complete set of field values, in .msg order
|
|
101
|
+
:param kwds: use keyword arguments corresponding to message field names
|
|
102
|
+
to set specific fields.
|
|
103
|
+
"""
|
|
104
|
+
if args or kwds:
|
|
105
|
+
super(AprilTagDetection, self).__init__(*args, **kwds)
|
|
106
|
+
# message fields cannot be None, assign default values for those that are
|
|
107
|
+
if self.id is None:
|
|
108
|
+
self.id = []
|
|
109
|
+
if self.size is None:
|
|
110
|
+
self.size = []
|
|
111
|
+
if self.pose is None:
|
|
112
|
+
self.pose = geometry_msgs.msg.PoseWithCovarianceStamped()
|
|
113
|
+
else:
|
|
114
|
+
self.id = []
|
|
115
|
+
self.size = []
|
|
116
|
+
self.pose = geometry_msgs.msg.PoseWithCovarianceStamped()
|
|
117
|
+
|
|
118
|
+
def _get_types(self):
|
|
119
|
+
"""
|
|
120
|
+
internal API method
|
|
121
|
+
"""
|
|
122
|
+
return self._slot_types
|
|
123
|
+
|
|
124
|
+
def serialize(self, buff):
|
|
125
|
+
"""
|
|
126
|
+
serialize message into buffer
|
|
127
|
+
:param buff: buffer, ``StringIO``
|
|
128
|
+
"""
|
|
129
|
+
try:
|
|
130
|
+
length = len(self.id)
|
|
131
|
+
buff.write(_struct_I.pack(length))
|
|
132
|
+
pattern = '<%si'%length
|
|
133
|
+
buff.write(struct.Struct(pattern).pack(*self.id))
|
|
134
|
+
length = len(self.size)
|
|
135
|
+
buff.write(_struct_I.pack(length))
|
|
136
|
+
pattern = '<%sd'%length
|
|
137
|
+
buff.write(struct.Struct(pattern).pack(*self.size))
|
|
138
|
+
_x = self
|
|
139
|
+
buff.write(_get_struct_3I().pack(_x.pose.header.seq, _x.pose.header.stamp.secs, _x.pose.header.stamp.nsecs))
|
|
140
|
+
_x = self.pose.header.frame_id
|
|
141
|
+
length = len(_x)
|
|
142
|
+
if python3 or type(_x) == unicode:
|
|
143
|
+
_x = _x.encode('utf-8')
|
|
144
|
+
length = len(_x)
|
|
145
|
+
buff.write(struct.Struct('<I%ss'%length).pack(length, _x))
|
|
146
|
+
_x = self
|
|
147
|
+
buff.write(_get_struct_7d().pack(_x.pose.pose.pose.position.x, _x.pose.pose.pose.position.y, _x.pose.pose.pose.position.z, _x.pose.pose.pose.orientation.x, _x.pose.pose.pose.orientation.y, _x.pose.pose.pose.orientation.z, _x.pose.pose.pose.orientation.w))
|
|
148
|
+
buff.write(_get_struct_36d().pack(*self.pose.pose.covariance))
|
|
149
|
+
except struct.error as se: self._check_types(struct.error("%s: '%s' when writing '%s'" % (type(se), str(se), str(locals().get('_x', self)))))
|
|
150
|
+
except TypeError as te: self._check_types(ValueError("%s: '%s' when writing '%s'" % (type(te), str(te), str(locals().get('_x', self)))))
|
|
151
|
+
|
|
152
|
+
def deserialize(self, str):
|
|
153
|
+
"""
|
|
154
|
+
unpack serialized message in str into this message instance
|
|
155
|
+
:param str: byte array of serialized message, ``str``
|
|
156
|
+
"""
|
|
157
|
+
if python3:
|
|
158
|
+
codecs.lookup_error("rosmsg").msg_type = self._type
|
|
159
|
+
try:
|
|
160
|
+
if self.pose is None:
|
|
161
|
+
self.pose = geometry_msgs.msg.PoseWithCovarianceStamped()
|
|
162
|
+
end = 0
|
|
163
|
+
start = end
|
|
164
|
+
end += 4
|
|
165
|
+
(length,) = _struct_I.unpack(str[start:end])
|
|
166
|
+
pattern = '<%si'%length
|
|
167
|
+
start = end
|
|
168
|
+
s = struct.Struct(pattern)
|
|
169
|
+
end += s.size
|
|
170
|
+
self.id = s.unpack(str[start:end])
|
|
171
|
+
start = end
|
|
172
|
+
end += 4
|
|
173
|
+
(length,) = _struct_I.unpack(str[start:end])
|
|
174
|
+
pattern = '<%sd'%length
|
|
175
|
+
start = end
|
|
176
|
+
s = struct.Struct(pattern)
|
|
177
|
+
end += s.size
|
|
178
|
+
self.size = s.unpack(str[start:end])
|
|
179
|
+
_x = self
|
|
180
|
+
start = end
|
|
181
|
+
end += 12
|
|
182
|
+
(_x.pose.header.seq, _x.pose.header.stamp.secs, _x.pose.header.stamp.nsecs,) = _get_struct_3I().unpack(str[start:end])
|
|
183
|
+
start = end
|
|
184
|
+
end += 4
|
|
185
|
+
(length,) = _struct_I.unpack(str[start:end])
|
|
186
|
+
start = end
|
|
187
|
+
end += length
|
|
188
|
+
if python3:
|
|
189
|
+
self.pose.header.frame_id = str[start:end].decode('utf-8', 'rosmsg')
|
|
190
|
+
else:
|
|
191
|
+
self.pose.header.frame_id = str[start:end]
|
|
192
|
+
_x = self
|
|
193
|
+
start = end
|
|
194
|
+
end += 56
|
|
195
|
+
(_x.pose.pose.pose.position.x, _x.pose.pose.pose.position.y, _x.pose.pose.pose.position.z, _x.pose.pose.pose.orientation.x, _x.pose.pose.pose.orientation.y, _x.pose.pose.pose.orientation.z, _x.pose.pose.pose.orientation.w,) = _get_struct_7d().unpack(str[start:end])
|
|
196
|
+
start = end
|
|
197
|
+
end += 288
|
|
198
|
+
self.pose.pose.covariance = _get_struct_36d().unpack(str[start:end])
|
|
199
|
+
return self
|
|
200
|
+
except struct.error as e:
|
|
201
|
+
raise genpy.DeserializationError(e) # most likely buffer underfill
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def serialize_numpy(self, buff, numpy):
|
|
205
|
+
"""
|
|
206
|
+
serialize message with numpy array types into buffer
|
|
207
|
+
:param buff: buffer, ``StringIO``
|
|
208
|
+
:param numpy: numpy python module
|
|
209
|
+
"""
|
|
210
|
+
try:
|
|
211
|
+
length = len(self.id)
|
|
212
|
+
buff.write(_struct_I.pack(length))
|
|
213
|
+
pattern = '<%si'%length
|
|
214
|
+
buff.write(self.id.tostring())
|
|
215
|
+
length = len(self.size)
|
|
216
|
+
buff.write(_struct_I.pack(length))
|
|
217
|
+
pattern = '<%sd'%length
|
|
218
|
+
buff.write(self.size.tostring())
|
|
219
|
+
_x = self
|
|
220
|
+
buff.write(_get_struct_3I().pack(_x.pose.header.seq, _x.pose.header.stamp.secs, _x.pose.header.stamp.nsecs))
|
|
221
|
+
_x = self.pose.header.frame_id
|
|
222
|
+
length = len(_x)
|
|
223
|
+
if python3 or type(_x) == unicode:
|
|
224
|
+
_x = _x.encode('utf-8')
|
|
225
|
+
length = len(_x)
|
|
226
|
+
buff.write(struct.Struct('<I%ss'%length).pack(length, _x))
|
|
227
|
+
_x = self
|
|
228
|
+
buff.write(_get_struct_7d().pack(_x.pose.pose.pose.position.x, _x.pose.pose.pose.position.y, _x.pose.pose.pose.position.z, _x.pose.pose.pose.orientation.x, _x.pose.pose.pose.orientation.y, _x.pose.pose.pose.orientation.z, _x.pose.pose.pose.orientation.w))
|
|
229
|
+
buff.write(self.pose.pose.covariance.tostring())
|
|
230
|
+
except struct.error as se: self._check_types(struct.error("%s: '%s' when writing '%s'" % (type(se), str(se), str(locals().get('_x', self)))))
|
|
231
|
+
except TypeError as te: self._check_types(ValueError("%s: '%s' when writing '%s'" % (type(te), str(te), str(locals().get('_x', self)))))
|
|
232
|
+
|
|
233
|
+
def deserialize_numpy(self, str, numpy):
|
|
234
|
+
"""
|
|
235
|
+
unpack serialized message in str into this message instance using numpy for array types
|
|
236
|
+
:param str: byte array of serialized message, ``str``
|
|
237
|
+
:param numpy: numpy python module
|
|
238
|
+
"""
|
|
239
|
+
if python3:
|
|
240
|
+
codecs.lookup_error("rosmsg").msg_type = self._type
|
|
241
|
+
try:
|
|
242
|
+
if self.pose is None:
|
|
243
|
+
self.pose = geometry_msgs.msg.PoseWithCovarianceStamped()
|
|
244
|
+
end = 0
|
|
245
|
+
start = end
|
|
246
|
+
end += 4
|
|
247
|
+
(length,) = _struct_I.unpack(str[start:end])
|
|
248
|
+
pattern = '<%si'%length
|
|
249
|
+
start = end
|
|
250
|
+
s = struct.Struct(pattern)
|
|
251
|
+
end += s.size
|
|
252
|
+
self.id = numpy.frombuffer(str[start:end], dtype=numpy.int32, count=length)
|
|
253
|
+
start = end
|
|
254
|
+
end += 4
|
|
255
|
+
(length,) = _struct_I.unpack(str[start:end])
|
|
256
|
+
pattern = '<%sd'%length
|
|
257
|
+
start = end
|
|
258
|
+
s = struct.Struct(pattern)
|
|
259
|
+
end += s.size
|
|
260
|
+
self.size = numpy.frombuffer(str[start:end], dtype=numpy.float64, count=length)
|
|
261
|
+
_x = self
|
|
262
|
+
start = end
|
|
263
|
+
end += 12
|
|
264
|
+
(_x.pose.header.seq, _x.pose.header.stamp.secs, _x.pose.header.stamp.nsecs,) = _get_struct_3I().unpack(str[start:end])
|
|
265
|
+
start = end
|
|
266
|
+
end += 4
|
|
267
|
+
(length,) = _struct_I.unpack(str[start:end])
|
|
268
|
+
start = end
|
|
269
|
+
end += length
|
|
270
|
+
if python3:
|
|
271
|
+
self.pose.header.frame_id = str[start:end].decode('utf-8', 'rosmsg')
|
|
272
|
+
else:
|
|
273
|
+
self.pose.header.frame_id = str[start:end]
|
|
274
|
+
_x = self
|
|
275
|
+
start = end
|
|
276
|
+
end += 56
|
|
277
|
+
(_x.pose.pose.pose.position.x, _x.pose.pose.pose.position.y, _x.pose.pose.pose.position.z, _x.pose.pose.pose.orientation.x, _x.pose.pose.pose.orientation.y, _x.pose.pose.pose.orientation.z, _x.pose.pose.pose.orientation.w,) = _get_struct_7d().unpack(str[start:end])
|
|
278
|
+
start = end
|
|
279
|
+
end += 288
|
|
280
|
+
self.pose.pose.covariance = numpy.frombuffer(str[start:end], dtype=numpy.float64, count=36)
|
|
281
|
+
return self
|
|
282
|
+
except struct.error as e:
|
|
283
|
+
raise genpy.DeserializationError(e) # most likely buffer underfill
|
|
284
|
+
|
|
285
|
+
_struct_I = genpy.struct_I
|
|
286
|
+
def _get_struct_I():
|
|
287
|
+
global _struct_I
|
|
288
|
+
return _struct_I
|
|
289
|
+
_struct_36d = None
|
|
290
|
+
def _get_struct_36d():
|
|
291
|
+
global _struct_36d
|
|
292
|
+
if _struct_36d is None:
|
|
293
|
+
_struct_36d = struct.Struct("<36d")
|
|
294
|
+
return _struct_36d
|
|
295
|
+
_struct_3I = None
|
|
296
|
+
def _get_struct_3I():
|
|
297
|
+
global _struct_3I
|
|
298
|
+
if _struct_3I is None:
|
|
299
|
+
_struct_3I = struct.Struct("<3I")
|
|
300
|
+
return _struct_3I
|
|
301
|
+
_struct_7d = None
|
|
302
|
+
def _get_struct_7d():
|
|
303
|
+
global _struct_7d
|
|
304
|
+
if _struct_7d is None:
|
|
305
|
+
_struct_7d = struct.Struct("<7d")
|
|
306
|
+
return _struct_7d
|