diff --git a/doc/fun.dio b/doc/fun.dio index b50af1f..c7bd992 100644 --- a/doc/fun.dio +++ b/doc/fun.dio @@ -1,6 +1,6 @@ - + @@ -22,7 +22,7 @@ - + diff --git a/doc/func.png b/doc/func.png index dad987b..11ac6d2 100644 Binary files a/doc/func.png and b/doc/func.png differ diff --git a/example/cpp/CMakeLists.txt b/example/cpp/CMakeLists.txt index 6dad92d..291ff21 100644 --- a/example/cpp/CMakeLists.txt +++ b/example/cpp/CMakeLists.txt @@ -1,9 +1,10 @@ cmake_minimum_required(VERSION 3.16) project(stand_go2) -include_directories(/usr/local/include/ddscxx /usr/local/include/iceoryx/v2.0.2) -link_libraries(unitree_sdk2 ddsc ddscxx rt pthread) +list(APPEND CMAKE_PREFIX_PATH "/opt/unitree_robotics/lib/cmake") +find_package(unitree_sdk2 REQUIRED) add_executable(stand_go2 stand_go2.cpp) +target_link_libraries(stand_go2 unitree_sdk2) SET(CMAKE_BUILD_TYPE Release) \ No newline at end of file diff --git a/readme.md b/readme.md index bc06f93..e35ee83 100644 --- a/readme.md +++ b/readme.md @@ -33,8 +33,10 @@ Note: ```bash git clone https://github.com/unitreerobotics/unitree_sdk2.git cd unitree_sdk2/ -chmod +x ./install.sh -sudo ./install.sh +mkdir build +cd build +cmake .. -DCMAKE_INSTALL_PREFIX=/opt/unitree_robotics +sudo make install ``` For more details, see: https://github.com/unitreerobotics/unitree_sdk2 #### mujoco >= 3.0.0 @@ -157,6 +159,11 @@ DOMAIN_ID = 1 # Domain id INTERFACE = "lo" # Interface # Whether to output robot link, joint, sensor information, True for output PRINT_SCENE_INFORMATION = True + +USE_JOYSTICK = 1 # Simulate Unitree WirelessController using a gamepad +JOYSTICK_TYPE = "xbox" # support "xbox" and "switch" gamepad layout +JOYSTICK_DEVICE = 0 # Joystick number + # Whether to use virtual tape, 1 to enable # Mainly used to simulate the hanging process of H1 robot initialization ENABLE_ELASTIC_BAND = False @@ -166,6 +173,62 @@ SIMULATE_DT = 0.003 # Visualization interface runtime step, 0.02 corresponds to 50fps/s VIEWER_DT = 0.02 ``` +### Joystick +The simulator will use an Xbox or Switch gamepad to simulate the wireless controller of the robot. The button and joystick information of the wireless controller will be published through "rt/wireless_controller" topic. `use_joystick/USE_JOYSTICK` in `config.yaml/config.py` needs to be set to 0, when there is no gamepad. If your gamepad is not in Xbox or Switch layout, you can modify it in the source code (The button and joystick IDs can be determined using `jstest`): + +In `simulate/src/unitree_sdk2_bridge/unitree_sdk2_bridge.cc`: +```C++ + if (js_type == "xbox") +{ + js_id_.axis["LX"] = 0; // Left stick axis x + js_id_.axis["LY"] = 1; // Left stick axis y + js_id_.axis["RX"] = 3; // Right stick axis x + js_id_.axis["RY"] = 4; // Right stick axis y + js_id_.axis["LT"] = 2; // Left trigger + js_id_.axis["RT"] = 5; // Right trigger + js_id_.axis["DX"] = 6; // Directional pad x + js_id_.axis["DY"] = 7; // Directional pad y + + js_id_.button["X"] = 2; + js_id_.button["Y"] = 3; + js_id_.button["B"] = 1; + js_id_.button["A"] = 0; + js_id_.button["LB"] = 4; + js_id_.button["RB"] = 5; + js_id_.button["SELECT"] = 6; + js_id_.button["START"] = 7; +} +``` + +In `simulate_python/unitree_sdk2_bridge.py`: +```python +if js_type == "xbox": + self.axis_id = { + "LX": 0, # Left stick axis x + "LY": 1, # Left stick axis y + "RX": 3, # Right stick axis x + "RY": 4, # Right stick axis y + "LT": 2, # Left trigger + "RT": 5, # Right trigger + "DX": 6, # Directional pad x + "DY": 7, # Directional pad y + } + + self.button_id = { + "X": 2, + "Y": 3, + "B": 1, + "A": 0, + "LB": 4, + "RB": 5, + "SELECT": 6, + "START": 7, + } +``` + +### Elastic band for humanoid +Consider humanoid robots are not suitable for starting in ground, a virtual elastic band was designed to simulate the lifting and lowering of humanoid robots. Setting ` enable_elastic_mand/ENABLE_ELSTIC_BAND=1 ` can enable the virtual elastic band. After loading the robot, press' 9 'to activate or release the strap, press' 7' to lower the robot, and press' 8 'to lift the robot. + ## 2. Terrain Generation Tool We provide a tool to parametrically create simple terrains in the mujoco simulator, including stairs, rough ground, and height maps. The program is located in the `terrain_tool` folder. For specific usage instructions, refer to the README file in the `terrain_tool` folder. ![Terrain Generation Example](./doc/terrain.png) diff --git a/readme_zh.md b/readme_zh.md index 52b45cc..e108797 100644 --- a/readme_zh.md +++ b/readme_zh.md @@ -35,8 +35,10 @@ ```bash git clone https://github.com/unitreerobotics/unitree_sdk2.git cd unitree_sdk2/ -chmod +x ./install.sh -sudo ./install.sh +mkdir build +cd build +cmake .. -DCMAKE_INSTALL_PREFIX=/opt/unitree_robotics +sudo make install ``` 详细见:https://github.com/unitreerobotics/unitree_sdk2 #### mujoco >= 3.0.0 @@ -164,6 +166,10 @@ INTERFACE = "lo" # Interface # 是否输出机器人连杆、关节、传感器等信息,True 为输出 PRINT_SCENE_INFORMATION = True +USE_JOYSTICK = 1 # Simulate Unitree WirelessController using a gamepad +JOYSTICK_TYPE = "xbox" # support "xbox" and "switch" gamepad layout +JOYSTICK_DEVICE = 0 # Joystick number + # 是否使用虚拟挂带, 1 为启用 # 主要用于模拟 H1 机器人初始化挂起的过程 ENABLE_ELASTIC_BAND = False @@ -175,6 +181,62 @@ SIMULATE_DT = 0.003 # 可视化界面的运行步长,0.02 对应 50fps/s VIEWER_DT = 0.02 ``` + +### 游戏手柄 +仿真器会使用 Xbox 或者 Switch 游戏来模拟机器人的无线控制器,并将手柄按键和摇杆信息发布在"rt/wireless_controller" topic。如果手上没有可以使用的游戏手柄,需要将 `config.yaml/config.py` 中的 `use_joystick/USE_JOYSTICK` 设置为 0。如果使用的手柄不属于 Xbox 和 Switch 映射,可以在源码中自行修改或添加(可以使用 `jstest` 工具查看按键和摇杆 id): + +In `simulate/src/unitree_sdk2_bridge/unitree_sdk2_bridge.cc`: +```C++ + if (js_type == "xbox") +{ + js_id_.axis["LX"] = 0; // Left stick axis x + js_id_.axis["LY"] = 1; // Left stick axis y + js_id_.axis["RX"] = 3; // Right stick axis x + js_id_.axis["RY"] = 4; // Right stick axis y + js_id_.axis["LT"] = 2; // Left trigger + js_id_.axis["RT"] = 5; // Right trigger + js_id_.axis["DX"] = 6; // Directional pad x + js_id_.axis["DY"] = 7; // Directional pad y + + js_id_.button["X"] = 2; + js_id_.button["Y"] = 3; + js_id_.button["B"] = 1; + js_id_.button["A"] = 0; + js_id_.button["LB"] = 4; + js_id_.button["RB"] = 5; + js_id_.button["SELECT"] = 6; + js_id_.button["START"] = 7; +} +``` + +In `simulate_python/unitree_sdk2_bridge.py`: +```python +if js_type == "xbox": + self.axis_id = { + "LX": 0, # Left stick axis x + "LY": 1, # Left stick axis y + "RX": 3, # Right stick axis x + "RY": 4, # Right stick axis y + "LT": 2, # Left trigger + "RT": 5, # Right trigger + "DX": 6, # Directional pad x + "DY": 7, # Directional pad y + } + + self.button_id = { + "X": 2, + "Y": 3, + "B": 1, + "A": 0, + "LB": 4, + "RB": 5, + "SELECT": 6, + "START": 7, + } +``` +### 人形机器人虚拟挂带 +考虑到人形机器人不便于从平地上启动并进行调试,在仿真中设计了一个虚拟挂带,用于模拟人形机器人的吊起和放下。设置 `enable_elastic_band/ENABLE_ELASTIC_BAND = 1` 可以启用虚拟挂带。加载机器人后,按 `9` 启用或松开挂带,按 `7` 放下机器人,按 `8` 吊起机器人。 + ## 2. 地形生成工具 我们提供了一个在 mujcoc 仿真器中参数化创建简单地形的工具,支持添加楼梯、杂乱地面、高程图等地形。程序位于 `terrain_tool` 文件夹中。具体的使用方法见 `terrain_tool` 文件夹下的 readme 文件。 ![](./doc/terrain.png) diff --git a/simulate/CMakeLists.txt b/simulate/CMakeLists.txt index a20f61d..1436e19 100644 --- a/simulate/CMakeLists.txt +++ b/simulate/CMakeLists.txt @@ -4,10 +4,12 @@ project(unitree_mujoco) enable_language(C) enable_language(CXX) set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +list(APPEND CMAKE_PREFIX_PATH "/opt/unitree_robotics/lib/cmake") find_package(mujoco REQUIRED) -include_directories(/usr/local/include/ddscxx /usr/local/include/iceoryx/v2.0.2) -link_libraries(unitree_sdk2 ddsc ddscxx rt pthread) +find_package(unitree_sdk2 REQUIRED) + FILE (GLOB SIM_SRC src/joystick/joystick.cc @@ -18,13 +20,16 @@ set(SIM_DEPENDENCIES pthread mujoco::mujoco glfw - yaml-cpp) + yaml-cpp + unitree_sdk2) add_executable(unitree_mujoco ${SIM_SRC} src/main.cc) target_link_libraries(unitree_mujoco ${SIM_DEPENDENCIES}) add_executable(test test/test_unitree_sdk2.cpp) +target_link_libraries(test unitree_sdk2) + add_executable(jstest src/joystick/jstest.cc src/joystick/joystick.cc) SET(CMAKE_BUILD_TYPE Release) \ No newline at end of file diff --git a/simulate/test/test_unitree_sdk2.cpp b/simulate/test/test_unitree_sdk2.cpp index 2626fe6..35996f5 100644 --- a/simulate/test/test_unitree_sdk2.cpp +++ b/simulate/test/test_unitree_sdk2.cpp @@ -35,7 +35,7 @@ void HighStateHandler(const void *msg) int main() { - ChannelFactory::Instance()->Init(27, "lo"); + ChannelFactory::Instance()->Init(1, "lo"); ChannelSubscriber lowstate_suber(TOPIC_LOWSTATE); lowstate_suber.InitChannel(LowStateHandler); diff --git a/simulate_python/unitree_mujoco.py b/simulate_python/unitree_mujoco.py index 7649b7d..2d727db 100755 --- a/simulate_python/unitree_mujoco.py +++ b/simulate_python/unitree_mujoco.py @@ -18,12 +18,13 @@ mj_data = mujoco.MjData(mj_model) if config.ENABLE_ELASTIC_BAND: elastic_band = ElasticBand() - if config.ROBOT=="h1": - band_attached_link=mj_model.body('torso_link').id + if config.ROBOT == "h1": + band_attached_link = mj_model.body("torso_link").id else: - band_attached_link=mj_model.body('base_link').id + band_attached_link = mj_model.body("base_link").id viewer = mujoco.viewer.launch_passive( - mj_model, mj_data, key_callback=elastic_band.MujuocoKeyCallback) + mj_model, mj_data, key_callback=elastic_band.MujuocoKeyCallback + ) else: viewer = mujoco.viewer.launch_passive(mj_model, mj_data) @@ -36,15 +37,15 @@ time.sleep(0.2) def SimulationThread(): global mj_data, mj_model - + ChannelFactoryInitialize(config.DOMAIN_ID, config.INTERFACE) unitree = UnitreeSdk2Bridge(mj_model, mj_data) if config.USE_JOYSTICK: - unitree.SetupJoystick() + unitree.SetupJoystick(device_id=0, js_type=config.JOYSTICK_TYPE) if config.PRINT_SCENE_INFORMATION: unitree.PrintSceneInformation() - + while viewer.is_running(): step_start = time.perf_counter() @@ -53,13 +54,15 @@ def SimulationThread(): if config.ENABLE_ELASTIC_BAND: if elastic_band.enable: mj_data.xfrc_applied[band_attached_link, :3] = elastic_band.Advance( - mj_data.qpos[:3], mj_data.qvel[:3]) + mj_data.qpos[:3], mj_data.qvel[:3] + ) mujoco.mj_step(mj_model, mj_data) locker.release() - time_until_next_step = mj_model.opt.timestep - (time.perf_counter() - - step_start) + time_until_next_step = mj_model.opt.timestep - ( + time.perf_counter() - step_start + ) if time_until_next_step > 0: time.sleep(time_until_next_step) diff --git a/simulate_python/unitree_sdk2py_bridge.py b/simulate_python/unitree_sdk2py_bridge.py index ad80a9b..2fe1a0e 100644 --- a/simulate_python/unitree_sdk2py_bridge.py +++ b/simulate_python/unitree_sdk2py_bridge.py @@ -317,7 +317,7 @@ class UnitreeSdk2Bridge: "START": 7, } - elif js_type == "stitch": + elif js_type == "switch": self.axis_id = { "LX": 0, # Left stick axis x "LY": 1, # Left stick axis y