kuavo-humanoid-sdk 1.2.1b3321__20250917182547-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/__init__.py +6 -0
- kuavo_humanoid_sdk/common/logger.py +45 -0
- kuavo_humanoid_sdk/interfaces/__init__.py +4 -0
- kuavo_humanoid_sdk/interfaces/data_types.py +288 -0
- kuavo_humanoid_sdk/interfaces/end_effector.py +62 -0
- kuavo_humanoid_sdk/interfaces/robot.py +22 -0
- kuavo_humanoid_sdk/interfaces/robot_info.py +56 -0
- kuavo_humanoid_sdk/kuavo/__init__.py +16 -0
- kuavo_humanoid_sdk/kuavo/core/audio.py +32 -0
- kuavo_humanoid_sdk/kuavo/core/core.py +666 -0
- kuavo_humanoid_sdk/kuavo/core/dex_hand_control.py +114 -0
- kuavo_humanoid_sdk/kuavo/core/leju_claw_control.py +67 -0
- kuavo_humanoid_sdk/kuavo/core/llm_doubao.py +608 -0
- kuavo_humanoid_sdk/kuavo/core/microphone.py +192 -0
- kuavo_humanoid_sdk/kuavo/core/navigation.py +70 -0
- kuavo_humanoid_sdk/kuavo/core/ros/audio.py +110 -0
- kuavo_humanoid_sdk/kuavo/core/ros/camera.py +105 -0
- kuavo_humanoid_sdk/kuavo/core/ros/control.py +1524 -0
- kuavo_humanoid_sdk/kuavo/core/ros/microphone.py +38 -0
- kuavo_humanoid_sdk/kuavo/core/ros/navigation.py +217 -0
- kuavo_humanoid_sdk/kuavo/core/ros/observation.py +94 -0
- kuavo_humanoid_sdk/kuavo/core/ros/param.py +201 -0
- kuavo_humanoid_sdk/kuavo/core/ros/sat_utils.py +103 -0
- kuavo_humanoid_sdk/kuavo/core/ros/state.py +652 -0
- kuavo_humanoid_sdk/kuavo/core/ros/tools.py +220 -0
- kuavo_humanoid_sdk/kuavo/core/ros/vision.py +234 -0
- kuavo_humanoid_sdk/kuavo/core/ros_env.py +238 -0
- kuavo_humanoid_sdk/kuavo/core/sdk_deprecated.py +41 -0
- kuavo_humanoid_sdk/kuavo/demo_climbstair.py +249 -0
- kuavo_humanoid_sdk/kuavo/dexterous_hand.py +238 -0
- kuavo_humanoid_sdk/kuavo/leju_claw.py +235 -0
- kuavo_humanoid_sdk/kuavo/logger_client.py +80 -0
- kuavo_humanoid_sdk/kuavo/robot.py +646 -0
- kuavo_humanoid_sdk/kuavo/robot_arm.py +411 -0
- kuavo_humanoid_sdk/kuavo/robot_audio.py +39 -0
- kuavo_humanoid_sdk/kuavo/robot_blockly.py +1154 -0
- kuavo_humanoid_sdk/kuavo/robot_climbstair.py +1607 -0
- kuavo_humanoid_sdk/kuavo/robot_head.py +95 -0
- kuavo_humanoid_sdk/kuavo/robot_info.py +134 -0
- kuavo_humanoid_sdk/kuavo/robot_microphone.py +19 -0
- kuavo_humanoid_sdk/kuavo/robot_navigation.py +135 -0
- kuavo_humanoid_sdk/kuavo/robot_observation.py +64 -0
- kuavo_humanoid_sdk/kuavo/robot_speech.py +24 -0
- kuavo_humanoid_sdk/kuavo/robot_state.py +310 -0
- kuavo_humanoid_sdk/kuavo/robot_tool.py +109 -0
- kuavo_humanoid_sdk/kuavo/robot_vision.py +81 -0
- kuavo_humanoid_sdk/kuavo_strategy/__init__.py +2 -0
- kuavo_humanoid_sdk/kuavo_strategy/grasp_box/grasp_box_strategy.py +1325 -0
- kuavo_humanoid_sdk/kuavo_strategy/kuavo_strategy.py +106 -0
- kuavo_humanoid_sdk/kuavo_strategy_v2/common/data_type.py +340 -0
- kuavo_humanoid_sdk/kuavo_strategy_v2/common/events/base_event.py +215 -0
- kuavo_humanoid_sdk/kuavo_strategy_v2/common/robot_sdk.py +25 -0
- kuavo_humanoid_sdk/kuavo_strategy_v2/pick_place_box/case.py +331 -0
- kuavo_humanoid_sdk/kuavo_strategy_v2/pick_place_box/strategy.py +504 -0
- kuavo_humanoid_sdk/kuavo_strategy_v2/utils/logger_setup.py +40 -0
- kuavo_humanoid_sdk/kuavo_strategy_v2/utils/utils.py +88 -0
- kuavo_humanoid_sdk/msg/__init__.py +4 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/__init__.py +7 -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/_AudioReceiverData.py +122 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_FTsensorData.py +260 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_JoySticks.py +191 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_Metadata.py +199 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_MmDetectionMsg.py +264 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_RobotActionState.py +112 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_TFArray.py +323 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_TaskPoint.py +175 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/msg/__init__.py +62 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_armCollisionCheckInfo.py +160 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_armHandPose.py +161 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_armHandPoseFree.py +171 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_armPoseWithTimeStamp.py +168 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_armTargetPoses.py +171 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_bezierCurveCubicPoint.py +178 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_dexhandCommand.py +229 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_dexhandTouchState.py +256 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_endEffectorData.py +227 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_footPose.py +123 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_footPose6D.py +123 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_footPose6DTargetTrajectories.py +320 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_footPoseTargetTrajectories.py +301 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_footPoseWithVision.py +136 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_footPoseWithVisionArray.py +231 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_footPoses.py +149 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_footPoses6D.py +149 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_fullBodyTargetTrajectories.py +258 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_gaitTimeName.py +147 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_gestureInfo.py +218 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_gestureTask.py +149 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_handPose.py +136 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_headBodyPose.py +145 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_ikSolveError.py +171 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_ikSolveParam.py +140 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_imuData.py +165 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_jointBezierTrajectory.py +201 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_jointCmd.py +390 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_jointData.py +205 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_kuavoModeSchedule.py +224 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_lejuClawCommand.py +320 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_lejuClawState.py +341 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_motorParam.py +122 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_picoPoseInfo.py +143 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_picoPoseInfoList.py +220 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_planArmState.py +120 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_qv.py +121 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_robotArmQVVD.py +177 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_robotBodyMatrices.py +332 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_robotHandPosition.py +225 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_robotHeadMotionData.py +128 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_robotState.py +222 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_sensorsData.py +655 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_switchGaitByName.py +200 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_tagDataArray.py +216 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_touchSensorStatus.py +162 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_twoArmHandPose.py +273 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_twoArmHandPoseCmd.py +316 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_twoArmHandPoseCmdFree.py +338 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_twoArmHandPoseFree.py +299 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_yoloDetection.py +251 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_yoloOutputData.py +168 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_CreatePath.py +581 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_ExecuteArmAction.py +281 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_GetAllMaps.py +241 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_GetCurrentMap.py +225 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_GetTargetPartPoseInCamera.py +298 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_InitialPoseWithTaskPoint.py +281 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_LoadMap.py +281 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_NavigateToTaskPoint.py +281 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_RepublishTFs.py +373 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_SetInitialPose.py +394 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_SetJoyTopic.py +282 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_SetLEDMode.py +468 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_SetLEDMode_free.py +289 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_SpeechSynthesis.py +270 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_TaskPointOperation.py +536 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/srv/__init__.py +43 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_adjustZeroPoint.py +277 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_changeArmCtrlMode.py +275 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_changeArmCtrlModeKuavo.py +236 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_changeMotorParam.py +299 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_changeTorsoCtrlMode.py +274 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_controlLejuClaw.py +408 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_enableHandTouchSensor.py +304 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_fkSrv.py +395 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_footPose6DTargetTrajectoriesSrv.py +426 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_footPoseTargetTrajectoriesSrv.py +409 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_gestureExecute.py +339 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_gestureExecuteState.py +257 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_gestureList.py +418 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_getCurrentGaitName.py +253 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_getMotorParam.py +299 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_getMotorZeroPoints.py +286 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_handForceLevel.py +330 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_jointMoveTo.py +302 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_planArmTrajectoryBezierCurve.py +422 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_planArmTrajectoryCubicSpline.py +490 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_playmusic.py +268 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_setHwIntialState.py +304 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_setMmCtrlFrame.py +273 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_setMotorEncoderRoundService.py +283 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_setTagId.py +275 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_singleStepControl.py +444 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_twoArmHandPoseCmdFreeSrv.py +716 -0
- kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_twoArmHandPoseCmdSrv.py +664 -0
- kuavo_humanoid_sdk/msg/motion_capture_ik/__init__.py +7 -0
- kuavo_humanoid_sdk/msg/ocs2_msgs/__init__.py +7 -0
- kuavo_humanoid_sdk/msg/ocs2_msgs/msg/__init__.py +12 -0
- kuavo_humanoid_sdk/msg/ocs2_msgs/msg/_constraint.py +142 -0
- kuavo_humanoid_sdk/msg/ocs2_msgs/msg/_controller_data.py +121 -0
- kuavo_humanoid_sdk/msg/ocs2_msgs/msg/_lagrangian_metrics.py +148 -0
- kuavo_humanoid_sdk/msg/ocs2_msgs/msg/_mode_schedule.py +150 -0
- kuavo_humanoid_sdk/msg/ocs2_msgs/msg/_mpc_flattened_controller.py +666 -0
- kuavo_humanoid_sdk/msg/ocs2_msgs/msg/_mpc_input.py +122 -0
- kuavo_humanoid_sdk/msg/ocs2_msgs/msg/_mpc_observation.py +209 -0
- kuavo_humanoid_sdk/msg/ocs2_msgs/msg/_mpc_performance_indices.py +140 -0
- kuavo_humanoid_sdk/msg/ocs2_msgs/msg/_mpc_solver_data.py +886 -0
- kuavo_humanoid_sdk/msg/ocs2_msgs/msg/_mpc_state.py +122 -0
- kuavo_humanoid_sdk/msg/ocs2_msgs/msg/_mpc_target_trajectories.py +239 -0
- kuavo_humanoid_sdk/msg/ocs2_msgs/msg/_multiplier.py +148 -0
- kuavo_humanoid_sdk/msg/ocs2_msgs/srv/__init__.py +1 -0
- kuavo_humanoid_sdk/msg/ocs2_msgs/srv/_reset.py +376 -0
- kuavo_humanoid_sdk-1.2.1b3321.dist-info/METADATA +297 -0
- kuavo_humanoid_sdk-1.2.1b3321.dist-info/RECORD +186 -0
- kuavo_humanoid_sdk-1.2.1b3321.dist-info/WHEEL +6 -0
- kuavo_humanoid_sdk-1.2.1b3321.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import rospy
|
|
2
|
+
import collections
|
|
3
|
+
import threading
|
|
4
|
+
from kuavo_humanoid_sdk.common.logger import SDKLogger
|
|
5
|
+
|
|
6
|
+
from kuavo_humanoid_sdk.msg.kuavo_msgs.msg import AudioReceiverData
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class Microphone:
|
|
10
|
+
"""
|
|
11
|
+
ROS-specific part for handling microphone data subscription.
|
|
12
|
+
It subscribes to an audio topic and buffers the received data.
|
|
13
|
+
"""
|
|
14
|
+
def __init__(self, subscribe_topic="/micphone_data"):
|
|
15
|
+
self._buffer = collections.deque()
|
|
16
|
+
self._lock = threading.Lock()
|
|
17
|
+
self.subscriber = rospy.Subscriber(subscribe_topic, AudioReceiverData, self._audio_callback)
|
|
18
|
+
SDKLogger.debug(f"MicrophoneROSNode subscribed to topic: {subscribe_topic}")
|
|
19
|
+
|
|
20
|
+
def _audio_callback(self, msg: AudioReceiverData):
|
|
21
|
+
"""
|
|
22
|
+
Callback function for the audio subscriber. Appends data to the buffer.
|
|
23
|
+
"""
|
|
24
|
+
with self._lock:
|
|
25
|
+
self._buffer.append(msg.data)
|
|
26
|
+
|
|
27
|
+
def get_data(self):
|
|
28
|
+
"""
|
|
29
|
+
Retrieves all data chunks from the buffer and clears it.
|
|
30
|
+
This is designed to be called by the processing layer.
|
|
31
|
+
"""
|
|
32
|
+
with self._lock:
|
|
33
|
+
if not self._buffer:
|
|
34
|
+
return None
|
|
35
|
+
|
|
36
|
+
data_batch = b''.join(self._buffer)
|
|
37
|
+
self._buffer.clear()
|
|
38
|
+
return data_batch
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# coding: utf-8
|
|
3
|
+
import rospy
|
|
4
|
+
from std_msgs.msg import Bool,String
|
|
5
|
+
from kuavo_humanoid_sdk.common.logger import SDKLogger
|
|
6
|
+
from kuavo_humanoid_sdk.kuavo.core.core import KuavoRobotCore
|
|
7
|
+
from kuavo_humanoid_sdk.msg.kuavo_msgs.srv import LoadMap, LoadMapRequest, LoadMapResponse
|
|
8
|
+
from kuavo_humanoid_sdk.msg.kuavo_msgs.srv import GetCurrentMap, GetCurrentMapRequest, GetCurrentMapResponse
|
|
9
|
+
from kuavo_humanoid_sdk.msg.kuavo_msgs.srv import GetAllMaps, GetAllMapsRequest, GetAllMapsResponse
|
|
10
|
+
from kuavo_humanoid_sdk.msg.kuavo_msgs.srv import TaskPointOperation, TaskPointOperationRequest, TaskPointOperationResponse
|
|
11
|
+
from kuavo_humanoid_sdk.msg.kuavo_msgs.srv import InitialPoseWithTaskPoint, InitialPoseWithTaskPointRequest, InitialPoseWithTaskPointResponse
|
|
12
|
+
from kuavo_humanoid_sdk.msg.kuavo_msgs.srv import NavigateToTaskPoint, NavigateToTaskPointRequest, NavigateToTaskPointResponse
|
|
13
|
+
from kuavo_humanoid_sdk.msg.kuavo_msgs.msg import TaskPoint as TaskPointMsg
|
|
14
|
+
from geometry_msgs.msg import Pose, Point, Quaternion, PoseStamped, PoseWithCovarianceStamped
|
|
15
|
+
from actionlib_msgs.msg import GoalStatusArray,GoalID
|
|
16
|
+
from enum import Enum
|
|
17
|
+
class NavigationStatus(Enum):
|
|
18
|
+
"""Navigation status."""
|
|
19
|
+
PENDING = 0
|
|
20
|
+
ACTIVE = 1
|
|
21
|
+
PREEMPTED = 2
|
|
22
|
+
SUCCEEDED = 3
|
|
23
|
+
ABORTED = 4
|
|
24
|
+
REJECTED = 5
|
|
25
|
+
|
|
26
|
+
class Navigation:
|
|
27
|
+
"""Navigation system interface for controlling navigation functionality of Kuavo humanoid robot.
|
|
28
|
+
|
|
29
|
+
Provides functionality to play music files.
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
def __init__(self):
|
|
33
|
+
"""Initialize the navigation system."""
|
|
34
|
+
self.init_with_pose_pub = rospy.Publisher('/initialpose', PoseWithCovarianceStamped, queue_size=10, latch=True)
|
|
35
|
+
self.init_with_task_point_pub = rospy.Publisher('initialpose_with_taskpoint', String, queue_size=10)
|
|
36
|
+
self.goal_pub = rospy.Publisher('/move_base_simple/goal', PoseStamped, queue_size=10, latch=True)
|
|
37
|
+
self.move_base_cancel = rospy.Publisher('/move_base/cancel', GoalID, queue_size=10)
|
|
38
|
+
self.status_sub = rospy.Subscriber('/move_base/status', GoalStatusArray, self.status_callback)
|
|
39
|
+
self.status = NavigationStatus.PENDING
|
|
40
|
+
# Wait for publisher initialization
|
|
41
|
+
|
|
42
|
+
def status_callback(self, msg: GoalStatusArray):
|
|
43
|
+
"""Callback for the status topic."""
|
|
44
|
+
if len(msg.status_list) > 0:
|
|
45
|
+
self.status = NavigationStatus(msg.status_list[0].status)
|
|
46
|
+
|
|
47
|
+
def srv_load_map(self, map_name: str):
|
|
48
|
+
"""Load the map."""
|
|
49
|
+
try:
|
|
50
|
+
service_name = '/load_map'
|
|
51
|
+
rospy.wait_for_service(service_name,timeout=3.0)
|
|
52
|
+
load_map_client = rospy.ServiceProxy(service_name, LoadMap)
|
|
53
|
+
|
|
54
|
+
# request
|
|
55
|
+
req = LoadMapRequest()
|
|
56
|
+
req.map_name = map_name
|
|
57
|
+
|
|
58
|
+
# response
|
|
59
|
+
res = load_map_client(req)
|
|
60
|
+
if res.success:
|
|
61
|
+
return True
|
|
62
|
+
else:
|
|
63
|
+
return False
|
|
64
|
+
except rospy.ServiceException as e:
|
|
65
|
+
SDKLogger.error(f"Service `load_map` call failed: {e}")
|
|
66
|
+
except rospy.ROSException as e:
|
|
67
|
+
SDKLogger.error(f"Service `load_map` call failed: {e}")
|
|
68
|
+
except Exception as e:
|
|
69
|
+
SDKLogger.error(f"Service `load_map` call failed: {e}")
|
|
70
|
+
return False
|
|
71
|
+
|
|
72
|
+
def srv_get_current_map(self):
|
|
73
|
+
"""Get the current map."""
|
|
74
|
+
try:
|
|
75
|
+
service_name = 'get_current_map'
|
|
76
|
+
rospy.wait_for_service(service_name,timeout=3.0)
|
|
77
|
+
get_current_map_client = rospy.ServiceProxy(service_name, GetCurrentMap)
|
|
78
|
+
|
|
79
|
+
# request
|
|
80
|
+
req = GetCurrentMapRequest()
|
|
81
|
+
|
|
82
|
+
# response
|
|
83
|
+
res = get_current_map_client(req)
|
|
84
|
+
return res.current_map
|
|
85
|
+
except rospy.ServiceException as e:
|
|
86
|
+
SDKLogger.error(f"Service `get_current_map` call failed: {e}")
|
|
87
|
+
except rospy.ROSException as e:
|
|
88
|
+
SDKLogger.error(f"Service `get_current_map` call failed: {e}")
|
|
89
|
+
except Exception as e:
|
|
90
|
+
SDKLogger.error(f"Service `get_current_map` call failed: {e}")
|
|
91
|
+
return None
|
|
92
|
+
|
|
93
|
+
def srv_get_all_maps(self):
|
|
94
|
+
"""Get all maps."""
|
|
95
|
+
try:
|
|
96
|
+
service_name = 'get_all_maps'
|
|
97
|
+
rospy.wait_for_service(service_name,timeout=3.0)
|
|
98
|
+
get_all_maps_client = rospy.ServiceProxy(service_name, GetAllMaps)
|
|
99
|
+
|
|
100
|
+
# request
|
|
101
|
+
req = GetAllMapsRequest()
|
|
102
|
+
|
|
103
|
+
# response
|
|
104
|
+
res = get_all_maps_client(req)
|
|
105
|
+
return res.maps
|
|
106
|
+
except rospy.ServiceException as e:
|
|
107
|
+
SDKLogger.error(f"Service `get_all_maps` call failed: {e}")
|
|
108
|
+
except rospy.ROSException as e:
|
|
109
|
+
SDKLogger.error(f"Service `get_all_maps` call failed: {e}")
|
|
110
|
+
except Exception as e:
|
|
111
|
+
SDKLogger.error(f"Service `get_all_maps` call failed: {e}")
|
|
112
|
+
return None
|
|
113
|
+
|
|
114
|
+
def srv_navigate_to_task_point(self, task_point_name: String):
|
|
115
|
+
"""Navigate to the task point."""
|
|
116
|
+
try:
|
|
117
|
+
service_name = 'navigate_to_task_point'
|
|
118
|
+
rospy.wait_for_service(service_name,timeout=3.0)
|
|
119
|
+
navigate_to_task_point_client = rospy.ServiceProxy(service_name, NavigateToTaskPoint)
|
|
120
|
+
|
|
121
|
+
# request
|
|
122
|
+
req = NavigateToTaskPointRequest()
|
|
123
|
+
req.task_name = task_point_name
|
|
124
|
+
|
|
125
|
+
# response
|
|
126
|
+
res = navigate_to_task_point_client(req)
|
|
127
|
+
return res.success
|
|
128
|
+
except rospy.ServiceException as e:
|
|
129
|
+
SDKLogger.error(f"Service `navigate_to_task_point` call failed: {e}")
|
|
130
|
+
except rospy.ROSException as e:
|
|
131
|
+
SDKLogger.error(f"Service `navigate_to_task_point` call failed: {e}")
|
|
132
|
+
except Exception as e:
|
|
133
|
+
SDKLogger.error(f"Service `navigate_to_task_point` call failed: {e}")
|
|
134
|
+
return False
|
|
135
|
+
|
|
136
|
+
def srv_init_localization_by_task_point(self, task_point_name: str):
|
|
137
|
+
"""Initialize the localization by task point."""
|
|
138
|
+
try:
|
|
139
|
+
service_name = '/initialpose_with_taskpoint'
|
|
140
|
+
rospy.wait_for_service(service_name,timeout=3.0)
|
|
141
|
+
init_localization_by_task_point_client = rospy.ServiceProxy(service_name, InitialPoseWithTaskPoint)
|
|
142
|
+
|
|
143
|
+
# request
|
|
144
|
+
req = InitialPoseWithTaskPointRequest()
|
|
145
|
+
req.task_point_name = task_point_name
|
|
146
|
+
# response
|
|
147
|
+
res = init_localization_by_task_point_client(req)
|
|
148
|
+
return res.success
|
|
149
|
+
except rospy.ServiceException as e:
|
|
150
|
+
SDKLogger.error(f"Service `/initialpose_with_taskpoint` call failed: {e}")
|
|
151
|
+
except rospy.ROSException as e:
|
|
152
|
+
SDKLogger.error(f"Service `/initialpose_with_taskpoint` call failed: {e}")
|
|
153
|
+
except Exception as e:
|
|
154
|
+
SDKLogger.error(f"Service `/initialpose_with_taskpoint` call failed: {e}")
|
|
155
|
+
return False
|
|
156
|
+
|
|
157
|
+
def pub_init_localization_by_pose(self, pose: Pose):
|
|
158
|
+
"""Initialize the localization by pose."""
|
|
159
|
+
try:
|
|
160
|
+
# request
|
|
161
|
+
initialpose_msg = PoseWithCovarianceStamped()
|
|
162
|
+
initialpose_msg.header.frame_id = "map"
|
|
163
|
+
initialpose_msg.header.stamp = rospy.Time.now()
|
|
164
|
+
initialpose_msg.pose.pose = pose
|
|
165
|
+
|
|
166
|
+
# 转发到/initialpose话题
|
|
167
|
+
self.init_with_pose_pub.publish(initialpose_msg)
|
|
168
|
+
except Exception as e:
|
|
169
|
+
SDKLogger.error(f"Failed to initialize localization by pose: {e}")
|
|
170
|
+
return False
|
|
171
|
+
return True
|
|
172
|
+
|
|
173
|
+
def pub_init_localization_by_task_point(self, task_point_name: str):
|
|
174
|
+
"""Initialize the localization by task point."""
|
|
175
|
+
try:
|
|
176
|
+
self.init_with_task_point_pub.publish(task_point_name)
|
|
177
|
+
rospy.sleep(3)
|
|
178
|
+
except Exception as e:
|
|
179
|
+
SDKLogger.error(f"Failed to initialize localization by task point: {e}")
|
|
180
|
+
return False
|
|
181
|
+
return True
|
|
182
|
+
|
|
183
|
+
def pub_navigate_to_goal(self, goal: Pose):
|
|
184
|
+
"""Navigate to the goal."""
|
|
185
|
+
try:
|
|
186
|
+
# request
|
|
187
|
+
goal_msg = PoseStamped()
|
|
188
|
+
goal_msg.header.frame_id = "map"
|
|
189
|
+
goal_msg.header.stamp = rospy.Time.now()
|
|
190
|
+
goal_msg.pose = goal
|
|
191
|
+
|
|
192
|
+
# 转发到/move_base/goal话题
|
|
193
|
+
self.goal_pub.publish(goal_msg)
|
|
194
|
+
except Exception as e:
|
|
195
|
+
SDKLogger.error(f"Failed to navigate to goal: {e}")
|
|
196
|
+
return False
|
|
197
|
+
return True
|
|
198
|
+
|
|
199
|
+
def get_current_status(self):
|
|
200
|
+
"""Get the current status."""
|
|
201
|
+
return self.status
|
|
202
|
+
|
|
203
|
+
def pub_stop_navigation(self):
|
|
204
|
+
"""Stop the navigation.Cancel all goal."""
|
|
205
|
+
try:
|
|
206
|
+
cancel_msg = GoalID()
|
|
207
|
+
cancel_msg.goal_id = self.goal_id
|
|
208
|
+
self.move_base_cancel.publish(cancel_msg)
|
|
209
|
+
except Exception as e:
|
|
210
|
+
SDKLogger.error(f"Failed to stop navigation: {e}")
|
|
211
|
+
return False
|
|
212
|
+
return True
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# coding: utf-8
|
|
3
|
+
from kuavo_humanoid_sdk.interfaces.data_types import (
|
|
4
|
+
KuavoJointCommand, KuavoTwist)
|
|
5
|
+
from kuavo_humanoid_sdk.common.logger import SDKLogger
|
|
6
|
+
import rospy
|
|
7
|
+
from geometry_msgs.msg import Twist
|
|
8
|
+
from kuavo_humanoid_sdk.msg.kuavo_msgs.msg import jointCmd
|
|
9
|
+
|
|
10
|
+
class KuavoRobotObservationCore:
|
|
11
|
+
_instance = None
|
|
12
|
+
|
|
13
|
+
def __new__(cls, *args, **kwargs):
|
|
14
|
+
if not cls._instance:
|
|
15
|
+
cls._instance = super().__new__(cls)
|
|
16
|
+
return cls._instance
|
|
17
|
+
|
|
18
|
+
def __init__(self):
|
|
19
|
+
if not hasattr(self, '_initialized'):
|
|
20
|
+
rospy.Subscriber("/joint_cmd", jointCmd, self._joint_cmd_callback)
|
|
21
|
+
rospy.Subscriber("/cmd_vel", Twist, self._cmd_vel_callback)
|
|
22
|
+
rospy.Subscriber("/cmd_pose", Twist, self._cmd_pose_callback)
|
|
23
|
+
|
|
24
|
+
""" data """
|
|
25
|
+
self._joint_cmd = KuavoJointCommand(
|
|
26
|
+
joint_q = [0.0] * 28,
|
|
27
|
+
joint_v = [0.0] * 28,
|
|
28
|
+
tau = [0.0] * 28,
|
|
29
|
+
tau_max = [0.0] * 28,
|
|
30
|
+
tau_ratio = [0.0] * 28,
|
|
31
|
+
joint_kp = [0.0] * 28,
|
|
32
|
+
joint_kd = [0.0] * 28,
|
|
33
|
+
control_modes = [0] * 28
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
self._cmd_vel = KuavoTwist(
|
|
37
|
+
linear = (0.0, 0.0, 0.0),
|
|
38
|
+
angular = (0.0, 0.0, 0.0)
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
self._cmd_pose = KuavoTwist(
|
|
42
|
+
linear = (0.0, 0.0, 0.0),
|
|
43
|
+
angular = (0.0, 0.0, 0.0)
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
self._initialized = True
|
|
47
|
+
|
|
48
|
+
def _joint_cmd_callback(self, msg):
|
|
49
|
+
self._joint_cmd.joint_q = list(msg.joint_q)
|
|
50
|
+
self._joint_cmd.joint_v = list(msg.joint_v)
|
|
51
|
+
self._joint_cmd.tau = list(msg.tau)
|
|
52
|
+
self._joint_cmd.tau_max = list(msg.tau_max)
|
|
53
|
+
self._joint_cmd.tau_ratio = list(msg.tau_ratio)
|
|
54
|
+
self._joint_cmd.joint_kp = list(msg.joint_kp)
|
|
55
|
+
self._joint_cmd.joint_kd = list(msg.joint_kd)
|
|
56
|
+
self._joint_cmd.control_modes = list(msg.control_modes)
|
|
57
|
+
|
|
58
|
+
def _cmd_vel_callback(self, msg):
|
|
59
|
+
self._cmd_vel.linear = (msg.linear.x, msg.linear.y, msg.linear.z)
|
|
60
|
+
self._cmd_vel.angular = (msg.angular.x, msg.angular.y, msg.angular.z)
|
|
61
|
+
|
|
62
|
+
def _cmd_pose_callback(self, msg):
|
|
63
|
+
self._cmd_pose.linear = (msg.linear.x, msg.linear.y, msg.linear.z)
|
|
64
|
+
self._cmd_pose.angular = (msg.angular.x, msg.angular.y, msg.angular.z)
|
|
65
|
+
|
|
66
|
+
@property
|
|
67
|
+
def joint_command(self) -> KuavoJointCommand:
|
|
68
|
+
return self._joint_cmd
|
|
69
|
+
|
|
70
|
+
@property
|
|
71
|
+
def cmd_vel(self) -> KuavoTwist:
|
|
72
|
+
return self._cmd_vel
|
|
73
|
+
|
|
74
|
+
@property
|
|
75
|
+
def cmd_pose(self) -> KuavoTwist:
|
|
76
|
+
return self._cmd_pose
|
|
77
|
+
|
|
78
|
+
@property
|
|
79
|
+
def arm_position_command(self) -> list:
|
|
80
|
+
"""Return the position commands for the arm joints (indices 12-25).
|
|
81
|
+
|
|
82
|
+
Returns:
|
|
83
|
+
list: Position commands for arm joints
|
|
84
|
+
"""
|
|
85
|
+
return self._joint_cmd.joint_q[12:26]
|
|
86
|
+
|
|
87
|
+
@property
|
|
88
|
+
def head_position_command(self) -> list:
|
|
89
|
+
"""Return the position commands for the head joints (indices 26-27).
|
|
90
|
+
|
|
91
|
+
Returns:
|
|
92
|
+
list: Position commands for head joints
|
|
93
|
+
"""
|
|
94
|
+
return self._joint_cmd.joint_q[-2:]
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import rospy
|
|
2
|
+
import json
|
|
3
|
+
import xml.etree.ElementTree as ET
|
|
4
|
+
from kuavo_humanoid_sdk.common.logger import SDKLogger
|
|
5
|
+
# End effector types
|
|
6
|
+
class EndEffectorType:
|
|
7
|
+
QIANGNAO = "qiangnao"
|
|
8
|
+
QIANGNAO_TOUCH = "qiangnao_touch"
|
|
9
|
+
LEJUCLAW = "lejuclaw"
|
|
10
|
+
class RosParameter:
|
|
11
|
+
def __init__(self):
|
|
12
|
+
pass
|
|
13
|
+
def robot_version(self)->str:
|
|
14
|
+
if not rospy.has_param('/robot_version'):
|
|
15
|
+
rospy.logerr("robot_version parameter not found")
|
|
16
|
+
return None
|
|
17
|
+
return rospy.get_param('/robot_version')
|
|
18
|
+
|
|
19
|
+
def arm_dof(self)->int:
|
|
20
|
+
if not rospy.has_param('/armRealDof'):
|
|
21
|
+
rospy.logerr("armRealDof parameter not found")
|
|
22
|
+
return None
|
|
23
|
+
return rospy.get_param('/armRealDof')
|
|
24
|
+
|
|
25
|
+
def head_dof(self)->int:
|
|
26
|
+
if not rospy.has_param('/headRealDof'):
|
|
27
|
+
rospy.logerr("headRealDof parameter not found")
|
|
28
|
+
return None
|
|
29
|
+
return rospy.get_param('/headRealDof')
|
|
30
|
+
|
|
31
|
+
def leg_dof(self)->int:
|
|
32
|
+
if not rospy.has_param('/legRealDof'):
|
|
33
|
+
rospy.logerr("legRealDof parameter not found")
|
|
34
|
+
return None
|
|
35
|
+
return rospy.get_param('/legRealDof')
|
|
36
|
+
|
|
37
|
+
def end_effector_type(self)->str:
|
|
38
|
+
if not rospy.has_param('/end_effector_type'):
|
|
39
|
+
return None
|
|
40
|
+
return rospy.get_param('/end_effector_type')
|
|
41
|
+
|
|
42
|
+
def humanoid_description(self)->str:
|
|
43
|
+
if not rospy.has_param('/humanoid_description'):
|
|
44
|
+
rospy.logerr("humanoid_description parameter not found")
|
|
45
|
+
return None
|
|
46
|
+
return rospy.get_param('/humanoid_description')
|
|
47
|
+
|
|
48
|
+
def model_path(self)->str:
|
|
49
|
+
if not rospy.has_param('/modelPath'):
|
|
50
|
+
rospy.logerr("modelPath parameter not found")
|
|
51
|
+
return None
|
|
52
|
+
return rospy.get_param('/modelPath')
|
|
53
|
+
|
|
54
|
+
def kuavo_config(self)->str:
|
|
55
|
+
if not rospy.has_param('/kuavo_configuration'):
|
|
56
|
+
rospy.logerr("kuavo_configuration parameter not found")
|
|
57
|
+
return None
|
|
58
|
+
return rospy.get_param('/kuavo_configuration')
|
|
59
|
+
|
|
60
|
+
def initial_state(self)->str:
|
|
61
|
+
if not rospy.has_param('/initial_state'):
|
|
62
|
+
rospy.logerr("initial_state parameter not found")
|
|
63
|
+
return None
|
|
64
|
+
return rospy.get_param('/initial_state')
|
|
65
|
+
def init_stand_height(self)->float:
|
|
66
|
+
if not rospy.has_param('/com_height'):
|
|
67
|
+
rospy.logerr("com_height parameter not found")
|
|
68
|
+
# KUAVO-4PRO
|
|
69
|
+
return 0.8328437523948975
|
|
70
|
+
return rospy.get_param('/com_height')
|
|
71
|
+
|
|
72
|
+
kuavo_ros_param = RosParameter()
|
|
73
|
+
|
|
74
|
+
def joint_names()->dict:
|
|
75
|
+
if(kuavo_ros_param.robot_version() == 13):
|
|
76
|
+
leg_link_names = [
|
|
77
|
+
'leg_l1_link', 'leg_l2_link', 'leg_l3_link', 'leg_l4_link', 'leg_l5_link', 'leg_l6_link',
|
|
78
|
+
'leg_r1_link', 'leg_r2_link', 'leg_r3_link', 'leg_r4_link', 'leg_r5_link', 'leg_r6_link'
|
|
79
|
+
]
|
|
80
|
+
arm_link_names = [
|
|
81
|
+
'zarm_l1_link', 'zarm_l2_link', 'zarm_l3_link', 'zarm_l4_link',
|
|
82
|
+
'zarm_r1_link', 'zarm_r2_link', 'zarm_r3_link', 'zarm_r4_link',
|
|
83
|
+
]
|
|
84
|
+
head_link_names = [
|
|
85
|
+
'zhead_1_link', 'zhead_2_link'
|
|
86
|
+
]
|
|
87
|
+
else:
|
|
88
|
+
leg_link_names = [
|
|
89
|
+
'leg_l1_link', 'leg_l2_link', 'leg_l3_link', 'leg_l4_link', 'leg_l5_link', 'leg_l6_link',
|
|
90
|
+
'leg_r1_link', 'leg_r2_link', 'leg_r3_link', 'leg_r4_link', 'leg_r5_link', 'leg_r6_link'
|
|
91
|
+
]
|
|
92
|
+
arm_link_names = [
|
|
93
|
+
'zarm_l1_link', 'zarm_l2_link', 'zarm_l3_link', 'zarm_l4_link', 'zarm_l5_link', 'zarm_l6_link', 'zarm_l7_link',
|
|
94
|
+
'zarm_r1_link', 'zarm_r2_link', 'zarm_r3_link', 'zarm_r4_link', 'zarm_r5_link', 'zarm_r6_link', 'zarm_r7_link',
|
|
95
|
+
]
|
|
96
|
+
head_link_names = [
|
|
97
|
+
'zhead_1_link', 'zhead_2_link'
|
|
98
|
+
]
|
|
99
|
+
robot_desc = kuavo_ros_param.humanoid_description()
|
|
100
|
+
if robot_desc is None:
|
|
101
|
+
return None
|
|
102
|
+
|
|
103
|
+
"""
|
|
104
|
+
<link name="leg_l1_link">
|
|
105
|
+
<inertial>
|
|
106
|
+
....
|
|
107
|
+
</inertial>
|
|
108
|
+
<visual>
|
|
109
|
+
...
|
|
110
|
+
<geometry>
|
|
111
|
+
<mesh filename="package://kuavo_assets/models/biped_s43/meshes/l_leg_roll.STL" />
|
|
112
|
+
</geometry>
|
|
113
|
+
...
|
|
114
|
+
</visual>
|
|
115
|
+
</link>
|
|
116
|
+
"""
|
|
117
|
+
root = ET.fromstring(robot_desc)
|
|
118
|
+
process_link_name = lambda link_name: (
|
|
119
|
+
(root.find(f".//link[@name='{link_name}']") is not None and
|
|
120
|
+
root.find(f".//link[@name='{link_name}']/visual") is not None and
|
|
121
|
+
root.find(f".//link[@name='{link_name}']/visual/geometry") is not None and
|
|
122
|
+
root.find(f".//link[@name='{link_name}']/visual/geometry/mesh") is not None and
|
|
123
|
+
root.find(f".//link[@name='{link_name}']/visual/geometry/mesh").get("filename") is not None)
|
|
124
|
+
and (
|
|
125
|
+
# Extract the basename (without path and extension)
|
|
126
|
+
root.find(f".//link[@name='{link_name}']/visual/geometry/mesh")
|
|
127
|
+
.get("filename")
|
|
128
|
+
.split("/")[-1]
|
|
129
|
+
.split(".")[0]
|
|
130
|
+
)
|
|
131
|
+
or (
|
|
132
|
+
SDKLogger.warn(f"Warning: {link_name} is not found or incomplete in robot_desc"),
|
|
133
|
+
None
|
|
134
|
+
)[1] # Return None after printing the warning
|
|
135
|
+
)
|
|
136
|
+
leg_joint_names = [process_link_name(link_name) for link_name in leg_link_names if process_link_name(link_name) is not None]
|
|
137
|
+
arm_joint_names = [process_link_name(link_name) for link_name in arm_link_names if process_link_name(link_name) is not None]
|
|
138
|
+
head_joint_names = [process_link_name(link_name) for link_name in head_link_names if process_link_name(link_name) is not None]
|
|
139
|
+
|
|
140
|
+
if len(leg_link_names) != len(leg_joint_names):
|
|
141
|
+
SDKLogger.warn(f"leg_joint_names is not equal to leg_link_names, {len(leg_link_names)} != {len(leg_joint_names)}")
|
|
142
|
+
return None
|
|
143
|
+
if len(arm_link_names)!= len(arm_joint_names):
|
|
144
|
+
SDKLogger.warn(f"arm_joint_names is not equal to arm_link_names, {len(arm_link_names)}!= {len(arm_joint_names)}")
|
|
145
|
+
return None
|
|
146
|
+
if len(head_link_names)!= len(head_joint_names):
|
|
147
|
+
SDKLogger.warn(f"head_joint_names is not equal to head_link_names, {len(head_link_names)}!= {len(head_joint_names)}")
|
|
148
|
+
return None
|
|
149
|
+
|
|
150
|
+
return leg_joint_names + arm_joint_names + head_joint_names
|
|
151
|
+
|
|
152
|
+
kuavo_ros_info = None
|
|
153
|
+
|
|
154
|
+
def end_frames_names()->dict:
|
|
155
|
+
default = ["torso", "zarm_l7_link", "zarm_r7_link", "zarm_l4_link", "zarm_r4_link"]
|
|
156
|
+
|
|
157
|
+
kuavo_ros_param = RosParameter()
|
|
158
|
+
|
|
159
|
+
kuavo_json = kuavo_ros_param.kuavo_config()
|
|
160
|
+
if kuavo_json is None:
|
|
161
|
+
return default
|
|
162
|
+
|
|
163
|
+
try:
|
|
164
|
+
kuavo_config = json.loads(kuavo_json)
|
|
165
|
+
if kuavo_config.get('end_frames_names') is not None:
|
|
166
|
+
return kuavo_config.get('end_frames_names')
|
|
167
|
+
else:
|
|
168
|
+
return default
|
|
169
|
+
except Exception as e:
|
|
170
|
+
print(f"Failed to get end_frames_names from kuavo_json: {e}")
|
|
171
|
+
return default
|
|
172
|
+
|
|
173
|
+
def make_robot_param()->dict:
|
|
174
|
+
global kuavo_ros_info
|
|
175
|
+
if kuavo_ros_info is not None:
|
|
176
|
+
return kuavo_ros_info
|
|
177
|
+
|
|
178
|
+
kuavo_ros_param = RosParameter()
|
|
179
|
+
|
|
180
|
+
kuavo_ros_info = {
|
|
181
|
+
'robot_version': kuavo_ros_param.robot_version(),
|
|
182
|
+
'arm_dof': kuavo_ros_param.arm_dof(),
|
|
183
|
+
'head_dof': kuavo_ros_param.head_dof(),
|
|
184
|
+
'leg_dof': kuavo_ros_param.leg_dof(),
|
|
185
|
+
'end_effector_type': kuavo_ros_param.end_effector_type(),
|
|
186
|
+
'joint_names': joint_names(),
|
|
187
|
+
'end_frames_names': end_frames_names(),
|
|
188
|
+
'init_stand_height': kuavo_ros_param.init_stand_height()
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
for key, value in kuavo_ros_info.items():
|
|
192
|
+
if value is None and key != 'end_effector_type':
|
|
193
|
+
SDKLogger.debug(f"[Error]: Failed to get '{key}' from ROS.")
|
|
194
|
+
kuavo_ros_info = None
|
|
195
|
+
raise Exception(f"[Error]: Failed to get '{key}' from ROS.")
|
|
196
|
+
|
|
197
|
+
return kuavo_ros_info
|
|
198
|
+
|
|
199
|
+
if __name__ == "__main__":
|
|
200
|
+
rospy.init_node("kuavo_ros_param_test")
|
|
201
|
+
print(make_robot_param())
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
class RotatingRectangle:
|
|
4
|
+
def __init__(self, center, width, height, angle):
|
|
5
|
+
self.center = center
|
|
6
|
+
self.width = width
|
|
7
|
+
self.height = height
|
|
8
|
+
self.angle = angle
|
|
9
|
+
|
|
10
|
+
def set_rotation(self, angle):
|
|
11
|
+
self.angle = angle
|
|
12
|
+
|
|
13
|
+
def rotate_point(self, point):
|
|
14
|
+
"""旋转点"""
|
|
15
|
+
px, py = point
|
|
16
|
+
cos_theta = np.cos(self.angle)
|
|
17
|
+
sin_theta = np.sin(self.angle)
|
|
18
|
+
return (cos_theta * px - sin_theta * py, sin_theta * px + cos_theta * py)
|
|
19
|
+
|
|
20
|
+
def get_vertices(self):
|
|
21
|
+
"""获取旋转长方形的顶点"""
|
|
22
|
+
cx, cy = self.center
|
|
23
|
+
half_w, half_h = self.width / 2, self.height / 2
|
|
24
|
+
vertices = [
|
|
25
|
+
(half_w, half_h),
|
|
26
|
+
(-half_w, half_h),
|
|
27
|
+
(-half_w, -half_h),
|
|
28
|
+
(half_w, -half_h)
|
|
29
|
+
]
|
|
30
|
+
return [(cx + x, cy + y) for x, y in (self.rotate_point(v) for v in vertices)]
|
|
31
|
+
|
|
32
|
+
@staticmethod
|
|
33
|
+
def project(vertices, axis):
|
|
34
|
+
"""将顶点投影到轴上"""
|
|
35
|
+
projections = [np.dot(v, axis) for v in vertices]
|
|
36
|
+
return min(projections), max(projections)
|
|
37
|
+
|
|
38
|
+
@staticmethod
|
|
39
|
+
def is_separating_axis(vertices1, vertices2, axis):
|
|
40
|
+
"""检查是否为分离轴"""
|
|
41
|
+
min1, max1 = RotatingRectangle.project(vertices1, axis)
|
|
42
|
+
min2, max2 = RotatingRectangle.project(vertices2, axis)
|
|
43
|
+
return max1 < min2 or max2 < min1
|
|
44
|
+
|
|
45
|
+
def is_collision(self, other):
|
|
46
|
+
"""检测两个旋转长方形是否发生碰撞"""
|
|
47
|
+
vertices1 = self.get_vertices()
|
|
48
|
+
vertices2 = other.get_vertices()
|
|
49
|
+
|
|
50
|
+
# 获取所有可能的分离轴
|
|
51
|
+
axes = []
|
|
52
|
+
for i in range(4):
|
|
53
|
+
edge = (vertices1[i][0] - vertices1[i-1][0], vertices1[i][1] - vertices1[i-1][1])
|
|
54
|
+
axis = (-edge[1], edge[0])
|
|
55
|
+
axes.append(axis)
|
|
56
|
+
for i in range(4):
|
|
57
|
+
edge = (vertices2[i][0] - vertices2[i-1][0], vertices2[i][1] - vertices2[i-1][1])
|
|
58
|
+
axis = (-edge[1], edge[0])
|
|
59
|
+
axes.append(axis)
|
|
60
|
+
|
|
61
|
+
# 检查所有轴上的投影是否重叠
|
|
62
|
+
for axis in axes:
|
|
63
|
+
if self.is_separating_axis(vertices1, vertices2, axis):
|
|
64
|
+
return False
|
|
65
|
+
return True
|
|
66
|
+
|
|
67
|
+
def show(self, color):
|
|
68
|
+
"""绘制旋转长方形"""
|
|
69
|
+
vertices = self.get_vertices()
|
|
70
|
+
vertices.append(vertices[0]) # 闭合多边形
|
|
71
|
+
xs, ys = zip(*vertices)
|
|
72
|
+
plt.fill(xs, ys, color=color, alpha=0.5)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
# 示例
|
|
76
|
+
if __name__ == "__main__":
|
|
77
|
+
rect1 = RotatingRectangle(center=(0, 0.1), width=0.2, height=0.1, angle=0)
|
|
78
|
+
rect2 = RotatingRectangle(center=(0, -0.1), width=0.2, height=0.1, angle=0)
|
|
79
|
+
|
|
80
|
+
collision = rect1.is_collision(rect2)
|
|
81
|
+
print("发生碰撞:", collision)
|
|
82
|
+
|
|
83
|
+
rect1.set_rotation(-np.pi / 4)
|
|
84
|
+
rect2.set_rotation(np.pi / 4)
|
|
85
|
+
collision = rect1.is_collision(rect2)
|
|
86
|
+
print("发生碰撞:", collision)
|
|
87
|
+
|
|
88
|
+
# visualize
|
|
89
|
+
import matplotlib.pyplot as plt
|
|
90
|
+
# 绘制长方形
|
|
91
|
+
plt.figure()
|
|
92
|
+
rect1.show(color='blue')
|
|
93
|
+
rect2.show(color='red')
|
|
94
|
+
|
|
95
|
+
# 设置显示区域
|
|
96
|
+
plt.xlim(-0.3, 0.3)
|
|
97
|
+
plt.ylim(-0.3, 0.3)
|
|
98
|
+
plt.xlabel('x')
|
|
99
|
+
plt.ylabel('y')
|
|
100
|
+
plt.gca().set_aspect('equal', adjustable='box')
|
|
101
|
+
plt.grid()
|
|
102
|
+
plt.title(f'Rotated Rectangle Collision Detection: {collision}')
|
|
103
|
+
plt.show()
|