├── 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 | 
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 |
--------------------------------------------------------------------------------