Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta"
# PyPI distribution name. Prefixed with "far-" to avoid colliding with any
# upstream Unitree project. The IMPORT name is unchanged: `import unitree_interface`.
name = "far-unitree-sdk"
version = "0.1.4"
version = "0.1.5"
description = "Unitree robot SDK Python bindings (FAR fork)"
readme = "README.md"
# Binary-only distribution (no sdist fallback): every interpreter allowed here
Expand Down
35 changes: 19 additions & 16 deletions python_binding/unitree_interface.pyi
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""
Type definitions for General Unitree Interface Python bindings
"""
from typing import List, Any, Optional
from typing import List, Any, Optional, overload
from enum import Enum

# Constants
Expand All @@ -18,21 +18,21 @@ GO2_GO2_CONFIG: RobotConfig

class RobotType(Enum):
"""Robot types supported by the interface"""
G1: int # G1 humanoid (29 motors)
H1: int # H1 humanoid (19 motors)
H1_2: int # H1-2 humanoid (29 motors)
GO2: int # GO2 quadruped (12 motors)
CUSTOM: int # Custom robot with specified motor count
G1 = ... # G1 humanoid (29 motors)
H1 = ... # H1 humanoid (19 motors)
H1_2 = ... # H1-2 humanoid (29 motors)
GO2 = ... # GO2 quadruped (12 motors)
CUSTOM = ... # Custom robot with specified motor count

class MessageType(Enum):
"""Message types for robot communication"""
HG: int # Humanoid/Go1 message format
GO2: int # Go2 message format
HG = ... # Humanoid/Go1 message format
GO2 = ... # Go2 message format

class ControlMode(Enum):
"""Control mode for robots"""
PR: int # Pitch/Roll mode
AB: int # A/B mode
PR = ... # Pitch/Roll mode
AB = ... # A/B mode

class RobotConfig:
"""Robot configuration structure"""
Expand Down Expand Up @@ -103,34 +103,37 @@ class LowState:

class UnitreeInterface:
"""Main interface class for general Unitree robot control"""

def __init__(self, network_interface: str, robot_type: RobotType,

@overload
def __init__(self, network_interface: str, robot_type: RobotType,
message_type: MessageType) -> None:
"""
Initialize UnitreeInterface with robot type and message type

Args:
network_interface: Network interface name (e.g., "eth0", "enp2s0")
robot_type: Type of robot (G1, H1, H1_2, GO2, CUSTOM)
message_type: Message format (HG or GO2)
"""
...

@overload
def __init__(self, network_interface: str, config: RobotConfig) -> None:
"""
Initialize UnitreeInterface with robot configuration

Args:
network_interface: Network interface name (e.g., "eth0", "enp2s0")
config: Robot configuration
"""
...

def __init__(self, network_interface: str, robot_type: RobotType,
@overload
def __init__(self, network_interface: str, robot_type: RobotType,
message_type: MessageType, num_motors: int) -> None:
"""
Initialize UnitreeInterface with custom motor count

Args:
network_interface: Network interface name (e.g., "eth0", "enp2s0")
robot_type: Type of robot (G1, H1, H1_2, GO2, CUSTOM)
Expand Down
35 changes: 27 additions & 8 deletions scripts/cibw_before_build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -53,17 +53,36 @@ cp -v "thirdparty/lib/$ARCH/"*.so* unitree_interface/ 2>/dev/null || true
[ -f libfastcdr.so ] && ln -sf libfastcdr.so libfastcdr.so.2 || true
)

# Generate type stubs (best-effort; never fail the build over stubs). Importing
# the module requires its staged DDS deps on the loader path. Wrapped in `if` so
# a stubgen/import failure is non-fatal under `set -e`.
if PYTHONPATH="unitree_interface:${PYTHONPATH:-}" \
LD_LIBRARY_PATH="$PWD/unitree_interface:${LD_LIBRARY_PATH:-}" \
pybind11-stubgen -o "$BUILD_DIR/stubs" unitree_interface >/dev/null 2>&1; then
cp -v "$BUILD_DIR/stubs/unitree_interface.pyi" unitree_interface/ 2>/dev/null || true
# Stage the type stub. The authoritative, hand-maintained stub lives at
# python_binding/unitree_interface.pyi and is the source of truth for the public
# API — prefer it so the wheel is reproducible and does not depend on
# pybind11-stubgen succeeding inside the manylinux container (importing the freshly
# linked extension there is fragile because of the vendored DDS .so deps).
# pybind11-stubgen is only a fallback for a checkout that somehow lacks the committed
# stub, and it must actually produce the file — no silent skip.
if [ -f python_binding/unitree_interface.pyi ]; then
cp -v python_binding/unitree_interface.pyi unitree_interface/unitree_interface.pyi
echo "[before-build] staged committed stub python_binding/unitree_interface.pyi"
elif PYTHONPATH="unitree_interface:${PYTHONPATH:-}" \
LD_LIBRARY_PATH="$PWD/unitree_interface:${LD_LIBRARY_PATH:-}" \
pybind11-stubgen -o "$BUILD_DIR/stubs" unitree_interface \
&& [ -f "$BUILD_DIR/stubs/unitree_interface.pyi" ]; then
cp -v "$BUILD_DIR/stubs/unitree_interface.pyi" unitree_interface/unitree_interface.pyi
echo "[before-build] staged stubgen-generated stub"
else
echo "[before-build] stub generation skipped (non-fatal)"
echo "[before-build] ERROR: no unitree_interface.pyi available (committed stub missing and stubgen failed)" >&2
exit 1
fi

# Ship py.typed ONLY alongside a real .pyi. A py.typed marker without a stub makes
# mypy treat the compiled extension as a typed-but-empty module and report
# `attr-defined` on every symbol downstream (exactly the holosoma CI break this
# fixes) — worse than shipping no type info at all. Fail loudly rather than
# regress that.
if [ ! -f unitree_interface/unitree_interface.pyi ]; then
echo "[before-build] ERROR: refusing to write py.typed without a .pyi stub" >&2
exit 1
fi
touch unitree_interface/py.typed
echo "[before-build] staged files:"
ls -la unitree_interface/
2 changes: 1 addition & 1 deletion uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.