update
This commit is contained in:
parent
bd79b8fbd1
commit
5735d899fb
@ -160,3 +160,60 @@ class CameraClient:
|
|||||||
except grpc.RpcError as e:
|
except grpc.RpcError as e:
|
||||||
print(f"停止录像失败: {e}")
|
print(f"停止录像失败: {e}")
|
||||||
return CMVRErrorCode.CMVR_RPC_FAILED
|
return CMVRErrorCode.CMVR_RPC_FAILED
|
||||||
|
|
||||||
|
def create_rgb_stream_request(self):
|
||||||
|
"""创建流请求(无参数)"""
|
||||||
|
generated = self._import_generated()
|
||||||
|
request = generated.camera_command_pb2.GetRGBImageStreamCommand.Request()
|
||||||
|
request.header.CopyFrom(self._create_command_header())
|
||||||
|
# 不需要设置其他参数
|
||||||
|
return request
|
||||||
|
|
||||||
|
def get_rgb_stream(self, request_generator):
|
||||||
|
"""
|
||||||
|
双向流获取传感器数据
|
||||||
|
参数:
|
||||||
|
request_generator: 请求生成器
|
||||||
|
返回:
|
||||||
|
传感器数据流迭代器
|
||||||
|
"""
|
||||||
|
generated = self._import_generated()
|
||||||
|
return self.stub.GetRGBImageStream(request_generator)
|
||||||
|
|
||||||
|
def create_depth_stream_request(self):
|
||||||
|
"""创建流请求(无参数)"""
|
||||||
|
generated = self._import_generated()
|
||||||
|
request = generated.camera_command_pb2.GetDepthImageStreamCommand.Request()
|
||||||
|
request.header.CopyFrom(self._create_command_header())
|
||||||
|
# 不需要设置其他参数
|
||||||
|
return request
|
||||||
|
|
||||||
|
def get_depth_stream(self, request_generator):
|
||||||
|
"""
|
||||||
|
双向流获取传感器数据
|
||||||
|
参数:
|
||||||
|
request_generator: 请求生成器
|
||||||
|
返回:
|
||||||
|
传感器数据流迭代器
|
||||||
|
"""
|
||||||
|
generated = self._import_generated()
|
||||||
|
return self.stub.GetDepthImageStream(request_generator)
|
||||||
|
|
||||||
|
def create_rgbd_stream_request(self):
|
||||||
|
"""创建流请求(无参数)"""
|
||||||
|
generated = self._import_generated()
|
||||||
|
request = generated.camera_command_pb2.GetRGBDImageStreamCommand.Request()
|
||||||
|
request.header.CopyFrom(self._create_command_header())
|
||||||
|
# 不需要设置其他参数
|
||||||
|
return request
|
||||||
|
|
||||||
|
def get_rgbd_stream(self, request_generator):
|
||||||
|
"""
|
||||||
|
双向流获取传感器数据
|
||||||
|
参数:
|
||||||
|
request_generator: 请求生成器
|
||||||
|
返回:
|
||||||
|
传感器数据流迭代器
|
||||||
|
"""
|
||||||
|
generated = self._import_generated()
|
||||||
|
return self.stub.GetRGBDImageStream(request_generator)
|
||||||
@ -5,7 +5,8 @@ from .enums import CMVRErrorCode
|
|||||||
from .biohead_client import BioHeadClient
|
from .biohead_client import BioHeadClient
|
||||||
from .camera_client import CameraClient
|
from .camera_client import CameraClient
|
||||||
from .dexhand_client import DexHandClient
|
from .dexhand_client import DexHandClient
|
||||||
|
from .micphone_client import MicphoneClient
|
||||||
|
from .speaker_client import SpeakerClient
|
||||||
class CMVRGrpcClient:
|
class CMVRGrpcClient:
|
||||||
"""CMVR gRPC 主客户端"""
|
"""CMVR gRPC 主客户端"""
|
||||||
|
|
||||||
@ -27,6 +28,12 @@ class CMVRGrpcClient:
|
|||||||
self.dexhand_stub = None
|
self.dexhand_stub = None
|
||||||
self.dexhand_map: Dict[str, DexHandClient] = {}
|
self.dexhand_map: Dict[str, DexHandClient] = {}
|
||||||
|
|
||||||
|
self.micphone_stub = None
|
||||||
|
self.micphone_map: Dict[str, MicphoneClient] = {}
|
||||||
|
|
||||||
|
self.speaker_stub = None
|
||||||
|
self.speaker_map: Dict[str, SpeakerClient] = {}
|
||||||
|
|
||||||
# 检查连接状态
|
# 检查连接状态
|
||||||
try:
|
try:
|
||||||
grpc.channel_ready_future(self.channel).result(timeout=5)
|
grpc.channel_ready_future(self.channel).result(timeout=5)
|
||||||
@ -38,6 +45,10 @@ class CMVRGrpcClient:
|
|||||||
|
|
||||||
self.dexhand_stub = self.generated.dexhand_service_pb2_grpc.DexHandServiceStub(self.channel)
|
self.dexhand_stub = self.generated.dexhand_service_pb2_grpc.DexHandServiceStub(self.channel)
|
||||||
|
|
||||||
|
self.speaker_stub = self.generated.speaker_service_pb2_grpc.SpeakerServiceStub(self.channel)
|
||||||
|
|
||||||
|
self.micphone_stub = self.generated.microphone_service_pb2_grpc.MicPhoneServiceStub(self.channel)
|
||||||
|
|
||||||
except grpc.FutureTimeoutError:
|
except grpc.FutureTimeoutError:
|
||||||
print(f"连接服务器超时: {server_address}")
|
print(f"连接服务器超时: {server_address}")
|
||||||
self.connected = False
|
self.connected = False
|
||||||
@ -53,6 +64,11 @@ class CMVRGrpcClient:
|
|||||||
from generated.cmvr.api import camera_command_pb2
|
from generated.cmvr.api import camera_command_pb2
|
||||||
from generated.cmvr.api import dexhand_command_pb2
|
from generated.cmvr.api import dexhand_command_pb2
|
||||||
from generated.cmvr.api import dexhand_service_pb2_grpc
|
from generated.cmvr.api import dexhand_service_pb2_grpc
|
||||||
|
from generated.cmvr.api import speaker_command_pb2
|
||||||
|
from generated.cmvr.api import speaker_service_pb2_grpc
|
||||||
|
from generated.cmvr.api import microphone_command_pb2
|
||||||
|
from generated.cmvr.api import microphone_service_pb2_grpc
|
||||||
|
|
||||||
self.generated = type('GeneratedModules', (), {
|
self.generated = type('GeneratedModules', (), {
|
||||||
'biohead_service_pb2_grpc': biohead_service_pb2_grpc,
|
'biohead_service_pb2_grpc': biohead_service_pb2_grpc,
|
||||||
'common_pb2': common_pb2,
|
'common_pb2': common_pb2,
|
||||||
@ -60,7 +76,11 @@ class CMVRGrpcClient:
|
|||||||
'camera_service_pb2_grpc': camera_service_pb2_grpc,
|
'camera_service_pb2_grpc': camera_service_pb2_grpc,
|
||||||
'camera_command_pb2': camera_command_pb2,
|
'camera_command_pb2': camera_command_pb2,
|
||||||
'dexhand_service_pb2_grpc': dexhand_service_pb2_grpc,
|
'dexhand_service_pb2_grpc': dexhand_service_pb2_grpc,
|
||||||
'dexhand_command_pb2': dexhand_command_pb2
|
'dexhand_command_pb2': dexhand_command_pb2,
|
||||||
|
'speaker_service_pb2_grpc': speaker_service_pb2_grpc,
|
||||||
|
'speaker_command_pb2': speaker_command_pb2,
|
||||||
|
'microphone_service_pb2_grpc': microphone_service_pb2_grpc,
|
||||||
|
'microphone_command_pb2': microphone_command_pb2
|
||||||
})
|
})
|
||||||
|
|
||||||
except ImportError as e:
|
except ImportError as e:
|
||||||
@ -89,6 +109,16 @@ class CMVRGrpcClient:
|
|||||||
self.dexhand_map[device_id] = DexHandClient(device_id, self.dexhand_stub)
|
self.dexhand_map[device_id] = DexHandClient(device_id, self.dexhand_stub)
|
||||||
return self.dexhand_map[device_id]
|
return self.dexhand_map[device_id]
|
||||||
|
|
||||||
|
def get_speaker(self, device_id: str) -> SpeakerClient:
|
||||||
|
if device_id not in self.speaker_map:
|
||||||
|
self.speaker_map[device_id] = SpeakerClient(device_id, self.speaker_stub)
|
||||||
|
return self.speaker_map[device_id]
|
||||||
|
|
||||||
|
def get_micphone(self, device_id: str) -> MicphoneClient:
|
||||||
|
if device_id not in self.micphone_map:
|
||||||
|
self.micphone_map[device_id] = MicphoneClient(device_id, self.micphone_stub)
|
||||||
|
return self.micphone_map[device_id]
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
"""关闭所有连接"""
|
"""关闭所有连接"""
|
||||||
# 关闭所有流式连接
|
# 关闭所有流式连接
|
||||||
|
|||||||
@ -231,21 +231,6 @@ class DexHandClient:
|
|||||||
print(f"获取灵巧手传感器数据失败: {e}")
|
print(f"获取灵巧手传感器数据失败: {e}")
|
||||||
return CMVRErrorCode.CMVR_RPC_FAILED, HandTactileSensors()
|
return CMVRErrorCode.CMVR_RPC_FAILED, HandTactileSensors()
|
||||||
|
|
||||||
def sensor_data_stream(self):
|
|
||||||
try:
|
|
||||||
generated = self._import_generated()
|
|
||||||
# 创建传感器数据请求
|
|
||||||
request = generated.dexhand_command_pb2.GetSensorDataCommand.Request()
|
|
||||||
request.header.CopyFrom(self._create_command_header())
|
|
||||||
|
|
||||||
# 调用RPC接口获取数据
|
|
||||||
response = self.stub.GetSensorData(request)
|
|
||||||
|
|
||||||
if not response.header.success:
|
|
||||||
return CMVRErrorCode.CMVR_RPC_FAILED, HandTactileSensors()
|
|
||||||
except grpc.RpcError as e:
|
|
||||||
print(f"获取灵巧手传感器数据失败: {e}")
|
|
||||||
|
|
||||||
def create_stream_request(self):
|
def create_stream_request(self):
|
||||||
"""创建流请求(无参数)"""
|
"""创建流请求(无参数)"""
|
||||||
generated = self._import_generated()
|
generated = self._import_generated()
|
||||||
|
|||||||
196
example_usage.py
196
example_usage.py
@ -231,6 +231,82 @@ def test_camera():
|
|||||||
|
|
||||||
client.close()
|
client.close()
|
||||||
|
|
||||||
|
def test_rgb_image_stream():
|
||||||
|
"""测试双向流视频帧数据接口"""
|
||||||
|
print("=== 测试双向流视频帧数据接口 ===")
|
||||||
|
|
||||||
|
# 初始化GRPC客户端
|
||||||
|
client = CMVRGrpcClient("192.168.1.222:50060")
|
||||||
|
if not client.is_connected():
|
||||||
|
print("连接服务器失败")
|
||||||
|
return
|
||||||
|
|
||||||
|
# 获取camera客户端
|
||||||
|
camera = client.get_camera("cam4")
|
||||||
|
if not camera:
|
||||||
|
print("获取camera客户端失败")
|
||||||
|
client.close()
|
||||||
|
return
|
||||||
|
# 启动相机
|
||||||
|
start_result = camera.start_camera()
|
||||||
|
if start_result == CMVRErrorCode.CMVR_SUCCESS:
|
||||||
|
print("相机启动成功")
|
||||||
|
else:
|
||||||
|
print(f"相机启动失败,错误码: {start_result}")
|
||||||
|
client.close()
|
||||||
|
return
|
||||||
|
# 等待相机启动
|
||||||
|
time.sleep(1)
|
||||||
|
try:
|
||||||
|
# 1. 启动传感器数据流
|
||||||
|
print("\n--- 启动rgb数据流 ---")
|
||||||
|
# 创建请求生成器(双向流不需要参数,发送空请求)
|
||||||
|
def request_generator() -> Generator:
|
||||||
|
# 发送初始请求启动流
|
||||||
|
yield camera.create_rgb_stream_request()
|
||||||
|
# 保持流连接,每5秒发送一次心跳(可选)
|
||||||
|
try:
|
||||||
|
while True:
|
||||||
|
time.sleep(5)
|
||||||
|
# 发送空请求保持连接
|
||||||
|
yield camera.create_rgb_stream_request()
|
||||||
|
except GeneratorExit:
|
||||||
|
print("请求生成器已关闭")
|
||||||
|
return
|
||||||
|
|
||||||
|
# 2. 接收并处理流数据
|
||||||
|
print("开始接收rgb流数据(5秒后自动停止)...")
|
||||||
|
start_time = time.time()
|
||||||
|
stream_duration = 15 # 接收15秒数据
|
||||||
|
|
||||||
|
keyframe_count = 0 # 关键帧计数器
|
||||||
|
total_frame_count = 0 # 总帧数计数器
|
||||||
|
# 存储流迭代器的变量
|
||||||
|
stream_iterator = camera.get_rgb_stream(request_generator())
|
||||||
|
# 调用双向流接口
|
||||||
|
for feedback in stream_iterator:
|
||||||
|
# 检查是否超时
|
||||||
|
if time.time() - start_time > stream_duration:
|
||||||
|
print("\n达到预设接收时间,停止接收")
|
||||||
|
break
|
||||||
|
total_frame_count += 1 # 累加总帧数
|
||||||
|
# 检查是否为关键帧并计数
|
||||||
|
if feedback.color_frame.is_key_frame:
|
||||||
|
keyframe_count += 1
|
||||||
|
print(f"[关键帧 #{keyframe_count}] 收到关键帧 (总帧数: {total_frame_count})")
|
||||||
|
stream_iterator.cancel()
|
||||||
|
print(f"\n流接收结束 - 总帧数: {total_frame_count}, 关键帧数: {keyframe_count}, 关键帧占比: {keyframe_count/total_frame_count:.2%}")
|
||||||
|
|
||||||
|
|
||||||
|
except grpc.RpcError as e:
|
||||||
|
print(f"双向流通信错误: {e}")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"处理流数据时发生错误: {e}")
|
||||||
|
finally:
|
||||||
|
# 关闭连接
|
||||||
|
client.close()
|
||||||
|
print("\n=== 双向流传感器数据测试完成 ===")
|
||||||
|
|
||||||
def test_dexhand():
|
def test_dexhand():
|
||||||
"""测试DexHand功能(获取状态、设置角度和传感器数据)"""
|
"""测试DexHand功能(获取状态、设置角度和传感器数据)"""
|
||||||
print("=== 测试DexHand功能 ===")
|
print("=== 测试DexHand功能 ===")
|
||||||
@ -466,8 +542,126 @@ def test_sensor_data_stream():
|
|||||||
# 关闭连接
|
# 关闭连接
|
||||||
client.close()
|
client.close()
|
||||||
print("\n=== 双向流传感器数据测试完成 ===")
|
print("\n=== 双向流传感器数据测试完成 ===")
|
||||||
|
|
||||||
|
def test_speaker():
|
||||||
|
"""测试扬声器功能"""
|
||||||
|
print("\n=== 测试扬声器功能 ===")
|
||||||
|
|
||||||
|
# 初始化GRPC客户端
|
||||||
|
client = CMVRGrpcClient("192.168.1.222:50060")
|
||||||
|
if not client.is_connected():
|
||||||
|
print("连接服务器失败")
|
||||||
|
return
|
||||||
|
|
||||||
|
speaker = client.get_speaker("spk1")
|
||||||
|
if speaker is None:
|
||||||
|
print("获取扬声器失败")
|
||||||
|
return
|
||||||
|
|
||||||
|
# 获取状态
|
||||||
|
result, status = speaker.get_status()
|
||||||
|
if result == CMVRErrorCode.CMVR_SUCCESS:
|
||||||
|
print(f"扬声器状态: 初始化={status.is_initialized}, 运行中={status.is_running}")
|
||||||
|
else:
|
||||||
|
print(f"获取扬声器状态失败,错误码: {result}")
|
||||||
|
|
||||||
|
# 设置音量
|
||||||
|
result = speaker.set_volume(80) # 80%音量
|
||||||
|
if result == CMVRErrorCode.CMVR_SUCCESS:
|
||||||
|
print("设置音量成功")
|
||||||
|
else:
|
||||||
|
print(f"设置音量失败,错误码: {result}")
|
||||||
|
|
||||||
|
# 获取音量
|
||||||
|
result, volume = speaker.get_volume()
|
||||||
|
if result == CMVRErrorCode.CMVR_SUCCESS:
|
||||||
|
print(f"当前音量: {volume}%")
|
||||||
|
else:
|
||||||
|
print(f"获取音量失败,错误码: {result}")
|
||||||
|
|
||||||
|
# 播放音频 (需要替换为实际存在的音频文件路径)
|
||||||
|
audio_path = "/home/share/assets/upload/员工女_车内温度有点低,是否需要调高空调?.wav"
|
||||||
|
print(f"尝试播放音频: {audio_path}")
|
||||||
|
result = speaker.play_audio(audio_path)
|
||||||
|
if result == CMVRErrorCode.CMVR_SUCCESS:
|
||||||
|
print("开始播放音频")
|
||||||
|
|
||||||
|
# 等待3秒
|
||||||
|
time.sleep(3)
|
||||||
|
|
||||||
|
# 暂停播放
|
||||||
|
result = speaker.pause_audio()
|
||||||
|
if result == CMVRErrorCode.CMVR_SUCCESS:
|
||||||
|
print("暂停播放")
|
||||||
|
|
||||||
|
# 等待1秒
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
# 继续播放
|
||||||
|
result = speaker.resume_audio()
|
||||||
|
if result == CMVRErrorCode.CMVR_SUCCESS:
|
||||||
|
print("继续播放")
|
||||||
|
|
||||||
|
# 等待2秒
|
||||||
|
time.sleep(2)
|
||||||
|
|
||||||
|
# 停止播放
|
||||||
|
result = speaker.stop_audio()
|
||||||
|
if result == CMVRErrorCode.CMVR_SUCCESS:
|
||||||
|
print("停止播放")
|
||||||
|
else:
|
||||||
|
print(f"停止播放失败,错误码: {result}")
|
||||||
|
else:
|
||||||
|
print(f"继续播放失败,错误码: {result}")
|
||||||
|
else:
|
||||||
|
print(f"暂停播放失败,错误码: {result}")
|
||||||
|
else:
|
||||||
|
print(f"播放音频失败,错误码: {result}")
|
||||||
|
|
||||||
|
def test_microphone():
|
||||||
|
"""测试麦克风功能"""
|
||||||
|
print("\n=== 测试麦克风功能 ===")
|
||||||
|
# 初始化GRPC客户端
|
||||||
|
client = CMVRGrpcClient("192.168.1.222:50060")
|
||||||
|
if not client.is_connected():
|
||||||
|
print("连接服务器失败")
|
||||||
|
return
|
||||||
|
|
||||||
|
microphone = client.get_micphone("mic2")
|
||||||
|
if microphone is None:
|
||||||
|
print("获取麦克风失败")
|
||||||
|
return
|
||||||
|
|
||||||
|
# 获取状态
|
||||||
|
result, status = microphone.get_status()
|
||||||
|
if result == CMVRErrorCode.CMVR_SUCCESS:
|
||||||
|
print(f"麦克风状态: 初始化={status.is_initialized}, 录音中={status.is_recording}")
|
||||||
|
else:
|
||||||
|
print(f"获取麦克风状态失败,错误码: {result}")
|
||||||
|
|
||||||
|
# 开始录音
|
||||||
|
audio_path = "/home/linbo/Data/Audio/recorded_audio.mp3"
|
||||||
|
result = microphone.start_record(audio_path)
|
||||||
|
if result == CMVRErrorCode.CMVR_SUCCESS:
|
||||||
|
print(f"开始录音,保存到: {audio_path}")
|
||||||
|
|
||||||
|
# 录音5秒
|
||||||
|
time.sleep(5)
|
||||||
|
|
||||||
|
# 停止录音
|
||||||
|
result = microphone.stop_record()
|
||||||
|
if result == CMVRErrorCode.CMVR_SUCCESS:
|
||||||
|
print("停止录音")
|
||||||
|
else:
|
||||||
|
print(f"停止录音失败,错误码: {result}")
|
||||||
|
else:
|
||||||
|
print(f"开始录音失败,错误码: {result}")
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
test_biohead()
|
# test_biohead()
|
||||||
# test_camera()
|
# test_camera()
|
||||||
|
# test_rgb_image_stream()
|
||||||
# test_dexhand()
|
# test_dexhand()
|
||||||
# test_sensor_data_stream()
|
# test_sensor_data_stream()
|
||||||
|
# test_speaker()
|
||||||
|
test_microphone()
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user