├── unitree_sdk2py ├── core │ ├── __init__.py │ ├── __pycache__ │ │ └── __init__.cpython-38.pyc │ ├── channel_name.py │ └── channel_config.py ├── rpc │ ├── __init__.py │ ├── __pycache__ │ │ └── __init__.cpython-38.pyc │ ├── internal.py │ ├── server_base.py │ ├── request_future.py │ ├── client_stub.py │ ├── server_stub.py │ ├── client.py │ ├── lease_client.py │ ├── client_base.py │ ├── server.py │ └── lease_server.py ├── utils │ ├── __init__.py │ ├── lib │ │ ├── crc_amd64.so │ │ └── crc_aarch64.so │ ├── __pycache__ │ │ └── __init__.cpython-38.pyc │ ├── singleton.py │ ├── clib_lookup.py │ ├── hz_sample.py │ ├── timerfd.py │ ├── bqueue.py │ ├── thread.py │ ├── future.py │ ├── joystick.py │ └── crc.py ├── comm │ └── motion_switcher │ │ ├── __init__.py │ │ ├── motion_switcher_api.py │ │ └── motion_switcher_client.py ├── __pycache__ │ └── __init__.cpython-38.pyc ├── idl │ ├── __pycache__ │ │ ├── default.cpython-38.pyc │ │ └── __init__.cpython-38.pyc │ ├── nav_msgs │ │ ├── __pycache__ │ │ │ └── __init__.cpython-38.pyc │ │ ├── msg │ │ │ ├── __pycache__ │ │ │ │ └── __init__.cpython-38.pyc │ │ │ ├── dds_ │ │ │ │ ├── __pycache__ │ │ │ │ │ ├── __init__.cpython-38.pyc │ │ │ │ │ ├── _Odometry_.cpython-38.pyc │ │ │ │ │ ├── _MapMetaData_.cpython-38.pyc │ │ │ │ │ └── _OccupancyGrid_.cpython-38.pyc │ │ │ │ ├── __init__.py │ │ │ │ ├── _OccupancyGrid_.py │ │ │ │ ├── _Odometry_.py │ │ │ │ └── _MapMetaData_.py │ │ │ └── __init__.py │ │ └── __init__.py │ ├── std_msgs │ │ ├── __pycache__ │ │ │ └── __init__.cpython-38.pyc │ │ ├── msg │ │ │ ├── __pycache__ │ │ │ │ └── __init__.cpython-38.pyc │ │ │ ├── dds_ │ │ │ │ ├── __pycache__ │ │ │ │ │ ├── _Header_.cpython-38.pyc │ │ │ │ │ ├── _String_.cpython-38.pyc │ │ │ │ │ └── __init__.cpython-38.pyc │ │ │ │ ├── __init__.py │ │ │ │ ├── _String_.py │ │ │ │ └── _Header_.py │ │ │ └── __init__.py │ │ └── __init__.py │ ├── sensor_msgs │ │ ├── __pycache__ │ │ │ └── __init__.cpython-38.pyc │ │ ├── msg │ │ │ ├── __pycache__ │ │ │ │ └── __init__.cpython-38.pyc │ │ │ ├── dds_ │ │ │ │ ├── __pycache__ │ │ │ │ │ ├── __init__.cpython-38.pyc │ │ │ │ │ ├── _PointCloud2_.cpython-38.pyc │ │ │ │ │ └── _PointField_.cpython-38.pyc │ │ │ │ ├── PointField_Constants │ │ │ │ │ ├── __pycache__ │ │ │ │ │ │ ├── __init__.cpython-38.pyc │ │ │ │ │ │ └── _PointField_.cpython-38.pyc │ │ │ │ │ ├── __init__.py │ │ │ │ │ └── _PointField_.py │ │ │ │ ├── __init__.py │ │ │ │ ├── _PointField_.py │ │ │ │ └── _PointCloud2_.py │ │ │ └── __init__.py │ │ └── __init__.py │ ├── unitree_api │ │ ├── __pycache__ │ │ │ └── __init__.cpython-38.pyc │ │ ├── msg │ │ │ ├── __pycache__ │ │ │ │ └── __init__.cpython-38.pyc │ │ │ ├── dds_ │ │ │ │ ├── __pycache__ │ │ │ │ │ ├── _Request_.cpython-38.pyc │ │ │ │ │ ├── __init__.cpython-38.pyc │ │ │ │ │ ├── _Response_.cpython-38.pyc │ │ │ │ │ ├── _RequestLease_.cpython-38.pyc │ │ │ │ │ ├── _RequestHeader_.cpython-38.pyc │ │ │ │ │ ├── _RequestPolicy_.cpython-38.pyc │ │ │ │ │ ├── _ResponseHeader_.cpython-38.pyc │ │ │ │ │ ├── _ResponseStatus_.cpython-38.pyc │ │ │ │ │ └── _RequestIdentity_.cpython-38.pyc │ │ │ │ ├── __init__.py │ │ │ │ ├── _RequestLease_.py │ │ │ │ ├── _ResponseStatus_.py │ │ │ │ ├── _RequestPolicy_.py │ │ │ │ ├── _RequestIdentity_.py │ │ │ │ ├── _Request_.py │ │ │ │ ├── _Response_.py │ │ │ │ ├── _ResponseHeader_.py │ │ │ │ └── _RequestHeader_.py │ │ │ └── __init__.py │ │ └── __init__.py │ ├── unitree_hg │ │ ├── __pycache__ │ │ │ └── __init__.cpython-38.pyc │ │ ├── msg │ │ │ ├── __pycache__ │ │ │ │ └── __init__.cpython-38.pyc │ │ │ ├── dds_ │ │ │ │ ├── __pycache__ │ │ │ │ │ ├── _BmsCmd_.cpython-38.pyc │ │ │ │ │ ├── _BmsState_.cpython-38.pyc │ │ │ │ │ ├── _HandCmd_.cpython-38.pyc │ │ │ │ │ ├── _IMUState_.cpython-38.pyc │ │ │ │ │ ├── _LowCmd_.cpython-38.pyc │ │ │ │ │ ├── _LowState_.cpython-38.pyc │ │ │ │ │ ├── _MotorCmd_.cpython-38.pyc │ │ │ │ │ ├── __init__.cpython-38.pyc │ │ │ │ │ ├── _HandState_.cpython-38.pyc │ │ │ │ │ ├── _MotorState_.cpython-38.pyc │ │ │ │ │ ├── _MainBoardState_.cpython-38.pyc │ │ │ │ │ └── _PressSensorState_.cpython-38.pyc │ │ │ │ ├── _BmsCmd_.py │ │ │ │ ├── __init__.py │ │ │ │ ├── _HandCmd_.py │ │ │ │ ├── _MotorCmd_.py │ │ │ │ ├── _PressSensorState_.py │ │ │ │ ├── _MainBoardState_.py │ │ │ │ ├── _LowCmd_.py │ │ │ │ ├── _IMUState_.py │ │ │ │ ├── _MotorState_.py │ │ │ │ ├── _LowState_.py │ │ │ │ ├── _BmsState_.py │ │ │ │ └── _HandState_.py │ │ │ └── __init__.py │ │ └── __init__.py │ ├── geometry_msgs │ │ ├── __pycache__ │ │ │ └── __init__.cpython-38.pyc │ │ ├── msg │ │ │ ├── __pycache__ │ │ │ │ └── __init__.cpython-38.pyc │ │ │ ├── dds_ │ │ │ │ ├── __pycache__ │ │ │ │ │ ├── _Point_.cpython-38.pyc │ │ │ │ │ ├── _Pose_.cpython-38.pyc │ │ │ │ │ ├── _Twist_.cpython-38.pyc │ │ │ │ │ ├── _Point32_.cpython-38.pyc │ │ │ │ │ ├── _Pose2D_.cpython-38.pyc │ │ │ │ │ ├── _Vector3_.cpython-38.pyc │ │ │ │ │ ├── __init__.cpython-38.pyc │ │ │ │ │ ├── _Quaternion_.cpython-38.pyc │ │ │ │ │ ├── _PointStamped_.cpython-38.pyc │ │ │ │ │ ├── _PoseStamped_.cpython-38.pyc │ │ │ │ │ ├── _TwistStamped_.cpython-38.pyc │ │ │ │ │ ├── _QuaternionStamped_.cpython-38.pyc │ │ │ │ │ ├── _PoseWithCovariance_.cpython-38.pyc │ │ │ │ │ ├── _TwistWithCovariance_.cpython-38.pyc │ │ │ │ │ ├── _PoseWithCovarianceStamped_.cpython-38.pyc │ │ │ │ │ └── _TwistWithCovarianceStamped_.cpython-38.pyc │ │ │ │ ├── _Point_.py │ │ │ │ ├── _Point32_.py │ │ │ │ ├── _Pose2D_.py │ │ │ │ ├── _Vector3_.py │ │ │ │ ├── _Quaternion_.py │ │ │ │ ├── _Pose_.py │ │ │ │ ├── _Twist_.py │ │ │ │ ├── _PoseWithCovariance_.py │ │ │ │ ├── _TwistWithCovariance_.py │ │ │ │ ├── _PointStamped_.py │ │ │ │ ├── _PoseStamped_.py │ │ │ │ ├── _TwistStamped_.py │ │ │ │ ├── _QuaternionStamped_.py │ │ │ │ ├── _PoseWithCovarianceStamped_.py │ │ │ │ ├── _TwistWithCovarianceStamped_.py │ │ │ │ └── __init__.py │ │ │ └── __init__.py │ │ └── __init__.py │ ├── builtin_interfaces │ │ ├── __pycache__ │ │ │ └── __init__.cpython-38.pyc │ │ ├── msg │ │ │ ├── __pycache__ │ │ │ │ └── __init__.cpython-38.pyc │ │ │ ├── dds_ │ │ │ │ ├── __pycache__ │ │ │ │ │ ├── _Time_.cpython-38.pyc │ │ │ │ │ └── __init__.cpython-38.pyc │ │ │ │ ├── __init__.py │ │ │ │ └── _Time_.py │ │ │ └── __init__.py │ │ └── __init__.py │ └── __init__.py ├── __init__.py ├── test │ ├── helloworld │ │ ├── helloworld.py │ │ ├── subscriber.py │ │ └── publisher.py │ ├── rpc │ │ ├── test_api.py │ │ ├── test_server_example.py │ │ └── test_client_example.py │ ├── lowlevel │ │ ├── unitree_go2_const.py │ │ ├── sub_lowstate.py │ │ ├── read_lowstate.py │ │ └── lowlevel_control.py │ ├── crc │ │ └── test_crc.py │ └── client │ │ ├── video_client_example.py │ │ ├── robot_service_client_example.py │ │ ├── vui_client_example.py │ │ ├── obstacles_avoid_client_example.py │ │ └── sport_client_example.py └── g1 │ ├── audio │ ├── g1_audio_api.py │ └── g1_audio_client.py │ └── loco │ ├── g1_loco_api.py │ └── g1_loco_client.py ├── pyproject.toml ├── examples ├── llm_ollama.py ├── speech_to_text.py ├── face_detection.py ├── pose_detection.py ├── camera_feed.py ├── rgb.py ├── distance_detection.py ├── depth_color_alignment.py ├── move_knee.py ├── move_wrist.py ├── highlevel_arm.py └── move_ankle.py ├── .gitignore ├── setup.py ├── LICENSE └── README.md /unitree_sdk2py/core/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /unitree_sdk2py/rpc/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /unitree_sdk2py/utils/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /unitree_sdk2py/comm/motion_switcher/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["setuptools", "wheel"] 3 | build-backend = "setuptools.build_meta" -------------------------------------------------------------------------------- /unitree_sdk2py/utils/lib/crc_amd64.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/utils/lib/crc_amd64.so -------------------------------------------------------------------------------- /unitree_sdk2py/utils/lib/crc_aarch64.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/utils/lib/crc_aarch64.so -------------------------------------------------------------------------------- /unitree_sdk2py/__pycache__/__init__.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/__pycache__/__init__.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/idl/__pycache__/default.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/idl/__pycache__/default.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/core/__pycache__/__init__.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/core/__pycache__/__init__.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/idl/__pycache__/__init__.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/idl/__pycache__/__init__.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/rpc/__pycache__/__init__.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/rpc/__pycache__/__init__.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/utils/__pycache__/__init__.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/utils/__pycache__/__init__.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/idl/nav_msgs/__pycache__/__init__.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/idl/nav_msgs/__pycache__/__init__.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/idl/std_msgs/__pycache__/__init__.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/idl/std_msgs/__pycache__/__init__.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/idl/sensor_msgs/__pycache__/__init__.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/idl/sensor_msgs/__pycache__/__init__.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/idl/unitree_api/__pycache__/__init__.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/idl/unitree_api/__pycache__/__init__.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/idl/unitree_hg/__pycache__/__init__.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/idl/unitree_hg/__pycache__/__init__.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/__init__.py: -------------------------------------------------------------------------------- 1 | from . import idl, utils, core, rpc 2 | 3 | __all__ = [ 4 | "idl" 5 | "utils" 6 | "core", 7 | "rpc", 8 | "go2", 9 | "b2", 10 | ] 11 | -------------------------------------------------------------------------------- /unitree_sdk2py/idl/geometry_msgs/__pycache__/__init__.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/idl/geometry_msgs/__pycache__/__init__.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/idl/nav_msgs/msg/__pycache__/__init__.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/idl/nav_msgs/msg/__pycache__/__init__.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/idl/std_msgs/msg/__pycache__/__init__.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/idl/std_msgs/msg/__pycache__/__init__.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/idl/sensor_msgs/msg/__pycache__/__init__.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/idl/sensor_msgs/msg/__pycache__/__init__.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/idl/unitree_api/msg/__pycache__/__init__.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/idl/unitree_api/msg/__pycache__/__init__.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/idl/unitree_hg/msg/__pycache__/__init__.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/idl/unitree_hg/msg/__pycache__/__init__.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/idl/builtin_interfaces/__pycache__/__init__.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/idl/builtin_interfaces/__pycache__/__init__.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/idl/geometry_msgs/msg/__pycache__/__init__.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/idl/geometry_msgs/msg/__pycache__/__init__.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/idl/nav_msgs/msg/dds_/__pycache__/__init__.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/idl/nav_msgs/msg/dds_/__pycache__/__init__.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/idl/std_msgs/msg/dds_/__pycache__/_Header_.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/idl/std_msgs/msg/dds_/__pycache__/_Header_.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/idl/std_msgs/msg/dds_/__pycache__/_String_.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/idl/std_msgs/msg/dds_/__pycache__/_String_.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/idl/std_msgs/msg/dds_/__pycache__/__init__.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/idl/std_msgs/msg/dds_/__pycache__/__init__.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/idl/geometry_msgs/msg/dds_/__pycache__/_Point_.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/idl/geometry_msgs/msg/dds_/__pycache__/_Point_.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/idl/geometry_msgs/msg/dds_/__pycache__/_Pose_.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/idl/geometry_msgs/msg/dds_/__pycache__/_Pose_.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/idl/geometry_msgs/msg/dds_/__pycache__/_Twist_.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/idl/geometry_msgs/msg/dds_/__pycache__/_Twist_.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/idl/nav_msgs/msg/dds_/__pycache__/_Odometry_.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/idl/nav_msgs/msg/dds_/__pycache__/_Odometry_.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/idl/sensor_msgs/msg/dds_/__pycache__/__init__.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/idl/sensor_msgs/msg/dds_/__pycache__/__init__.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/idl/unitree_api/msg/dds_/__pycache__/_Request_.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/idl/unitree_api/msg/dds_/__pycache__/_Request_.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/idl/unitree_api/msg/dds_/__pycache__/__init__.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/idl/unitree_api/msg/dds_/__pycache__/__init__.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/idl/unitree_hg/msg/dds_/__pycache__/_BmsCmd_.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/idl/unitree_hg/msg/dds_/__pycache__/_BmsCmd_.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/idl/unitree_hg/msg/dds_/__pycache__/_BmsState_.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/idl/unitree_hg/msg/dds_/__pycache__/_BmsState_.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/idl/unitree_hg/msg/dds_/__pycache__/_HandCmd_.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/idl/unitree_hg/msg/dds_/__pycache__/_HandCmd_.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/idl/unitree_hg/msg/dds_/__pycache__/_IMUState_.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/idl/unitree_hg/msg/dds_/__pycache__/_IMUState_.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/idl/unitree_hg/msg/dds_/__pycache__/_LowCmd_.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/idl/unitree_hg/msg/dds_/__pycache__/_LowCmd_.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/idl/unitree_hg/msg/dds_/__pycache__/_LowState_.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/idl/unitree_hg/msg/dds_/__pycache__/_LowState_.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/idl/unitree_hg/msg/dds_/__pycache__/_MotorCmd_.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/idl/unitree_hg/msg/dds_/__pycache__/_MotorCmd_.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/idl/unitree_hg/msg/dds_/__pycache__/__init__.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/idl/unitree_hg/msg/dds_/__pycache__/__init__.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/test/helloworld/helloworld.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | from cyclonedds.idl import IdlStruct 3 | 4 | @dataclass 5 | class HelloWorld(IdlStruct, typename="HelloWorld"): 6 | data: str -------------------------------------------------------------------------------- /unitree_sdk2py/test/rpc/test_api.py: -------------------------------------------------------------------------------- 1 | # service name 2 | TEST_SERVICE_NAME = "test" 3 | 4 | # api version 5 | TEST_API_VERSION = "1.0.0.1" 6 | 7 | # api id 8 | TEST_API_ID_MOVE = 1008 9 | TEST_API_ID_STOP = 1002 -------------------------------------------------------------------------------- /unitree_sdk2py/idl/builtin_interfaces/msg/__pycache__/__init__.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/idl/builtin_interfaces/msg/__pycache__/__init__.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/idl/geometry_msgs/msg/dds_/__pycache__/_Point32_.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/idl/geometry_msgs/msg/dds_/__pycache__/_Point32_.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/idl/geometry_msgs/msg/dds_/__pycache__/_Pose2D_.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/idl/geometry_msgs/msg/dds_/__pycache__/_Pose2D_.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/idl/geometry_msgs/msg/dds_/__pycache__/_Vector3_.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/idl/geometry_msgs/msg/dds_/__pycache__/_Vector3_.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/idl/geometry_msgs/msg/dds_/__pycache__/__init__.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/idl/geometry_msgs/msg/dds_/__pycache__/__init__.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/idl/nav_msgs/msg/dds_/__pycache__/_MapMetaData_.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/idl/nav_msgs/msg/dds_/__pycache__/_MapMetaData_.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/idl/unitree_api/msg/dds_/__pycache__/_Response_.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/idl/unitree_api/msg/dds_/__pycache__/_Response_.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/idl/unitree_hg/msg/dds_/__pycache__/_HandState_.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/idl/unitree_hg/msg/dds_/__pycache__/_HandState_.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/idl/unitree_hg/msg/dds_/__pycache__/_MotorState_.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/idl/unitree_hg/msg/dds_/__pycache__/_MotorState_.cpython-38.pyc -------------------------------------------------------------------------------- /examples/llm_ollama.py: -------------------------------------------------------------------------------- 1 | import ollama 2 | 3 | response = ollama.chat(model='llama3', messages=[ 4 | {"role": "user", "content": "What is the capital of France?"} 5 | ]) 6 | 7 | print(response['message']['content']) 8 | -------------------------------------------------------------------------------- /unitree_sdk2py/idl/builtin_interfaces/msg/dds_/__pycache__/_Time_.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/idl/builtin_interfaces/msg/dds_/__pycache__/_Time_.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/idl/geometry_msgs/msg/dds_/__pycache__/_Quaternion_.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/idl/geometry_msgs/msg/dds_/__pycache__/_Quaternion_.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/idl/nav_msgs/msg/dds_/__pycache__/_OccupancyGrid_.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/idl/nav_msgs/msg/dds_/__pycache__/_OccupancyGrid_.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/idl/sensor_msgs/msg/dds_/__pycache__/_PointCloud2_.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/idl/sensor_msgs/msg/dds_/__pycache__/_PointCloud2_.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/idl/sensor_msgs/msg/dds_/__pycache__/_PointField_.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/idl/sensor_msgs/msg/dds_/__pycache__/_PointField_.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/idl/unitree_api/msg/dds_/__pycache__/_RequestLease_.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/idl/unitree_api/msg/dds_/__pycache__/_RequestLease_.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/idl/builtin_interfaces/msg/dds_/__pycache__/__init__.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/idl/builtin_interfaces/msg/dds_/__pycache__/__init__.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/idl/geometry_msgs/msg/dds_/__pycache__/_PointStamped_.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/idl/geometry_msgs/msg/dds_/__pycache__/_PointStamped_.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/idl/geometry_msgs/msg/dds_/__pycache__/_PoseStamped_.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/idl/geometry_msgs/msg/dds_/__pycache__/_PoseStamped_.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/idl/geometry_msgs/msg/dds_/__pycache__/_TwistStamped_.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/idl/geometry_msgs/msg/dds_/__pycache__/_TwistStamped_.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/idl/unitree_api/msg/dds_/__pycache__/_RequestHeader_.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/idl/unitree_api/msg/dds_/__pycache__/_RequestHeader_.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/idl/unitree_api/msg/dds_/__pycache__/_RequestPolicy_.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/idl/unitree_api/msg/dds_/__pycache__/_RequestPolicy_.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/idl/unitree_api/msg/dds_/__pycache__/_ResponseHeader_.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/idl/unitree_api/msg/dds_/__pycache__/_ResponseHeader_.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/idl/unitree_api/msg/dds_/__pycache__/_ResponseStatus_.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/idl/unitree_api/msg/dds_/__pycache__/_ResponseStatus_.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/idl/unitree_hg/msg/dds_/__pycache__/_MainBoardState_.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/idl/unitree_hg/msg/dds_/__pycache__/_MainBoardState_.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/idl/unitree_api/msg/dds_/__pycache__/_RequestIdentity_.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/idl/unitree_api/msg/dds_/__pycache__/_RequestIdentity_.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/idl/unitree_hg/msg/dds_/__pycache__/_PressSensorState_.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/idl/unitree_hg/msg/dds_/__pycache__/_PressSensorState_.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/idl/geometry_msgs/msg/dds_/__pycache__/_QuaternionStamped_.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/idl/geometry_msgs/msg/dds_/__pycache__/_QuaternionStamped_.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/idl/geometry_msgs/msg/dds_/__pycache__/_PoseWithCovariance_.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/idl/geometry_msgs/msg/dds_/__pycache__/_PoseWithCovariance_.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/idl/geometry_msgs/msg/dds_/__pycache__/_TwistWithCovariance_.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/idl/geometry_msgs/msg/dds_/__pycache__/_TwistWithCovariance_.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/idl/nav_msgs/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generated by Eclipse Cyclone DDS idlc Python Backend 3 | Cyclone DDS IDL version: v0.11.0 4 | Module: nav_msgs 5 | 6 | """ 7 | 8 | from . import msg 9 | __all__ = ["msg", ] 10 | -------------------------------------------------------------------------------- /unitree_sdk2py/idl/std_msgs/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generated by Eclipse Cyclone DDS idlc Python Backend 3 | Cyclone DDS IDL version: v0.11.0 4 | Module: std_msgs 5 | 6 | """ 7 | 8 | from . import msg 9 | __all__ = ["msg", ] 10 | -------------------------------------------------------------------------------- /unitree_sdk2py/idl/sensor_msgs/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generated by Eclipse Cyclone DDS idlc Python Backend 3 | Cyclone DDS IDL version: v0.11.0 4 | Module: sensor_msgs 5 | 6 | """ 7 | 8 | from . import msg 9 | __all__ = ["msg", ] 10 | -------------------------------------------------------------------------------- /unitree_sdk2py/idl/unitree_api/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generated by Eclipse Cyclone DDS idlc Python Backend 3 | Cyclone DDS IDL version: v0.10.2 4 | Module: unitree_api 5 | 6 | """ 7 | 8 | from . import msg 9 | __all__ = ["msg", ] 10 | -------------------------------------------------------------------------------- /unitree_sdk2py/idl/unitree_hg/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generated by Eclipse Cyclone DDS idlc Python Backend 3 | Cyclone DDS IDL version: v0.11.0 4 | Module: unitree_hg 5 | 6 | """ 7 | 8 | from . import msg 9 | __all__ = ["msg", ] 10 | -------------------------------------------------------------------------------- /unitree_sdk2py/idl/geometry_msgs/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generated by Eclipse Cyclone DDS idlc Python Backend 3 | Cyclone DDS IDL version: v0.11.0 4 | Module: geometry_msgs 5 | 6 | """ 7 | 8 | from . import msg 9 | __all__ = ["msg", ] 10 | -------------------------------------------------------------------------------- /unitree_sdk2py/idl/geometry_msgs/msg/dds_/__pycache__/_PoseWithCovarianceStamped_.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/idl/geometry_msgs/msg/dds_/__pycache__/_PoseWithCovarianceStamped_.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/idl/nav_msgs/msg/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generated by Eclipse Cyclone DDS idlc Python Backend 3 | Cyclone DDS IDL version: v0.11.0 4 | Module: nav_msgs.msg 5 | 6 | """ 7 | 8 | from . import dds_ 9 | __all__ = ["dds_", ] 10 | -------------------------------------------------------------------------------- /unitree_sdk2py/idl/sensor_msgs/msg/dds_/PointField_Constants/__pycache__/__init__.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/idl/sensor_msgs/msg/dds_/PointField_Constants/__pycache__/__init__.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/idl/std_msgs/msg/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generated by Eclipse Cyclone DDS idlc Python Backend 3 | Cyclone DDS IDL version: v0.11.0 4 | Module: std_msgs.msg 5 | 6 | """ 7 | 8 | from . import dds_ 9 | __all__ = ["dds_", ] 10 | -------------------------------------------------------------------------------- /unitree_sdk2py/idl/geometry_msgs/msg/dds_/__pycache__/_TwistWithCovarianceStamped_.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/idl/geometry_msgs/msg/dds_/__pycache__/_TwistWithCovarianceStamped_.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/idl/sensor_msgs/msg/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generated by Eclipse Cyclone DDS idlc Python Backend 3 | Cyclone DDS IDL version: v0.11.0 4 | Module: sensor_msgs.msg 5 | 6 | """ 7 | 8 | from . import dds_ 9 | __all__ = ["dds_", ] 10 | -------------------------------------------------------------------------------- /unitree_sdk2py/idl/unitree_api/msg/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generated by Eclipse Cyclone DDS idlc Python Backend 3 | Cyclone DDS IDL version: v0.10.2 4 | Module: unitree_api.msg 5 | 6 | """ 7 | 8 | from . import dds_ 9 | __all__ = ["dds_", ] 10 | -------------------------------------------------------------------------------- /unitree_sdk2py/idl/unitree_hg/msg/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generated by Eclipse Cyclone DDS idlc Python Backend 3 | Cyclone DDS IDL version: v0.11.0 4 | Module: unitree_hg.msg 5 | 6 | """ 7 | 8 | from . import dds_ 9 | __all__ = ["dds_", ] 10 | -------------------------------------------------------------------------------- /unitree_sdk2py/idl/builtin_interfaces/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generated by Eclipse Cyclone DDS idlc Python Backend 3 | Cyclone DDS IDL version: v0.11.0 4 | Module: builtin_interfaces 5 | 6 | """ 7 | 8 | from . import msg 9 | __all__ = ["msg", ] 10 | -------------------------------------------------------------------------------- /unitree_sdk2py/idl/geometry_msgs/msg/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generated by Eclipse Cyclone DDS idlc Python Backend 3 | Cyclone DDS IDL version: v0.11.0 4 | Module: geometry_msgs.msg 5 | 6 | """ 7 | 8 | from . import dds_ 9 | __all__ = ["dds_", ] 10 | -------------------------------------------------------------------------------- /unitree_sdk2py/idl/sensor_msgs/msg/dds_/PointField_Constants/__pycache__/_PointField_.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notdana/unitree_g1_python/HEAD/unitree_sdk2py/idl/sensor_msgs/msg/dds_/PointField_Constants/__pycache__/_PointField_.cpython-38.pyc -------------------------------------------------------------------------------- /unitree_sdk2py/idl/builtin_interfaces/msg/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generated by Eclipse Cyclone DDS idlc Python Backend 3 | Cyclone DDS IDL version: v0.11.0 4 | Module: builtin_interfaces.msg 5 | 6 | """ 7 | 8 | from . import dds_ 9 | __all__ = ["dds_", ] 10 | -------------------------------------------------------------------------------- /unitree_sdk2py/idl/builtin_interfaces/msg/dds_/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generated by Eclipse Cyclone DDS idlc Python Backend 3 | Cyclone DDS IDL version: v0.11.0 4 | Module: builtin_interfaces.msg.dds_ 5 | 6 | """ 7 | 8 | from ._Time_ import Time_ 9 | __all__ = ["Time_", ] 10 | -------------------------------------------------------------------------------- /unitree_sdk2py/idl/std_msgs/msg/dds_/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generated by Eclipse Cyclone DDS idlc Python Backend 3 | Cyclone DDS IDL version: v0.11.0 4 | Module: std_msgs.msg.dds_ 5 | 6 | """ 7 | 8 | from ._Header_ import Header_ 9 | from ._String_ import String_ 10 | __all__ = ["Header_", "String_", ] 11 | -------------------------------------------------------------------------------- /unitree_sdk2py/idl/__init__.py: -------------------------------------------------------------------------------- 1 | from .default import * 2 | from . import builtin_interfaces, geometry_msgs, sensor_msgs, std_msgs, unitree_api 3 | 4 | __all__ = [ 5 | "builtin_interfaces", 6 | "geometry_msgs", 7 | "sensor_msgs", 8 | "std_msgs", 9 | "unitree_hg", 10 | "unitree_api", 11 | ] 12 | -------------------------------------------------------------------------------- /unitree_sdk2py/utils/singleton.py: -------------------------------------------------------------------------------- 1 | class Singleton: 2 | __instance = None 3 | 4 | def __new__(cls, *args, **kwargs): 5 | if cls.__instance is None: 6 | cls.__instance = super(Singleton, cls).__new__(cls) 7 | return cls.__instance 8 | 9 | def __init__(self): 10 | pass 11 | 12 | -------------------------------------------------------------------------------- /unitree_sdk2py/idl/nav_msgs/msg/dds_/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generated by Eclipse Cyclone DDS idlc Python Backend 3 | Cyclone DDS IDL version: v0.11.0 4 | Module: nav_msgs.msg.dds_ 5 | 6 | """ 7 | 8 | from ._MapMetaData_ import MapMetaData_ 9 | from ._OccupancyGrid_ import OccupancyGrid_ 10 | from ._Odometry_ import Odometry_ 11 | __all__ = ["MapMetaData_", "OccupancyGrid_", "Odometry_", ] 12 | -------------------------------------------------------------------------------- /unitree_sdk2py/idl/sensor_msgs/msg/dds_/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generated by Eclipse Cyclone DDS idlc Python Backend 3 | Cyclone DDS IDL version: v0.11.0 4 | Module: sensor_msgs.msg.dds_ 5 | 6 | """ 7 | 8 | from . import PointField_Constants 9 | from ._PointCloud2_ import PointCloud2_ 10 | from ._PointField_ import PointField_ 11 | __all__ = ["PointField_Constants", "PointCloud2_", "PointField_", ] 12 | -------------------------------------------------------------------------------- /unitree_sdk2py/idl/sensor_msgs/msg/dds_/PointField_Constants/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generated by Eclipse Cyclone DDS idlc Python Backend 3 | Cyclone DDS IDL version: v0.11.0 4 | Module: sensor_msgs.msg.dds_.PointField_Constants 5 | 6 | """ 7 | 8 | from ._PointField_ import FLOAT32_, FLOAT64_, INT16_, INT32_, INT8_, UINT16_, UINT32_, UINT8_ 9 | __all__ = ["FLOAT32_", "FLOAT64_", "INT16_", "INT32_", "INT8_", "UINT16_", "UINT32_", "UINT8_", ] 10 | -------------------------------------------------------------------------------- /unitree_sdk2py/test/lowlevel/unitree_go2_const.py: -------------------------------------------------------------------------------- 1 | LegID = { 2 | "FR_0": 0, # Front right hip 3 | "FR_1": 1, # Front right thigh 4 | "FR_2": 2, # Front right calf 5 | "FL_0": 3, 6 | "FL_1": 4, 7 | "FL_2": 5, 8 | "RR_0": 6, 9 | "RR_1": 7, 10 | "RR_2": 8, 11 | "RL_0": 9, 12 | "RL_1": 10, 13 | "RL_2": 11, 14 | } 15 | 16 | HIGHLEVEL = 0xEE 17 | LOWLEVEL = 0xFF 18 | TRIGERLEVEL = 0xF0 19 | PosStopF = 2.146e9 20 | VelStopF = 16000.0 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by MacOS 2 | .DS_Store 3 | 4 | # Generated by Windows 5 | Thumbs.db 6 | 7 | # Applications 8 | *.app 9 | *.exe 10 | *.war 11 | 12 | # Large media files 13 | *.mp4 14 | *.tiff 15 | *.avi 16 | *.flv 17 | *.mov 18 | *.wmv 19 | *.jpg 20 | *.png 21 | 22 | # VS Code 23 | .vscode 24 | 25 | # other 26 | *.egg-info 27 | __pycache__ 28 | 29 | # IDEs 30 | .idea 31 | 32 | # cache 33 | .pytest_cache 34 | 35 | # JetBrains IDE 36 | .idea/ 37 | 38 | # python 39 | dist/ 40 | -------------------------------------------------------------------------------- /unitree_sdk2py/test/helloworld/subscriber.py: -------------------------------------------------------------------------------- 1 | import time 2 | 3 | from unitree_sdk2py.core.channel import ChannelSubscriber, ChannelFactoryInitialize 4 | from helloworld import HelloWorld 5 | 6 | ChannelFactoryInitialize() 7 | 8 | sub = ChannelSubscriber("topic", HelloWorld) 9 | sub.Init() 10 | 11 | while True: 12 | msg = sub.Read() 13 | 14 | if msg is None: 15 | print("subscribe error.") 16 | else: 17 | print("subscribe success. msg:", msg) 18 | 19 | pub.Close() -------------------------------------------------------------------------------- /unitree_sdk2py/utils/clib_lookup.py: -------------------------------------------------------------------------------- 1 | import os 2 | import ctypes 3 | 4 | clib = ctypes.CDLL(None, use_errno=True) 5 | 6 | def CLIBCheckError(ret, func, args): 7 | if ret < 0: 8 | code = ctypes.get_errno() 9 | raise OSError(code, os.strerror(code)) 10 | return ret 11 | 12 | def CLIBLookup(name, resType, argTypes): 13 | func = clib[name] 14 | func.restye = resType 15 | func.argtypes = argTypes 16 | func.errcheck = CLIBCheckError 17 | return func 18 | -------------------------------------------------------------------------------- /examples/speech_to_text.py: -------------------------------------------------------------------------------- 1 | import speech_recognition as sr 2 | 3 | recognizer = sr.Recognizer() 4 | 5 | with sr.Microphone() as source: 6 | print("Say something:") 7 | audio = recognizer.listen(source) 8 | 9 | try: 10 | text = recognizer.recognize_google(audio) 11 | print("You said:", text) 12 | except sr.UnknownValueError: 13 | print("Sorry, I couldn't understand.") 14 | except sr.RequestError: 15 | print("Could not reach the Google API.") 16 | -------------------------------------------------------------------------------- /unitree_sdk2py/g1/audio/g1_audio_api.py: -------------------------------------------------------------------------------- 1 | """ 2 | " service name 3 | """ 4 | AUDIO_SERVICE_NAME = "voice" 5 | 6 | """ 7 | " service api version 8 | """ 9 | AUDIO_API_VERSION = "1.0.0.0" 10 | 11 | """ 12 | " api id 13 | """ 14 | ROBOT_API_ID_AUDIO_TTS = 1001 15 | ROBOT_API_ID_AUDIO_ASR = 1002 16 | ROBOT_API_ID_AUDIO_START_PLAY = 1003 17 | ROBOT_API_ID_AUDIO_STOP_PLAY = 1004 18 | ROBOT_API_ID_AUDIO_GET_VOLUME = 1005 19 | ROBOT_API_ID_AUDIO_SET_VOLUME = 1006 20 | ROBOT_API_ID_AUDIO_SET_RGB_LED = 1010 21 | 22 | """ 23 | " error code 24 | """ -------------------------------------------------------------------------------- /unitree_sdk2py/test/lowlevel/sub_lowstate.py: -------------------------------------------------------------------------------- 1 | import time 2 | from unitree_sdk2py.core.channel import ChannelSubscriber, ChannelFactoryInitialize 3 | from unitree_sdk2py.idl.default import unitree_go_msg_dds__LowState_ 4 | from unitree_sdk2py.idl.unitree_go.msg.dds_ import LowState_ 5 | 6 | def LowStateHandler(msg: LowState_): 7 | print(msg.motor_state) 8 | 9 | 10 | ChannelFactoryInitialize(0, "enp2s0") 11 | sub = ChannelSubscriber("rt/lowstate", LowState_) 12 | sub.Init(LowStateHandler, 10) 13 | 14 | while True: 15 | time.sleep(10.0) -------------------------------------------------------------------------------- /unitree_sdk2py/test/helloworld/publisher.py: -------------------------------------------------------------------------------- 1 | import time 2 | 3 | from unitree_sdk2py.core.channel import ChannelPublisher, ChannelFactoryInitialize 4 | from helloworld import HelloWorld 5 | 6 | ChannelFactoryInitialize() 7 | 8 | pub = ChannelPublisher("topic", HelloWorld) 9 | pub.Init() 10 | 11 | for i in range(30): 12 | msg = HelloWorld("Hello world. time:" + str(time.time())) 13 | # msg.data = "Hello world. time:" + str(time.time()) 14 | 15 | if pub.Write(msg, 0.5): 16 | print("publish success. msg:", msg) 17 | else: 18 | print("publish error.") 19 | 20 | time.sleep(1) 21 | 22 | pub.Close() -------------------------------------------------------------------------------- /unitree_sdk2py/comm/motion_switcher/motion_switcher_api.py: -------------------------------------------------------------------------------- 1 | """ 2 | " service name 3 | """ 4 | MOTION_SWITCHER_SERVICE_NAME = "motion_switcher" 5 | 6 | 7 | """ 8 | " service api version 9 | """ 10 | MOTION_SWITCHER_API_VERSION = "1.0.0.1" 11 | 12 | 13 | """ 14 | " api id 15 | """ 16 | MOTION_SWITCHER_API_ID_CHECK_MODE = 1001 17 | MOTION_SWITCHER_API_ID_SELECT_MODE = 1002 18 | MOTION_SWITCHER_API_ID_RELEASE_MODE = 1003 19 | MOTION_SWITCHER_API_ID_SET_SILENT = 1004 20 | MOTION_SWITCHER_API_ID_GET_SILENT = 1005 21 | 22 | # """ 23 | # " error code 24 | # """ 25 | # # client side 26 | # SPORT_ERR_CLIENT_POINT_PATH = 4101 27 | # # server side 28 | # SPORT_ERR_SERVER_OVERTIME = 4201 29 | # SPORT_ERR_SERVER_NOT_INIT = 4202 30 | -------------------------------------------------------------------------------- /unitree_sdk2py/idl/unitree_api/msg/dds_/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generated by Eclipse Cyclone DDS idlc Python Backend 3 | Cyclone DDS IDL version: v0.10.2 4 | Module: unitree_api.msg.dds_ 5 | 6 | """ 7 | 8 | from ._RequestHeader_ import RequestHeader_ 9 | from ._RequestIdentity_ import RequestIdentity_ 10 | from ._RequestLease_ import RequestLease_ 11 | from ._RequestPolicy_ import RequestPolicy_ 12 | from ._Request_ import Request_ 13 | from ._ResponseHeader_ import ResponseHeader_ 14 | from ._ResponseStatus_ import ResponseStatus_ 15 | from ._Response_ import Response_ 16 | __all__ = ["RequestHeader_", "RequestIdentity_", "RequestLease_", "RequestPolicy_", "Request_", "ResponseHeader_", "ResponseStatus_", "Response_", ] 17 | -------------------------------------------------------------------------------- /unitree_sdk2py/idl/std_msgs/msg/dds_/_String_.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generated by Eclipse Cyclone DDS idlc Python Backend 3 | Cyclone DDS IDL version: v0.11.0 4 | Module: std_msgs.msg.dds_ 5 | IDL file: String_.idl 6 | 7 | """ 8 | 9 | from enum import auto 10 | from typing import TYPE_CHECKING, Optional 11 | from dataclasses import dataclass 12 | 13 | import cyclonedds.idl as idl 14 | import cyclonedds.idl.annotations as annotate 15 | import cyclonedds.idl.types as types 16 | 17 | # root module import for resolving types 18 | # import std_msgs 19 | 20 | 21 | @dataclass 22 | @annotate.final 23 | @annotate.autoid("sequential") 24 | class String_(idl.IdlStruct, typename="std_msgs.msg.dds_.String_"): 25 | data: str 26 | 27 | 28 | -------------------------------------------------------------------------------- /unitree_sdk2py/idl/sensor_msgs/msg/dds_/PointField_Constants/_PointField_.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generated by Eclipse Cyclone DDS idlc Python Backend 3 | Cyclone DDS IDL version: v0.11.0 4 | Module: sensor_msgs.msg.dds_.PointField_Constants 5 | IDL file: PointField_.idl 6 | 7 | """ 8 | 9 | from enum import auto 10 | from typing import TYPE_CHECKING, Optional 11 | from dataclasses import dataclass 12 | 13 | import cyclonedds.idl as idl 14 | import cyclonedds.idl.annotations as annotate 15 | import cyclonedds.idl.types as types 16 | 17 | # root module import for resolving types 18 | # import sensor_msgs 19 | 20 | INT8_ = 1 21 | UINT8_ = 2 22 | INT16_ = 3 23 | UINT16_ = 4 24 | INT32_ = 5 25 | UINT32_ = 6 26 | FLOAT32_ = 7 27 | FLOAT64_ = 8 28 | 29 | -------------------------------------------------------------------------------- /unitree_sdk2py/idl/unitree_api/msg/dds_/_RequestLease_.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generated by Eclipse Cyclone DDS idlc Python Backend 3 | Cyclone DDS IDL version: v0.10.2 4 | Module: unitree_api.msg.dds_ 5 | IDL file: RequestLease_.idl 6 | 7 | """ 8 | 9 | from enum import auto 10 | from typing import TYPE_CHECKING, Optional 11 | from dataclasses import dataclass 12 | 13 | import cyclonedds.idl as idl 14 | import cyclonedds.idl.annotations as annotate 15 | import cyclonedds.idl.types as types 16 | 17 | # root module import for resolving types 18 | # import unitree_api 19 | 20 | 21 | @dataclass 22 | @annotate.final 23 | @annotate.autoid("sequential") 24 | class RequestLease_(idl.IdlStruct, typename="unitree_api.msg.dds_.RequestLease_"): 25 | id: types.int64 26 | 27 | 28 | -------------------------------------------------------------------------------- /unitree_sdk2py/utils/hz_sample.py: -------------------------------------------------------------------------------- 1 | import time 2 | from threading import Lock 3 | from .thread import RecurrentThread 4 | 5 | class HZSample: 6 | def __init__(self, interval: float = 1.0): 7 | self.__count = 0 8 | self.__inter = interval if interval > 0.0 else 1.0 9 | self.__lock = Lock() 10 | self.__thread = RecurrentThread(self.__inter, target=self.TimerFunc) 11 | 12 | def Start(self): 13 | self.__thread.Start() 14 | 15 | def Sample(self): 16 | with self.__lock: 17 | self.__count += 1 18 | 19 | def TimerFunc(self): 20 | count = 0 21 | with self.__lock: 22 | count = self.__count 23 | self.__count = 0 24 | print("HZ: {}".format(count/self.__inter)) 25 | -------------------------------------------------------------------------------- /unitree_sdk2py/idl/unitree_api/msg/dds_/_ResponseStatus_.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generated by Eclipse Cyclone DDS idlc Python Backend 3 | Cyclone DDS IDL version: v0.10.2 4 | Module: unitree_api.msg.dds_ 5 | IDL file: ResponseStatus_.idl 6 | 7 | """ 8 | 9 | from enum import auto 10 | from typing import TYPE_CHECKING, Optional 11 | from dataclasses import dataclass 12 | 13 | import cyclonedds.idl as idl 14 | import cyclonedds.idl.annotations as annotate 15 | import cyclonedds.idl.types as types 16 | 17 | # root module import for resolving types 18 | # import unitree_api 19 | 20 | 21 | @dataclass 22 | @annotate.final 23 | @annotate.autoid("sequential") 24 | class ResponseStatus_(idl.IdlStruct, typename="unitree_api.msg.dds_.ResponseStatus_"): 25 | code: types.int32 26 | 27 | 28 | -------------------------------------------------------------------------------- /unitree_sdk2py/idl/unitree_hg/msg/dds_/_BmsCmd_.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generated by Eclipse Cyclone DDS idlc Python Backend 3 | Cyclone DDS IDL version: v0.11.0 4 | Module: unitree_hg.msg.dds_ 5 | IDL file: BmsCmd_.idl 6 | 7 | """ 8 | 9 | from enum import auto 10 | from typing import TYPE_CHECKING, Optional 11 | from dataclasses import dataclass 12 | 13 | import cyclonedds.idl as idl 14 | import cyclonedds.idl.annotations as annotate 15 | import cyclonedds.idl.types as types 16 | 17 | # root module import for resolving types 18 | # import unitree_hg 19 | 20 | 21 | @dataclass 22 | @annotate.final 23 | @annotate.autoid("sequential") 24 | class BmsCmd_(idl.IdlStruct, typename="unitree_hg.msg.dds_.BmsCmd_"): 25 | cmd: types.uint8 26 | reserve: types.array[types.uint8, 40] 27 | 28 | 29 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup, find_packages 2 | 3 | setup(name='unitree_sdk2py', 4 | version='1.0.1', 5 | author='UnitreeRobotics', 6 | author_email='unitree@unitree.com', 7 | long_description=open('README.md').read(), 8 | long_description_content_type="text/markdown", 9 | license="BSD-3-Clause", 10 | packages=find_packages(include=['unitree_sdk2py','unitree_sdk2py.*']), 11 | description='Unitree robot sdk version 2 for python', 12 | project_urls={ 13 | "Source Code": "https://github.com/unitreerobotics/unitree_sdk2_python", 14 | }, 15 | python_requires='>=3.8', 16 | install_requires=[ 17 | "cyclonedds==0.10.2", 18 | "numpy", 19 | "opencv-python", 20 | ], 21 | ) -------------------------------------------------------------------------------- /unitree_sdk2py/idl/builtin_interfaces/msg/dds_/_Time_.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generated by Eclipse Cyclone DDS idlc Python Backend 3 | Cyclone DDS IDL version: v0.11.0 4 | Module: builtin_interfaces.msg.dds_ 5 | IDL file: Time_.idl 6 | 7 | """ 8 | 9 | from enum import auto 10 | from typing import TYPE_CHECKING, Optional 11 | from dataclasses import dataclass 12 | 13 | import cyclonedds.idl as idl 14 | import cyclonedds.idl.annotations as annotate 15 | import cyclonedds.idl.types as types 16 | 17 | # root module import for resolving types 18 | # import builtin_interfaces 19 | 20 | 21 | @dataclass 22 | @annotate.final 23 | @annotate.autoid("sequential") 24 | class Time_(idl.IdlStruct, typename="builtin_interfaces.msg.dds_.Time_"): 25 | sec: types.int32 26 | nanosec: types.uint32 27 | 28 | 29 | -------------------------------------------------------------------------------- /unitree_sdk2py/idl/geometry_msgs/msg/dds_/_Point_.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generated by Eclipse Cyclone DDS idlc Python Backend 3 | Cyclone DDS IDL version: v0.11.0 4 | Module: geometry_msgs.msg.dds_ 5 | IDL file: Point_.idl 6 | 7 | """ 8 | 9 | from enum import auto 10 | from typing import TYPE_CHECKING, Optional 11 | from dataclasses import dataclass 12 | 13 | import cyclonedds.idl as idl 14 | import cyclonedds.idl.annotations as annotate 15 | import cyclonedds.idl.types as types 16 | 17 | # root module import for resolving types 18 | # import geometry_msgs 19 | 20 | 21 | @dataclass 22 | @annotate.final 23 | @annotate.autoid("sequential") 24 | class Point_(idl.IdlStruct, typename="geometry_msgs.msg.dds_.Point_"): 25 | x: types.float64 26 | y: types.float64 27 | z: types.float64 28 | 29 | 30 | -------------------------------------------------------------------------------- /unitree_sdk2py/idl/unitree_api/msg/dds_/_RequestPolicy_.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generated by Eclipse Cyclone DDS idlc Python Backend 3 | Cyclone DDS IDL version: v0.10.2 4 | Module: unitree_api.msg.dds_ 5 | IDL file: RequestPolicy_.idl 6 | 7 | """ 8 | 9 | from enum import auto 10 | from typing import TYPE_CHECKING, Optional 11 | from dataclasses import dataclass 12 | 13 | import cyclonedds.idl as idl 14 | import cyclonedds.idl.annotations as annotate 15 | import cyclonedds.idl.types as types 16 | 17 | # root module import for resolving types 18 | # import unitree_api 19 | 20 | 21 | @dataclass 22 | @annotate.final 23 | @annotate.autoid("sequential") 24 | class RequestPolicy_(idl.IdlStruct, typename="unitree_api.msg.dds_.RequestPolicy_"): 25 | priority: types.int32 26 | noreply: bool 27 | 28 | 29 | -------------------------------------------------------------------------------- /unitree_sdk2py/g1/loco/g1_loco_api.py: -------------------------------------------------------------------------------- 1 | """ 2 | " service name 3 | """ 4 | LOCO_SERVICE_NAME = "loco" 5 | 6 | 7 | """ 8 | " service api version 9 | """ 10 | LOCO_API_VERSION = "1.0.0.0" 11 | 12 | 13 | """ 14 | " api id 15 | """ 16 | ROBOT_API_ID_LOCO_GET_FSM_ID = 7001 17 | ROBOT_API_ID_LOCO_GET_FSM_MODE = 7002 18 | ROBOT_API_ID_LOCO_GET_BALANCE_MODE = 7003 19 | ROBOT_API_ID_LOCO_GET_SWING_HEIGHT = 7004 20 | ROBOT_API_ID_LOCO_GET_STAND_HEIGHT = 7005 21 | ROBOT_API_ID_LOCO_GET_PHASE = 7006 # deprecated 22 | 23 | ROBOT_API_ID_LOCO_SET_FSM_ID = 7101 24 | ROBOT_API_ID_LOCO_SET_BALANCE_MODE = 7102 25 | ROBOT_API_ID_LOCO_SET_SWING_HEIGHT = 7103 26 | ROBOT_API_ID_LOCO_SET_STAND_HEIGHT = 7104 27 | ROBOT_API_ID_LOCO_SET_VELOCITY = 7105 28 | ROBOT_API_ID_LOCO_SET_ARM_TASK = 7106 29 | 30 | """ 31 | " error code 32 | """ -------------------------------------------------------------------------------- /unitree_sdk2py/idl/geometry_msgs/msg/dds_/_Point32_.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generated by Eclipse Cyclone DDS idlc Python Backend 3 | Cyclone DDS IDL version: v0.11.0 4 | Module: geometry_msgs.msg.dds_ 5 | IDL file: Point32_.idl 6 | 7 | """ 8 | 9 | from enum import auto 10 | from typing import TYPE_CHECKING, Optional 11 | from dataclasses import dataclass 12 | 13 | import cyclonedds.idl as idl 14 | import cyclonedds.idl.annotations as annotate 15 | import cyclonedds.idl.types as types 16 | 17 | # root module import for resolving types 18 | # import geometry_msgs 19 | 20 | 21 | @dataclass 22 | @annotate.final 23 | @annotate.autoid("sequential") 24 | class Point32_(idl.IdlStruct, typename="geometry_msgs.msg.dds_.Point32_"): 25 | x: types.float32 26 | y: types.float32 27 | z: types.float32 28 | 29 | 30 | -------------------------------------------------------------------------------- /unitree_sdk2py/idl/geometry_msgs/msg/dds_/_Pose2D_.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generated by Eclipse Cyclone DDS idlc Python Backend 3 | Cyclone DDS IDL version: v0.11.0 4 | Module: geometry_msgs.msg.dds_ 5 | IDL file: Pose2D_.idl 6 | 7 | """ 8 | 9 | from enum import auto 10 | from typing import TYPE_CHECKING, Optional 11 | from dataclasses import dataclass 12 | 13 | import cyclonedds.idl as idl 14 | import cyclonedds.idl.annotations as annotate 15 | import cyclonedds.idl.types as types 16 | 17 | # root module import for resolving types 18 | # import geometry_msgs 19 | 20 | 21 | @dataclass 22 | @annotate.final 23 | @annotate.autoid("sequential") 24 | class Pose2D_(idl.IdlStruct, typename="geometry_msgs.msg.dds_.Pose2D_"): 25 | x: types.float64 26 | y: types.float64 27 | theta: types.float64 28 | 29 | 30 | -------------------------------------------------------------------------------- /unitree_sdk2py/idl/geometry_msgs/msg/dds_/_Vector3_.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generated by Eclipse Cyclone DDS idlc Python Backend 3 | Cyclone DDS IDL version: v0.11.0 4 | Module: geometry_msgs.msg.dds_ 5 | IDL file: Vector3_.idl 6 | 7 | """ 8 | 9 | from enum import auto 10 | from typing import TYPE_CHECKING, Optional 11 | from dataclasses import dataclass 12 | 13 | import cyclonedds.idl as idl 14 | import cyclonedds.idl.annotations as annotate 15 | import cyclonedds.idl.types as types 16 | 17 | # root module import for resolving types 18 | # import geometry_msgs 19 | 20 | 21 | @dataclass 22 | @annotate.final 23 | @annotate.autoid("sequential") 24 | class Vector3_(idl.IdlStruct, typename="geometry_msgs.msg.dds_.Vector3_"): 25 | x: types.float64 26 | y: types.float64 27 | z: types.float64 28 | 29 | 30 | -------------------------------------------------------------------------------- /unitree_sdk2py/idl/unitree_api/msg/dds_/_RequestIdentity_.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generated by Eclipse Cyclone DDS idlc Python Backend 3 | Cyclone DDS IDL version: v0.10.2 4 | Module: unitree_api.msg.dds_ 5 | IDL file: RequestIdentity_.idl 6 | 7 | """ 8 | 9 | from enum import auto 10 | from typing import TYPE_CHECKING, Optional 11 | from dataclasses import dataclass 12 | 13 | import cyclonedds.idl as idl 14 | import cyclonedds.idl.annotations as annotate 15 | import cyclonedds.idl.types as types 16 | 17 | # root module import for resolving types 18 | # import unitree_api 19 | 20 | 21 | @dataclass 22 | @annotate.final 23 | @annotate.autoid("sequential") 24 | class RequestIdentity_(idl.IdlStruct, typename="unitree_api.msg.dds_.RequestIdentity_"): 25 | id: types.int64 26 | api_id: types.int64 27 | 28 | 29 | -------------------------------------------------------------------------------- /unitree_sdk2py/idl/unitree_hg/msg/dds_/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generated by Eclipse Cyclone DDS idlc Python Backend 3 | Cyclone DDS IDL version: v0.11.0 4 | Module: unitree_hg.msg.dds_ 5 | 6 | """ 7 | 8 | from ._BmsCmd_ import BmsCmd_ 9 | from ._BmsState_ import BmsState_ 10 | from ._HandCmd_ import HandCmd_ 11 | from ._HandState_ import HandState_ 12 | from ._IMUState_ import IMUState_ 13 | from ._LowCmd_ import LowCmd_ 14 | from ._LowState_ import LowState_ 15 | from ._MainBoardState_ import MainBoardState_ 16 | from ._MotorCmd_ import MotorCmd_ 17 | from ._MotorState_ import MotorState_ 18 | from ._PressSensorState_ import PressSensorState_ 19 | __all__ = ["BmsCmd_", "BmsState_", "HandCmd_", "HandState_", "IMUState_", "LowCmd_", "LowState_", "MainBoardState_", "MotorCmd_", "MotorState_", "PressSensorState_", ] 20 | -------------------------------------------------------------------------------- /unitree_sdk2py/core/channel_name.py: -------------------------------------------------------------------------------- 1 | from enum import Enum 2 | 3 | """ 4 | " Enum ChannelType 5 | """ 6 | class ChannelType(Enum): 7 | SEND = 0 8 | RECV = 1 9 | 10 | """ 11 | " function GetClientChannelName 12 | """ 13 | def GetClientChannelName(serviceName: str, channelType: ChannelType): 14 | name = "rt/api/" + serviceName 15 | 16 | if channelType == ChannelType.SEND: 17 | name += "/request" 18 | else: 19 | name += "/response" 20 | 21 | return name 22 | 23 | """ 24 | " function GetClientChannelName 25 | """ 26 | def GetServerChannelName(serviceName: str, channelType: ChannelType): 27 | name = "rt/api/" + serviceName 28 | 29 | if channelType == ChannelType.SEND: 30 | name += "/response" 31 | else: 32 | name += "/request" 33 | 34 | return name -------------------------------------------------------------------------------- /unitree_sdk2py/idl/geometry_msgs/msg/dds_/_Quaternion_.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generated by Eclipse Cyclone DDS idlc Python Backend 3 | Cyclone DDS IDL version: v0.11.0 4 | Module: geometry_msgs.msg.dds_ 5 | IDL file: Quaternion_.idl 6 | 7 | """ 8 | 9 | from enum import auto 10 | from typing import TYPE_CHECKING, Optional 11 | from dataclasses import dataclass 12 | 13 | import cyclonedds.idl as idl 14 | import cyclonedds.idl.annotations as annotate 15 | import cyclonedds.idl.types as types 16 | 17 | # root module import for resolving types 18 | # import geometry_msgs 19 | 20 | 21 | @dataclass 22 | @annotate.final 23 | @annotate.autoid("sequential") 24 | class Quaternion_(idl.IdlStruct, typename="geometry_msgs.msg.dds_.Quaternion_"): 25 | x: types.float64 26 | y: types.float64 27 | z: types.float64 28 | w: types.float64 29 | 30 | 31 | -------------------------------------------------------------------------------- /unitree_sdk2py/idl/sensor_msgs/msg/dds_/_PointField_.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generated by Eclipse Cyclone DDS idlc Python Backend 3 | Cyclone DDS IDL version: v0.11.0 4 | Module: sensor_msgs.msg.dds_ 5 | IDL file: PointField_.idl 6 | 7 | """ 8 | 9 | from enum import auto 10 | from typing import TYPE_CHECKING, Optional 11 | from dataclasses import dataclass 12 | 13 | import cyclonedds.idl as idl 14 | import cyclonedds.idl.annotations as annotate 15 | import cyclonedds.idl.types as types 16 | 17 | # root module import for resolving types 18 | # import sensor_msgs 19 | 20 | 21 | @dataclass 22 | @annotate.final 23 | @annotate.autoid("sequential") 24 | class PointField_(idl.IdlStruct, typename="sensor_msgs.msg.dds_.PointField_"): 25 | name: str 26 | offset: types.uint32 27 | datatype: types.uint8 28 | count: types.uint32 29 | 30 | 31 | -------------------------------------------------------------------------------- /unitree_sdk2py/idl/unitree_hg/msg/dds_/_HandCmd_.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generated by Eclipse Cyclone DDS idlc Python Backend 3 | Cyclone DDS IDL version: v0.11.0 4 | Module: unitree_hg.msg.dds_ 5 | IDL file: HandCmd_.idl 6 | 7 | """ 8 | 9 | from enum import auto 10 | from typing import TYPE_CHECKING, Optional 11 | from dataclasses import dataclass 12 | 13 | import cyclonedds.idl as idl 14 | import cyclonedds.idl.annotations as annotate 15 | import cyclonedds.idl.types as types 16 | 17 | # root module import for resolving types 18 | # import unitree_hg 19 | 20 | 21 | @dataclass 22 | @annotate.final 23 | @annotate.autoid("sequential") 24 | class HandCmd_(idl.IdlStruct, typename="unitree_hg.msg.dds_.HandCmd_"): 25 | motor_cmd: types.sequence['unitree_sdk2py.idl.unitree_hg.msg.dds_.MotorCmd_'] 26 | reserve: types.array[types.uint32, 4] 27 | 28 | 29 | -------------------------------------------------------------------------------- /unitree_sdk2py/idl/unitree_api/msg/dds_/_Request_.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generated by Eclipse Cyclone DDS idlc Python Backend 3 | Cyclone DDS IDL version: v0.10.2 4 | Module: unitree_api.msg.dds_ 5 | IDL file: Request_.idl 6 | 7 | """ 8 | 9 | from enum import auto 10 | from typing import TYPE_CHECKING, Optional 11 | from dataclasses import dataclass 12 | 13 | import cyclonedds.idl as idl 14 | import cyclonedds.idl.annotations as annotate 15 | import cyclonedds.idl.types as types 16 | 17 | # root module import for resolving types 18 | # import unitree_api 19 | 20 | 21 | @dataclass 22 | @annotate.final 23 | @annotate.autoid("sequential") 24 | class Request_(idl.IdlStruct, typename="unitree_api.msg.dds_.Request_"): 25 | header: 'unitree_sdk2py.idl.unitree_api.msg.dds_.RequestHeader_' 26 | parameter: str 27 | binary: types.sequence[types.uint8] 28 | 29 | -------------------------------------------------------------------------------- /unitree_sdk2py/idl/unitree_api/msg/dds_/_Response_.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generated by Eclipse Cyclone DDS idlc Python Backend 3 | Cyclone DDS IDL version: v0.10.2 4 | Module: unitree_api.msg.dds_ 5 | IDL file: Response_.idl 6 | 7 | """ 8 | 9 | from enum import auto 10 | from typing import TYPE_CHECKING, Optional 11 | from dataclasses import dataclass 12 | 13 | import cyclonedds.idl as idl 14 | import cyclonedds.idl.annotations as annotate 15 | import cyclonedds.idl.types as types 16 | 17 | # root module import for resolving types 18 | # import unitree_api 19 | 20 | @dataclass 21 | @annotate.final 22 | @annotate.autoid("sequential") 23 | class Response_(idl.IdlStruct, typename="unitree_api.msg.dds_.Response_"): 24 | header: 'unitree_sdk2py.idl.unitree_api.msg.dds_.ResponseHeader_' 25 | data: str 26 | binary: types.sequence[types.uint8] 27 | 28 | 29 | -------------------------------------------------------------------------------- /unitree_sdk2py/test/crc/test_crc.py: -------------------------------------------------------------------------------- 1 | from unitree_sdk2py.idl.default import unitree_go_msg_dds__LowCmd_, unitree_go_msg_dds__LowState_ 2 | from unitree_sdk2py.idl.default import unitree_hg_msg_dds__LowCmd_, unitree_hg_msg_dds__LowState_ 3 | from unitree_sdk2py.utils.crc import CRC 4 | 5 | crc = CRC() 6 | 7 | """ 8 | " LowCmd/LowState CRC 9 | """ 10 | cmd = unitree_go_msg_dds__LowCmd_() 11 | cmd.crc = crc.Crc(cmd) 12 | 13 | state = unitree_go_msg_dds__LowState_() 14 | state.crc = crc.Crc(state) 15 | 16 | print("CRC[LowCmd, LowState]: {}, {}".format(cmd.crc, state.crc)) 17 | 18 | """ 19 | " LowCmd/LowState for HG CRC. () 20 | """ 21 | cmd = unitree_hg_msg_dds__LowCmd_() 22 | cmd.crc = crc.Crc(cmd) 23 | 24 | state = unitree_hg_msg_dds__LowState_() 25 | state.crc = crc.Crc(state) 26 | 27 | print("CRC[HGLowCmd, HGLowState]: {}, {}".format(cmd.crc, state.crc)) 28 | -------------------------------------------------------------------------------- /unitree_sdk2py/idl/geometry_msgs/msg/dds_/_Pose_.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generated by Eclipse Cyclone DDS idlc Python Backend 3 | Cyclone DDS IDL version: v0.11.0 4 | Module: geometry_msgs.msg.dds_ 5 | IDL file: Pose_.idl 6 | 7 | """ 8 | 9 | from enum import auto 10 | from typing import TYPE_CHECKING, Optional 11 | from dataclasses import dataclass 12 | 13 | import cyclonedds.idl as idl 14 | import cyclonedds.idl.annotations as annotate 15 | import cyclonedds.idl.types as types 16 | 17 | # root module import for resolving types 18 | # import geometry_msgs 19 | 20 | 21 | @dataclass 22 | @annotate.final 23 | @annotate.autoid("sequential") 24 | class Pose_(idl.IdlStruct, typename="geometry_msgs.msg.dds_.Pose_"): 25 | position: 'unitree_sdk2py.idl.geometry_msgs.msg.dds_.Point_' 26 | orientation: 'unitree_sdk2py.idl.geometry_msgs.msg.dds_.Quaternion_' 27 | 28 | 29 | -------------------------------------------------------------------------------- /unitree_sdk2py/idl/geometry_msgs/msg/dds_/_Twist_.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generated by Eclipse Cyclone DDS idlc Python Backend 3 | Cyclone DDS IDL version: v0.11.0 4 | Module: geometry_msgs.msg.dds_ 5 | IDL file: Twist_.idl 6 | 7 | """ 8 | 9 | from enum import auto 10 | from typing import TYPE_CHECKING, Optional 11 | from dataclasses import dataclass 12 | 13 | import cyclonedds.idl as idl 14 | import cyclonedds.idl.annotations as annotate 15 | import cyclonedds.idl.types as types 16 | 17 | # root module import for resolving types 18 | # import geometry_msgs 19 | 20 | 21 | @dataclass 22 | @annotate.final 23 | @annotate.autoid("sequential") 24 | class Twist_(idl.IdlStruct, typename="geometry_msgs.msg.dds_.Twist_"): 25 | linear: 'unitree_sdk2py.idl.geometry_msgs.msg.dds_.Vector3_' 26 | angular: 'unitree_sdk2py.idl.geometry_msgs.msg.dds_.Vector3_' 27 | 28 | 29 | -------------------------------------------------------------------------------- /unitree_sdk2py/test/client/video_client_example.py: -------------------------------------------------------------------------------- 1 | import time 2 | import os 3 | 4 | from unitree_sdk2py.core.channel import ChannelFactoryInitialize 5 | from unitree_sdk2py.go2.video.video_client import VideoClient 6 | 7 | if __name__ == "__main__": 8 | ChannelFactoryInitialize(0, "enp2s0") 9 | 10 | client = VideoClient() 11 | client.SetTimeout(3.0) 12 | client.Init() 13 | 14 | print("##################GetImageSample###################") 15 | code, data = client.GetImageSample() 16 | 17 | if code != 0: 18 | print("get image sample error. code:", code) 19 | else: 20 | imageName = os.path.dirname(__file__) + time.strftime('/%Y%m%d%H%M%S.jpg',time.localtime()) 21 | print("ImageName:", imageName) 22 | 23 | with open(imageName, "+wb") as f: 24 | f.write(bytes(data)) 25 | 26 | time.sleep(1) 27 | -------------------------------------------------------------------------------- /unitree_sdk2py/idl/std_msgs/msg/dds_/_Header_.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generated by Eclipse Cyclone DDS idlc Python Backend 3 | Cyclone DDS IDL version: v0.11.0 4 | Module: std_msgs.msg.dds_ 5 | IDL file: Header_.idl 6 | 7 | """ 8 | 9 | from enum import auto 10 | from typing import TYPE_CHECKING, Optional 11 | from dataclasses import dataclass 12 | 13 | import cyclonedds.idl as idl 14 | import cyclonedds.idl.annotations as annotate 15 | import cyclonedds.idl.types as types 16 | 17 | # root module import for resolving types 18 | # import std_msgs 19 | 20 | # if TYPE_CHECKING: 21 | # import builtin_interfaces.msg.dds_ 22 | 23 | 24 | 25 | @dataclass 26 | @annotate.final 27 | @annotate.autoid("sequential") 28 | class Header_(idl.IdlStruct, typename="std_msgs.msg.dds_.Header_"): 29 | stamp: 'unitree_sdk2py.idl.builtin_interfaces.msg.dds_.Time_' 30 | frame_id: str 31 | 32 | 33 | -------------------------------------------------------------------------------- /unitree_sdk2py/idl/geometry_msgs/msg/dds_/_PoseWithCovariance_.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generated by Eclipse Cyclone DDS idlc Python Backend 3 | Cyclone DDS IDL version: v0.11.0 4 | Module: geometry_msgs.msg.dds_ 5 | IDL file: PoseWithCovariance_.idl 6 | 7 | """ 8 | 9 | from enum import auto 10 | from typing import TYPE_CHECKING, Optional 11 | from dataclasses import dataclass 12 | 13 | import cyclonedds.idl as idl 14 | import cyclonedds.idl.annotations as annotate 15 | import cyclonedds.idl.types as types 16 | 17 | # root module import for resolving types 18 | # import geometry_msgs 19 | 20 | 21 | @dataclass 22 | @annotate.final 23 | @annotate.autoid("sequential") 24 | class PoseWithCovariance_(idl.IdlStruct, typename="geometry_msgs.msg.dds_.PoseWithCovariance_"): 25 | pose: 'unitree_sdk2py.idl.geometry_msgs.msg.dds_.Pose_' 26 | covariance: types.array[types.float64, 36] 27 | 28 | 29 | -------------------------------------------------------------------------------- /unitree_sdk2py/idl/geometry_msgs/msg/dds_/_TwistWithCovariance_.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generated by Eclipse Cyclone DDS idlc Python Backend 3 | Cyclone DDS IDL version: v0.11.0 4 | Module: geometry_msgs.msg.dds_ 5 | IDL file: TwistWithCovariance_.idl 6 | 7 | """ 8 | 9 | from enum import auto 10 | from typing import TYPE_CHECKING, Optional 11 | from dataclasses import dataclass 12 | 13 | import cyclonedds.idl as idl 14 | import cyclonedds.idl.annotations as annotate 15 | import cyclonedds.idl.types as types 16 | 17 | # root module import for resolving types 18 | # import geometry_msgs 19 | 20 | 21 | @dataclass 22 | @annotate.final 23 | @annotate.autoid("sequential") 24 | class TwistWithCovariance_(idl.IdlStruct, typename="geometry_msgs.msg.dds_.TwistWithCovariance_"): 25 | twist: 'unitree_sdk2py.idl.geometry_msgs.msg.dds_.Twist_' 26 | covariance: types.array[types.float64, 36] 27 | 28 | 29 | -------------------------------------------------------------------------------- /unitree_sdk2py/idl/unitree_api/msg/dds_/_ResponseHeader_.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generated by Eclipse Cyclone DDS idlc Python Backend 3 | Cyclone DDS IDL version: v0.10.2 4 | Module: unitree_api.msg.dds_ 5 | IDL file: ResponseHeader_.idl 6 | 7 | """ 8 | 9 | from enum import auto 10 | from typing import TYPE_CHECKING, Optional 11 | from dataclasses import dataclass 12 | 13 | import cyclonedds.idl as idl 14 | import cyclonedds.idl.annotations as annotate 15 | import cyclonedds.idl.types as types 16 | 17 | # root module import for resolving types 18 | # import unitree_api 19 | 20 | 21 | @dataclass 22 | @annotate.final 23 | @annotate.autoid("sequential") 24 | class ResponseHeader_(idl.IdlStruct, typename="unitree_api.msg.dds_.ResponseHeader_"): 25 | identity: 'unitree_sdk2py.idl.unitree_api.msg.dds_.RequestIdentity_' 26 | status: 'unitree_sdk2py.idl.unitree_api.msg.dds_.ResponseStatus_' 27 | 28 | 29 | -------------------------------------------------------------------------------- /unitree_sdk2py/rpc/internal.py: -------------------------------------------------------------------------------- 1 | # internal api id max 2 | RPC_INTERNAL_API_ID_MAX = 100 3 | 4 | # internal api id 5 | RPC_API_ID_INTERNAL_API_VERSION = 1 6 | 7 | # lease api id 8 | RPC_API_ID_LEASE_APPLY = 101 9 | RPC_API_ID_LEASE_RENEWAL = 102 10 | 11 | # lease term default 12 | RPC_LEASE_TERM = 1.0 13 | 14 | # internal error 15 | RPC_OK = 0 16 | # client error 17 | RPC_ERR_UNKNOWN = 3001 18 | RPC_ERR_CLIENT_SEND = 3102 19 | RPC_ERR_CLIENT_API_NOT_REG = 3103 20 | RPC_ERR_CLIENT_API_TIMEOUT = 3104 21 | RPC_ERR_CLIENT_API_NOT_MATCH = 3105 22 | RPC_ERR_CLIENT_API_DATA = 3106 23 | RPC_ERR_CLIENT_LEASE_INVALID = 3107 24 | # server error 25 | RPC_ERR_SERVER_SEND = 3201 26 | RPC_ERR_SERVER_INTERNAL = 3202 27 | RPC_ERR_SERVER_API_NOT_IMPL = 3203 28 | RPC_ERR_SERVER_API_PARAMETER = 3204 29 | RPC_ERR_SERVER_LEASE_DENIED = 3205 30 | RPC_ERR_SERVER_LEASE_NOT_EXIST = 3206 31 | RPC_ERR_SERVER_LEASE_EXIST = 3207 32 | -------------------------------------------------------------------------------- /unitree_sdk2py/idl/unitree_hg/msg/dds_/_MotorCmd_.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generated by Eclipse Cyclone DDS idlc Python Backend 3 | Cyclone DDS IDL version: v0.11.0 4 | Module: unitree_hg.msg.dds_ 5 | IDL file: MotorCmd_.idl 6 | 7 | """ 8 | 9 | from enum import auto 10 | from typing import TYPE_CHECKING, Optional 11 | from dataclasses import dataclass 12 | 13 | import cyclonedds.idl as idl 14 | import cyclonedds.idl.annotations as annotate 15 | import cyclonedds.idl.types as types 16 | 17 | # root module import for resolving types 18 | # import unitree_hg 19 | 20 | 21 | @dataclass 22 | @annotate.final 23 | @annotate.autoid("sequential") 24 | class MotorCmd_(idl.IdlStruct, typename="unitree_hg.msg.dds_.MotorCmd_"): 25 | mode: types.uint8 26 | q: types.float32 27 | dq: types.float32 28 | tau: types.float32 29 | kp: types.float32 30 | kd: types.float32 31 | reserve: types.uint32 32 | 33 | 34 | -------------------------------------------------------------------------------- /unitree_sdk2py/idl/unitree_hg/msg/dds_/_PressSensorState_.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generated by Eclipse Cyclone DDS idlc Python Backend 3 | Cyclone DDS IDL version: v0.11.0 4 | Module: unitree_hg.msg.dds_ 5 | IDL file: PressSensorState_.idl 6 | 7 | """ 8 | 9 | from enum import auto 10 | from typing import TYPE_CHECKING, Optional 11 | from dataclasses import dataclass 12 | 13 | import cyclonedds.idl as idl 14 | import cyclonedds.idl.annotations as annotate 15 | import cyclonedds.idl.types as types 16 | 17 | # root module import for resolving types 18 | # import unitree_hg 19 | 20 | 21 | @dataclass 22 | @annotate.final 23 | @annotate.autoid("sequential") 24 | class PressSensorState_(idl.IdlStruct, typename="unitree_hg.msg.dds_.PressSensorState_"): 25 | pressure: types.array[types.float32, 12] 26 | temperature: types.array[types.float32, 12] 27 | lost: types.uint32 28 | reserve: types.uint32 29 | 30 | 31 | -------------------------------------------------------------------------------- /unitree_sdk2py/test/lowlevel/read_lowstate.py: -------------------------------------------------------------------------------- 1 | import time 2 | from unitree_sdk2py.core.channel import ChannelSubscriber, ChannelFactoryInitialize 3 | from unitree_sdk2py.idl.default import unitree_go_msg_dds__LowState_ 4 | from unitree_sdk2py.idl.unitree_go.msg.dds_ import LowState_ 5 | 6 | import unitree_go2_const as go2 7 | 8 | 9 | def LowStateHandler(msg: LowState_): 10 | 11 | # print front right hip motor states 12 | print("FR_0 motor state: ", msg.motor_state[go2.LegID["FR_0"]]) 13 | print("IMU state: ", msg.imu_state) 14 | print("Battery state: voltage: ", msg.power_v, "current: ", msg.power_a) 15 | 16 | 17 | if __name__ == "__main__": 18 | # Modify "enp2s0" to the actual network interface 19 | ChannelFactoryInitialize(0, "enp2s0") 20 | sub = ChannelSubscriber("rt/lowstate", LowState_) 21 | sub.Init(LowStateHandler, 10) 22 | 23 | while True: 24 | time.sleep(10.0) 25 | -------------------------------------------------------------------------------- /unitree_sdk2py/idl/unitree_hg/msg/dds_/_MainBoardState_.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generated by Eclipse Cyclone DDS idlc Python Backend 3 | Cyclone DDS IDL version: v0.11.0 4 | Module: unitree_hg.msg.dds_ 5 | IDL file: MainBoardState_.idl 6 | 7 | """ 8 | 9 | from enum import auto 10 | from typing import TYPE_CHECKING, Optional 11 | from dataclasses import dataclass 12 | 13 | import cyclonedds.idl as idl 14 | import cyclonedds.idl.annotations as annotate 15 | import cyclonedds.idl.types as types 16 | 17 | # root module import for resolving types 18 | # import unitree_hg 19 | 20 | 21 | @dataclass 22 | @annotate.final 23 | @annotate.autoid("sequential") 24 | class MainBoardState_(idl.IdlStruct, typename="unitree_hg.msg.dds_.MainBoardState_"): 25 | fan_state: types.array[types.uint16, 6] 26 | temperature: types.array[types.int16, 6] 27 | value: types.array[types.float32, 6] 28 | state: types.array[types.uint32, 6] 29 | 30 | 31 | -------------------------------------------------------------------------------- /unitree_sdk2py/idl/unitree_hg/msg/dds_/_LowCmd_.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generated by Eclipse Cyclone DDS idlc Python Backend 3 | Cyclone DDS IDL version: v0.11.0 4 | Module: unitree_hg.msg.dds_ 5 | IDL file: LowCmd_.idl 6 | 7 | """ 8 | 9 | from enum import auto 10 | from typing import TYPE_CHECKING, Optional 11 | from dataclasses import dataclass 12 | 13 | import cyclonedds.idl as idl 14 | import cyclonedds.idl.annotations as annotate 15 | import cyclonedds.idl.types as types 16 | 17 | # root module import for resolving types 18 | # import unitree_hg 19 | 20 | 21 | @dataclass 22 | @annotate.final 23 | @annotate.autoid("sequential") 24 | class LowCmd_(idl.IdlStruct, typename="unitree_hg.msg.dds_.LowCmd_"): 25 | mode_pr: types.uint8 26 | mode_machine: types.uint8 27 | motor_cmd: types.array['unitree_sdk2py.idl.unitree_hg.msg.dds_.MotorCmd_', 35] 28 | reserve: types.array[types.uint32, 4] 29 | crc: types.uint32 30 | 31 | 32 | -------------------------------------------------------------------------------- /unitree_sdk2py/idl/geometry_msgs/msg/dds_/_PointStamped_.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generated by Eclipse Cyclone DDS idlc Python Backend 3 | Cyclone DDS IDL version: v0.11.0 4 | Module: geometry_msgs.msg.dds_ 5 | IDL file: PointStamped_.idl 6 | 7 | """ 8 | 9 | from enum import auto 10 | from typing import TYPE_CHECKING, Optional 11 | from dataclasses import dataclass 12 | 13 | import cyclonedds.idl as idl 14 | import cyclonedds.idl.annotations as annotate 15 | import cyclonedds.idl.types as types 16 | 17 | # root module import for resolving types 18 | # import geometry_msgs 19 | 20 | # if TYPE_CHECKING: 21 | # import std_msgs.msg.dds_ 22 | 23 | 24 | @dataclass 25 | @annotate.final 26 | @annotate.autoid("sequential") 27 | class PointStamped_(idl.IdlStruct, typename="geometry_msgs.msg.dds_.PointStamped_"): 28 | header: 'unitree_sdk2py.idl.std_msgs.msg.dds_.Header_' 29 | point: 'unitree_sdk2py.idl.geometry_msgs.msg.dds_.Point_' 30 | 31 | 32 | -------------------------------------------------------------------------------- /unitree_sdk2py/idl/geometry_msgs/msg/dds_/_PoseStamped_.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generated by Eclipse Cyclone DDS idlc Python Backend 3 | Cyclone DDS IDL version: v0.11.0 4 | Module: geometry_msgs.msg.dds_ 5 | IDL file: PoseStamped_.idl 6 | 7 | """ 8 | 9 | from enum import auto 10 | from typing import TYPE_CHECKING, Optional 11 | from dataclasses import dataclass 12 | 13 | import cyclonedds.idl as idl 14 | import cyclonedds.idl.annotations as annotate 15 | import cyclonedds.idl.types as types 16 | 17 | # root module import for resolving types 18 | # import geometry_msgs 19 | 20 | # if TYPE_CHECKING: 21 | # import std_msgs.msg.dds_ 22 | 23 | 24 | 25 | @dataclass 26 | @annotate.final 27 | @annotate.autoid("sequential") 28 | class PoseStamped_(idl.IdlStruct, typename="geometry_msgs.msg.dds_.PoseStamped_"): 29 | header: 'unitree_sdk2py.idl.std_msgs.msg.dds_.Header_' 30 | pose: 'unitree_sdk2py.idl.geometry_msgs.msg.dds_.Pose_' 31 | 32 | 33 | -------------------------------------------------------------------------------- /unitree_sdk2py/idl/geometry_msgs/msg/dds_/_TwistStamped_.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generated by Eclipse Cyclone DDS idlc Python Backend 3 | Cyclone DDS IDL version: v0.11.0 4 | Module: geometry_msgs.msg.dds_ 5 | IDL file: TwistStamped_.idl 6 | 7 | """ 8 | 9 | from enum import auto 10 | from typing import TYPE_CHECKING, Optional 11 | from dataclasses import dataclass 12 | 13 | import cyclonedds.idl as idl 14 | import cyclonedds.idl.annotations as annotate 15 | import cyclonedds.idl.types as types 16 | 17 | # root module import for resolving types 18 | # import geometry_msgs 19 | 20 | # if TYPE_CHECKING: 21 | # import std_msgs.msg.dds_ 22 | 23 | 24 | 25 | @dataclass 26 | @annotate.final 27 | @annotate.autoid("sequential") 28 | class TwistStamped_(idl.IdlStruct, typename="geometry_msgs.msg.dds_.TwistStamped_"): 29 | header: 'unitree_sdk2py.idl.std_msgs.msg.dds_.Header_' 30 | twist: 'unitree_sdk2py.idl.geometry_msgs.msg.dds_.Twist_' 31 | 32 | 33 | -------------------------------------------------------------------------------- /unitree_sdk2py/idl/unitree_hg/msg/dds_/_IMUState_.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generated by Eclipse Cyclone DDS idlc Python Backend 3 | Cyclone DDS IDL version: v0.11.0 4 | Module: unitree_hg.msg.dds_ 5 | IDL file: IMUState_.idl 6 | 7 | """ 8 | 9 | from enum import auto 10 | from typing import TYPE_CHECKING, Optional 11 | from dataclasses import dataclass 12 | 13 | import cyclonedds.idl as idl 14 | import cyclonedds.idl.annotations as annotate 15 | import cyclonedds.idl.types as types 16 | 17 | # root module import for resolving types 18 | # import unitree_hg 19 | 20 | 21 | @dataclass 22 | @annotate.final 23 | @annotate.autoid("sequential") 24 | class IMUState_(idl.IdlStruct, typename="unitree_hg.msg.dds_.IMUState_"): 25 | quaternion: types.array[types.float32, 4] 26 | gyroscope: types.array[types.float32, 3] 27 | accelerometer: types.array[types.float32, 3] 28 | rpy: types.array[types.float32, 3] 29 | temperature: types.int16 30 | 31 | 32 | -------------------------------------------------------------------------------- /unitree_sdk2py/idl/unitree_api/msg/dds_/_RequestHeader_.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generated by Eclipse Cyclone DDS idlc Python Backend 3 | Cyclone DDS IDL version: v0.10.2 4 | Module: unitree_api.msg.dds_ 5 | IDL file: RequestHeader_.idl 6 | 7 | """ 8 | 9 | from enum import auto 10 | from typing import TYPE_CHECKING, Optional 11 | from dataclasses import dataclass 12 | 13 | import cyclonedds.idl as idl 14 | import cyclonedds.idl.annotations as annotate 15 | import cyclonedds.idl.types as types 16 | 17 | # root module import for resolving types 18 | # import unitree_api 19 | 20 | 21 | @dataclass 22 | @annotate.final 23 | @annotate.autoid("sequential") 24 | class RequestHeader_(idl.IdlStruct, typename="unitree_api.msg.dds_.RequestHeader_"): 25 | identity: 'unitree_sdk2py.idl.unitree_api.msg.dds_.RequestIdentity_' 26 | lease: 'unitree_sdk2py.idl.unitree_api.msg.dds_.RequestLease_' 27 | policy: 'unitree_sdk2py.idl.unitree_api.msg.dds_.RequestPolicy_' 28 | 29 | 30 | -------------------------------------------------------------------------------- /unitree_sdk2py/idl/geometry_msgs/msg/dds_/_QuaternionStamped_.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generated by Eclipse Cyclone DDS idlc Python Backend 3 | Cyclone DDS IDL version: v0.11.0 4 | Module: geometry_msgs.msg.dds_ 5 | IDL file: QuaternionStamped_.idl 6 | 7 | """ 8 | 9 | from enum import auto 10 | from typing import TYPE_CHECKING, Optional 11 | from dataclasses import dataclass 12 | 13 | import cyclonedds.idl as idl 14 | import cyclonedds.idl.annotations as annotate 15 | import cyclonedds.idl.types as types 16 | 17 | # root module import for resolving types 18 | # import geometry_msgs 19 | 20 | # if TYPE_CHECKING: 21 | # import std_msgs.msg.dds_ 22 | 23 | 24 | 25 | @dataclass 26 | @annotate.final 27 | @annotate.autoid("sequential") 28 | class QuaternionStamped_(idl.IdlStruct, typename="geometry_msgs.msg.dds_.QuaternionStamped_"): 29 | header: 'unitree_sdk2py.idl.std_msgs.msg.dds_.Header_' 30 | quaternion: 'unitree_sdk2py.idl.geometry_msgs.msg.dds_.Quaternion_' 31 | 32 | 33 | -------------------------------------------------------------------------------- /unitree_sdk2py/idl/nav_msgs/msg/dds_/_OccupancyGrid_.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generated by Eclipse Cyclone DDS idlc Python Backend 3 | Cyclone DDS IDL version: v0.11.0 4 | Module: nav_msgs.msg.dds_ 5 | IDL file: OccupancyGrid_.idl 6 | 7 | """ 8 | 9 | from enum import auto 10 | from typing import TYPE_CHECKING, Optional 11 | from dataclasses import dataclass 12 | 13 | import cyclonedds.idl as idl 14 | import cyclonedds.idl.annotations as annotate 15 | import cyclonedds.idl.types as types 16 | 17 | # root module import for resolving types 18 | # import nav_msgs 19 | 20 | # if TYPE_CHECKING: 21 | # import std_msgs.msg.dds_ 22 | 23 | 24 | 25 | @dataclass 26 | @annotate.final 27 | @annotate.autoid("sequential") 28 | class OccupancyGrid_(idl.IdlStruct, typename="nav_msgs.msg.dds_.OccupancyGrid_"): 29 | header: 'unitree_sdk2py.idl.std_msgs.msg.dds_.Header_' 30 | info: 'unitree_sdk2py.idl.nav_msgs.msg.dds_.MapMetaData_' 31 | data: types.sequence[types.uint8] 32 | 33 | 34 | -------------------------------------------------------------------------------- /unitree_sdk2py/core/channel_config.py: -------------------------------------------------------------------------------- 1 | ChannelConfigHasInterface = ''' 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | config 11 | /tmp/cdds.LOG 12 | 13 | 14 | ''' 15 | 16 | ChannelConfigAutoDetermine = ''' 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | ''' 26 | -------------------------------------------------------------------------------- /unitree_sdk2py/idl/geometry_msgs/msg/dds_/_PoseWithCovarianceStamped_.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generated by Eclipse Cyclone DDS idlc Python Backend 3 | Cyclone DDS IDL version: v0.11.0 4 | Module: geometry_msgs.msg.dds_ 5 | IDL file: PoseWithCovarianceStamped_.idl 6 | 7 | """ 8 | 9 | from enum import auto 10 | from typing import TYPE_CHECKING, Optional 11 | from dataclasses import dataclass 12 | 13 | import cyclonedds.idl as idl 14 | import cyclonedds.idl.annotations as annotate 15 | import cyclonedds.idl.types as types 16 | 17 | # root module import for resolving types 18 | # import geometry_msgs 19 | 20 | # if TYPE_CHECKING: 21 | # import std_msgs.msg.dds_ 22 | 23 | 24 | 25 | @dataclass 26 | @annotate.final 27 | @annotate.autoid("sequential") 28 | class PoseWithCovarianceStamped_(idl.IdlStruct, typename="geometry_msgs.msg.dds_.PoseWithCovarianceStamped_"): 29 | header: 'unitree_sdk2py.idl.std_msgs.msg.dds_.Header_' 30 | pose: 'unitree_sdk2py.idl.geometry_msgs.msg.dds_.PoseWithCovariance_' 31 | 32 | 33 | -------------------------------------------------------------------------------- /unitree_sdk2py/idl/geometry_msgs/msg/dds_/_TwistWithCovarianceStamped_.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generated by Eclipse Cyclone DDS idlc Python Backend 3 | Cyclone DDS IDL version: v0.11.0 4 | Module: geometry_msgs.msg.dds_ 5 | IDL file: TwistWithCovarianceStamped_.idl 6 | 7 | """ 8 | 9 | from enum import auto 10 | from typing import TYPE_CHECKING, Optional 11 | from dataclasses import dataclass 12 | 13 | import cyclonedds.idl as idl 14 | import cyclonedds.idl.annotations as annotate 15 | import cyclonedds.idl.types as types 16 | 17 | # root module import for resolving types 18 | # import geometry_msgs 19 | 20 | # if TYPE_CHECKING: 21 | # import std_msgs.msg.dds_ 22 | 23 | 24 | 25 | @dataclass 26 | @annotate.final 27 | @annotate.autoid("sequential") 28 | class TwistWithCovarianceStamped_(idl.IdlStruct, typename="geometry_msgs.msg.dds_.TwistWithCovarianceStamped_"): 29 | header: 'unitree_sdk2py.idl.std_msgs.msg.dds_.Header_' 30 | twist: 'unitree_sdk2py.idl.geometry_msgs.msg.dds_.TwistWithCovariance_' 31 | 32 | 33 | -------------------------------------------------------------------------------- /unitree_sdk2py/idl/unitree_hg/msg/dds_/_MotorState_.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generated by Eclipse Cyclone DDS idlc Python Backend 3 | Cyclone DDS IDL version: v0.11.0 4 | Module: unitree_hg.msg.dds_ 5 | IDL file: MotorState_.idl 6 | 7 | """ 8 | 9 | from enum import auto 10 | from typing import TYPE_CHECKING, Optional 11 | from dataclasses import dataclass 12 | 13 | import cyclonedds.idl as idl 14 | import cyclonedds.idl.annotations as annotate 15 | import cyclonedds.idl.types as types 16 | 17 | # root module import for resolving types 18 | # import unitree_hg 19 | 20 | 21 | @dataclass 22 | @annotate.final 23 | @annotate.autoid("sequential") 24 | class MotorState_(idl.IdlStruct, typename="unitree_hg.msg.dds_.MotorState_"): 25 | mode: types.uint8 26 | q: types.float32 27 | dq: types.float32 28 | ddq: types.float32 29 | tau_est: types.float32 30 | temperature: types.array[types.int16, 2] 31 | vol: types.float32 32 | sensor: types.array[types.uint32, 2] 33 | motorstate: types.uint32 34 | reserve: types.array[types.uint32, 4] 35 | 36 | 37 | -------------------------------------------------------------------------------- /unitree_sdk2py/idl/nav_msgs/msg/dds_/_Odometry_.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generated by Eclipse Cyclone DDS idlc Python Backend 3 | Cyclone DDS IDL version: v0.11.0 4 | Module: nav_msgs.msg.dds_ 5 | IDL file: Odometry_.idl 6 | 7 | """ 8 | 9 | from enum import auto 10 | from typing import TYPE_CHECKING, Optional 11 | from dataclasses import dataclass 12 | 13 | import cyclonedds.idl as idl 14 | import cyclonedds.idl.annotations as annotate 15 | import cyclonedds.idl.types as types 16 | 17 | # root module import for resolving types 18 | # import nav_msgs 19 | 20 | # if TYPE_CHECKING: 21 | # import geometry_msgs.msg.dds_ 22 | # import std_msgs.msg.dds_ 23 | 24 | 25 | 26 | @dataclass 27 | @annotate.final 28 | @annotate.autoid("sequential") 29 | class Odometry_(idl.IdlStruct, typename="nav_msgs.msg.dds_.Odometry_"): 30 | header: 'unitree_sdk2py.idl.std_msgs.msg.dds_.Header_' 31 | child_frame_id: str 32 | pose: 'unitree_sdk2py.idl.geometry_msgs.msg.dds_.PoseWithCovariance_' 33 | twist: 'unitree_sdk2py.idl.geometry_msgs.msg.dds_.TwistWithCovariance_' 34 | 35 | 36 | -------------------------------------------------------------------------------- /unitree_sdk2py/idl/nav_msgs/msg/dds_/_MapMetaData_.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generated by Eclipse Cyclone DDS idlc Python Backend 3 | Cyclone DDS IDL version: v0.11.0 4 | Module: nav_msgs.msg.dds_ 5 | IDL file: MapMetaData_.idl 6 | 7 | """ 8 | 9 | from enum import auto 10 | from typing import TYPE_CHECKING, Optional 11 | from dataclasses import dataclass 12 | 13 | import cyclonedds.idl as idl 14 | import cyclonedds.idl.annotations as annotate 15 | import cyclonedds.idl.types as types 16 | 17 | # root module import for resolving types 18 | # import nav_msgs 19 | 20 | # if TYPE_CHECKING: 21 | # import builtin_interfaces.msg.dds_ 22 | # import geometry_msgs.msg.dds_ 23 | 24 | 25 | 26 | @dataclass 27 | @annotate.final 28 | @annotate.autoid("sequential") 29 | class MapMetaData_(idl.IdlStruct, typename="nav_msgs.msg.dds_.MapMetaData_"): 30 | map_load_time: 'unitree_sdk2py.idl.builtin_interfaces.msg.dds_.Time_' 31 | resolution: types.float32 32 | width: types.uint32 33 | height: types.uint32 34 | origin: 'unitree_sdk2py.idl.geometry_msgs.msg.dds_.Pose_' 35 | 36 | -------------------------------------------------------------------------------- /examples/face_detection.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import pyrealsense2 as rs 3 | import numpy as np 4 | 5 | face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml') 6 | 7 | #Configure RealSense pipeline 8 | pipeline = rs.pipeline() 9 | config = rs.config() 10 | config.enable_stream(rs.stream.color, 640, 480, rs.format.bgr8, 30) 11 | pipeline.start(config) 12 | 13 | try: 14 | while True: 15 | 16 | frames = pipeline.wait_for_frames() 17 | color_frame = frames.get_color_frame() 18 | if not color_frame: 19 | continue 20 | 21 | frame = np.asanyarray(color_frame.get_data()) 22 | gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) 23 | 24 | faces = face_cascade.detectMultiScale(gray, 1.3, 6) 25 | 26 | for (x, y, w, h) in faces: 27 | cv2.rectangle(frame, (x, y), (x+w, y+h), (255, 0, 0), 2) 28 | 29 | cv2.imshow('RealSense Face Detection', frame) 30 | 31 | if cv2.waitKey(1) & 0xFF == ord('q'): 32 | break 33 | 34 | finally: 35 | pipeline.stop() 36 | cv2.destroyAllWindows() 37 | -------------------------------------------------------------------------------- /unitree_sdk2py/idl/unitree_hg/msg/dds_/_LowState_.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generated by Eclipse Cyclone DDS idlc Python Backend 3 | Cyclone DDS IDL version: v0.11.0 4 | Module: unitree_hg.msg.dds_ 5 | IDL file: LowState_.idl 6 | 7 | """ 8 | 9 | from enum import auto 10 | from typing import TYPE_CHECKING, Optional 11 | from dataclasses import dataclass 12 | 13 | import cyclonedds.idl as idl 14 | import cyclonedds.idl.annotations as annotate 15 | import cyclonedds.idl.types as types 16 | 17 | # root module import for resolving types 18 | # import unitree_hg 19 | 20 | 21 | @dataclass 22 | @annotate.final 23 | @annotate.autoid("sequential") 24 | class LowState_(idl.IdlStruct, typename="unitree_hg.msg.dds_.LowState_"): 25 | version: types.array[types.uint32, 2] 26 | mode_pr: types.uint8 27 | mode_machine: types.uint8 28 | tick: types.uint32 29 | imu_state: 'unitree_sdk2py.idl.unitree_hg.msg.dds_.IMUState_' 30 | motor_state: types.array['unitree_sdk2py.idl.unitree_hg.msg.dds_.MotorState_', 35] 31 | wireless_remote: types.array[types.uint8, 40] 32 | reserve: types.array[types.uint32, 4] 33 | crc: types.uint32 34 | 35 | 36 | -------------------------------------------------------------------------------- /unitree_sdk2py/rpc/server_base.py: -------------------------------------------------------------------------------- 1 | import time 2 | 3 | from typing import Callable, Any 4 | 5 | from ..idl.unitree_api.msg.dds_ import Request_ as Request 6 | from ..idl.unitree_api.msg.dds_ import Response_ as Response 7 | 8 | from .server_stub import ServerStub 9 | 10 | 11 | """ 12 | " class ServerBase 13 | """ 14 | class ServerBase: 15 | def __init__(self, name: str): 16 | self.__name = name 17 | self.__serverRequestHandler = None 18 | self.__serverStub = ServerStub(self.__name) 19 | 20 | def GetName(self): 21 | return self.__name 22 | 23 | def _Start(self, enablePrioQueue: bool = False): 24 | self.__serverStub.Init(self.__serverRequestHandler, enablePrioQueue) 25 | print("[ServerBase] server started. name:", self.__name, ", enable proirity queue:", enablePrioQueue) 26 | 27 | def _SetServerRequestHandler(self, serverRequestHandler: Callable): 28 | self.__serverRequestHandler = serverRequestHandler 29 | 30 | def _SendResponse(self, response: Response): 31 | if not self.__serverStub.Send(response, 1.0): 32 | print("[ServerBase] send response error.") 33 | -------------------------------------------------------------------------------- /unitree_sdk2py/idl/geometry_msgs/msg/dds_/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generated by Eclipse Cyclone DDS idlc Python Backend 3 | Cyclone DDS IDL version: v0.11.0 4 | Module: geometry_msgs.msg.dds_ 5 | 6 | """ 7 | 8 | from ._Point32_ import Point32_ 9 | from ._Point_ import Point_ 10 | from ._PointStamped_ import PointStamped_ 11 | from ._Pose2D_ import Pose2D_ 12 | from ._Pose_ import Pose_ 13 | from ._PoseStamped_ import PoseStamped_ 14 | from ._PoseWithCovariance_ import PoseWithCovariance_ 15 | from ._PoseWithCovarianceStamped_ import PoseWithCovarianceStamped_ 16 | from ._Quaternion_ import Quaternion_ 17 | from ._QuaternionStamped_ import QuaternionStamped_ 18 | from ._Twist_ import Twist_ 19 | from ._TwistStamped_ import TwistStamped_ 20 | from ._TwistWithCovariance_ import TwistWithCovariance_ 21 | from ._TwistWithCovarianceStamped_ import TwistWithCovarianceStamped_ 22 | from ._Vector3_ import Vector3_ 23 | __all__ = ["Point32_", "Point_", "PointStamped_", "Pose2D_", "Pose_", "PoseStamped_", "PoseWithCovariance_", "PoseWithCovarianceStamped_", "Quaternion_", "QuaternionStamped_", "Twist_", "TwistStamped_", "TwistWithCovariance_", "TwistWithCovarianceStamped_", "Vector3_", ] 24 | -------------------------------------------------------------------------------- /unitree_sdk2py/idl/sensor_msgs/msg/dds_/_PointCloud2_.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generated by Eclipse Cyclone DDS idlc Python Backend 3 | Cyclone DDS IDL version: v0.11.0 4 | Module: sensor_msgs.msg.dds_ 5 | IDL file: PointCloud2_.idl 6 | 7 | """ 8 | 9 | from enum import auto 10 | from typing import TYPE_CHECKING, Optional 11 | from dataclasses import dataclass 12 | 13 | import cyclonedds.idl as idl 14 | import cyclonedds.idl.annotations as annotate 15 | import cyclonedds.idl.types as types 16 | 17 | # root module import for resolving types 18 | # import sensor_msgs 19 | 20 | # if TYPE_CHECKING: 21 | # import std_msgs.msg.dds_ 22 | 23 | 24 | 25 | @dataclass 26 | @annotate.final 27 | @annotate.autoid("sequential") 28 | class PointCloud2_(idl.IdlStruct, typename="sensor_msgs.msg.dds_.PointCloud2_"): 29 | header: 'unitree_sdk2py.idl.std_msgs.msg.dds_.Header_' 30 | height: types.uint32 31 | width: types.uint32 32 | fields: types.sequence['unitree_sdk2py.idl.sensor_msgs.msg.dds_.PointField_'] 33 | is_bigendian: bool 34 | point_step: types.uint32 35 | row_step: types.uint32 36 | data: types.sequence[types.uint8] 37 | is_dense: bool 38 | 39 | 40 | -------------------------------------------------------------------------------- /unitree_sdk2py/idl/unitree_hg/msg/dds_/_BmsState_.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generated by Eclipse Cyclone DDS idlc Python Backend 3 | Cyclone DDS IDL version: v0.11.0 4 | Module: unitree_hg.msg.dds_ 5 | IDL file: BmsState_.idl 6 | 7 | """ 8 | 9 | from enum import auto 10 | from typing import TYPE_CHECKING, Optional 11 | from dataclasses import dataclass 12 | 13 | import cyclonedds.idl as idl 14 | import cyclonedds.idl.annotations as annotate 15 | import cyclonedds.idl.types as types 16 | 17 | # root module import for resolving types 18 | # import unitree_hg 19 | 20 | 21 | @dataclass 22 | @annotate.final 23 | @annotate.autoid("sequential") 24 | class BmsState_(idl.IdlStruct, typename="unitree_hg.msg.dds_.BmsState_"): 25 | version_high: types.uint8 26 | version_low: types.uint8 27 | fn: types.uint8 28 | cell_vol: types.array[types.uint16, 40] 29 | bmsvoltage: types.array[types.uint32, 3] 30 | current: types.int32 31 | soc: types.uint8 32 | soh: types.uint8 33 | temperature: types.array[types.int16, 12] 34 | cycle: types.uint16 35 | manufacturer_date: types.uint16 36 | bmsstate: types.array[types.uint32, 5] 37 | reserve: types.array[types.uint32, 3] 38 | 39 | 40 | -------------------------------------------------------------------------------- /unitree_sdk2py/idl/unitree_hg/msg/dds_/_HandState_.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generated by Eclipse Cyclone DDS idlc Python Backend 3 | Cyclone DDS IDL version: v0.11.0 4 | Module: unitree_hg.msg.dds_ 5 | IDL file: HandState_.idl 6 | 7 | """ 8 | 9 | from enum import auto 10 | from typing import TYPE_CHECKING, Optional 11 | from dataclasses import dataclass 12 | 13 | import cyclonedds.idl as idl 14 | import cyclonedds.idl.annotations as annotate 15 | import cyclonedds.idl.types as types 16 | 17 | # root module import for resolving types 18 | # import unitree_hg 19 | 20 | 21 | @dataclass 22 | @annotate.final 23 | @annotate.autoid("sequential") 24 | class HandState_(idl.IdlStruct, typename="unitree_hg.msg.dds_.HandState_"): 25 | motor_state: types.sequence['unitree_sdk2py.idl.unitree_hg.msg.dds_.MotorState_'] 26 | press_sensor_state: types.sequence['unitree_sdk2py.idl.unitree_hg.msg.dds_.PressSensorState_'] 27 | imu_state: 'unitree_sdk2py.idl.unitree_hg.msg.dds_.IMUState_' 28 | power_v: types.float32 29 | power_a: types.float32 30 | system_v: types.float32 31 | device_v: types.float32 32 | error: types.array[types.uint32, 2] 33 | reserve: types.array[types.uint32, 2] 34 | 35 | 36 | -------------------------------------------------------------------------------- /examples/pose_detection.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | import pyrealsense2 as rs 4 | from ultralytics import YOLO 5 | 6 | # Load YOLOv11 pose model (replace with correct model path if local) 7 | model = YOLO("yolo11n-pose.pt") # or 'yolov11-pose.pt' when available 8 | 9 | # Configure RealSense pipeline 10 | pipeline = rs.pipeline() 11 | config = rs.config() 12 | config.enable_stream(rs.stream.color, 640, 480, rs.format.bgr8, 30) 13 | pipeline.start(config) 14 | 15 | try: 16 | while True: 17 | # Get RealSense color frame 18 | frames = pipeline.wait_for_frames() 19 | color_frame = frames.get_color_frame() 20 | if not color_frame: 21 | continue 22 | 23 | frame = np.asanyarray(color_frame.get_data()) 24 | 25 | # Run YOLOv11 pose detection 26 | results = model.predict(frame, verbose=False) 27 | 28 | # Visualize pose results 29 | annotated_frame = results[0].plot() 30 | 31 | # Show the frame 32 | cv2.imshow("YOLOv Pose on RealSense", annotated_frame) 33 | if cv2.waitKey(1) & 0xFF == ord('q'): 34 | break 35 | 36 | finally: 37 | pipeline.stop() 38 | cv2.destroyAllWindows() 39 | -------------------------------------------------------------------------------- /unitree_sdk2py/test/rpc/test_server_example.py: -------------------------------------------------------------------------------- 1 | import time 2 | import json 3 | 4 | from unitree_sdk2py.core.channel import ChannelFactoryInitialize 5 | from unitree_sdk2py.rpc.server import Server 6 | 7 | from test_api import * 8 | 9 | 10 | """ 11 | " class TestServer 12 | """ 13 | class TestServer(Server): 14 | def __init__(self): 15 | super().__init__("test") 16 | 17 | def Init(self): 18 | self._RegistHandler(TEST_API_ID_MOVE, self.Move, 1) 19 | self._RegistHandler(TEST_API_ID_STOP, self.Stop, 0) 20 | self._SetApiVersion(TEST_API_VERSION) 21 | 22 | def Move(self, parameter: str): 23 | p = json.loads(parameter) 24 | x = p["vx"] 25 | y = p["vy"] 26 | yaw = p["vyaw"] 27 | print("Move Called. vx:", x, ", vy:", y, ", vyaw:", yaw) 28 | return 0, "" 29 | 30 | def Stop(self, parameter: str): 31 | print("Stop Called.") 32 | return 0, "" 33 | 34 | if __name__ == "__main__": 35 | # initialize channel factory. 36 | ChannelFactoryInitialize(0) 37 | 38 | # create server 39 | server = TestServer() 40 | server.Init() 41 | server.StartLease(1.0) 42 | server.Start(False) 43 | 44 | while True: 45 | time.sleep(10) -------------------------------------------------------------------------------- /unitree_sdk2py/rpc/request_future.py: -------------------------------------------------------------------------------- 1 | from threading import Condition, Lock 2 | from enum import Enum 3 | 4 | from ..idl.unitree_api.msg.dds_ import Response_ as Response 5 | from ..utils.future import Future, FutureResult 6 | 7 | 8 | """ 9 | " class RequestFuture 10 | """ 11 | class RequestFuture(Future): 12 | def __init__(self): 13 | self.__requestId = None 14 | super().__init__() 15 | 16 | def SetRequestId(self, requestId: int): 17 | self.__requestId = requestId 18 | 19 | def GetRequestId(self): 20 | return self.__requestId 21 | 22 | 23 | class RequestFutureQueue: 24 | def __init__(self): 25 | self.__data = {} 26 | self.__lock = Lock() 27 | 28 | def Set(self, requestId: int, future: RequestFuture): 29 | if future is None: 30 | return False 31 | with self.__lock: 32 | self.__data[requestId] = future 33 | return True 34 | 35 | def Get(self, requestId: int): 36 | future = None 37 | with self.__lock: 38 | future = self.__data.get(requestId) 39 | if future is not None: 40 | self.__data.pop(requestId) 41 | return future 42 | 43 | def Remove(self, requestId: int): 44 | with self.__lock: 45 | if id in self.__data: 46 | self.__data.pop(requestId) -------------------------------------------------------------------------------- /examples/camera_feed.py: -------------------------------------------------------------------------------- 1 | import pyrealsense2 as rs 2 | import numpy as np 3 | import cv2 4 | 5 | # Configure the pipeline 6 | pipeline = rs.pipeline() 7 | config = rs.config() 8 | 9 | # Enable depth and color streams 10 | config.enable_stream(rs.stream.depth, 640, 480, rs.format.z16, 30) 11 | config.enable_stream(rs.stream.color, 640, 480, rs.format.bgr8, 30) 12 | 13 | # Start streaming 14 | pipeline.start(config) 15 | 16 | try: 17 | while True: 18 | # Wait for a coherent pair of frames: depth and color 19 | frames = pipeline.wait_for_frames() 20 | depth_frame = frames.get_depth_frame() 21 | color_frame = frames.get_color_frame() 22 | if not depth_frame or not color_frame: 23 | continue 24 | 25 | # Convert images to numpy arrays 26 | depth_image = np.asanyarray(depth_frame.get_data()) 27 | color_image = np.asanyarray(color_frame.get_data()) 28 | 29 | # Apply colormap on depth image (for better visualization) 30 | depth_colormap = cv2.applyColorMap( 31 | cv2.convertScaleAbs(depth_image, alpha=0.03), 32 | cv2.COLORMAP_JET 33 | ) 34 | 35 | # Stack both images horizontally 36 | images = np.hstack((color_image, depth_colormap)) 37 | 38 | # Show the images 39 | cv2.imshow('RealSense RGB and Depth', images) 40 | if cv2.waitKey(1) & 0xFF == ord('q'): 41 | break 42 | 43 | finally: 44 | # Stop streaming 45 | pipeline.stop() 46 | cv2.destroyAllWindows() 47 | -------------------------------------------------------------------------------- /unitree_sdk2py/utils/timerfd.py: -------------------------------------------------------------------------------- 1 | import math 2 | import ctypes 3 | from .clib_lookup import CLIBLookup 4 | 5 | class timespec(ctypes.Structure): 6 | _fields_ = [("sec", ctypes.c_long), ("nsec", ctypes.c_long)] 7 | __slots__ = [name for name,type in _fields_] 8 | 9 | @classmethod 10 | def from_seconds(cls, secs): 11 | c = cls() 12 | c.seconds = secs 13 | return c 14 | 15 | @property 16 | def seconds(self): 17 | return self.sec + self.nsec / 1000000000 18 | 19 | @seconds.setter 20 | def seconds(self, secs): 21 | x, y = math.modf(secs) 22 | self.sec = int(y) 23 | self.nsec = int(x * 1000000000) 24 | 25 | 26 | class itimerspec(ctypes.Structure): 27 | _fields_ = [("interval", timespec),("value", timespec)] 28 | __slots__ = [name for name,type in _fields_] 29 | 30 | @classmethod 31 | def from_seconds(cls, interval, value): 32 | spec = cls() 33 | spec.interval.seconds = interval 34 | spec.value.seconds = value 35 | return spec 36 | 37 | 38 | # function timerfd_create 39 | timerfd_create = CLIBLookup("timerfd_create", ctypes.c_int, (ctypes.c_long, ctypes.c_int)) 40 | 41 | # function timerfd_settime 42 | timerfd_settime = CLIBLookup("timerfd_settime", ctypes.c_int, (ctypes.c_int, ctypes.c_int, ctypes.POINTER(itimerspec), ctypes.POINTER(itimerspec))) 43 | 44 | # function timerfd_gettime 45 | timerfd_gettime = CLIBLookup("timerfd_gettime", ctypes.c_int, (ctypes.c_int, ctypes.POINTER(itimerspec))) 46 | -------------------------------------------------------------------------------- /examples/rgb.py: -------------------------------------------------------------------------------- 1 | import time 2 | import sys 3 | from unitree_sdk2py.core.channel import ChannelSubscriber, ChannelFactoryInitialize 4 | from unitree_sdk2py.g1.audio.g1_audio_client import AudioClient 5 | 6 | def set_rgb_light(audio_client, r, g, b, duration=1): 7 | """ 8 | Controls the G1 RGB light strip. 9 | 10 | :param audio_client: Initialized AudioClient instance 11 | :param r: Red intensity (0-255) 12 | :param g: Green intensity (0-255) 13 | :param b: Blue intensity (0-255) 14 | :param duration: How long the color remains before turning off (in seconds) 15 | """ 16 | result = audio_client.LedControl(r, g, b) 17 | if result == 0: 18 | print(f"✅ RGB Light set to ({r}, {g}, {b}) for {duration} seconds") 19 | else: 20 | print(f"❌ Error setting RGB Light: Error Code {result}") 21 | 22 | time.sleep(duration) # Keep light on for the duration 23 | audio_client.LedControl(0, 0, 0) # Turn off light 24 | 25 | # Initialize AudioClient 26 | if __name__ == "__main__": 27 | if len(sys.argv) < 2: 28 | print(f"Usage: python3 {sys.argv[0]} networkInterface") 29 | sys.exit(-1) 30 | 31 | ChannelFactoryInitialize(0, sys.argv[1]) 32 | 33 | audio_client = AudioClient() 34 | audio_client.SetTimeout(10.0) 35 | audio_client.Init() 36 | 37 | # Set RGB light examples 38 | set_rgb_light(audio_client, 255, 0, 0, 1) # Red 39 | set_rgb_light(audio_client, 0, 255, 0, 1) # Green 40 | set_rgb_light(audio_client, 0, 0, 255, 1) # Blue 41 | set_rgb_light(audio_client, 255, 255, 0, 1) # Yellow 42 | set_rgb_light(audio_client, 255, 255, 255, 1) # White 43 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2016-2024 HangZhou YuShu TECHNOLOGY CO.,LTD. ("Unitree Robotics") 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /unitree_sdk2py/comm/motion_switcher/motion_switcher_client.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | from ...rpc.client import Client 4 | from .motion_switcher_api import * 5 | 6 | """ 7 | " class MotionSwitcherClient 8 | """ 9 | class MotionSwitcherClient(Client): 10 | def __init__(self): 11 | super().__init__(MOTION_SWITCHER_SERVICE_NAME, False) 12 | 13 | 14 | def Init(self): 15 | # set api version 16 | self._SetApiVerson(MOTION_SWITCHER_API_VERSION) 17 | 18 | # regist api 19 | self._RegistApi(MOTION_SWITCHER_API_ID_CHECK_MODE, 0) 20 | self._RegistApi(MOTION_SWITCHER_API_ID_SELECT_MODE, 0) 21 | self._RegistApi(MOTION_SWITCHER_API_ID_RELEASE_MODE, 0) 22 | self._RegistApi(MOTION_SWITCHER_API_ID_SET_SILENT, 0) 23 | self._RegistApi(MOTION_SWITCHER_API_ID_GET_SILENT, 0) 24 | 25 | # 1001 26 | def CheckMode(self): 27 | p = {} 28 | parameter = json.dumps(p) 29 | code, data = self._Call(MOTION_SWITCHER_API_ID_CHECK_MODE, parameter) 30 | if code == 0: 31 | return code, json.loads(data) 32 | else: 33 | return code, None 34 | 35 | # 1002 36 | def SelectMode(self, nameOrAlias): 37 | p = {} 38 | p["name"] = nameOrAlias 39 | parameter = json.dumps(p) 40 | code, data = self._Call(MOTION_SWITCHER_API_ID_SELECT_MODE, parameter) 41 | 42 | return code, None 43 | 44 | # 1003 45 | def ReleaseMode(self): 46 | p = {} 47 | parameter = json.dumps(p) 48 | code, data = self._Call(MOTION_SWITCHER_API_ID_RELEASE_MODE, parameter) 49 | 50 | return code, None 51 | -------------------------------------------------------------------------------- /unitree_sdk2py/test/rpc/test_client_example.py: -------------------------------------------------------------------------------- 1 | import time 2 | import json 3 | 4 | from unitree_sdk2py.core.channel import ChannelFactoryInitialize 5 | from unitree_sdk2py.rpc.client import Client 6 | 7 | from test_api import * 8 | 9 | """ 10 | " class TestClient 11 | """ 12 | class TestClient(Client): 13 | def __init__(self, enableLease: bool = False): 14 | super().__init__("test", enableLease) 15 | 16 | def Init(self): 17 | self._RegistApi(TEST_API_ID_MOVE, 0) 18 | self._RegistApi(TEST_API_ID_STOP, 1) 19 | self._SetApiVerson(TEST_API_VERSION) 20 | 21 | def Move(self, vx: float, vy: float, vyaw: float): 22 | parameter = {} 23 | parameter["vx"] = vx 24 | parameter["vy"] = vy 25 | parameter["vyaw"] = vyaw 26 | p = json.dumps(parameter) 27 | 28 | c, d = self._Call(TEST_API_ID_MOVE, p) 29 | return c 30 | 31 | def Stop(self): 32 | parameter = {} 33 | p = json.dumps(parameter) 34 | 35 | c, d = self._Call(TEST_API_ID_STOP, p) 36 | return c 37 | 38 | if __name__ == "__main__": 39 | # initialize channel factory. 40 | ChannelFactoryInitialize(0) 41 | 42 | # create client 43 | client = TestClient(True) 44 | client.Init() 45 | client.SetTimeout(5.0) 46 | 47 | # get server version 48 | code, serverApiVersion = client.GetServerApiVersion() 49 | print("server api version:", serverApiVersion) 50 | 51 | # wait lease applied 52 | client.WaitLeaseApplied() 53 | 54 | # test api 55 | while True: 56 | code = client.Move(0.2, 0, 0) 57 | print("client move ret:", code) 58 | time.sleep(1.0) 59 | 60 | code = client.Stop() 61 | print("client stop ret:", code) 62 | time.sleep(1.0) 63 | -------------------------------------------------------------------------------- /unitree_sdk2py/test/client/robot_service_client_example.py: -------------------------------------------------------------------------------- 1 | import time 2 | from unitree_sdk2py.core.channel import ChannelFactoryInitialize 3 | from unitree_sdk2py.go2.robot_state.robot_state_client import RobotStateClient 4 | 5 | if __name__ == "__main__": 6 | ChannelFactoryInitialize(0, "enx000ec6768747") 7 | rsc = RobotStateClient() 8 | rsc.SetTimeout(3.0) 9 | rsc.Init() 10 | 11 | while True: 12 | print("##################GetServerApiVersion###################") 13 | code, serverAPiVersion = rsc.GetServerApiVersion() 14 | 15 | if code != 0: 16 | print("get server api error. code:", code) 17 | else: 18 | print("get server api version:", serverAPiVersion) 19 | 20 | time.sleep(3) 21 | 22 | print("##################ServiceList###################") 23 | code, lst = rsc.ServiceList() 24 | 25 | if code != 0: 26 | print("list sevrice error. code:", code) 27 | else: 28 | print("list service success. len:", len(lst)) 29 | for s in lst: 30 | print("name:", s.name, ", protect:", s.protect, ", status:", s.status) 31 | 32 | time.sleep(3) 33 | 34 | print("##################ServiceSwitch###################") 35 | code = rsc.ServiceSwitch("sport_mode", False) 36 | if code != 0: 37 | print("service stop sport_mode error. code:", code) 38 | else: 39 | print("service stop sport_mode success. code:", code) 40 | 41 | time.sleep(1) 42 | 43 | code = rsc.ServiceSwitch("sport_mode", True) 44 | if code != 0: 45 | print("service start sport_mode error. code:", code) 46 | else: 47 | print("service start sport_mode success. code:", code) 48 | 49 | time.sleep(3) 50 | 51 | -------------------------------------------------------------------------------- /unitree_sdk2py/utils/bqueue.py: -------------------------------------------------------------------------------- 1 | from typing import Any 2 | from collections import deque 3 | from threading import Condition 4 | 5 | class BQueue: 6 | def __init__(self, maxLen: int = 10): 7 | self.__curLen = 0 8 | self.__maxLen = maxLen 9 | self.__queue = deque() 10 | self.__condition = Condition() 11 | 12 | def Put(self, x: Any, replace: bool = False): 13 | noReplaced = True 14 | with self.__condition: 15 | if self.__curLen >= self.__maxLen: 16 | if not replace: 17 | return False 18 | else: 19 | noReplaced = False 20 | self.__queue.popleft() 21 | self.__curLen -= 1 22 | 23 | self.__queue.append(x) 24 | self.__curLen += 1 25 | self.__condition.notify() 26 | 27 | return noReplaced 28 | 29 | def Get(self, timeout: float = None): 30 | with self.__condition: 31 | if not self.__queue: 32 | try: 33 | self.__condition.wait(timeout) 34 | except: 35 | return None 36 | 37 | if not self.__queue: 38 | return None 39 | 40 | self.__curLen -= 1 41 | return self.__queue.popleft() 42 | 43 | def Clear(self): 44 | with self.__condition: 45 | if self.__queue: 46 | self.__queue.clear() 47 | self.__curLen = 0 48 | 49 | def Size(self): 50 | with self.__condition: 51 | return self.__curLen 52 | 53 | def Interrupt(self, notifyAll: bool = False): 54 | with self.__condition: 55 | if notifyAll: 56 | self.__condition.notify() 57 | else: 58 | self.__condition.notify_all() 59 | -------------------------------------------------------------------------------- /unitree_sdk2py/g1/audio/g1_audio_client.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | from ...rpc.client import Client 4 | from .g1_audio_api import * 5 | 6 | """ 7 | " class SportClient 8 | """ 9 | class AudioClient(Client): 10 | def __init__(self): 11 | super().__init__(AUDIO_SERVICE_NAME, False) 12 | self.tts_index = 0 13 | 14 | def Init(self): 15 | # set api version 16 | self._SetApiVerson(AUDIO_API_VERSION) 17 | 18 | # regist api 19 | self._RegistApi(ROBOT_API_ID_AUDIO_TTS, 0) 20 | self._RegistApi(ROBOT_API_ID_AUDIO_ASR, 0) 21 | self._RegistApi(ROBOT_API_ID_AUDIO_START_PLAY, 0) 22 | self._RegistApi(ROBOT_API_ID_AUDIO_STOP_PLAY, 0) 23 | self._RegistApi(ROBOT_API_ID_AUDIO_GET_VOLUME, 0) 24 | self._RegistApi(ROBOT_API_ID_AUDIO_SET_VOLUME, 0) 25 | self._RegistApi(ROBOT_API_ID_AUDIO_SET_RGB_LED, 0) 26 | 27 | ## API Call ## 28 | def TtsMaker(self, text: str, speaker_id: int): 29 | self.tts_index += self.tts_index 30 | p = {} 31 | p["index"] = self.tts_index 32 | p["text"] = text 33 | p["speaker_id"] = speaker_id 34 | parameter = json.dumps(p) 35 | code, data = self._Call(ROBOT_API_ID_AUDIO_TTS, parameter) 36 | return code 37 | 38 | def GetVolume(self): 39 | p = {} 40 | parameter = json.dumps(p) 41 | code, data = self._Call(ROBOT_API_ID_AUDIO_GET_VOLUME, parameter) 42 | if code == 0: 43 | return code, json.loads(data) 44 | else: 45 | return code, None 46 | 47 | def SetVolume(self, volume: int): 48 | p = {} 49 | p["volume"] = volume 50 | # p["name"] = 'volume' 51 | parameter = json.dumps(p) 52 | code, data = self._Call(ROBOT_API_ID_AUDIO_SET_VOLUME, parameter) 53 | return code 54 | 55 | def LedControl(self, R: int, G: int, B: int): 56 | p = {} 57 | p["R"] = R 58 | p["G"] = G 59 | p["B"] = B 60 | parameter = json.dumps(p) 61 | code, data = self._Call(ROBOT_API_ID_AUDIO_SET_RGB_LED, parameter) 62 | return code 63 | -------------------------------------------------------------------------------- /examples/distance_detection.py: -------------------------------------------------------------------------------- 1 | import pyrealsense2 as rs 2 | import numpy as np 3 | import cv2 4 | 5 | # Configure the pipeline 6 | pipeline = rs.pipeline() 7 | config = rs.config() 8 | 9 | # Enable depth and color streams 10 | config.enable_stream(rs.stream.depth, 640, 480, rs.format.z16, 30) 11 | config.enable_stream(rs.stream.color, 640, 480, rs.format.bgr8, 30) 12 | 13 | # Start streaming 14 | pipeline.start(config) 15 | 16 | try: 17 | while True: 18 | # Wait for a coherent pair of frames: depth and color 19 | frames = pipeline.wait_for_frames() 20 | depth_frame = frames.get_depth_frame() 21 | color_frame = frames.get_color_frame() 22 | if not depth_frame or not color_frame: 23 | continue 24 | 25 | # Convert images to numpy arrays 26 | depth_image = np.asanyarray(depth_frame.get_data()) 27 | color_image = np.asanyarray(color_frame.get_data()) 28 | 29 | # Find the closest point (excluding 0, which means invalid) 30 | non_zero_depths = depth_image[depth_image > 0] 31 | if non_zero_depths.size > 0: 32 | min_distance = np.min(non_zero_depths) # in millimeters 33 | else: 34 | min_distance = -1 # No valid depth 35 | 36 | # Convert depth image to color for visualization 37 | depth_colormap = cv2.applyColorMap( 38 | cv2.convertScaleAbs(depth_image, alpha=0.03), 39 | cv2.COLORMAP_JET 40 | ) 41 | 42 | # Overlay distance info on the color image 43 | if min_distance > 0: 44 | text = f"Closest object: {min_distance} mm" 45 | else: 46 | text = "No valid depth data" 47 | 48 | cv2.putText(color_image, text, (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 49 | 0.8, (0, 255, 0), 2) 50 | 51 | # Stack both images horizontally 52 | images = np.hstack((color_image, depth_colormap)) 53 | 54 | # Show the images 55 | cv2.imshow('RealSense RGB and Depth', images) 56 | 57 | if cv2.waitKey(1) & 0xFF == ord('q'): 58 | break 59 | 60 | finally: 61 | # Stop streaming 62 | pipeline.stop() 63 | cv2.destroyAllWindows() 64 | -------------------------------------------------------------------------------- /unitree_sdk2py/test/lowlevel/lowlevel_control.py: -------------------------------------------------------------------------------- 1 | import time 2 | 3 | from unitree_sdk2py.core.channel import ChannelPublisher, ChannelFactoryInitialize 4 | from unitree_sdk2py.core.channel import ChannelSubscriber, ChannelFactoryInitialize 5 | from unitree_sdk2py.idl.default import unitree_go_msg_dds__LowCmd_ 6 | from unitree_sdk2py.idl.unitree_go.msg.dds_ import LowCmd_ 7 | from unitree_sdk2py.utils.crc import CRC 8 | from unitree_sdk2py.utils.thread import Thread 9 | import unitree_go2_const as go2 10 | 11 | crc = CRC() 12 | lowCmdThreadPtr=Thread() 13 | 14 | if __name__ == '__main__': 15 | 16 | ChannelFactoryInitialize(1, "enp2s0") 17 | # Create a publisher to publish the data defined in UserData class 18 | pub = ChannelPublisher("lowcmd", LowCmd_) 19 | pub.Init() 20 | 21 | while True: 22 | # Create a Userdata message 23 | cmd = unitree_go_msg_dds__LowCmd_() 24 | 25 | # Toque controle, set RL_2 toque 26 | cmd.motor_cmd[go2.LegID["RL_2"]].mode = 0x01 27 | cmd.motor_cmd[go2.LegID["RL_2"]].q = go2.PosStopF # Set to stop position(rad) 28 | cmd.motor_cmd[go2.LegID["RL_2"]].kp = 0 29 | cmd.motor_cmd[go2.LegID["RL_2"]].dq = go2.VelStopF # Set to stop angular velocity(rad/s) 30 | cmd.motor_cmd[go2.LegID["RL_2"]].kd = 0 31 | cmd.motor_cmd[go2.LegID["RL_2"]].tau = 1 # target toque is set to 1N.m 32 | 33 | # Poinstion(rad) control, set RL_0 rad 34 | cmd.motor_cmd[go2.LegID["RL_0"]].mode = 0x01 35 | cmd.motor_cmd[go2.LegID["RL_0"]].q = 0 # Taregt angular(rad) 36 | cmd.motor_cmd[go2.LegID["RL_0"]].kp = 10 # Poinstion(rad) control kp gain 37 | cmd.motor_cmd[go2.LegID["RL_0"]].dq = 0 # Taregt angular velocity(rad/ss) 38 | cmd.motor_cmd[go2.LegID["RL_0"]].kd = 1 # Poinstion(rad) control kd gain 39 | cmd.motor_cmd[go2.LegID["RL_0"]].tau = 0 # Feedforward toque 1N.m 40 | 41 | cmd.crc = crc.Crc(cmd) 42 | 43 | #Publish message 44 | if pub.Write(cmd): 45 | print("Publish success. msg:", cmd.crc) 46 | else: 47 | print("Waitting for subscriber.") 48 | 49 | time.sleep(0.002) 50 | 51 | pub.Close() 52 | -------------------------------------------------------------------------------- /unitree_sdk2py/test/client/vui_client_example.py: -------------------------------------------------------------------------------- 1 | import time 2 | import os 3 | 4 | from unitree_sdk2py.core.channel import ChannelFactoryInitialize 5 | from unitree_sdk2py.go2.vui.vui_client import VuiClient 6 | 7 | if __name__ == "__main__": 8 | ChannelFactoryInitialize(0, "enp2s0") 9 | 10 | client = VuiClient() 11 | client.SetTimeout(3.0) 12 | client.Init() 13 | 14 | for i in range(1, 11): 15 | print("#################GetBrightness####################") 16 | code, level = client.GetBrightness() 17 | 18 | if code != 0: 19 | print("get brightness error. code:", code) 20 | else: 21 | print("get brightness success. level:", level) 22 | 23 | time.sleep(1) 24 | 25 | print("#################SetBrightness####################") 26 | 27 | code = client.SetBrightness(i) 28 | 29 | if code != 0: 30 | print("set brightness error. code:", code) 31 | else: 32 | print("set brightness success. level:", i) 33 | 34 | time.sleep(1) 35 | 36 | print("#################SetBrightness 0####################") 37 | 38 | code = client.SetBrightness(0) 39 | 40 | if code != 0: 41 | print("set brightness error. code:", code) 42 | else: 43 | print("set brightness 0 success.") 44 | 45 | for i in range(1, 11): 46 | print("#################GetVolume####################") 47 | code, level = client.GetVolume() 48 | 49 | if code != 0: 50 | print("get volume error. code:", code) 51 | else: 52 | print("get volume success. level:", level) 53 | 54 | time.sleep(1) 55 | 56 | print("#################SetVolume####################") 57 | 58 | code = client.SetVolume(i) 59 | 60 | if code != 0: 61 | print("set volume error. code:", code) 62 | else: 63 | print("set volume success. level:", i) 64 | 65 | time.sleep(1) 66 | 67 | print("#################SetVolume 0####################") 68 | 69 | code = client.SetVolume(0) 70 | 71 | if code != 0: 72 | print("set volume error. code:", code) 73 | else: 74 | print("set volume 0 success.") 75 | -------------------------------------------------------------------------------- /unitree_sdk2py/rpc/client_stub.py: -------------------------------------------------------------------------------- 1 | import time 2 | 3 | from enum import Enum 4 | from threading import Thread, Condition 5 | 6 | from ..idl.unitree_api.msg.dds_ import Request_ as Request 7 | from ..idl.unitree_api.msg.dds_ import Response_ as Response 8 | 9 | from ..core.channel import ChannelFactory 10 | from ..core.channel_name import ChannelType, GetClientChannelName 11 | from .request_future import RequestFuture, RequestFutureQueue 12 | 13 | 14 | """ 15 | " class ClientStub 16 | """ 17 | class ClientStub: 18 | def __init__(self, serviceName: str): 19 | self.__serviceName = serviceName 20 | self.__futureQueue = None 21 | 22 | self.__sendChannel = None 23 | self.__recvChannel = None 24 | 25 | def Init(self): 26 | factory = ChannelFactory() 27 | self.__futureQueue = RequestFutureQueue() 28 | 29 | # create channel 30 | self.__sendChannel = factory.CreateSendChannel(GetClientChannelName(self.__serviceName, ChannelType.SEND), Request) 31 | self.__recvChannel = factory.CreateRecvChannel(GetClientChannelName(self.__serviceName, ChannelType.RECV), Response, 32 | self.__ResponseHandler,10) 33 | time.sleep(0.5) 34 | 35 | 36 | def Send(self, request: Request, timeout: float): 37 | if self.__sendChannel.Write(request, timeout): 38 | return True 39 | else: 40 | print("[ClientStub] send error. id:", request.header.identity.id) 41 | return False 42 | 43 | def SendRequest(self, request: Request, timeout: float): 44 | id = request.header.identity.id 45 | 46 | future = RequestFuture() 47 | future.SetRequestId(id) 48 | self.__futureQueue.Set(id, future) 49 | 50 | if self.__sendChannel.Write(request, timeout): 51 | return future 52 | else: 53 | print("[ClientStub] send request error. id:", request.header.identity.id) 54 | self.__futureQueue.Remove(id) 55 | return None 56 | 57 | def RemoveFuture(self, requestId: int): 58 | self.__futureQueue.Remove(requestId) 59 | 60 | def __ResponseHandler(self, response: Response): 61 | id = response.header.identity.id 62 | # apiId = response.header.identity.api_id 63 | # print("[ClientStub] responseHandler recv response id:", id, ", apiId:", apiId) 64 | future = self.__futureQueue.Get(id) 65 | if future is None: 66 | # print("[ClientStub] get future from queue error. id:", id) 67 | pass 68 | elif not future.Ready(response): 69 | print("[ClientStub] set future ready error.") 70 | -------------------------------------------------------------------------------- /unitree_sdk2py/rpc/server_stub.py: -------------------------------------------------------------------------------- 1 | import time 2 | 3 | from enum import Enum 4 | from threading import Thread, Condition 5 | from typing import Callable, Any 6 | 7 | from ..utils.bqueue import BQueue 8 | from ..idl.unitree_api.msg.dds_ import Request_ as Request 9 | from ..idl.unitree_api.msg.dds_ import Response_ as Response 10 | 11 | from ..core.channel import ChannelFactory 12 | from ..core.channel_name import ChannelType, GetServerChannelName 13 | 14 | 15 | """ 16 | " class ServerStub 17 | """ 18 | class ServerStub: 19 | def __init__(self, serviceName: str): 20 | self.__serviceName = serviceName 21 | self.__serverRquestHandler = None 22 | self.__sendChannel = None 23 | self.__recvChannel = None 24 | self.__enablePriority = None 25 | self.__queue = None 26 | self.__prioQueue = None 27 | self.__queueThread = None 28 | self.__prioQueueThread = None 29 | 30 | def Init(self, serverRequestHander: Callable, enablePriority: bool = False): 31 | self.__serverRquestHandler = serverRequestHander 32 | self.__enablePriority = enablePriority 33 | 34 | factory = ChannelFactory() 35 | 36 | # create channel 37 | self.__sendChannel = factory.CreateSendChannel(GetServerChannelName(self.__serviceName, ChannelType.SEND), Response) 38 | self.__recvChannel = factory.CreateRecvChannel(GetServerChannelName(self.__serviceName, ChannelType.RECV), Request, self.__Enqueue, 10) 39 | 40 | # start priority request thread 41 | self.__queue = BQueue(10) 42 | self.__queueThread = Thread(target=self.__QueueThreadFunc, name="server_queue", daemon=True) 43 | self.__queueThread.start() 44 | 45 | if enablePriority: 46 | self.__prioQueue = BQueue(5) 47 | self.__prioQueueThread = Thread(target=self.__PrioQueueThreadFunc, name="server_prio_queue", daemon=True) 48 | self.__prioQueueThread.start() 49 | 50 | # wait thread started 51 | time.sleep(0.5) 52 | 53 | def Send(self, response: Response, timeout: float): 54 | if self.__sendChannel.Write(response, timeout): 55 | return True 56 | else: 57 | print("[ServerStub] send error. id:", response.header.identity.id) 58 | return False 59 | 60 | def __Enqueue(self, request: Request): 61 | if self.__enablePriority and request.header.policy.priority > 0: 62 | self.__prioQueue.Put(request, True) 63 | else: 64 | self.__queue.Put(request, True) 65 | 66 | def __QueueThreadFunc(self): 67 | while True: 68 | request = self.__queue.Get() 69 | if request is None: 70 | continue 71 | self.__serverRquestHandler(request) 72 | 73 | def __PrioQueueThreadFunc(self): 74 | while True: 75 | request = self.__prioQueue.Get() 76 | if request is None: 77 | continue 78 | self.__serverRquestHandler(request) 79 | -------------------------------------------------------------------------------- /unitree_sdk2py/utils/thread.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import os 3 | import errno 4 | import ctypes 5 | import struct 6 | import threading 7 | 8 | from .future import Future 9 | from .timerfd import * 10 | 11 | class Thread(Future): 12 | def __init__(self, target = None, name = None, args = (), kwargs = None): 13 | super().__init__() 14 | self.__target = target 15 | self.__args = args 16 | self.__kwargs = {} if kwargs is None else kwargs 17 | self.__thread = threading.Thread(target=self.__ThreadFunc, name=name, daemon=True) 18 | 19 | def Start(self): 20 | return self.__thread.start() 21 | 22 | def GetId(self): 23 | return self.__thread.ident 24 | 25 | def GetNativeId(self): 26 | return self.__thread.native_id 27 | 28 | def __ThreadFunc(self): 29 | value = None 30 | try: 31 | value = self.__target(*self.__args, **self.__kwargs) 32 | self.Ready(value) 33 | except: 34 | info = sys.exc_info() 35 | self.Fail(f"[Thread] target func raise exception: name={info[0].__name__}, args={str(info[1].args)}") 36 | 37 | class RecurrentThread(Thread): 38 | def __init__(self, interval: float = 1.0, target = None, name = None, args = (), kwargs = None): 39 | self.__quit = False 40 | self.__inter = interval 41 | self.__loopTarget = target 42 | self.__loopArgs = args 43 | self.__loopKwargs = {} if kwargs is None else kwargs 44 | 45 | if interval is None or interval <= 0.0: 46 | super().__init__(target=self.__LoopFunc_0, name=name) 47 | else: 48 | super().__init__(target=self.__LoopFunc, name=name) 49 | 50 | def Wait(self, timeout: float = None): 51 | self.__quit = True 52 | super().Wait(timeout) 53 | 54 | def __LoopFunc(self): 55 | # clock type CLOCK_MONOTONIC = 1 56 | tfd = timerfd_create(1, 0) 57 | spec = itimerspec.from_seconds(self.__inter, self.__inter) 58 | timerfd_settime(tfd, 0, ctypes.byref(spec), None) 59 | 60 | while not self.__quit: 61 | try: 62 | self.__loopTarget(*self.__loopArgs, **self.__loopKwargs) 63 | except: 64 | info = sys.exc_info() 65 | print(f"[RecurrentThread] target func raise exception: name={info[0].__name__}, args={str(info[1].args)}") 66 | 67 | try: 68 | buf = os.read(tfd, 8) 69 | # print(struct.unpack("Q", buf)[0]) 70 | except OSError as e: 71 | if e.errno != errno.EAGAIN: 72 | raise e 73 | 74 | os.close(tfd) 75 | 76 | def __LoopFunc_0(self): 77 | while not self.__quit: 78 | try: 79 | self.__loopTarget(*self.__args, **self.__kwargs) 80 | except: 81 | info = sys.exc_info() 82 | print(f"[RecurrentThread] target func raise exception: name={info[0].__name__}, args={str(info[1].args)}") 83 | 84 | -------------------------------------------------------------------------------- /unitree_sdk2py/test/client/obstacles_avoid_client_example.py: -------------------------------------------------------------------------------- 1 | import time 2 | import os 3 | 4 | from unitree_sdk2py.core.channel import ChannelFactoryInitialize 5 | from unitree_sdk2py.go2.obstacles_avoid.obstacles_avoid_client import ObstaclesAvoidClient 6 | 7 | if __name__ == "__main__": 8 | ChannelFactoryInitialize(0, "enp3s0") 9 | 10 | client = ObstaclesAvoidClient() 11 | client.SetTimeout(3.0) 12 | client.Init() 13 | 14 | while True: 15 | print("##################GetServerApiVersion###################") 16 | code, serverAPiVersion = client.GetServerApiVersion() 17 | if code != 0: 18 | print("get server api error. code:", code) 19 | else: 20 | print("get server api version:", serverAPiVersion) 21 | 22 | if serverAPiVersion != client.GetApiVersion(): 23 | print("api version not equal.") 24 | 25 | time.sleep(3) 26 | 27 | print("##################SwitchGet###################") 28 | code, enable = client.SwitchGet() 29 | if code != 0: 30 | print("switch get error. code:", code) 31 | else: 32 | print("switch get success. enable:", enable) 33 | 34 | time.sleep(3) 35 | 36 | print("##################SwitchSet (on)###################") 37 | code = client.SwitchSet(True) 38 | if code != 0: 39 | print("switch set error. code:", code) 40 | else: 41 | print("switch set success.") 42 | 43 | time.sleep(3) 44 | 45 | print("##################SwitchGet###################") 46 | code, enable1 = client.SwitchGet() 47 | if code != 0: 48 | print("switch get error. code:", code) 49 | else: 50 | print("switch get success. enable:", enable1) 51 | 52 | time.sleep(3) 53 | 54 | print("##################SwitchSet (off)###################") 55 | code = client.SwitchSet(False) 56 | if code != 0: 57 | print("switch set error. code:", code) 58 | else: 59 | print("switch set success.") 60 | 61 | time.sleep(3) 62 | 63 | print("##################SwitchGet###################") 64 | code, enable1 = client.SwitchGet() 65 | if code != 0: 66 | print("switch get error. code:", code) 67 | else: 68 | print("switch get success. enable:", enable1) 69 | 70 | time.sleep(3) 71 | 72 | 73 | print("##################SwitchSet (enable)###################") 74 | 75 | code = client.SwitchSet(enable) 76 | if code != 0: 77 | print("switch set error. code:", code) 78 | else: 79 | print("switch set success. enable:", enable) 80 | 81 | time.sleep(3) 82 | 83 | print("##################SwitchGet###################") 84 | code, enable = client.SwitchGet() 85 | if code != 0: 86 | print("switch get error. code:", code) 87 | else: 88 | print("switch get success. enable:", enable) 89 | 90 | time.sleep(3) 91 | -------------------------------------------------------------------------------- /unitree_sdk2py/rpc/client.py: -------------------------------------------------------------------------------- 1 | from .client_base import ClientBase 2 | from .lease_client import LeaseClient 3 | from .internal import * 4 | 5 | """ 6 | " class Client 7 | """ 8 | class Client(ClientBase): 9 | def __init__(self, serviceName: str, enabaleLease: bool = False): 10 | super().__init__(serviceName) 11 | 12 | self.__apiMapping = {} 13 | self.__apiVersion = None 14 | self.__leaseClient = None 15 | self.__enableLease = enabaleLease 16 | 17 | if (self.__enableLease): 18 | self.__leaseClient = LeaseClient(serviceName) 19 | self.__leaseClient.Init() 20 | 21 | def WaitLeaseApplied(self): 22 | if self.__enableLease: 23 | self.__leaseClient.WaitApplied() 24 | 25 | def GetLeaseId(self): 26 | if self.__enableLease: 27 | return self.__leaseClient.GetId() 28 | else: 29 | return None 30 | 31 | def GetApiVersion(self): 32 | return self.__apiVersion 33 | 34 | def GetServerApiVersion(self): 35 | code, apiVerson = self._CallBase(RPC_API_ID_INTERNAL_API_VERSION, "{}", 0, 0) 36 | if code != 0: 37 | print("[Client] get server api version error:", code) 38 | return code, None 39 | else: 40 | return code, apiVerson 41 | 42 | def _SetApiVerson(self, apiVersion: str): 43 | self.__apiVersion = apiVersion 44 | 45 | def _Call(self, apiId: int, parameter: str): 46 | ret, proirity, leaseId = self.__CheckApi(apiId) 47 | if ret == 0: 48 | return self._CallBase(apiId, parameter, proirity, leaseId) 49 | else: 50 | return RPC_ERR_CLIENT_API_NOT_REG, None 51 | 52 | def _CallNoReply(self, apiId: int, parameter: str): 53 | ret, proirity, leaseId = self.__CheckApi(apiId) 54 | if ret == 0: 55 | return self._CallNoReplyBase(apiId, parameter, proirity, leaseId) 56 | else: 57 | return RPC_ERR_CLIENT_API_NOT_REG 58 | 59 | def _CallBinary(self, apiId: int, parameter: list): 60 | ret, proirity, leaseId = self.__CheckApi(apiId) 61 | if ret == 0: 62 | return self._CallBinaryBase(apiId, parameter, proirity, leaseId) 63 | else: 64 | return RPC_ERR_CLIENT_API_NOT_REG, None 65 | 66 | def _CallBinaryNoReply(self, apiId: int, parameter: list): 67 | ret, proirity, leaseId = self.__CheckApi(apiId) 68 | if ret == 0: 69 | return self._CallBinaryNoReplyBase(apiId, parameter, proirity, leaseId) 70 | else: 71 | return RPC_ERR_CLIENT_API_NOT_REG 72 | 73 | def _RegistApi(self, apiId: int, proirity: int): 74 | self.__apiMapping[apiId] = proirity 75 | 76 | def __CheckApi(self, apiId: int): 77 | proirity = 0 78 | leaseId = 0 79 | 80 | if apiId > RPC_INTERNAL_API_ID_MAX: 81 | proirity = self.__apiMapping.get(apiId) 82 | 83 | if proirity is None: 84 | return RPC_ERR_CLIENT_API_NOT_REG, proirity, leaseId 85 | 86 | if self.__enableLease: 87 | leaseId = self.__leaseClient.GetId() 88 | 89 | return 0, proirity, leaseId -------------------------------------------------------------------------------- /unitree_sdk2py/rpc/lease_client.py: -------------------------------------------------------------------------------- 1 | import time 2 | import socket 3 | import os 4 | import json 5 | 6 | from threading import Thread, Lock 7 | 8 | from .client_base import ClientBase 9 | from .internal import * 10 | 11 | 12 | """ 13 | " class LeaseContext 14 | """ 15 | class LeaseContext: 16 | def __init__(self): 17 | self.id = 0 18 | self.term = RPC_LEASE_TERM 19 | 20 | def Update(self, id, term): 21 | self.id = id 22 | self.term = term 23 | 24 | def Reset(self): 25 | self.id = 0 26 | self.term = RPC_LEASE_TERM 27 | 28 | def Valid(self): 29 | return self.id != 0 30 | 31 | 32 | """ 33 | " class LeaseClient 34 | """ 35 | class LeaseClient(ClientBase): 36 | def __init__(self, name: str): 37 | self.__name = name + "_lease" 38 | self.__contextName = socket.gethostname() + "/" + name + "/" + str(os.getpid()) 39 | self.__context = LeaseContext() 40 | self.__thread = None 41 | self.__lock = Lock() 42 | super().__init__(self.__name) 43 | print("[LeaseClient] lease name:", self.__name, ", context name:", self.__contextName) 44 | 45 | def Init(self): 46 | self.SetTimeout(1.0) 47 | self.__thread = Thread(target=self.__ThreadFunc, name=self.__name, daemon=True) 48 | self.__thread.start() 49 | 50 | def WaitApplied(self): 51 | while True: 52 | with self.__lock: 53 | if self.__context.Valid(): 54 | break 55 | time.sleep(0.1) 56 | 57 | def GetId(self): 58 | with self.__lock: 59 | return self.__context.id 60 | 61 | def Applied(self): 62 | with self.__lock: 63 | return self.__context.Valid() 64 | 65 | def __Apply(self): 66 | parameter = {} 67 | parameter["name"] = self.__contextName 68 | p = json.dumps(parameter) 69 | 70 | c, d = self._CallBase(RPC_API_ID_LEASE_APPLY, p) 71 | if c != 0: 72 | print("[LeaseClient] apply lease error. code:", c) 73 | return 74 | 75 | data = json.loads(d) 76 | 77 | id = data["id"] 78 | term = data["term"] 79 | 80 | print("[LeaseClient] lease applied id:", id, ", term:", term) 81 | 82 | with self.__lock: 83 | self.__context.Update(id, float(term/1000000)) 84 | 85 | def __Renewal(self): 86 | parameter = {} 87 | p = json.dumps(parameter) 88 | 89 | c, d = self._CallBase(RPC_API_ID_LEASE_RENEWAL, p, 0, self.__context.id) 90 | if c != 0: 91 | print("[LeaseClient] renewal lease error. code:", c) 92 | if c == RPC_ERR_SERVER_LEASE_NOT_EXIST: 93 | with self.__lock: 94 | self.__context.Reset() 95 | 96 | def __GetWaitSec(self): 97 | waitsec = 0.0 98 | if self.__context.Valid(): 99 | waitsec = self.__context.term 100 | 101 | if waitsec <= 0: 102 | waitsec = RPC_LEASE_TERM 103 | 104 | return waitsec * 0.3 105 | 106 | def __ThreadFunc(self): 107 | while True: 108 | if self.__context.Valid(): 109 | self.__Renewal() 110 | else: 111 | self.__Apply() 112 | # sleep waitsec 113 | time.sleep(self.__GetWaitSec()) 114 | -------------------------------------------------------------------------------- /unitree_sdk2py/utils/future.py: -------------------------------------------------------------------------------- 1 | from threading import Condition 2 | from typing import Any 3 | from enum import Enum 4 | 5 | """ 6 | " Enum RequtestFutureState 7 | """ 8 | class FutureState(Enum): 9 | DEFER = 0 10 | READY = 1 11 | FAILED = 2 12 | 13 | """ 14 | " class FutureException 15 | """ 16 | class FutureResult: 17 | FUTURE_SUCC = 0 18 | FUTUTE_ERR_TIMEOUT = 1 19 | FUTURE_ERR_FAILED = 2 20 | FUTURE_ERR_UNKNOWN = 3 21 | 22 | def __init__(self, code: int, msg: str, value: Any = None): 23 | self.code = code 24 | self.msg = msg 25 | self.value = value 26 | 27 | def __str__(self): 28 | return f"FutureResult(code={str(self.code)}, msg='{self.msg}', value={self.value})" 29 | 30 | class Future: 31 | def __init__(self): 32 | self.__state = FutureState.DEFER 33 | self.__msg = None 34 | self.__condition = Condition() 35 | 36 | def GetResult(self, timeout: float = None): 37 | with self.__condition: 38 | return self.__WaitResult(timeout) 39 | 40 | def Wait(self, timeout: float = None): 41 | with self.__condition: 42 | return self.__Wait(timeout) 43 | 44 | def Ready(self, value): 45 | with self.__condition: 46 | ready = self.__Ready(value) 47 | self.__condition.notify() 48 | return ready 49 | 50 | def Fail(self, reason: str): 51 | with self.__condition: 52 | fail = self.__Fail(reason) 53 | self.__condition.notify() 54 | return fail 55 | 56 | def __Wait(self, timeout: float = None): 57 | if not self.__IsDeferred(): 58 | return True 59 | try: 60 | if timeout is None: 61 | return self.__condition.wait() 62 | else: 63 | return self.__condition.wait(timeout) 64 | except: 65 | print("[Future] future wait error") 66 | return False 67 | 68 | def __WaitResult(self, timeout: float = None): 69 | if not self.__Wait(timeout): 70 | return FutureResult(FutureResult.FUTUTE_ERR_TIMEOUT, "future wait timeout") 71 | 72 | if self.__IsReady(): 73 | return FutureResult(FutureResult.FUTURE_SUCC, "success", self.__value) 74 | elif self.__IsFailed(): 75 | return FutureResult(FutureResult.FUTURE_ERR_FAILED, self.__msg) 76 | else: 77 | return FutureResult(FutureResult.FUTURE_ERR_UNKNOWN, "future state error:" + str(self.__state)) 78 | 79 | def __Ready(self, value): 80 | if not self.__IsDeferred(): 81 | print("[Future] futrue state is not defer") 82 | return False 83 | else: 84 | self.__value = value 85 | self.__state = FutureState.READY 86 | return True 87 | 88 | def __Fail(self, message: str): 89 | if not self.__IsDeferred(): 90 | print("[Future] futrue state is not DEFER") 91 | return False 92 | else: 93 | self.__msg = message 94 | self.__state = FutureState.FAILED 95 | return True 96 | 97 | def __IsDeferred(self): 98 | return self.__state == FutureState.DEFER 99 | 100 | def __IsReady(self): 101 | return self.__state == FutureState.READY 102 | 103 | def __IsFailed(self): 104 | return self.__state == FutureState.FAILED -------------------------------------------------------------------------------- /unitree_sdk2py/test/client/sport_client_example.py: -------------------------------------------------------------------------------- 1 | import time 2 | from unitree_sdk2py.core.channel import ChannelFactoryInitialize 3 | from unitree_sdk2py.go2.sport.sport_client import SportClient, PathPoint, SPORT_PATH_POINT_SIZE 4 | 5 | if __name__ == "__main__": 6 | ChannelFactoryInitialize(0, "enp2s0") 7 | client = SportClient() 8 | client.SetTimeout(10.0) 9 | client.Init() 10 | 11 | print("##################GetServerApiVersion###################") 12 | code, serverAPiVersion = client.GetServerApiVersion() 13 | if code != 0: 14 | print("get server api error. code:", code) 15 | else: 16 | print("get server api version:", serverAPiVersion) 17 | 18 | if serverAPiVersion != client.GetApiVersion(): 19 | print("api version not equal.") 20 | 21 | time.sleep(3) 22 | 23 | print("##################Trigger###################") 24 | code = client.Trigger() 25 | if code != 0: 26 | print("sport trigger error. code:", code) 27 | else: 28 | print("sport trigger success.") 29 | 30 | time.sleep(3) 31 | 32 | while True: 33 | print("##################RecoveryStand###################") 34 | code = client.RecoveryStand() 35 | 36 | if code != 0: 37 | print("sport recovery stand error. code:", code) 38 | else: 39 | print("sport recovery stand success.") 40 | 41 | time.sleep(3) 42 | 43 | print("##################StandDown###################") 44 | code = client.StandDown() 45 | if code != 0: 46 | print("sport stand down error. code:", code) 47 | else: 48 | print("sport stand down success.") 49 | 50 | time.sleep(3) 51 | 52 | print("##################Damp###################") 53 | code = client.Damp() 54 | if code != 0: 55 | print("sport damp error. code:", code) 56 | else: 57 | print("sport damp down success.") 58 | 59 | time.sleep(3) 60 | 61 | print("##################RecoveryStand###################") 62 | code = client.RecoveryStand() 63 | 64 | if code != 0: 65 | print("sport recovery stand error. code:", code) 66 | else: 67 | print("sport recovery stand success.") 68 | 69 | time.sleep(3) 70 | 71 | print("##################Sit###################") 72 | code = client.Sit() 73 | if code != 0: 74 | print("sport stand down error. code:", code) 75 | else: 76 | print("sport stand down success.") 77 | 78 | time.sleep(3) 79 | 80 | print("##################RiseSit###################") 81 | code = client.RiseSit() 82 | 83 | if code != 0: 84 | print("sport rise sit error. code:", code) 85 | else: 86 | print("sport rise sit success.") 87 | 88 | time.sleep(3) 89 | 90 | print("##################SetBodyHight###################") 91 | code = client.BodyHeight(0.18) 92 | 93 | if code != 0: 94 | print("sport body hight error. code:", code) 95 | else: 96 | print("sport body hight success.") 97 | 98 | time.sleep(3) 99 | 100 | print("##################GetState#################") 101 | keys = ["state", "bodyHeight", "footRaiseHeight", "speedLevel", "gait"] 102 | code, data = client.GetState(keys) 103 | 104 | if code != 0: 105 | print("sport get state error. code:", code) 106 | else: 107 | print("sport get state success. data:", data) 108 | 109 | time.sleep(3) 110 | -------------------------------------------------------------------------------- /unitree_sdk2py/rpc/client_base.py: -------------------------------------------------------------------------------- 1 | import time 2 | 3 | from ..idl.unitree_api.msg.dds_ import Request_ as Request 4 | from ..idl.unitree_api.msg.dds_ import RequestHeader_ as RequestHeader 5 | from ..idl.unitree_api.msg.dds_ import RequestLease_ as RequestLease 6 | from ..idl.unitree_api.msg.dds_ import RequestIdentity_ as RequestIdentity 7 | from ..idl.unitree_api.msg.dds_ import RequestPolicy_ as RequestPolicy 8 | 9 | from ..utils.future import FutureResult 10 | 11 | from .client_stub import ClientStub 12 | from .internal import * 13 | 14 | 15 | """ 16 | " class ClientBase 17 | """ 18 | class ClientBase: 19 | def __init__(self, serviceName: str): 20 | self.__timeout = 1.0 21 | self.__stub = ClientStub(serviceName) 22 | self.__stub.Init() 23 | 24 | def SetTimeout(self, timeout: float): 25 | self.__timeout = timeout 26 | 27 | def _CallBase(self, apiId: int, parameter: str, proirity: int = 0, leaseId: int = 0): 28 | # print("[CallBase] call apiId:", apiId, ", proirity:", proirity, ", leaseId:", leaseId) 29 | header = self.__SetHeader(apiId, leaseId, proirity, False) 30 | request = Request(header, parameter, []) 31 | 32 | future = self.__stub.SendRequest(request, self.__timeout) 33 | if future is None: 34 | return RPC_ERR_CLIENT_SEND, None 35 | 36 | result = future.GetResult(self.__timeout) 37 | 38 | if result.code != FutureResult.FUTURE_SUCC: 39 | self.__stub.RemoveFuture(request.header.identity.id) 40 | code = RPC_ERR_CLIENT_API_TIMEOUT if result.code == FutureResult.FUTUTE_ERR_TIMEOUT else RPC_ERR_UNKNOWN 41 | return code, None 42 | 43 | response = result.value 44 | 45 | if response.header.identity.api_id != apiId: 46 | return RPC_ERR_CLIENT_API_NOT_MATCH, None 47 | else: 48 | return response.header.status.code, response.data 49 | 50 | def _CallNoReplyBase(self, apiId: int, parameter: str, proirity: int, leaseId: int): 51 | header = self.__SetHeader(apiId, leaseId, proirity, True) 52 | request = Request(header, parameter, []) 53 | 54 | if self.__stub.Send(request, self.__timeout): 55 | return 0 56 | else: 57 | return RPC_ERR_CLIENT_SEND 58 | 59 | def _CallBinaryBase(self, apiId: int, parameter: list, proirity: int, leaseId: int): 60 | header = self.__SetHeader(apiId, leaseId, proirity, False) 61 | request = Request(header, "", parameter) 62 | 63 | future = self.__stub.SendRequest(request, self.__timeout) 64 | if future is None: 65 | return RPC_ERR_CLIENT_SEND, None 66 | 67 | result = future.GetResult(self.__timeout) 68 | if result.code != FutureResult.FUTURE_SUCC: 69 | self.__stub.RemoveFuture(request.header.identity.id) 70 | code = RPC_ERR_CLIENT_API_TIMEOUT if result.code == FutureResult.FUTUTE_ERR_TIMEOUT else RPC_ERR_UNKNOWN 71 | return code, None 72 | 73 | response = result.value 74 | 75 | if response.header.identity.api_id != apiId: 76 | return RPC_ERR_CLIENT_API_NOT_MATCH, None 77 | else: 78 | return response.header.status.code, response.binary 79 | 80 | def _CallBinaryNoReplyBase(self, apiId: int, parameter: list, proirity: int, leaseId: int): 81 | header = self.__SetHeader(apiId, leaseId, proirity, True) 82 | request = Request(header, "", parameter) 83 | 84 | if self.__stub.Send(request, self.__timeout): 85 | return 0 86 | else: 87 | return RPC_ERR_CLIENT_SEND 88 | 89 | def __SetHeader(self, apiId: int, leaseId: int, priority: int, noReply: bool): 90 | identity = RequestIdentity(time.monotonic_ns(), apiId) 91 | lease = RequestLease(leaseId) 92 | policy = RequestPolicy(priority, noReply) 93 | return RequestHeader(identity, lease, policy) 94 | -------------------------------------------------------------------------------- /examples/depth_color_alignment.py: -------------------------------------------------------------------------------- 1 | ## License: Apache 2.0. See LICENSE file in root directory. 2 | ## Copyright(c) 2017 Intel Corporation. All Rights Reserved. 3 | 4 | ##################################################### 5 | ## Align Depth to Color ## 6 | ##################################################### 7 | 8 | # First import the library 9 | import pyrealsense2 as rs 10 | # Import Numpy for easy array manipulation 11 | import numpy as np 12 | # Import OpenCV for easy image rendering 13 | import cv2 14 | 15 | # Create a pipeline 16 | pipeline = rs.pipeline() 17 | 18 | # Create a config and configure the pipeline to stream 19 | # different resolutions of color and depth streams 20 | config = rs.config() 21 | 22 | # Get device product line for setting a supporting resolution 23 | pipeline_wrapper = rs.pipeline_wrapper(pipeline) 24 | pipeline_profile = config.resolve(pipeline_wrapper) 25 | device = pipeline_profile.get_device() 26 | device_product_line = str(device.get_info(rs.camera_info.product_line)) 27 | 28 | found_rgb = False 29 | for s in device.sensors: 30 | if s.get_info(rs.camera_info.name) == 'RGB Camera': 31 | found_rgb = True 32 | break 33 | if not found_rgb: 34 | print("The demo requires Depth camera with Color sensor") 35 | exit(0) 36 | 37 | config.enable_stream(rs.stream.depth, 640, 480, rs.format.z16, 30) 38 | config.enable_stream(rs.stream.color, 640, 480, rs.format.bgr8, 30) 39 | 40 | # Start streaming 41 | profile = pipeline.start(config) 42 | 43 | # Getting the depth sensor's depth scale (see rs-align example for explanation) 44 | depth_sensor = profile.get_device().first_depth_sensor() 45 | depth_scale = depth_sensor.get_depth_scale() 46 | print("Depth Scale is: " , depth_scale) 47 | 48 | # We will be removing the background of objects more than 49 | # clipping_distance_in_meters meters away 50 | clipping_distance_in_meters = 1 #1 meter 51 | clipping_distance = clipping_distance_in_meters / depth_scale 52 | 53 | # Create an align object 54 | # rs.align allows us to perform alignment of depth frames to others frames 55 | # The "align_to" is the stream type to which we plan to align depth frames. 56 | align_to = rs.stream.color 57 | align = rs.align(align_to) 58 | 59 | # Streaming loop 60 | try: 61 | while True: 62 | # Get frameset of color and depth 63 | frames = pipeline.wait_for_frames() 64 | # frames.get_depth_frame() is a 640x360 depth image 65 | 66 | # Align the depth frame to color frame 67 | aligned_frames = align.process(frames) 68 | 69 | # Get aligned frames 70 | aligned_depth_frame = aligned_frames.get_depth_frame() # aligned_depth_frame is a 640x480 depth image 71 | color_frame = aligned_frames.get_color_frame() 72 | 73 | # Validate that both frames are valid 74 | if not aligned_depth_frame or not color_frame: 75 | continue 76 | 77 | depth_image = np.asanyarray(aligned_depth_frame.get_data()) 78 | color_image = np.asanyarray(color_frame.get_data()) 79 | 80 | # Remove background - Set pixels further than clipping_distance to grey 81 | grey_color = 153 82 | depth_image_3d = np.dstack((depth_image,depth_image,depth_image)) #depth image is 1 channel, color is 3 channels 83 | bg_removed = np.where((depth_image_3d > clipping_distance) | (depth_image_3d <= 0), grey_color, color_image) 84 | 85 | # Render images: 86 | # depth align to color on left 87 | # depth on right 88 | depth_colormap = cv2.applyColorMap(cv2.convertScaleAbs(depth_image, alpha=0.03), cv2.COLORMAP_JET) 89 | images = np.hstack((bg_removed, depth_colormap)) 90 | 91 | cv2.namedWindow('Align Example', cv2.WINDOW_NORMAL) 92 | cv2.imshow('Align Example', images) 93 | key = cv2.waitKey(1) 94 | # Press esc or 'q' to close the image window 95 | if key & 0xFF == ord('q') or key == 27: 96 | cv2.destroyAllWindows() 97 | break 98 | finally: 99 | pipeline.stop() -------------------------------------------------------------------------------- /unitree_sdk2py/g1/loco/g1_loco_client.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | from ...rpc.client import Client 4 | from .g1_loco_api import * 5 | 6 | """ 7 | " class SportClient 8 | """ 9 | class LocoClient(Client): 10 | def __init__(self): 11 | super().__init__(LOCO_SERVICE_NAME, False) 12 | self.first_shake_hand_stage_ = -1 13 | 14 | def Init(self): 15 | # set api version 16 | self._SetApiVerson(LOCO_API_VERSION) 17 | 18 | # regist api 19 | self._RegistApi(ROBOT_API_ID_LOCO_GET_FSM_ID, 0) 20 | self._RegistApi(ROBOT_API_ID_LOCO_GET_FSM_MODE, 0) 21 | self._RegistApi(ROBOT_API_ID_LOCO_GET_BALANCE_MODE, 0) 22 | self._RegistApi(ROBOT_API_ID_LOCO_GET_SWING_HEIGHT, 0) 23 | self._RegistApi(ROBOT_API_ID_LOCO_GET_STAND_HEIGHT, 0) 24 | self._RegistApi(ROBOT_API_ID_LOCO_GET_PHASE, 0) # deprecated 25 | 26 | self._RegistApi(ROBOT_API_ID_LOCO_SET_FSM_ID, 0) 27 | self._RegistApi(ROBOT_API_ID_LOCO_SET_BALANCE_MODE, 0) 28 | self._RegistApi(ROBOT_API_ID_LOCO_SET_SWING_HEIGHT, 0) 29 | self._RegistApi(ROBOT_API_ID_LOCO_SET_STAND_HEIGHT, 0) 30 | self._RegistApi(ROBOT_API_ID_LOCO_SET_VELOCITY, 0) 31 | self._RegistApi(ROBOT_API_ID_LOCO_SET_ARM_TASK, 0) 32 | 33 | # 7101 34 | def SetFsmId(self, fsm_id: int): 35 | p = {} 36 | p["data"] = fsm_id 37 | parameter = json.dumps(p) 38 | code, data = self._Call(ROBOT_API_ID_LOCO_SET_FSM_ID, parameter) 39 | return code 40 | 41 | # 7102 42 | def SetBalanceMode(self, balance_mode: int): 43 | p = {} 44 | p["data"] = balance_mode 45 | parameter = json.dumps(p) 46 | code, data = self._Call(ROBOT_API_ID_LOCO_SET_BALANCE_MODE, parameter) 47 | return code 48 | 49 | # 7104 50 | def SetStandHeight(self, stand_height: float): 51 | p = {} 52 | p["data"] = stand_height 53 | parameter = json.dumps(p) 54 | code, data = self._Call(ROBOT_API_ID_LOCO_SET_STAND_HEIGHT, parameter) 55 | return code 56 | 57 | # 7105 58 | def SetVelocity(self, vx: float, vy: float, omega: float, duration: float = 1.0): 59 | p = {} 60 | velocity = [vx,vy,omega] 61 | p["velocity"] = velocity 62 | p["duration"] = duration 63 | parameter = json.dumps(p) 64 | code, data = self._Call(ROBOT_API_ID_LOCO_SET_VELOCITY, parameter) 65 | return code 66 | 67 | # 7106 68 | def SetTaskId(self, task_id: float): 69 | p = {} 70 | p["data"] = task_id 71 | parameter = json.dumps(p) 72 | code, data = self._Call(ROBOT_API_ID_LOCO_SET_ARM_TASK, parameter) 73 | return code 74 | 75 | def Damp(self): 76 | self.SetFsmId(1) 77 | 78 | def Start(self): 79 | self.SetFsmId(200) 80 | 81 | def Squat(self): 82 | self.SetFsmId(2) 83 | 84 | def Sit(self): 85 | self.SetFsmId(3) 86 | 87 | def StandUp(self): 88 | self.SetFsmId(4) 89 | 90 | def ZeroTorque(self): 91 | self.SetFsmId(0) 92 | 93 | def StopMove(self): 94 | self.SetVelocity(0., 0., 0.) 95 | 96 | def HighStand(self): 97 | UINT32_MAX = (1 << 32) - 1 98 | self.SetStandHeight(UINT32_MAX) 99 | 100 | def LowStand(self): 101 | UINT32_MIN = 0 102 | self.SetStandHeight(UINT32_MIN) 103 | 104 | def Move(self, vx: float, vy: float, vyaw: float, continous_move: bool = False): 105 | duration = 864000.0 if continous_move else 1 106 | self.SetVelocity(vx, vy, vyaw, duration) 107 | 108 | def BalanceStand(self, balance_mode: int): 109 | self.SetBalanceMode(balance_mode) 110 | 111 | def WaveHand(self, turn_flag: bool = False): 112 | self.SetTaskId(1 if turn_flag else 0) 113 | 114 | def ShakeHand(self, stage: int = -1): 115 | if stage == 0: 116 | self.first_shake_hand_stage_ = False 117 | self.SetTaskId(2) 118 | elif stage == 1: 119 | self.first_shake_hand_stage_ = True 120 | self.SetTaskId(3) 121 | else: 122 | self.first_shake_hand_stage_ = not self.first_shake_hand_stage_ 123 | return self.SetTaskId(3 if self.first_shake_hand_stage_ else 2) 124 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # Unitree SDK2 in Python Modified for G1 23 DOF 3 | 4 | ![Unitree Robotics Support Page for G1](https://support.unitree.com/home/en/G1_developer/about_G1) 5 | 6 | This repository is a modified version of **Unitree SDK2 Python**, edited so that its only for **Unitree G1 with 23 Degrees of Freedom (DOF)**. 7 | 8 | 9 | # Pre-requisites of working with examples included in this repo 10 | 11 | 12 | ## Working with the Depth Camera 13 | 14 | ```bash 15 | sudo apt install librealsense2-utils librealsense2-dev 16 | pip install pyrealsense2 opencv-python ultralytics 17 | ``` 18 | 19 | ## Working with YOLO11 20 | 21 | to be added 22 | 23 | ## Working with Ollama (Local LLM) 24 | 25 | Ollama allows you to run local large language models like `llama3` on your machine. 26 | 27 | 1. Install Ollama from [https://ollama.com](https://ollama.com) 28 | 2. Pull a model such as `llama3`: 29 | ```bash 30 | ollama pull llama3 31 | ``` 32 | 3. Install the Python client: 33 | ```bash 34 | pip install ollama 35 | ``` 36 | 37 | ## Working with Microphone & Speech Recognition 38 | 39 | If you want to **work with microphone and speech recognition on the Unitree G1**, you might face issues installing `PyAudio`, which is needed for capturing audio input. 40 | 41 | To avoid these issues: 42 | 43 | ### Install system dependencies 44 | 45 | ```bash 46 | sudo apt-get install libasound-dev portaudio19-dev libportaudio2 libportaudiocpp0 47 | 48 | ``` 49 | 50 | ### Install PyAudio and SpeechRecognition 51 | 52 | ```bash 53 | pip install pyaudio 54 | pip install speechrecognition 55 | ``` 56 | 57 | #Common Issues & Fixes 58 | 59 | ## WiFi Connection (Manual Configuration) 60 | 61 | ### 1. Connect to a Network Using `wpa_cli` 62 | 63 | ```bash 64 | sudo wpa_cli 65 | 66 | add_network 67 | 68 | set_network 0 ssid "your_ssid" 69 | 70 | set_network 0 psk "your_password" 71 | 72 | enable_network 0 73 | 74 | status 75 | ``` 76 | 77 | > You'll need to repeat this after every reboot unless automated. 78 | 79 | ### 2. Assign an IP Address (if not automatically assigned) 80 | 81 | Check current routes: 82 | ```bash 83 | ip route 84 | ``` 85 | 86 | If no IP is assigned: 87 | ```bash 88 | sudo dhclient wlan0 89 | ``` 90 | 91 | Then confirm again: 92 | ```bash 93 | ip route 94 | ``` 95 | 96 | --- 97 | 98 | ## GUI Setup for NoMachine Access 99 | 100 | You may encounter an issue while connecting noMachine to your G1, showing a black screen while connected. 101 | Below are steps to fixing that issue. 102 | 103 | ### Install XFCE Desktop Environment 104 | 105 | ```bash 106 | sudo apt update 107 | sudo apt install xfce4 108 | ``` 109 | 110 | ### Set NoMachine to Use XFCE 111 | 112 | ```bash 113 | sudo nano /usr/NX/etc/node.cfg 114 | ``` 115 | 116 | Add or update the following line: 117 | ```bash 118 | DefaultDesktopCommand "/usr/bin/startxfce4" 119 | ``` 120 | 121 | Restart NoMachine: 122 | ```bash 123 | sudo /etc/NX/nxserver --restart 124 | ``` 125 | 126 | ### Auto-Launch XFCE on Boot 127 | 128 | ```bash 129 | echo "startxfce4" > ~/.xsession 130 | sudo reboot 131 | ``` 132 | 133 | --- 134 | 135 | ## Virtual Display for Headless Mode (Fix NoMachine Zoom Issue) 136 | 137 | If you're running G1 without a physical monitor, set up a virtual screen: 138 | 139 | ### 1. Install Dummy Video Driver 140 | 141 | ```bash 142 | sudo apt install xserver-xorg-video-dummy 143 | ``` 144 | 145 | ### 2. Create a Dummy X11 Configuration 146 | 147 | ```bash 148 | sudo nano /etc/X11/xorg.conf 149 | ``` 150 | 151 | Paste the following config: 152 | 153 | ``` 154 | Section "Monitor" 155 | Identifier "Monitor0" 156 | HorizSync 28.0-80.0 157 | VertRefresh 48.0-75.0 158 | Option "DPMS" 159 | EndSection 160 | 161 | Section "Device" 162 | Identifier "Card0" 163 | Driver "dummy" 164 | VideoRam 256000 165 | EndSection 166 | 167 | Section "Screen" 168 | Identifier "Screen0" 169 | Device "Card0" 170 | Monitor "Monitor0" 171 | DefaultDepth 24 172 | SubSection "Display" 173 | Depth 24 174 | Modes "1280x720" 175 | EndSubSection 176 | EndSection 177 | 178 | Section "ServerLayout" 179 | Identifier "Layout0" 180 | Screen 0 "Screen0" 181 | EndSection 182 | ``` 183 | 184 | ### 3. Reboot and Confirm Resolution 185 | 186 | ```bash 187 | sudo reboot 188 | DISPLAY=:0 xrandr 189 | ``` 190 | 191 | You should see: 192 | ``` 193 | Screen 0: minimum 8 x 8, current 1280 x 720, maximum ... 194 | ``` 195 | 196 | --- 197 | -------------------------------------------------------------------------------- /unitree_sdk2py/rpc/server.py: -------------------------------------------------------------------------------- 1 | import time 2 | 3 | from typing import Callable, Any 4 | 5 | from ..idl.unitree_api.msg.dds_ import Request_ as Request 6 | from ..idl.unitree_api.msg.dds_ import ResponseStatus_ as ResponseStatus 7 | from ..idl.unitree_api.msg.dds_ import ResponseHeader_ as ResponseHeader 8 | from ..idl.unitree_api.msg.dds_ import Response_ as Response 9 | 10 | from .server_base import ServerBase 11 | from .lease_server import LeaseServer 12 | from .internal import * 13 | 14 | """ 15 | " class Server 16 | """ 17 | class Server(ServerBase): 18 | def __init__(self, name: str): 19 | self.__apiVersion = "" 20 | self.__apiHandlerMapping = {} 21 | self.__apiBinaryHandlerMapping = {} 22 | self.__apiBinarySet = {} 23 | self.__enableLease = False 24 | self.__leaseServer = None 25 | super().__init__(name) 26 | 27 | def Init(self): 28 | pass 29 | 30 | def StartLease(self, term: float = 1.0): 31 | self.__enableLease = True 32 | self.__leaseServer = LeaseServer(self.GetName(), term) 33 | self.__leaseServer.Init() 34 | self.__leaseServer.Start(False) 35 | 36 | def Start(self, enablePrioQueue: bool = False): 37 | super()._SetServerRequestHandler(self.__ServerRequestHandler) 38 | super()._Start(enablePrioQueue) 39 | 40 | def GetApiVersion(self): 41 | return self.__apiVersion 42 | 43 | def _SetApiVersion(self, apiVersion: str): 44 | self.__apiVersion = apiVersion 45 | print("[Server] set api version:", self.__apiVersion) 46 | 47 | def _RegistHandler(self, apiId: int, handler: Callable, checkLease: bool): 48 | self.__apiHandlerMapping[apiId] = (handler, checkLease) 49 | 50 | def _RegistBinaryHandler(self, apiId: int, handler: Callable, checkLease: bool): 51 | self.__apiBinaryHandlerMapping[apiId] = (handler, checkLease) 52 | self.__apiBinarySet.add(apiId) 53 | 54 | def __GetHandler(self, apiId: int): 55 | if apiId in self.__apiHandlerMapping: 56 | return self.__apiHandlerMapping.get(apiId) 57 | else: 58 | return None, False 59 | 60 | def __GetBinaryHandler(self, apiId: int): 61 | if apiId in self.__apiBinaryHandlerMapping: 62 | return self.__apiBinaryHandlerMapping.get(apiId) 63 | else: 64 | return None, False 65 | 66 | def __IsBinary(self, apiId): 67 | return apiId in self.__apiBinarySet 68 | 69 | def __CheckLeaseDenied(self, leaseId: int): 70 | if (self.__enableLease): 71 | return self.__leaseServer.CheckRequestLeaseDenied(leaseId) 72 | else: 73 | return False 74 | 75 | def __ServerRequestHandler(self, request: Request): 76 | parameter = request.parameter 77 | parameterBinary = request.binary 78 | 79 | identity = request.header.identity 80 | leaseId = request.header.lease.id 81 | apiId = identity.api_id 82 | 83 | code = 0 84 | data = "" 85 | dataBinary = [] 86 | 87 | if apiId == RPC_API_ID_INTERNAL_API_VERSION: 88 | data = self.__apiVersion 89 | else: 90 | requestHandler = None 91 | binaryRequestHandler = None 92 | checkLease = False 93 | 94 | if self.__IsBinary(apiId): 95 | binaryRequestHandler, checkLease = self.__GetBinaryHandler(apiId) 96 | else: 97 | requestHandler, checkLease = self.__GetHandler(apiId) 98 | 99 | if requestHandler is None and binaryRequestHandler is None: 100 | code = RPC_ERR_SERVER_API_NOT_IMPL 101 | elif checkLease and self.__CheckLeaseDenied(leaseId): 102 | code = RPC_ERR_SERVER_LEASE_DENIED 103 | else: 104 | try: 105 | if binaryRequestHandler is None: 106 | code, data = requestHandler(parameter) 107 | if code != 0: 108 | data = "" 109 | else: 110 | code, dataBinary = binaryRequestHandler(parameterBinary) 111 | if code != 0: 112 | dataBinary = [] 113 | except: 114 | code = RPC_ERR_SERVER_INTERNAL 115 | 116 | if request.header.policy.noreply: 117 | return 118 | 119 | status = ResponseStatus(code) 120 | response = Response(ResponseHeader(identity, status), data, dataBinary) 121 | 122 | self._SendResponse(response) -------------------------------------------------------------------------------- /unitree_sdk2py/rpc/lease_server.py: -------------------------------------------------------------------------------- 1 | import time 2 | import json 3 | 4 | from threading import Lock 5 | 6 | from ..idl.unitree_api.msg.dds_ import Request_ as Request 7 | from ..idl.unitree_api.msg.dds_ import ResponseHeader_ as ResponseHeader 8 | from ..idl.unitree_api.msg.dds_ import ResponseStatus_ as ResponseStatus 9 | from ..idl.unitree_api.msg.dds_ import Response_ as Response 10 | 11 | from .internal import * 12 | from .server_base import ServerBase 13 | 14 | 15 | """ 16 | " class LeaseCache 17 | """ 18 | class LeaseCache: 19 | def __init__(self): 20 | self.lastModified = 0 21 | self.id = 0 22 | self.name = None 23 | 24 | def Set(self, id: int, name: str, lastModified: int) : 25 | self.id = id 26 | self.name = name 27 | self.lastModified = lastModified 28 | 29 | def Renewal(self, lastModified: int): 30 | self.lastModified = lastModified 31 | 32 | def Clear(self): 33 | self.id = 0 34 | self.lastModified = 0 35 | self.name = None 36 | 37 | 38 | """ 39 | " class LeaseServer 40 | """ 41 | class LeaseServer(ServerBase): 42 | def __init__(self, name: str, term: float): 43 | self.__term = int(term * 1000000) 44 | self.__lock = Lock() 45 | self.__cache = LeaseCache() 46 | super().__init__(name + "_lease") 47 | 48 | def Init(self): 49 | pass 50 | 51 | def Start(self, enablePrioQueue: bool = False): 52 | super()._SetServerRequestHandler(self.__ServerRequestHandler) 53 | super()._Start(enablePrioQueue) 54 | 55 | def CheckRequestLeaseDenied(self, leaseId: int): 56 | with self.__lock: 57 | if self.__cache.id == 0: 58 | return self.__cache.id != leaseId 59 | 60 | now = self.__Now() 61 | if now > self.__cache.lastModified + self.__term: 62 | self.__cache.Clear() 63 | return False 64 | else: 65 | return self.__cache.id != leaseId 66 | 67 | def __Apply(self, parameter: str): 68 | name = "" 69 | data = "" 70 | 71 | try: 72 | p = json.loads(parameter) 73 | name = p.get("name") 74 | 75 | except: 76 | print("[LeaseServer] apply json loads error. parameter:", parameter) 77 | return RPC_ERR_SERVER_API_PARAMETER, data 78 | 79 | if not name: 80 | name = "anonymous" 81 | 82 | id = 0 83 | lastModified = 0 84 | setted = False 85 | 86 | now = self.__Now() 87 | 88 | with self.__lock: 89 | id = self.__cache.id 90 | lastModified = self.__cache.lastModified 91 | 92 | if id == 0 or now > lastModified + self.__term: 93 | if id != 0: 94 | print("[LeaseServer] id expired:", id, ", name:", self.__cache.name) 95 | 96 | id = self.__GenerateId() 97 | self.__cache.Set(id, name, now) 98 | setted = True 99 | 100 | print("[LeaseServer] id stored:", id, ", name:", name) 101 | 102 | if setted: 103 | d = {} 104 | d["id"] = id 105 | d["term"] = self.__term 106 | data = json.dumps(d) 107 | return 0, data 108 | else: 109 | return RPC_ERR_SERVER_LEASE_EXIST, data 110 | 111 | 112 | def __Renewal(self, id: int): 113 | now = self.__Now() 114 | 115 | with self.__lock: 116 | if self.__cache.id != id: 117 | return RPC_ERR_SERVER_LEASE_NOT_EXIST 118 | 119 | if now > self.__cache.lastModified + self.__term: 120 | self.__cache.Clear() 121 | return RPC_ERR_SERVER_LEASE_NOT_EXIST 122 | else: 123 | self.__cache.Renewal(now) 124 | return 0 125 | 126 | def __ServerRequestHandler(self, request: Request): 127 | identity = request.header.identity 128 | parameter = request.parameter 129 | apiId = identity.api_id 130 | code = RPC_ERR_SERVER_API_NOT_IMPL 131 | data = "" 132 | 133 | if apiId == RPC_API_ID_LEASE_APPLY: 134 | code, data = self.__Apply(parameter) 135 | elif apiId == RPC_API_ID_LEASE_RENEWAL: 136 | code = self.__Renewal(request.header.lease.id) 137 | else: 138 | print("[LeaseServer] api is not implemented. apiId", apiId) 139 | 140 | if request.header.policy.noreply: 141 | return 142 | 143 | status = ResponseStatus(code) 144 | response = Response(ResponseHeader(identity, status), data, []) 145 | self._SendResponse(response) 146 | 147 | def __GenerateId(self): 148 | return self.__Now() 149 | 150 | def __Now(self): 151 | return int(time.time_ns()/1000) -------------------------------------------------------------------------------- /examples/move_knee.py: -------------------------------------------------------------------------------- 1 | import time 2 | import sys 3 | 4 | from unitree_sdk2py.core.channel import ChannelPublisher, ChannelFactoryInitialize 5 | from unitree_sdk2py.core.channel import ChannelSubscriber, ChannelFactoryInitialize 6 | from unitree_sdk2py.idl.default import unitree_hg_msg_dds__LowCmd_ 7 | from unitree_sdk2py.idl.default import unitree_hg_msg_dds__LowState_ 8 | from unitree_sdk2py.idl.unitree_hg.msg.dds_ import LowCmd_ 9 | from unitree_sdk2py.idl.unitree_hg.msg.dds_ import LowState_ 10 | from unitree_sdk2py.utils.crc import CRC 11 | from unitree_sdk2py.utils.thread import RecurrentThread 12 | from unitree_sdk2py.comm.motion_switcher.motion_switcher_client import MotionSwitcherClient 13 | 14 | import numpy as np 15 | 16 | G1_NUM_MOTOR = 29 17 | 18 | Kp = [ 19 | 60, 60, 60, 100, 40, 40, # legs 20 | 60, 60, 60, 100, 40, 40, # legs 21 | 60, 40, 40, # waist 22 | 40, 40, 40, 40, 40, 40, 40, # arms 23 | 40, 40, 40, 40, 40, 40, 40 # arms 24 | ] 25 | 26 | Kd = [ 27 | 1, 1, 1, 2, 1, 1, # legs 28 | 1, 1, 1, 2, 1, 1, # legs 29 | 1, 1, 1, # waist 30 | 1, 1, 1, 1, 1, 1, 1, # arms 31 | 1, 1, 1, 1, 1, 1, 1 # arms 32 | ] 33 | 34 | class G1JointIndex: 35 | LeftHipPitch = 0 36 | LeftHipRoll = 1 37 | LeftHipYaw = 2 38 | LeftKnee = 3 39 | LeftAnklePitch = 4 40 | LeftAnkleB = 4 41 | LeftAnkleRoll = 5 42 | LeftAnkleA = 5 43 | RightHipPitch = 6 44 | RightHipRoll = 7 45 | RightHipYaw = 8 46 | RightKnee = 9 47 | RightAnklePitch = 10 48 | RightAnkleB = 10 49 | RightAnkleRoll = 11 50 | RightAnkleA = 11 51 | WaistYaw = 12 52 | LeftShoulderPitch = 15 53 | LeftShoulderRoll = 16 54 | LeftShoulderYaw = 17 55 | LeftElbow = 18 56 | LeftWristRoll = 19 57 | RightShoulderPitch = 22 58 | RightShoulderRoll = 23 59 | RightShoulderYaw = 24 60 | RightElbow = 25 61 | RightWristRoll = 26 62 | 63 | 64 | 65 | class Mode: 66 | PR = 0 # Series Control for Pitch/Roll Joints 67 | AB = 1 # Parallel Control for A/B Joints 68 | 69 | class Custom: 70 | def __init__(self): 71 | self.time_ = 0.0 72 | self.control_dt_ = 0.002 # [2ms] 73 | self.duration_ = 3.0 # [3 s] 74 | self.counter_ = 0 75 | self.mode_pr_ = Mode.PR 76 | self.mode_machine_ = 0 77 | self.low_cmd = unitree_hg_msg_dds__LowCmd_() 78 | self.low_state = None 79 | self.update_mode_machine_ = False 80 | self.crc = CRC() 81 | 82 | def Init(self): 83 | self.msc = MotionSwitcherClient() 84 | self.msc.SetTimeout(5.0) 85 | self.msc.Init() 86 | 87 | status, result = self.msc.CheckMode() 88 | while result['name']: 89 | self.msc.ReleaseMode() 90 | status, result = self.msc.CheckMode() 91 | time.sleep(1) 92 | 93 | # create publisher # 94 | self.lowcmd_publisher_ = ChannelPublisher("rt/lowcmd", LowCmd_) 95 | self.lowcmd_publisher_.Init() 96 | 97 | # create subscriber # 98 | self.lowstate_subscriber = ChannelSubscriber("rt/lowstate", LowState_) 99 | self.lowstate_subscriber.Init(self.LowStateHandler, 10) 100 | 101 | def Start(self): 102 | self.lowCmdWriteThreadPtr = RecurrentThread( 103 | interval=self.control_dt_, target=self.LowCmdWrite, name="control" 104 | ) 105 | while self.update_mode_machine_ == False: 106 | time.sleep(1) 107 | 108 | if self.update_mode_machine_ == True: 109 | self.lowCmdWriteThreadPtr.Start() 110 | 111 | def LowStateHandler(self, msg: LowState_): 112 | self.low_state = msg 113 | 114 | if self.update_mode_machine_ == False: 115 | self.mode_machine_ = self.low_state.mode_machine 116 | self.update_mode_machine_ = True 117 | 118 | self.counter_ +=1 119 | if (self.counter_ % 500 == 0) : 120 | self.counter_ = 0 121 | print(self.low_state.motor_state[G1JointIndex.LeftKnee].q ) 122 | 123 | def LowCmdWrite(self): 124 | self.time_ += self.control_dt_ 125 | 126 | if self.time_ < self.duration_ : 127 | # [Stage 1]: set robot to zero posture 128 | for i in range(G1_NUM_MOTOR): 129 | ratio = np.clip(self.time_ / self.duration_, 0.0, 1.0) 130 | self.low_cmd.mode_machine = self.mode_machine_ 131 | self.low_cmd.motor_cmd[i].mode = 1 # 1:Enable, 0:Disable 132 | self.low_cmd.motor_cmd[i].tau = 0. 133 | self.low_cmd.motor_cmd[i].q = (1.0 - ratio) * self.low_state.motor_state[i].q 134 | self.low_cmd.motor_cmd[i].dq = 0. 135 | self.low_cmd.motor_cmd[i].kp = Kp[i] 136 | self.low_cmd.motor_cmd[i].kd = Kd[i] 137 | 138 | elif self.time_ < self.duration_ * 2 : 139 | #Move Right Wrist 140 | ratio = np.clip((self.time_ - self.duration_) / (self.duration_*2), 0.0, 1.0) 141 | target_pos = 2.5 142 | calc_q = ratio * target_pos + (1.0 - ratio) * self.low_state.motor_state[G1JointIndex.LeftKnee].q 143 | self.low_cmd.mode_machine = self.mode_machine_ 144 | self.low_cmd.motor_cmd[G1JointIndex.LeftKnee].q = calc_q 145 | 146 | 147 | self.low_cmd.crc = self.crc.Crc(self.low_cmd) 148 | self.lowcmd_publisher_.Write(self.low_cmd) 149 | 150 | if __name__ == '__main__': 151 | 152 | print("WARNING: Please ensure there are no obstacles around the robot while running this example.") 153 | input("Press Enter to continue...") 154 | 155 | if len(sys.argv)>1: 156 | ChannelFactoryInitialize(0, sys.argv[1]) 157 | else: 158 | ChannelFactoryInitialize(0) 159 | 160 | custom = Custom() 161 | custom.Init() 162 | custom.Start() 163 | 164 | while True: 165 | time.sleep(1) -------------------------------------------------------------------------------- /examples/move_wrist.py: -------------------------------------------------------------------------------- 1 | import time 2 | import sys 3 | 4 | from unitree_sdk2py.core.channel import ChannelPublisher, ChannelFactoryInitialize 5 | from unitree_sdk2py.core.channel import ChannelSubscriber, ChannelFactoryInitialize 6 | from unitree_sdk2py.idl.default import unitree_hg_msg_dds__LowCmd_ 7 | from unitree_sdk2py.idl.default import unitree_hg_msg_dds__LowState_ 8 | from unitree_sdk2py.idl.unitree_hg.msg.dds_ import LowCmd_ 9 | from unitree_sdk2py.idl.unitree_hg.msg.dds_ import LowState_ 10 | from unitree_sdk2py.utils.crc import CRC 11 | from unitree_sdk2py.utils.thread import RecurrentThread 12 | from unitree_sdk2py.comm.motion_switcher.motion_switcher_client import MotionSwitcherClient 13 | 14 | import numpy as np 15 | 16 | G1_NUM_MOTOR = 29 17 | 18 | Kp = [ 19 | 60, 60, 60, 100, 40, 40, # legs 20 | 60, 60, 60, 100, 40, 40, # legs 21 | 60, 40, 40, # waist 22 | 40, 40, 40, 40, 40, 40, 40, # arms 23 | 40, 40, 40, 40, 40, 40, 40 # arms 24 | ] 25 | 26 | Kd = [ 27 | 1, 1, 1, 2, 1, 1, # legs 28 | 1, 1, 1, 2, 1, 1, # legs 29 | 1, 1, 1, # waist 30 | 1, 1, 1, 1, 1, 1, 1, # arms 31 | 1, 1, 1, 1, 1, 1, 1 # arms 32 | ] 33 | 34 | class G1JointIndex: 35 | LeftHipPitch = 0 36 | LeftHipRoll = 1 37 | LeftHipYaw = 2 38 | LeftKnee = 3 39 | LeftAnklePitch = 4 40 | LeftAnkleB = 4 41 | LeftAnkleRoll = 5 42 | LeftAnkleA = 5 43 | RightHipPitch = 6 44 | RightHipRoll = 7 45 | RightHipYaw = 8 46 | RightKnee = 9 47 | RightAnklePitch = 10 48 | RightAnkleB = 10 49 | RightAnkleRoll = 11 50 | RightAnkleA = 11 51 | WaistYaw = 12 52 | LeftShoulderPitch = 15 53 | LeftShoulderRoll = 16 54 | LeftShoulderYaw = 17 55 | LeftElbow = 18 56 | LeftWristRoll = 19 57 | RightShoulderPitch = 22 58 | RightShoulderRoll = 23 59 | RightShoulderYaw = 24 60 | RightElbow = 25 61 | RightWristRoll = 26 62 | 63 | 64 | 65 | class Mode: 66 | PR = 0 # Series Control for Pitch/Roll Joints 67 | AB = 1 # Parallel Control for A/B Joints 68 | 69 | class Custom: 70 | def __init__(self): 71 | self.time_ = 0.0 72 | self.control_dt_ = 0.002 # [2ms] 73 | self.duration_ = 3.0 # [3 s] 74 | self.counter_ = 0 75 | self.mode_pr_ = Mode.PR 76 | self.mode_machine_ = 0 77 | self.low_cmd = unitree_hg_msg_dds__LowCmd_() 78 | self.low_state = None 79 | self.update_mode_machine_ = False 80 | self.crc = CRC() 81 | 82 | def Init(self): 83 | self.msc = MotionSwitcherClient() 84 | self.msc.SetTimeout(5.0) 85 | self.msc.Init() 86 | 87 | status, result = self.msc.CheckMode() 88 | while result['name']: 89 | self.msc.ReleaseMode() 90 | status, result = self.msc.CheckMode() 91 | time.sleep(1) 92 | 93 | # create publisher # 94 | self.lowcmd_publisher_ = ChannelPublisher("rt/lowcmd", LowCmd_) 95 | self.lowcmd_publisher_.Init() 96 | 97 | # create subscriber # 98 | self.lowstate_subscriber = ChannelSubscriber("rt/lowstate", LowState_) 99 | self.lowstate_subscriber.Init(self.LowStateHandler, 10) 100 | 101 | def Start(self): 102 | self.lowCmdWriteThreadPtr = RecurrentThread( 103 | interval=self.control_dt_, target=self.LowCmdWrite, name="control" 104 | ) 105 | while self.update_mode_machine_ == False: 106 | time.sleep(1) 107 | 108 | if self.update_mode_machine_ == True: 109 | self.lowCmdWriteThreadPtr.Start() 110 | 111 | def LowStateHandler(self, msg: LowState_): 112 | self.low_state = msg 113 | 114 | if self.update_mode_machine_ == False: 115 | self.mode_machine_ = self.low_state.mode_machine 116 | self.update_mode_machine_ = True 117 | 118 | self.counter_ +=1 119 | if (self.counter_ % 500 == 0) : 120 | self.counter_ = 0 121 | print(self.low_state.imu_state.rpy) 122 | 123 | def LowCmdWrite(self): 124 | self.time_ += self.control_dt_ 125 | 126 | if self.time_ < self.duration_ : 127 | # [Stage 1]: set robot to zero posture 128 | for i in range(G1_NUM_MOTOR): 129 | ratio = np.clip(self.time_ / self.duration_, 0.0, 1.0) 130 | self.low_cmd.mode_machine = self.mode_machine_ 131 | self.low_cmd.motor_cmd[i].mode = 1 # 1:Enable, 0:Disable 132 | self.low_cmd.motor_cmd[i].tau = 0. 133 | self.low_cmd.motor_cmd[i].q = (1.0 - ratio) * self.low_state.motor_state[i].q 134 | self.low_cmd.motor_cmd[i].dq = 0. 135 | self.low_cmd.motor_cmd[i].kp = Kp[i] 136 | self.low_cmd.motor_cmd[i].kd = Kd[i] 137 | 138 | elif self.time_ < self.duration_ * 2 : 139 | #Move Right Wrist 140 | t = self.time_ - self.duration_ * 2 141 | max_WristYaw = np.pi * 30.0 / 180.0 142 | L_WristYaw_des = max_WristYaw * np.sin(2.0 * np.pi * t) 143 | R_WristYaw_des = max_WristYaw * np.sin(2.0 * np.pi * t) 144 | self.low_cmd.mode_machine = self.mode_machine_ 145 | self.low_cmd.motor_cmd[G1JointIndex.LeftWristRoll].q = L_WristYaw_des 146 | self.low_cmd.motor_cmd[G1JointIndex.RightWristRoll].q = R_WristYaw_des 147 | 148 | 149 | 150 | 151 | self.low_cmd.crc = self.crc.Crc(self.low_cmd) 152 | self.lowcmd_publisher_.Write(self.low_cmd) 153 | 154 | if __name__ == '__main__': 155 | 156 | print("WARNING: Please ensure there are no obstacles around the robot while running this example.") 157 | input("Press Enter to continue...") 158 | 159 | if len(sys.argv)>1: 160 | ChannelFactoryInitialize(0, sys.argv[1]) 161 | else: 162 | ChannelFactoryInitialize(0) 163 | 164 | custom = Custom() 165 | custom.Init() 166 | custom.Start() 167 | 168 | while True: 169 | time.sleep(1) -------------------------------------------------------------------------------- /examples/highlevel_arm.py: -------------------------------------------------------------------------------- 1 | import time 2 | import sys 3 | 4 | from unitree_sdk2py.core.channel import ChannelPublisher, ChannelFactoryInitialize 5 | from unitree_sdk2py.core.channel import ChannelSubscriber, ChannelFactoryInitialize 6 | from unitree_sdk2py.idl.default import unitree_hg_msg_dds__LowCmd_ 7 | from unitree_sdk2py.idl.default import unitree_hg_msg_dds__LowState_ 8 | from unitree_sdk2py.idl.unitree_hg.msg.dds_ import LowCmd_ 9 | from unitree_sdk2py.idl.unitree_hg.msg.dds_ import LowState_ 10 | from unitree_sdk2py.utils.crc import CRC 11 | from unitree_sdk2py.utils.thread import RecurrentThread 12 | from unitree_sdk2py.comm.motion_switcher.motion_switcher_client import MotionSwitcherClient 13 | 14 | import numpy as np 15 | 16 | kPi = 3.141592654 17 | kPi_2 = 1.57079632 18 | 19 | class G1JointIndex: 20 | # Left leg 21 | LeftHipPitch = 0 22 | LeftHipRoll = 1 23 | LeftHipYaw = 2 24 | LeftKnee = 3 25 | LeftAnklePitch = 4 26 | LeftAnkleB = 4 27 | LeftAnkleRoll = 5 28 | LeftAnkleA = 5 29 | 30 | # Right leg 31 | RightHipPitch = 6 32 | RightHipRoll = 7 33 | RightHipYaw = 8 34 | RightKnee = 9 35 | RightAnklePitch = 10 36 | RightAnkleB = 10 37 | RightAnkleRoll = 11 38 | RightAnkleA = 11 39 | 40 | WaistYaw = 12 41 | WaistRoll = 13 # NOTE: INVALID for g1 23dof/29dof with waist locked 42 | WaistA = 13 # NOTE: INVALID for g1 23dof/29dof with waist locked 43 | WaistPitch = 14 # NOTE: INVALID for g1 23dof/29dof with waist locked 44 | WaistB = 14 # NOTE: INVALID for g1 23dof/29dof with waist locked 45 | 46 | # Left arm 47 | LeftShoulderPitch = 15 48 | LeftShoulderRoll = 16 49 | LeftShoulderYaw = 17 50 | LeftElbow = 18 51 | LeftWristRoll = 19 52 | LeftWristPitch = 20 # NOTE: INVALID for g1 23dof 53 | LeftWristYaw = 21 # NOTE: INVALID for g1 23dof 54 | 55 | # Right arm 56 | RightShoulderPitch = 22 57 | RightShoulderRoll = 23 58 | RightShoulderYaw = 24 59 | RightElbow = 25 60 | RightWristRoll = 26 61 | RightWristPitch = 27 # NOTE: INVALID for g1 23dof 62 | RightWristYaw = 28 # NOTE: INVALID for g1 23dof 63 | 64 | kNotUsedJoint = 29 # NOTE: Weight 65 | 66 | class Custom: 67 | def __init__(self): 68 | self.time_ = 0.0 69 | self.control_dt_ = 0.02 70 | self.duration_ = 3.0 71 | self.counter_ = 0 72 | self.weight = 0. 73 | self.weight_rate = 0.2 74 | self.kp = 60. 75 | self.kd = 1.5 76 | self.dq = 0. 77 | self.tau_ff = 0. 78 | self.mode_machine_ = 0 79 | self.low_cmd = unitree_hg_msg_dds__LowCmd_() 80 | self.low_state = None 81 | self.first_update_low_state = False 82 | self.crc = CRC() 83 | self.done = False 84 | 85 | self.target_pos = [ 86 | 0.0, kPi_2, 0.0, kPi_2, 0.0, 87 | 0.0, -kPi_2, 0.0, kPi_2, 0.0, 88 | 0.0, 0.0, 0.0 89 | ] 90 | 91 | self.arm_joints = [ 92 | G1JointIndex.LeftShoulderPitch, G1JointIndex.LeftShoulderRoll, 93 | G1JointIndex.LeftShoulderYaw, G1JointIndex.LeftElbow, 94 | G1JointIndex.LeftWristRoll, 95 | G1JointIndex.RightShoulderPitch, G1JointIndex.RightShoulderRoll, 96 | G1JointIndex.RightShoulderYaw, G1JointIndex.RightElbow, 97 | G1JointIndex.RightWristRoll, 98 | G1JointIndex.WaistYaw, 99 | G1JointIndex.WaistRoll, 100 | G1JointIndex.WaistPitch 101 | ] 102 | 103 | def Init(self): 104 | # create publisher # 105 | self.arm_sdk_publisher = ChannelPublisher("rt/arm_sdk", LowCmd_) 106 | self.arm_sdk_publisher.Init() 107 | 108 | # create subscriber # 109 | self.lowstate_subscriber = ChannelSubscriber("rt/lowstate", LowState_) 110 | self.lowstate_subscriber.Init(self.LowStateHandler, 10) 111 | 112 | def Start(self): 113 | self.lowCmdWriteThreadPtr = RecurrentThread( 114 | interval=self.control_dt_, target=self.LowCmdWrite, name="control" 115 | ) 116 | while self.first_update_low_state == False: 117 | time.sleep(1) 118 | 119 | if self.first_update_low_state == True: 120 | self.lowCmdWriteThreadPtr.Start() 121 | 122 | def LowStateHandler(self, msg: LowState_): 123 | self.low_state = msg 124 | 125 | if self.first_update_low_state == False: 126 | self.first_update_low_state = True 127 | 128 | def LowCmdWrite(self): 129 | self.time_ += self.control_dt_ 130 | 131 | if self.time_ < self.duration_ : 132 | # [Stage 1]: set robot to zero posture 133 | self.low_cmd.motor_cmd[G1JointIndex.kNotUsedJoint].q = 1 # 1:Enable arm_sdk, 0:Disable arm_sdk 134 | for i,joint in enumerate(self.arm_joints): 135 | ratio = np.clip(self.time_ / self.duration_, 0.0, 1.0) 136 | self.low_cmd.motor_cmd[joint].tau = 0. 137 | self.low_cmd.motor_cmd[joint].q = (1.0 - ratio) * self.low_state.motor_state[joint].q 138 | self.low_cmd.motor_cmd[joint].dq = 0. 139 | self.low_cmd.motor_cmd[joint].kp = self.kp 140 | self.low_cmd.motor_cmd[joint].kd = self.kd 141 | 142 | elif self.time_ < self.duration_ * 3 : 143 | # [Stage 2]: lift arms up 144 | for i,joint in enumerate(self.arm_joints): 145 | ratio = np.clip((self.time_ - self.duration_) / (self.duration_ * 2), 0.0, 1.0) 146 | self.low_cmd.motor_cmd[joint].tau = 0. 147 | self.low_cmd.motor_cmd[joint].q = ratio * self.target_pos[i] + (1.0 - ratio) * self.low_state.motor_state[joint].q 148 | self.low_cmd.motor_cmd[joint].dq = 0. 149 | self.low_cmd.motor_cmd[joint].kp = self.kp 150 | self.low_cmd.motor_cmd[joint].kd = self.kd 151 | 152 | elif self.time_ < self.duration_ * 6 : 153 | # [Stage 3]: set robot back to zero posture 154 | for i,joint in enumerate(self.arm_joints): 155 | ratio = np.clip((self.time_ - self.duration_*3) / (self.duration_ * 3), 0.0, 1.0) 156 | self.low_cmd.motor_cmd[joint].tau = 0. 157 | self.low_cmd.motor_cmd[joint].q = (1.0 - ratio) * self.low_state.motor_state[joint].q 158 | self.low_cmd.motor_cmd[joint].dq = 0. 159 | self.low_cmd.motor_cmd[joint].kp = self.kp 160 | self.low_cmd.motor_cmd[joint].kd = self.kd 161 | 162 | elif self.time_ < self.duration_ * 7 : 163 | # [Stage 4]: release arm_sdk 164 | for i,joint in enumerate(self.arm_joints): 165 | ratio = np.clip((self.time_ - self.duration_*6) / (self.duration_), 0.0, 1.0) 166 | self.low_cmd.motor_cmd[G1JointIndex.LeftWristRoll].q = (1 - ratio) # 1:Enable arm_sdk, 0:Disable arm_sdk 167 | 168 | else: 169 | self.done = True 170 | 171 | self.low_cmd.crc = self.crc.Crc(self.low_cmd) 172 | self.arm_sdk_publisher.Write(self.low_cmd) 173 | 174 | if __name__ == '__main__': 175 | 176 | print("WARNING: Please ensure there are no obstacles around the robot while running this example.") 177 | input("Press Enter to continue...") 178 | 179 | if len(sys.argv)>1: 180 | ChannelFactoryInitialize(0, sys.argv[1]) 181 | else: 182 | ChannelFactoryInitialize(0) 183 | 184 | custom = Custom() 185 | custom.Init() 186 | custom.Start() 187 | 188 | while True: 189 | time.sleep(1) 190 | if custom.done: 191 | print("Done!") 192 | sys.exit(-1) -------------------------------------------------------------------------------- /examples/move_ankle.py: -------------------------------------------------------------------------------- 1 | import time 2 | import sys 3 | 4 | from unitree_sdk2py.core.channel import ChannelPublisher, ChannelFactoryInitialize 5 | from unitree_sdk2py.core.channel import ChannelSubscriber, ChannelFactoryInitialize 6 | from unitree_sdk2py.idl.default import unitree_hg_msg_dds__LowCmd_ 7 | from unitree_sdk2py.idl.default import unitree_hg_msg_dds__LowState_ 8 | from unitree_sdk2py.idl.unitree_hg.msg.dds_ import LowCmd_ 9 | from unitree_sdk2py.idl.unitree_hg.msg.dds_ import LowState_ 10 | from unitree_sdk2py.utils.crc import CRC 11 | from unitree_sdk2py.utils.thread import RecurrentThread 12 | from unitree_sdk2py.comm.motion_switcher.motion_switcher_client import MotionSwitcherClient 13 | 14 | import numpy as np 15 | 16 | G1_NUM_MOTOR = 29 17 | 18 | Kp = [ 19 | 60, 60, 60, 100, 40, 40, # legs 20 | 60, 60, 60, 100, 40, 40, # legs 21 | 60, 40, 40, # waist 22 | 40, 40, 40, 40, 40, 40, 40, # arms 23 | 40, 40, 40, 40, 40, 40, 40 # arms 24 | ] 25 | 26 | Kd = [ 27 | 1, 1, 1, 2, 1, 1, # legs 28 | 1, 1, 1, 2, 1, 1, # legs 29 | 1, 1, 1, # waist 30 | 1, 1, 1, 1, 1, 1, 1, # arms 31 | 1, 1, 1, 1, 1, 1, 1 # arms 32 | ] 33 | 34 | class G1JointIndex: 35 | LeftHipPitch = 0 36 | LeftHipRoll = 1 37 | LeftHipYaw = 2 38 | LeftKnee = 3 39 | LeftAnklePitch = 4 40 | LeftAnkleB = 4 41 | LeftAnkleRoll = 5 42 | LeftAnkleA = 5 43 | RightHipPitch = 6 44 | RightHipRoll = 7 45 | RightHipYaw = 8 46 | RightKnee = 9 47 | RightAnklePitch = 10 48 | RightAnkleB = 10 49 | RightAnkleRoll = 11 50 | RightAnkleA = 11 51 | WaistYaw = 12 52 | WaistRoll = 13 # NOTE: INVALID for g1 23dof/29dof with waist locked 53 | WaistA = 13 # NOTE: INVALID for g1 23dof/29dof with waist locked 54 | WaistPitch = 14 # NOTE: INVALID for g1 23dof/29dof with waist locked 55 | WaistB = 14 # NOTE: INVALID for g1 23dof/29dof with waist locked 56 | LeftShoulderPitch = 15 57 | LeftShoulderRoll = 16 58 | LeftShoulderYaw = 17 59 | LeftElbow = 18 60 | LeftWristRoll = 19 61 | LeftWristPitch = 20 # NOTE: INVALID for g1 23dof 62 | LeftWristYaw = 21 # NOTE: INVALID for g1 23dof 63 | RightShoulderPitch = 22 64 | RightShoulderRoll = 23 65 | RightShoulderYaw = 24 66 | RightElbow = 25 67 | RightWristRoll = 26 68 | RightWristPitch = 27 # NOTE: INVALID for g1 23dof 69 | RightWristYaw = 28 # NOTE: INVALID for g1 23dof 70 | 71 | 72 | class Mode: 73 | PR = 0 # Series Control for Pitch/Roll Joints 74 | AB = 1 # Parallel Control for A/B Joints 75 | 76 | class Custom: 77 | def __init__(self): 78 | self.time_ = 0.0 79 | self.control_dt_ = 0.002 # [2ms] 80 | self.duration_ = 3.0 # [3 s] 81 | self.counter_ = 0 82 | self.mode_pr_ = Mode.PR 83 | self.mode_machine_ = 0 84 | self.low_cmd = unitree_hg_msg_dds__LowCmd_() 85 | self.low_state = None 86 | self.update_mode_machine_ = False 87 | self.crc = CRC() 88 | 89 | def Init(self): 90 | self.msc = MotionSwitcherClient() 91 | self.msc.SetTimeout(5.0) 92 | self.msc.Init() 93 | 94 | status, result = self.msc.CheckMode() 95 | while result['name']: 96 | self.msc.ReleaseMode() 97 | status, result = self.msc.CheckMode() 98 | time.sleep(1) 99 | 100 | # create publisher # 101 | self.lowcmd_publisher_ = ChannelPublisher("rt/lowcmd", LowCmd_) 102 | self.lowcmd_publisher_.Init() 103 | 104 | # create subscriber # 105 | self.lowstate_subscriber = ChannelSubscriber("rt/lowstate", LowState_) 106 | self.lowstate_subscriber.Init(self.LowStateHandler, 10) 107 | 108 | def Start(self): 109 | self.lowCmdWriteThreadPtr = RecurrentThread( 110 | interval=self.control_dt_, target=self.LowCmdWrite, name="control" 111 | ) 112 | while self.update_mode_machine_ == False: 113 | time.sleep(1) 114 | 115 | if self.update_mode_machine_ == True: 116 | self.lowCmdWriteThreadPtr.Start() 117 | 118 | def LowStateHandler(self, msg: LowState_): 119 | self.low_state = msg 120 | 121 | if self.update_mode_machine_ == False: 122 | self.mode_machine_ = self.low_state.mode_machine 123 | self.update_mode_machine_ = True 124 | 125 | self.counter_ +=1 126 | if (self.counter_ % 500 == 0) : 127 | self.counter_ = 0 128 | print(self.low_state.imu_state.rpy) 129 | 130 | def LowCmdWrite(self): 131 | self.time_ += self.control_dt_ 132 | 133 | if self.time_ < self.duration_ : 134 | # [Stage 1]: set robot to zero posture 135 | for i in range(G1_NUM_MOTOR): 136 | ratio = np.clip(self.time_ / self.duration_, 0.0, 1.0) 137 | self.low_cmd.mode_pr = Mode.PR 138 | self.low_cmd.mode_machine = self.mode_machine_ 139 | self.low_cmd.motor_cmd[i].mode = 1 # 1:Enable, 0:Disable 140 | self.low_cmd.motor_cmd[i].tau = 0. 141 | self.low_cmd.motor_cmd[i].q = (1.0 - ratio) * self.low_state.motor_state[i].q 142 | self.low_cmd.motor_cmd[i].dq = 0. 143 | self.low_cmd.motor_cmd[i].kp = Kp[i] 144 | self.low_cmd.motor_cmd[i].kd = Kd[i] 145 | 146 | elif self.time_ < self.duration_ * 2 : 147 | # [Stage 2]: swing ankle using PR mode 148 | max_P = np.pi * 30.0 / 180.0 149 | max_R = np.pi * 10.0 / 180.0 150 | t = self.time_ - self.duration_ 151 | L_P_des = max_P * np.sin(2.0 * np.pi * t) 152 | L_R_des = max_R * np.sin(2.0 * np.pi * t) 153 | R_P_des = max_P * np.sin(2.0 * np.pi * t) 154 | R_R_des = -max_R * np.sin(2.0 * np.pi * t) 155 | 156 | self.low_cmd.mode_pr = Mode.PR 157 | self.low_cmd.mode_machine = self.mode_machine_ 158 | self.low_cmd.motor_cmd[G1JointIndex.LeftAnklePitch].q = L_P_des 159 | self.low_cmd.motor_cmd[G1JointIndex.LeftAnkleRoll].q = L_R_des 160 | self.low_cmd.motor_cmd[G1JointIndex.RightAnklePitch].q = R_P_des 161 | self.low_cmd.motor_cmd[G1JointIndex.RightAnkleRoll].q = R_R_des 162 | 163 | else : 164 | # [Stage 3]: swing ankle using AB mode 165 | max_A = np.pi * 30.0 / 180.0 166 | max_B = np.pi * 10.0 / 180.0 167 | t = self.time_ - self.duration_ * 2 168 | L_A_des = max_A * np.sin(2.0 * np.pi * t) 169 | L_B_des = max_B * np.sin(2.0 * np.pi * t + np.pi) 170 | R_A_des = -max_A * np.sin(2.0 * np.pi * t) 171 | R_B_des = -max_B * np.sin(2.0 * np.pi * t + np.pi) 172 | 173 | self.low_cmd.mode_pr = Mode.AB 174 | self.low_cmd.mode_machine = self.mode_machine_ 175 | self.low_cmd.motor_cmd[G1JointIndex.LeftAnkleA].q = L_A_des 176 | self.low_cmd.motor_cmd[G1JointIndex.LeftAnkleB].q = L_B_des 177 | self.low_cmd.motor_cmd[G1JointIndex.RightAnkleA].q = R_A_des 178 | self.low_cmd.motor_cmd[G1JointIndex.RightAnkleB].q = R_B_des 179 | 180 | max_WristYaw = np.pi * 30.0 / 180.0 181 | L_WristYaw_des = max_WristYaw * np.sin(2.0 * np.pi * t) 182 | R_WristYaw_des = max_WristYaw * np.sin(2.0 * np.pi * t) 183 | self.low_cmd.motor_cmd[G1JointIndex.LeftWristRoll].q = L_WristYaw_des 184 | self.low_cmd.motor_cmd[G1JointIndex.RightWristRoll].q = R_WristYaw_des 185 | 186 | 187 | self.low_cmd.crc = self.crc.Crc(self.low_cmd) 188 | self.lowcmd_publisher_.Write(self.low_cmd) 189 | 190 | if __name__ == '__main__': 191 | 192 | print("WARNING: Please ensure there are no obstacles around the robot while running this example.") 193 | input("Press Enter to continue...") 194 | 195 | if len(sys.argv)>1: 196 | ChannelFactoryInitialize(0, sys.argv[1]) 197 | else: 198 | ChannelFactoryInitialize(0) 199 | 200 | custom = Custom() 201 | custom.Init() 202 | custom.Start() 203 | 204 | while True: 205 | time.sleep(1) -------------------------------------------------------------------------------- /unitree_sdk2py/utils/joystick.py: -------------------------------------------------------------------------------- 1 | import math 2 | import struct 3 | import os 4 | os.environ['PYGAME_HIDE_SUPPORT_PROMPT'] = "hide" # Disable pygame welcome message 5 | import pygame 6 | import time 7 | 8 | class Button: 9 | def __init__(self) -> None: 10 | self.pressed = False 11 | self.on_pressed = False 12 | self.on_released = False 13 | self.data = 0 14 | self.click_count = 0 # 记录连续点击次数 15 | self.last_pressed_time = 0 # 上次按下时间 16 | 17 | def __call__(self, data) -> None: 18 | current_time = time.perf_counter() 19 | # print('before',self.data) 20 | 21 | self.pressed = (data != 0) 22 | self.on_pressed = self.pressed and self.data == 0 23 | self.on_released = not self.pressed and self.data != 0 24 | 25 | # print('after',self.data) 26 | # 处理连续点击 27 | if self.on_pressed: 28 | # print('on_pressed') 29 | # print('on_pressed current_time',current_time) 30 | # print('on_pressed last_pressed_time',self.last_pressed_time) 31 | # print('on_pressed diff',current_time-self.last_pressed_time) 32 | 33 | if current_time - self.last_pressed_time <= 0.3: # 0.1 秒以内的连续点击 34 | self.click_count += 1 35 | # print(self.click_count) 36 | else: 37 | self.click_count = 0 # 超过时间间隔,重置计数器 38 | self.last_pressed_time = current_time 39 | self.data = data 40 | 41 | def reset_click_count(self): 42 | """手动重置连续点击计数器""" 43 | self.click_count = 0 44 | 45 | class Axis: 46 | def __init__(self) -> None: 47 | self.data = 0.0 48 | self.pressed = False 49 | self.on_pressed = False 50 | self.on_released = False 51 | 52 | self.smooth = 0.03 53 | self.deadzone = 0.01 54 | self.threshold = 0.5 55 | 56 | def __call__(self, data) -> None: 57 | data_deadzone = 0.0 if math.fabs(data) < self.deadzone else data 58 | new_data = self.data * (1 - self.smooth) + data_deadzone * self.smooth 59 | self.pressed = math.fabs(new_data) > self.threshold 60 | self.on_pressed = self.pressed and math.fabs(self.data) < self.threshold 61 | self.on_released = not self.pressed and math.fabs(self.data) > self.threshold 62 | self.data = new_data 63 | 64 | 65 | class Joystick: 66 | def __init__(self) -> None: 67 | # Buttons 68 | self.back = Button() 69 | self.start = Button() 70 | # self.LS = Button() 71 | # self.RS = Button() 72 | self.LB = Button() 73 | self.RB = Button() 74 | self.LT = Button() 75 | self.RT = Button() 76 | self.A = Button() 77 | self.B = Button() 78 | self.X = Button() 79 | self.Y = Button() 80 | self.up = Button() 81 | self.down = Button() 82 | self.left = Button() 83 | self.right = Button() 84 | self.F1 = Button() 85 | self.F2 = Button() 86 | 87 | # Axes 88 | # self.LT = Axis() 89 | # self.RT = Axis() 90 | self.lx = Axis() 91 | self.ly = Axis() 92 | self.rx = Axis() 93 | self.ry = Axis() 94 | 95 | self.last_active_time = time.perf_counter() # 最后一次活动时间 96 | self.inactive_timeout = 0.5 # 超时时间(单位:秒) 97 | def update(self): 98 | """ 99 | Update the current handle key based on the original data 100 | Used to update flag bits such as on_pressed 101 | 102 | Examples: 103 | >>> new_A_data = 1 104 | >>> self.A( new_A_data ) 105 | """ 106 | pass 107 | 108 | def extract(self, wireless_remote): 109 | """ 110 | Extract data from unitree_joystick 111 | wireless_remote: uint8_t[40] 112 | """ 113 | # Buttons 114 | button1 = [int(data) for data in f'{wireless_remote[2]:08b}'] 115 | button2 = [int(data) for data in f'{wireless_remote[3]:08b}'] 116 | self.LT(button1[2]) 117 | self.RT(button1[3]) 118 | self.back(button1[4]) 119 | self.start(button1[5]) 120 | self.LB(button1[6]) 121 | self.RB(button1[7]) 122 | self.left(button2[0]) 123 | self.down(button2[1]) 124 | self.right(button2[2]) 125 | self.up(button2[3]) 126 | self.Y(button2[4]) 127 | self.X(button2[5]) 128 | self.B(button2[6]) 129 | self.A(button2[7]) 130 | # Axes 131 | self.lx( struct.unpack('f', bytes(wireless_remote[4:8]))[0] ) 132 | self.rx( struct.unpack('f', bytes(wireless_remote[8:12]))[0] ) 133 | self.ry( struct.unpack('f', bytes(wireless_remote[12:16]))[0] ) 134 | self.ly( struct.unpack('f', bytes(wireless_remote[20:24]))[0] ) 135 | 136 | 137 | # 检查是否有按键按下 138 | if any([ 139 | self.LT.pressed, self.RT.pressed, self.back.pressed, self.start.pressed, 140 | self.LB.pressed, self.RB.pressed, self.left.pressed, self.down.pressed, 141 | self.right.pressed, self.up.pressed, self.Y.pressed, self.X.pressed, 142 | self.B.pressed, self.A.pressed 143 | ]): 144 | self.last_active_time = time.perf_counter() # 更新最后一次活动时间 145 | elif time.perf_counter() - self.last_active_time > self.inactive_timeout: 146 | # 超过设定的超时时间未按下任何键,重置所有按键的点击计数 147 | self.reset_all_click_counts() 148 | self.last_active_time = time.perf_counter() # 重置最后活动时间 149 | 150 | def reset_all_click_counts(self): 151 | """重置所有按键的连续点击计数器""" 152 | for button in [ 153 | self.LT, self.RT, self.back, self.start, self.LB, self.RB, 154 | self.left, self.down, self.right, self.up, self.Y, self.X, self.B, self.A 155 | ]: 156 | button.reset_click_count() 157 | 158 | def combine(self): 159 | """ 160 | Merge data from Joystick to wireless_remote 161 | """ 162 | # prepare an empty list 163 | wireless_remote = [0 for _ in range(40)] 164 | 165 | # Buttons 166 | wireless_remote[2] = int(''.join([f'{key}' for key in [ 167 | 0, 0, round(self.LT.data), round(self.RT.data), 168 | self.back.data, self.start.data, self.LB.data, self.RB.data, 169 | ]]), 2) 170 | wireless_remote[3] = int(''.join([f'{key}' for key in [ 171 | self.left.data, self.down.data, self.right.data, 172 | self.up.data, self.Y.data, self.X.data, self.B.data, self.A.data, 173 | ]]), 2) 174 | 175 | # Axes 176 | sticks = [self.lx.data, self.rx.data, self.ry.data, self.ly.data] 177 | packs = list(map(lambda x: struct.pack('f', x), sticks)) 178 | wireless_remote[4:8] = packs[0] 179 | wireless_remote[8:12] = packs[1] 180 | wireless_remote[12:16] = packs[2] 181 | wireless_remote[20:24] = packs[3] 182 | return wireless_remote 183 | 184 | class PyGameJoystick(Joystick): 185 | def __init__(self) -> None: 186 | super().__init__() 187 | 188 | pygame.init() 189 | pygame.joystick.init() 190 | if pygame.joystick.get_count() <= 0: 191 | raise Exception("No joystick found!") 192 | 193 | self._joystick = pygame.joystick.Joystick(0) 194 | self._joystick.init() 195 | 196 | def print(self): 197 | print("\naxes: ") 198 | for i in range(self._joystick.get_numaxes()): 199 | print(self._joystick.get_axis(i), end=" ") 200 | print("\nbuttons: ") 201 | for i in range(self._joystick.get_numbuttons()): 202 | print(self._joystick.get_button(i), end=" ") 203 | print("\nhats: ") 204 | for i in range(self._joystick.get_numhats()): 205 | print(self._joystick.get_hat(i), end=" ") 206 | print("\nballs: ") 207 | for i in range(self._joystick.get_numballs()): 208 | print(self._joystick.get_ball(i), end=" ") 209 | print("\n") 210 | 211 | class LogicJoystick(PyGameJoystick): 212 | """ Logic F710 """ 213 | def __init__(self) -> None: 214 | super().__init__() 215 | 216 | def update(self): 217 | pygame.event.pump() 218 | 219 | self.back(self._joystick.get_button(6)) 220 | self.start(self._joystick.get_button(7)) 221 | self.LS(self._joystick.get_button(9)) 222 | self.RS(self._joystick.get_button(10)) 223 | self.LB(self._joystick.get_button(4)) 224 | self.RB(self._joystick.get_button(5)) 225 | self.A(self._joystick.get_button(0)) 226 | self.B(self._joystick.get_button(1)) 227 | self.X(self._joystick.get_button(2)) 228 | self.Y(self._joystick.get_button(3)) 229 | 230 | self.LT((self._joystick.get_axis(2) + 1)/2) 231 | self.RT((self._joystick.get_axis(5) + 1)/2) 232 | self.rx(self._joystick.get_axis(3)) 233 | self.ry(-self._joystick.get_axis(4)) 234 | 235 | 236 | # Logitech controller has 2 modes 237 | # mode 1: light down 238 | self.up(1 if self._joystick.get_hat(0)[1] > 0.5 else 0) 239 | self.down(1 if self._joystick.get_hat(0)[1] < -0.5 else 0) 240 | self.left(1 if self._joystick.get_hat(0)[0] < -0.5 else 0) 241 | self.right(1 if self._joystick.get_hat(0)[0] > 0.5 else 0) 242 | self.lx(self._joystick.get_axis(0)) 243 | self.ly(-self._joystick.get_axis(1)) 244 | # mode 2: light up 245 | # self.up(1 if self._joystick.get_axis(1) < -0.5 else 0) 246 | # self.down(1 if self._joystick.get_axis(0) > 0.5 else 0) 247 | # self.left(1 if self._joystick.get_axis(0) < -0.5 else 0) 248 | # self.right(1 if self._joystick.get_axis(0) > 0.5 else 0) 249 | # self.lx(self._joystick.get_hat(0)[1]) 250 | # self.ly(self._joystick.get_hat(0)[1]) 251 | 252 | -------------------------------------------------------------------------------- /unitree_sdk2py/utils/crc.py: -------------------------------------------------------------------------------- 1 | import struct 2 | import cyclonedds 3 | import cyclonedds.idl as idl 4 | 5 | from .singleton import Singleton 6 | from ..idl.unitree_go.msg.dds_ import LowCmd_ 7 | from ..idl.unitree_go.msg.dds_ import LowState_ 8 | 9 | from ..idl.unitree_hg.msg.dds_ import LowCmd_ as HGLowCmd_ 10 | from ..idl.unitree_hg.msg.dds_ import LowState_ as HGLowState_ 11 | import ctypes 12 | import os 13 | import platform 14 | 15 | class CRC(Singleton): 16 | def __init__(self): 17 | #4 bytes aligned, little-endian format. 18 | #size 812 19 | self.__packFmtLowCmd = '<4B4IH2x' + 'B3x5f3I' * 20 + '4B' + '55Bx2I' 20 | #size 1180 21 | self.__packFmtLowState = '<4B4IH2x' + '13fb3x' + 'B3x7fb3x3I' * 20 + '4BiH4b15H' + '8hI41B3xf2b2x2f4h2I' 22 | #size 1004 23 | self.__packFmtHGLowCmd = '<2B2x' + 'B3x5fI' * 35 + '5I' 24 | #size 2092 25 | self.__packFmtHGLowState = '<2I2B2xI' + '13fh2x' + 'B3x4f2hf7I' * 35 + '40B5I' 26 | 27 | 28 | script_dir = os.path.dirname(os.path.abspath(__file__)) 29 | self.platform = platform.system() 30 | if self.platform == "Linux": 31 | if platform.machine()=="x86_64": 32 | self.crc_lib = ctypes.CDLL(script_dir + '/lib/crc_amd64.so') 33 | elif platform.machine()=="aarch64": 34 | self.crc_lib = ctypes.CDLL(script_dir + '/lib/crc_aarch64.so') 35 | 36 | self.crc_lib.crc32_core.argtypes = (ctypes.POINTER(ctypes.c_uint32), ctypes.c_uint32) 37 | self.crc_lib.crc32_core.restype = ctypes.c_uint32 38 | 39 | def Crc(self, msg: idl.IdlStruct): 40 | if msg.__idl_typename__ == 'unitree_go.msg.dds_.LowCmd_': 41 | return self.__Crc32(self.__PackLowCmd(msg)) 42 | elif msg.__idl_typename__ == 'unitree_go.msg.dds_.LowState_': 43 | return self.__Crc32(self.__PackLowState(msg)) 44 | if msg.__idl_typename__ == 'unitree_hg.msg.dds_.LowCmd_': 45 | return self.__Crc32(self.__PackHGLowCmd(msg)) 46 | elif msg.__idl_typename__ == 'unitree_hg.msg.dds_.LowState_': 47 | return self.__Crc32(self.__PackHGLowState(msg)) 48 | else: 49 | raise TypeError('unknown IDL message type to crc') 50 | 51 | def __PackLowCmd(self, cmd: LowCmd_): 52 | origData = [] 53 | origData.extend(cmd.head) 54 | origData.append(cmd.level_flag) 55 | origData.append(cmd.frame_reserve) 56 | origData.extend(cmd.sn) 57 | origData.extend(cmd.version) 58 | origData.append(cmd.bandwidth) 59 | 60 | for i in range(20): 61 | origData.append(cmd.motor_cmd[i].mode) 62 | origData.append(cmd.motor_cmd[i].q) 63 | origData.append(cmd.motor_cmd[i].dq) 64 | origData.append(cmd.motor_cmd[i].tau) 65 | origData.append(cmd.motor_cmd[i].kp) 66 | origData.append(cmd.motor_cmd[i].kd) 67 | origData.extend(cmd.motor_cmd[i].reserve) 68 | 69 | origData.append(cmd.bms_cmd.off) 70 | origData.extend(cmd.bms_cmd.reserve) 71 | 72 | origData.extend(cmd.wireless_remote) 73 | origData.extend(cmd.led) 74 | origData.extend(cmd.fan) 75 | origData.append(cmd.gpio) 76 | origData.append(cmd.reserve) 77 | origData.append(cmd.crc) 78 | 79 | return self.__Trans(struct.pack(self.__packFmtLowCmd, *origData)) 80 | 81 | def __PackLowState(self, state: LowState_): 82 | origData = [] 83 | origData.extend(state.head) 84 | origData.append(state.level_flag) 85 | origData.append(state.frame_reserve) 86 | origData.extend(state.sn) 87 | origData.extend(state.version) 88 | origData.append(state.bandwidth) 89 | 90 | origData.extend(state.imu_state.quaternion) 91 | origData.extend(state.imu_state.gyroscope) 92 | origData.extend(state.imu_state.accelerometer) 93 | origData.extend(state.imu_state.rpy) 94 | origData.append(state.imu_state.temperature) 95 | 96 | for i in range(20): 97 | origData.append(state.motor_state[i].mode) 98 | origData.append(state.motor_state[i].q) 99 | origData.append(state.motor_state[i].dq) 100 | origData.append(state.motor_state[i].ddq) 101 | origData.append(state.motor_state[i].tau_est) 102 | origData.append(state.motor_state[i].q_raw) 103 | origData.append(state.motor_state[i].dq_raw) 104 | origData.append(state.motor_state[i].ddq_raw) 105 | origData.append(state.motor_state[i].temperature) 106 | origData.append(state.motor_state[i].lost) 107 | origData.extend(state.motor_state[i].reserve) 108 | 109 | origData.append(state.bms_state.version_high) 110 | origData.append(state.bms_state.version_low) 111 | origData.append(state.bms_state.status) 112 | origData.append(state.bms_state.soc) 113 | origData.append(state.bms_state.current) 114 | origData.append(state.bms_state.cycle) 115 | origData.extend(state.bms_state.bq_ntc) 116 | origData.extend(state.bms_state.mcu_ntc) 117 | origData.extend(state.bms_state.cell_vol) 118 | 119 | origData.extend(state.foot_force) 120 | origData.extend(state.foot_force_est) 121 | origData.append(state.tick) 122 | origData.extend(state.wireless_remote) 123 | origData.append(state.bit_flag) 124 | origData.append(state.adc_reel) 125 | origData.append(state.temperature_ntc1) 126 | origData.append(state.temperature_ntc2) 127 | origData.append(state.power_v) 128 | origData.append(state.power_a) 129 | origData.extend(state.fan_frequency) 130 | origData.append(state.reserve) 131 | origData.append(state.crc) 132 | 133 | return self.__Trans(struct.pack(self.__packFmtLowState, *origData)) 134 | 135 | def __PackHGLowCmd(self, cmd: HGLowCmd_): 136 | origData = [] 137 | origData.append(cmd.mode_pr) 138 | origData.append(cmd.mode_machine) 139 | 140 | for i in range(35): 141 | origData.append(cmd.motor_cmd[i].mode) 142 | origData.append(cmd.motor_cmd[i].q) 143 | origData.append(cmd.motor_cmd[i].dq) 144 | origData.append(cmd.motor_cmd[i].tau) 145 | origData.append(cmd.motor_cmd[i].kp) 146 | origData.append(cmd.motor_cmd[i].kd) 147 | origData.append(cmd.motor_cmd[i].reserve) 148 | 149 | origData.extend(cmd.reserve) 150 | origData.append(cmd.crc) 151 | 152 | return self.__Trans(struct.pack(self.__packFmtHGLowCmd, *origData)) 153 | 154 | def __PackHGLowState(self, state: HGLowState_): 155 | origData = [] 156 | origData.extend(state.version) 157 | origData.append(state.mode_pr) 158 | origData.append(state.mode_machine) 159 | origData.append(state.tick) 160 | 161 | origData.extend(state.imu_state.quaternion) 162 | origData.extend(state.imu_state.gyroscope) 163 | origData.extend(state.imu_state.accelerometer) 164 | origData.extend(state.imu_state.rpy) 165 | origData.append(state.imu_state.temperature) 166 | 167 | for i in range(35): 168 | origData.append(state.motor_state[i].mode) 169 | origData.append(state.motor_state[i].q) 170 | origData.append(state.motor_state[i].dq) 171 | origData.append(state.motor_state[i].ddq) 172 | origData.append(state.motor_state[i].tau_est) 173 | origData.extend(state.motor_state[i].temperature) 174 | origData.append(state.motor_state[i].vol) 175 | origData.extend(state.motor_state[i].sensor) 176 | origData.append(state.motor_state[i].motorstate) 177 | origData.extend(state.motor_state[i].reserve) 178 | 179 | origData.extend(state.wireless_remote) 180 | origData.extend(state.reserve) 181 | origData.append(state.crc) 182 | 183 | return self.__Trans(struct.pack(self.__packFmtHGLowState, *origData)) 184 | 185 | def __Trans(self, packData): 186 | calcData = [] 187 | calcLen = ((len(packData)>>2)-1) 188 | 189 | for i in range(calcLen): 190 | d = ((packData[i*4+3] << 24) | (packData[i*4+2] << 16) | (packData[i*4+1] << 8) | (packData[i*4])) 191 | calcData.append(d) 192 | 193 | return calcData 194 | 195 | def _crc_py(self, data): 196 | bit = 0 197 | crc = 0xFFFFFFFF 198 | polynomial = 0x04c11db7 199 | 200 | for i in range(len(data)): 201 | bit = 1 << 31 202 | current = data[i] 203 | 204 | for b in range(32): 205 | if crc & 0x80000000: 206 | crc = (crc << 1) & 0xFFFFFFFF 207 | crc ^= polynomial 208 | else: 209 | crc = (crc << 1) & 0xFFFFFFFF 210 | 211 | if current & bit: 212 | crc ^= polynomial 213 | 214 | bit >>= 1 215 | 216 | return crc 217 | 218 | def _crc_ctypes(self, data): 219 | uint32_array = (ctypes.c_uint32 * len(data))(*data) 220 | length = len(data) 221 | crc=self.crc_lib.crc32_core(uint32_array, length) 222 | return crc 223 | 224 | def __Crc32(self, data): 225 | if self.platform == "Linux": 226 | return self._crc_ctypes(data) 227 | else: 228 | return self._crc_py(data) 229 | --------------------------------------------------------------------------------