feat:add readme.txt
This commit is contained in:
parent
a7413e293c
commit
6b9bf3be30
3
.idea/grpc_client.iml
generated
3
.idea/grpc_client.iml
generated
@ -2,9 +2,10 @@
|
|||||||
<module type="PYTHON_MODULE" version="4">
|
<module type="PYTHON_MODULE" version="4">
|
||||||
<component name="NewModuleRootManager">
|
<component name="NewModuleRootManager">
|
||||||
<content url="file://$MODULE_DIR$">
|
<content url="file://$MODULE_DIR$">
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/generated" isTestSource="false" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/.venv" />
|
<excludeFolder url="file://$MODULE_DIR$/.venv" />
|
||||||
</content>
|
</content>
|
||||||
<orderEntry type="inheritedJdk" />
|
<orderEntry type="jdk" jdkName="grpc_client" jdkType="Python SDK" />
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
</component>
|
</component>
|
||||||
</module>
|
</module>
|
||||||
2
.idea/misc.xml
generated
2
.idea/misc.xml
generated
@ -3,5 +3,5 @@
|
|||||||
<component name="Black">
|
<component name="Black">
|
||||||
<option name="sdkName" value="Python 3.8 (grpc_client)" />
|
<option name="sdkName" value="Python 3.8 (grpc_client)" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.9" project-jdk-type="Python SDK" />
|
<component name="ProjectRootManager" version="2" project-jdk-name="grpc_client" project-jdk-type="Python SDK" />
|
||||||
</project>
|
</project>
|
||||||
44
README.md
Normal file
44
README.md
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
# grpc_client
|
||||||
|
|
||||||
|
## Environment
|
||||||
|
|
||||||
|
- Python: 3.9.25
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pip install -r requirements.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
## Generate gRPC code
|
||||||
|
|
||||||
|
From repo root:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python scripts/gen_grpc_py.py
|
||||||
|
```
|
||||||
|
|
||||||
|
This reads `.proto` files under `protos/` and writes Python code to `generated/`.
|
||||||
|
|
||||||
|
## Run (module mode)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python -m clients.movej_client
|
||||||
|
python -m clients.get_joint_state_client
|
||||||
|
python -m clients.get_pose_client
|
||||||
|
python -m clients.torque_on_client
|
||||||
|
python -m clients.torque_off_client
|
||||||
|
python -m clients.torque_key_client
|
||||||
|
python -m clients.press_client
|
||||||
|
python -m clients.save_joint_to_csv
|
||||||
|
python -m clients.http_server
|
||||||
|
```
|
||||||
|
|
||||||
|
## Runtime parameters
|
||||||
|
|
||||||
|
- gRPC server address/port: set in `clients/base_client.py` (default `192.168.0.222:50052`).
|
||||||
|
- HTTP server host/port: set in `clients/http_server.py` (default `0.0.0.0:8000`).
|
||||||
|
- `device_id` defaults to `hc01` in most clients; change in code if needed.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Binary file not shown.
BIN
clients/__pycache__/_path_setup.cpython-39.pyc
Normal file
BIN
clients/__pycache__/_path_setup.cpython-39.pyc
Normal file
Binary file not shown.
Binary file not shown.
BIN
clients/__pycache__/get_joint_state_client.cpython-39.pyc
Normal file
BIN
clients/__pycache__/get_joint_state_client.cpython-39.pyc
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
11
clients/_path_setup.py
Normal file
11
clients/_path_setup.py
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
from pathlib import Path
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
def ensure_paths() -> None:
|
||||||
|
root = Path(__file__).resolve().parents[1]
|
||||||
|
generated = root / "generated"
|
||||||
|
for path in (root, generated):
|
||||||
|
path_str = str(path)
|
||||||
|
if path_str not in sys.path:
|
||||||
|
sys.path.insert(0, path_str)
|
||||||
@ -1,13 +1,14 @@
|
|||||||
import grpc
|
|
||||||
import time
|
import time
|
||||||
import sys
|
|
||||||
from pathlib import Path
|
|
||||||
BASE_DIR = Path(__file__).resolve().parent.parent # 上一级目录
|
|
||||||
|
|
||||||
sys.path.append(str(BASE_DIR / "generated"))
|
import grpc
|
||||||
sys.path.append(str(BASE_DIR / "generated" / "cmvr"))
|
|
||||||
from cmvr.api import humanoid_robot_service_pb2_grpc
|
from clients._path_setup import ensure_paths
|
||||||
|
|
||||||
|
ensure_paths()
|
||||||
|
|
||||||
from cmvr.api import dexhand_service_pb2_grpc
|
from cmvr.api import dexhand_service_pb2_grpc
|
||||||
|
from cmvr.api import humanoid_robot_service_pb2_grpc
|
||||||
|
|
||||||
|
|
||||||
class RobotClientBase:
|
class RobotClientBase:
|
||||||
def __init__(self, address="192.168.0.222:50052", timeout=2, retries=1):
|
def __init__(self, address="192.168.0.222:50052", timeout=2, retries=1):
|
||||||
|
|||||||
165
clients/cal.py
165
clients/cal.py
@ -1,165 +0,0 @@
|
|||||||
|
|
||||||
import csv
|
|
||||||
|
|
||||||
import math
|
|
||||||
import sys
|
|
||||||
from google.protobuf import timestamp_pb2
|
|
||||||
|
|
||||||
sys.path.append("../generated")
|
|
||||||
import math
|
|
||||||
from typing import List, Dict, Literal
|
|
||||||
from generated.cmvr.api import humanoid_robot_command_pb2 as pb
|
|
||||||
from generated.cmvr.api import common_pb2
|
|
||||||
from generated.cmvr.api import humanoid_robot_service_pb2_grpc as rpc
|
|
||||||
from clients.base_client import RobotClientBase
|
|
||||||
|
|
||||||
|
|
||||||
class MoveJClient(RobotClientBase):
|
|
||||||
"""Client to send MoveJ commands to the robot"""
|
|
||||||
|
|
||||||
def send(self, joint_list, vel=1.0, acc=0.5, device_id="hc01"):
|
|
||||||
"""
|
|
||||||
joint_list: list of dicts, e.g.,
|
|
||||||
[
|
|
||||||
{"joint_name": "L_SHOULDER_P", "rad": 0.0},
|
|
||||||
{"joint_name": "L_SHOULDER_R", "rad": -1.31873},
|
|
||||||
...
|
|
||||||
]
|
|
||||||
vel: velocity
|
|
||||||
acc: acceleration
|
|
||||||
device_id: device ID
|
|
||||||
"""
|
|
||||||
# Construct JointCmd list
|
|
||||||
cmds = [pb.JointCmd(joint_name=j["joint_name"], rad=j["rad"], vel=vel) for j in joint_list]
|
|
||||||
|
|
||||||
# Construct request header
|
|
||||||
header = common_pb2.CommandHeader.Request()
|
|
||||||
header.device_id = device_id
|
|
||||||
ts = timestamp_pb2.Timestamp()
|
|
||||||
ts.GetCurrentTime()
|
|
||||||
header.timestamp.CopyFrom(ts)
|
|
||||||
|
|
||||||
# Construct MoveJ request
|
|
||||||
req = pb.MoveJ.Request(
|
|
||||||
header=header,
|
|
||||||
vel=vel,
|
|
||||||
acc=acc,
|
|
||||||
cmds=cmds
|
|
||||||
)
|
|
||||||
|
|
||||||
# Call RPC
|
|
||||||
try:
|
|
||||||
resp = self.stub.moveJ(req, timeout=10)
|
|
||||||
success = getattr(resp.header, "success", None)
|
|
||||||
error_msg = getattr(resp.header, "error_message", "")
|
|
||||||
timestamp_sec = getattr(resp.header.timestamp, "seconds", 0)
|
|
||||||
print("MoveJ RPC call succeeded")
|
|
||||||
print(f"Success: {success}")
|
|
||||||
print(f"Error message: {error_msg}")
|
|
||||||
print(f"Timestamp: {timestamp_sec}")
|
|
||||||
except Exception as e:
|
|
||||||
print("MoveJ RPC call failed:", e)
|
|
||||||
|
|
||||||
def read_joint_from_csv(self, file_name, row_num):
|
|
||||||
"""Read joint data from a CSV file and return joint list for the specified row."""
|
|
||||||
joint_order = [
|
|
||||||
'R_SHOULDER_P', 'R_SHOULDER_R', 'R_SHOULDER_Y',
|
|
||||||
'R_ELBOW_R', 'R_WRIST_P', 'R_WRIST_Y', 'R_WRIST_R'
|
|
||||||
]
|
|
||||||
|
|
||||||
try:
|
|
||||||
with open(file_name, newline='') as csvfile:
|
|
||||||
reader = csv.reader(csvfile)
|
|
||||||
# Skip header row
|
|
||||||
next(reader)
|
|
||||||
# Read specific row
|
|
||||||
for i, row in enumerate(reader, start=1):
|
|
||||||
if i == row_num:
|
|
||||||
# Assign joint values to the list
|
|
||||||
joint_list = [
|
|
||||||
{'joint_name': joint_order[j], 'rad': round(float(row[j]) * math.pi / 180, 10)}
|
|
||||||
for j in range(len(joint_order))
|
|
||||||
]
|
|
||||||
return joint_list
|
|
||||||
print(f"Row {row_num} not found.")
|
|
||||||
return []
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Error reading CSV: {e}")
|
|
||||||
return []
|
|
||||||
|
|
||||||
def apply_joint_offsets(self,
|
|
||||||
joint_list: List[Dict[str, float]],
|
|
||||||
on_missing: Literal["ignore", "error", "warn"] = "ignore",
|
|
||||||
) -> List[Dict[str, float]]:
|
|
||||||
"""
|
|
||||||
将零偏置 joint_zero_offset 叠加到 joint_list 上,按 joint_name 对齐。
|
|
||||||
|
|
||||||
参数:
|
|
||||||
joint_list: [{'joint_name': str, 'rad': float}, ...] 原始指令
|
|
||||||
joint_zero_offset: [{'joint_name': str, 'rad': float}, ...] 零偏置
|
|
||||||
on_missing: 当 joint_list 中出现 zero_offset 里没有的关节名时的处理:
|
|
||||||
- "ignore": 当作偏置为 0(默认)
|
|
||||||
- "warn": 打印警告,再当作 0
|
|
||||||
- "error": 抛出 KeyError
|
|
||||||
|
|
||||||
返回:
|
|
||||||
与 joint_list 顺序一致、已叠加偏置的新列表
|
|
||||||
"""
|
|
||||||
# 构造偏置表,并检查是否有重复关节名
|
|
||||||
|
|
||||||
deg_to_rad = math.pi / 180.0
|
|
||||||
|
|
||||||
joint_zero_offset = [
|
|
||||||
{'joint_name': 'R_SHOULDER_P', 'rad': 0},
|
|
||||||
{'joint_name': 'R_SHOULDER_R', 'rad': 0 * deg_to_rad},
|
|
||||||
{'joint_name': 'R_SHOULDER_Y', 'rad': 0.2 * deg_to_rad},
|
|
||||||
{'joint_name': 'R_ELBOW_R', 'rad': 0.2 * deg_to_rad},
|
|
||||||
{'joint_name': 'R_WRIST_P', 'rad': 0.6 * deg_to_rad},
|
|
||||||
{'joint_name': 'R_WRIST_Y', 'rad': 2.5 * deg_to_rad},
|
|
||||||
{'joint_name': 'R_WRIST_R', 'rad': 0},
|
|
||||||
]
|
|
||||||
|
|
||||||
offset_map: Dict[str, float] = {}
|
|
||||||
for j in joint_zero_offset:
|
|
||||||
name = j["joint_name"]
|
|
||||||
if name in offset_map:
|
|
||||||
raise ValueError(f"Duplicated joint in zero_offset: {name}")
|
|
||||||
offset_map[name] = float(j["rad"])
|
|
||||||
|
|
||||||
joint_cmd: List[Dict[str, float]] = []
|
|
||||||
for j in joint_list:
|
|
||||||
name = j["joint_name"]
|
|
||||||
base = float(j["rad"])
|
|
||||||
if name not in offset_map:
|
|
||||||
if on_missing == "error":
|
|
||||||
raise KeyError(f"Missing zero offset for joint: {name}")
|
|
||||||
elif on_missing == "warn":
|
|
||||||
print(f"[apply_joint_offsets] WARN: Missing zero offset for {name}, using 0.0")
|
|
||||||
off = 0.0
|
|
||||||
else:
|
|
||||||
off = offset_map[name]
|
|
||||||
|
|
||||||
joint_cmd.append({"joint_name": name, "rad": base + off})
|
|
||||||
return joint_cmd
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
# Initialize client
|
|
||||||
client = MoveJClient()
|
|
||||||
|
|
||||||
# Specify CSV file and row number to read from
|
|
||||||
file_name = 'joint_states.csv'
|
|
||||||
row_num = 2 # Row number you want to read (e.g., 2 for the second row)
|
|
||||||
|
|
||||||
# Read joint data from CSV
|
|
||||||
joint_list = client.read_joint_from_csv(file_name, 8)
|
|
||||||
joint_list = client.apply_joint_offsets(joint_list)
|
|
||||||
print(joint_list)
|
|
||||||
|
|
||||||
if joint_list:
|
|
||||||
|
|
||||||
# Send MoveJ command with the read joint data
|
|
||||||
client.send(joint_list, vel=0.8, acc=0.8)
|
|
||||||
|
|
||||||
# Close client
|
|
||||||
client.close()
|
|
||||||
@ -1,14 +1,14 @@
|
|||||||
import sys
|
|
||||||
import time
|
import time
|
||||||
from google.protobuf import timestamp_pb2
|
from google.protobuf import timestamp_pb2
|
||||||
|
|
||||||
import matplotlib.pyplot as plt # 新增
|
import matplotlib.pyplot as plt # 新增
|
||||||
|
|
||||||
sys.path.append("../generated")
|
from clients._path_setup import ensure_paths
|
||||||
|
|
||||||
|
ensure_paths()
|
||||||
|
|
||||||
from generated.cmvr.api import humanoid_robot_service_pb2_grpc as rpc
|
|
||||||
from generated.cmvr.api import humanoid_robot_command_pb2 as pb
|
|
||||||
from clients.base_client import RobotClientBase
|
from clients.base_client import RobotClientBase
|
||||||
|
from cmvr.api import humanoid_robot_command_pb2 as pb
|
||||||
|
from cmvr.api import humanoid_robot_service_pb2_grpc as rpc
|
||||||
|
|
||||||
# 固定关节顺序
|
# 固定关节顺序
|
||||||
JOINT_ORDER = [
|
JOINT_ORDER = [
|
||||||
@ -88,12 +88,11 @@ class GetJointStateClient(RobotClientBase):
|
|||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
print("\nStopped fetching joint states.")
|
print("\nStopped fetching joint states.")
|
||||||
# 例子:退出时画几个关节的角度 & 速度曲线
|
# 例子:退出时画几个关节的角度 & 速度曲线
|
||||||
# try:
|
try:
|
||||||
# # 你可以根据需要改关节列表
|
# 你可以根据需要改关节列表
|
||||||
# self.plot_pos_and_vel([ "R_SHOULDER_P", "R_SHOULDER_R", "R_SHOULDER_Y",
|
self.plot_pos_and_vel([ "L_SHOULDER_R"])
|
||||||
# "R_ELBOW_R", "R_WRIST_P", "R_WRIST_Y", "R_WRIST_R"])
|
except Exception as e:
|
||||||
# except Exception as e:
|
print(f"绘图失败: {e}")
|
||||||
# print(f"绘图失败: {e}")
|
|
||||||
|
|
||||||
# ====== 3. 绘制速度和角度(同一张图,两行子图) ======
|
# ====== 3. 绘制速度和角度(同一张图,两行子图) ======
|
||||||
def plot_pos_and_vel(self, joint_names):
|
def plot_pos_and_vel(self, joint_names):
|
||||||
|
|||||||
@ -1,12 +1,14 @@
|
|||||||
import sys
|
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
from clients._path_setup import ensure_paths
|
||||||
|
|
||||||
|
ensure_paths()
|
||||||
|
|
||||||
from google.protobuf import timestamp_pb2
|
from google.protobuf import timestamp_pb2
|
||||||
|
|
||||||
sys.path.append("../generated")
|
|
||||||
|
|
||||||
from generated.cmvr.api import humanoid_robot_service_pb2_grpc as rpc
|
|
||||||
from generated.cmvr.api import humanoid_robot_command_pb2 as pb
|
|
||||||
from clients.base_client import RobotClientBase
|
from clients.base_client import RobotClientBase
|
||||||
|
from cmvr.api import humanoid_robot_command_pb2 as pb
|
||||||
|
from cmvr.api import humanoid_robot_service_pb2_grpc as rpc
|
||||||
|
|
||||||
|
|
||||||
class GetPoseClient(RobotClientBase):
|
class GetPoseClient(RobotClientBase):
|
||||||
|
|||||||
@ -1,12 +1,12 @@
|
|||||||
import sys
|
from clients._path_setup import ensure_paths
|
||||||
|
|
||||||
|
ensure_paths()
|
||||||
|
|
||||||
from google.protobuf import timestamp_pb2
|
from google.protobuf import timestamp_pb2
|
||||||
|
|
||||||
sys.path.append("../generated")
|
|
||||||
|
|
||||||
|
|
||||||
from generated.cmvr.api import dexhand_command_pb2 as pb
|
|
||||||
from generated.cmvr.api import common_pb2
|
|
||||||
from clients.base_client import RobotClientBase
|
from clients.base_client import RobotClientBase
|
||||||
|
from cmvr.api import common_pb2
|
||||||
|
from cmvr.api import dexhand_command_pb2 as pb
|
||||||
|
|
||||||
|
|
||||||
handshake = [
|
handshake = [
|
||||||
|
|||||||
@ -1,5 +1,9 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from clients._path_setup import ensure_paths
|
||||||
|
|
||||||
|
ensure_paths()
|
||||||
|
|
||||||
import time
|
import time
|
||||||
from threading import Lock
|
from threading import Lock
|
||||||
from fastapi import FastAPI
|
from fastapi import FastAPI
|
||||||
|
|||||||
@ -1,18 +1,18 @@
|
|||||||
import sys
|
import math
|
||||||
import time
|
import time
|
||||||
|
from typing import Dict, List, Literal
|
||||||
|
|
||||||
|
from clients._path_setup import ensure_paths
|
||||||
|
|
||||||
|
ensure_paths()
|
||||||
|
|
||||||
from google.protobuf import timestamp_pb2
|
from google.protobuf import timestamp_pb2
|
||||||
|
|
||||||
from clients.hand_client import DexHandClient
|
|
||||||
|
|
||||||
sys.path.append("../generated")
|
|
||||||
|
|
||||||
from generated.cmvr.api import humanoid_robot_command_pb2 as pb
|
|
||||||
from generated.cmvr.api import common_pb2
|
|
||||||
from generated.cmvr.api import humanoid_robot_service_pb2_grpc as rpc
|
|
||||||
from clients.base_client import RobotClientBase
|
from clients.base_client import RobotClientBase
|
||||||
import math
|
from clients.hand_client import DexHandClient
|
||||||
from typing import List, Dict, Literal
|
from cmvr.api import common_pb2
|
||||||
|
from cmvr.api import humanoid_robot_command_pb2 as pb
|
||||||
|
from cmvr.api import humanoid_robot_service_pb2_grpc as rpc
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -212,7 +212,7 @@ head_screen_joint_list = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
singal_joint_list = [
|
singal_joint_list = [
|
||||||
{'joint_name': 'R_WRIST_P', 'rad': 0.217252876821},
|
{'joint_name': 'L_SHOULDER_R', 'rad': 0},
|
||||||
]
|
]
|
||||||
|
|
||||||
hand_touch = [
|
hand_touch = [
|
||||||
@ -263,6 +263,18 @@ hello_r_joint_list = [
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
test_joint_list = [
|
||||||
|
# {'joint_name': 'R_SHOULDER_P', 'rad':0},
|
||||||
|
{'joint_name': 'R_SHOULDER_R', 'rad': 0},
|
||||||
|
# {'joint_name': 'R_SHOULDER_Y', 'rad': 0},
|
||||||
|
# {'joint_name': 'R_ELBOW_R', 'rad':0},
|
||||||
|
# {'joint_name': 'R_WRIST_P', 'rad': 0},
|
||||||
|
# {'joint_name': 'R_WRIST_Y', 'rad': 0},
|
||||||
|
# {'joint_name': 'R_WRIST_R', 'rad': 0},
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|
||||||
@ -363,8 +375,8 @@ if __name__ == "__main__":
|
|||||||
# Initialize client
|
# Initialize client
|
||||||
|
|
||||||
# action_air(client)
|
# action_air(client)
|
||||||
action_hello(client)
|
# action_hello(client)
|
||||||
# client.send(head_front_joint_list, vel=1.0, acc=1.0)
|
client.send(test_joint_list, vel=1.0, acc=1.0)
|
||||||
# client.send(go_home_joint_list, vel=3.0, acc=3.0)
|
# client.send(go_home_joint_list, vel=3.0, acc=3.0)
|
||||||
# action_music(client)
|
# action_music(client)
|
||||||
|
|
||||||
|
|||||||
@ -1,10 +1,11 @@
|
|||||||
import sys
|
from clients._path_setup import ensure_paths
|
||||||
|
|
||||||
|
ensure_paths()
|
||||||
|
|
||||||
from google.protobuf import timestamp_pb2
|
from google.protobuf import timestamp_pb2
|
||||||
|
|
||||||
sys.path.append("../generated")
|
|
||||||
|
|
||||||
from generated.cmvr.api import hlc_command_pb2 as pb
|
|
||||||
from clients.base_client import RobotClientBase
|
from clients.base_client import RobotClientBase
|
||||||
|
from cmvr.api import hlc_command_pb2 as pb
|
||||||
|
|
||||||
|
|
||||||
class TouchClient(RobotClientBase):
|
class TouchClient(RobotClientBase):
|
||||||
|
|||||||
@ -1,13 +1,15 @@
|
|||||||
import sys
|
|
||||||
import csv
|
import csv
|
||||||
import math
|
import math
|
||||||
|
|
||||||
|
from clients._path_setup import ensure_paths
|
||||||
|
|
||||||
|
ensure_paths()
|
||||||
|
|
||||||
from google.protobuf import timestamp_pb2
|
from google.protobuf import timestamp_pb2
|
||||||
|
|
||||||
sys.path.append("../generated")
|
|
||||||
|
|
||||||
from generated.cmvr.api import humanoid_robot_service_pb2_grpc as rpc
|
|
||||||
from generated.cmvr.api import humanoid_robot_command_pb2 as pb
|
|
||||||
from clients.base_client import RobotClientBase
|
from clients.base_client import RobotClientBase
|
||||||
|
from cmvr.api import humanoid_robot_command_pb2 as pb
|
||||||
|
from cmvr.api import humanoid_robot_service_pb2_grpc as rpc
|
||||||
|
|
||||||
|
|
||||||
class GetJointStateClient(RobotClientBase):
|
class GetJointStateClient(RobotClientBase):
|
||||||
|
|||||||
@ -1,19 +1,17 @@
|
|||||||
|
|
||||||
import sys
|
import sys
|
||||||
import tty
|
|
||||||
import termios
|
import termios
|
||||||
|
import tty
|
||||||
|
|
||||||
|
from clients._path_setup import ensure_paths
|
||||||
|
|
||||||
|
ensure_paths()
|
||||||
|
|
||||||
from google.protobuf import timestamp_pb2
|
from google.protobuf import timestamp_pb2
|
||||||
|
|
||||||
# sys.path.append("../generated")
|
from clients.base_client import RobotClientBase
|
||||||
sys.path.append("/home/lgv/cmvr/0-workspace/grpc_client/generated") # 指向 generated
|
|
||||||
sys.path.append("/home/lgv/cmvr/0-workspace/grpc_client/generated/cmvr") # 指向 cmvr 顶层
|
|
||||||
|
|
||||||
from cmvr.api import humanoid_robot_service_pb2_grpc as rpc
|
|
||||||
from cmvr.api import humanoid_robot_command_pb2 as pb
|
|
||||||
from cmvr.api import common_pb2
|
from cmvr.api import common_pb2
|
||||||
|
from cmvr.api import humanoid_robot_command_pb2 as pb
|
||||||
|
from cmvr.api import humanoid_robot_service_pb2_grpc as rpc
|
||||||
from base_client import RobotClientBase
|
|
||||||
|
|
||||||
|
|
||||||
class TorqueClient(RobotClientBase):
|
class TorqueClient(RobotClientBase):
|
||||||
|
|||||||
@ -1,12 +1,13 @@
|
|||||||
import sys
|
from clients._path_setup import ensure_paths
|
||||||
|
|
||||||
|
ensure_paths()
|
||||||
|
|
||||||
from google.protobuf import timestamp_pb2
|
from google.protobuf import timestamp_pb2
|
||||||
|
|
||||||
sys.path.append("../generated")
|
|
||||||
|
|
||||||
from generated.cmvr.api import humanoid_robot_service_pb2_grpc as rpc
|
|
||||||
from generated.cmvr.api import humanoid_robot_command_pb2 as pb
|
|
||||||
from generated.cmvr.api import common_pb2
|
|
||||||
from clients.base_client import RobotClientBase
|
from clients.base_client import RobotClientBase
|
||||||
|
from cmvr.api import common_pb2
|
||||||
|
from cmvr.api import humanoid_robot_command_pb2 as pb
|
||||||
|
from cmvr.api import humanoid_robot_service_pb2_grpc as rpc
|
||||||
|
|
||||||
|
|
||||||
class TorqueOffClient(RobotClientBase):
|
class TorqueOffClient(RobotClientBase):
|
||||||
|
|||||||
@ -1,12 +1,13 @@
|
|||||||
import sys
|
from clients._path_setup import ensure_paths
|
||||||
|
|
||||||
|
ensure_paths()
|
||||||
|
|
||||||
from google.protobuf import timestamp_pb2
|
from google.protobuf import timestamp_pb2
|
||||||
|
|
||||||
sys.path.append("../generated")
|
|
||||||
|
|
||||||
from generated.cmvr.api import humanoid_robot_service_pb2_grpc as rpc
|
|
||||||
from generated.cmvr.api import humanoid_robot_command_pb2 as pb
|
|
||||||
from generated.cmvr.api import common_pb2
|
|
||||||
from clients.base_client import RobotClientBase
|
from clients.base_client import RobotClientBase
|
||||||
|
from cmvr.api import common_pb2
|
||||||
|
from cmvr.api import humanoid_robot_command_pb2 as pb
|
||||||
|
from cmvr.api import humanoid_robot_service_pb2_grpc as rpc
|
||||||
|
|
||||||
|
|
||||||
class TorqueOnClient(RobotClientBase):
|
class TorqueOnClient(RobotClientBase):
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
8
requirements.txt
Normal file
8
requirements.txt
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
fastapi==0.124.4
|
||||||
|
grpcio==1.76.0
|
||||||
|
grpcio-tools==1.76.0
|
||||||
|
matplotlib==3.9.4
|
||||||
|
protobuf==6.33.2
|
||||||
|
pydantic==2.12.5
|
||||||
|
requests==2.32.5
|
||||||
|
uvicorn==0.38.0
|
||||||
@ -1,9 +1,9 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
"""
|
"""
|
||||||
统一启动 gRPC 客户端脚本
|
Unified entrypoint for running client scripts.
|
||||||
自动设置 PYTHONPATH,让 generated 下的 cmvr 包可用
|
|
||||||
用法:
|
Usage:
|
||||||
python run_client.py get_joint_state_client
|
python run_client.py get_joint_state_client
|
||||||
python run_client.py movej_client
|
python run_client.py movej_client
|
||||||
"""
|
"""
|
||||||
@ -16,20 +16,25 @@ PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__))
|
|||||||
GENERATED_DIR = os.path.join(PROJECT_ROOT, "generated")
|
GENERATED_DIR = os.path.join(PROJECT_ROOT, "generated")
|
||||||
CLIENTS_DIR = os.path.join(PROJECT_ROOT, "clients")
|
CLIENTS_DIR = os.path.join(PROJECT_ROOT, "clients")
|
||||||
|
|
||||||
# 添加 generated 到 PYTHONPATH
|
|
||||||
sys.path.insert(0, GENERATED_DIR)
|
|
||||||
os.environ["PYTHONPATH"] = GENERATED_DIR + os.pathsep + os.environ.get("PYTHONPATH", "")
|
|
||||||
|
|
||||||
if len(sys.argv) < 2:
|
if len(sys.argv) < 2:
|
||||||
print("请指定要运行的客户端脚本名,例如:get_joint_state_client")
|
print("Please provide a client script name, e.g. get_joint_state_client")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
client_name = sys.argv[1]
|
client_name = sys.argv[1]
|
||||||
client_script = os.path.join(CLIENTS_DIR, f"{client_name}.py")
|
client_script = os.path.join(CLIENTS_DIR, f"{client_name}.py")
|
||||||
|
|
||||||
if not os.path.isfile(client_script):
|
if not os.path.isfile(client_script):
|
||||||
print(f"客户端脚本不存在: {client_script}")
|
print(f"Client script not found: {client_script}")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
# 支持传递额外参数给客户端
|
module_name = f"clients.{client_name}"
|
||||||
subprocess.run([sys.executable, client_script] + sys.argv[2:])
|
env = os.environ.copy()
|
||||||
|
extra_paths = [PROJECT_ROOT, GENERATED_DIR]
|
||||||
|
existing = env.get("PYTHONPATH", "")
|
||||||
|
env["PYTHONPATH"] = os.pathsep.join(extra_paths + ([existing] if existing else []))
|
||||||
|
|
||||||
|
subprocess.run(
|
||||||
|
[sys.executable, "-m", module_name] + sys.argv[2:],
|
||||||
|
cwd=PROJECT_ROOT,
|
||||||
|
env=env,
|
||||||
|
)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user