feat(lekiwi): release V0.10.1 初步集成 LeKiwi,优化碰撞模型
集成通用机器人数值接口、本机控制桥、LeRobot 插件和统一键盘遥操作。采用离线 CoACD 全臂碰撞配方 revision 4、局部装配区切分与结构自接触,限制直接关节位姿写入并保留安全看门狗。同步版本号、变更记录、来源许可证和兼容性验证。
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
"""Run the installed upstream's pure methods, without constructing a hardware robot."""
|
||||
|
||||
import ast
|
||||
import importlib.metadata
|
||||
import json
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
import numpy as np
|
||||
|
||||
|
||||
class UpstreamKinematicsTests(unittest.TestCase):
|
||||
def test_actual_061_methods_match_shared_wheel_fixture(self):
|
||||
self.assertEqual(importlib.metadata.version("lerobot"), "0.6.1")
|
||||
path = importlib.metadata.distribution("lerobot").locate_file(
|
||||
"lerobot/robots/lekiwi/lekiwi.py"
|
||||
)
|
||||
tree = ast.parse(path.read_text())
|
||||
robot = next(
|
||||
node for node in tree.body if isinstance(node, ast.ClassDef) and node.name == "LeKiwi"
|
||||
)
|
||||
names = {"_degps_to_raw", "_raw_to_degps", "_body_to_wheel_raw", "_wheel_raw_to_body"}
|
||||
methods = [
|
||||
node for node in robot.body if isinstance(node, ast.FunctionDef) and node.name in names
|
||||
]
|
||||
self.assertEqual({node.name for node in methods}, names)
|
||||
# Only the four audited numeric methods. No imports, constructors, buses or cameras.
|
||||
cls = ast.ClassDef(
|
||||
name="PureKinematics",
|
||||
bases=[],
|
||||
keywords=[],
|
||||
body=methods,
|
||||
decorator_list=[],
|
||||
type_params=[],
|
||||
)
|
||||
namespace = {"np": np, "Any": Any}
|
||||
module = ast.fix_missing_locations(ast.Module(body=[cls], type_ignores=[]))
|
||||
exec(compile(module, str(path), "exec"), namespace)
|
||||
pure = namespace["PureKinematics"]()
|
||||
fixture = json.loads(
|
||||
(
|
||||
Path(__file__).resolve().parents[3] / "contracts/fixtures/lekiwi-kinematics.json"
|
||||
).read_text()
|
||||
)
|
||||
for case in fixture["cases"]:
|
||||
with self.subTest(body=case["body"]):
|
||||
raw = pure._body_to_wheel_raw(*case["body"])
|
||||
self.assertEqual(list(raw), fixture["wheelOrder"])
|
||||
self.assertEqual(list(raw.values()), case["wheelRaw"])
|
||||
if max(abs(v) for v in case["wheelRaw"]) < 3000:
|
||||
body = pure._wheel_raw_to_body(*case["wheelRaw"])
|
||||
for observed, expected in zip(body.values(), case["body"], strict=True):
|
||||
self.assertAlmostEqual(observed, expected, delta=0.02)
|
||||
Reference in New Issue
Block a user