diff --git a/example/go2/high_level/go2_sport_client.py b/example/go2/high_level/go2_sport_client.py index b14d79d..3a3bbf2 100644 --- a/example/go2/high_level/go2_sport_client.py +++ b/example/go2/high_level/go2_sport_client.py @@ -1,170 +1,178 @@ +#!/usr/bin/env python3 +""" +Interactive high-level control demo for Unitree Go2 Edu +====================================================== + +* Connects via DDS to the robot (`eth0`, `enp2s0`, …). +* Lets you pick a command from a dynamic list and executes it via SportClient. +* Covers **all** V1.1.6 high-level / AI-switcher functions that are exposed in the + current C++ header. + (`WalkStair` was removed in V1.1.6 → no longer listed or called.) + +Run: + + python3 go2_sport_client.py + +Example: + + python3 go2_sport_client.py eth0 +""" + import time import sys -from unitree_sdk2py.core.channel import ChannelSubscriber, ChannelFactoryInitialize -from unitree_sdk2py.idl.default import unitree_go_msg_dds__SportModeState_ -from unitree_sdk2py.idl.unitree_go.msg.dds_ import SportModeState_ -from unitree_sdk2py.go2.sport.sport_client import ( - SportClient, - PathPoint, - SPORT_PATH_POINT_SIZE, -) -import math from dataclasses import dataclass +from unitree_sdk2py.core.channel import ChannelFactoryInitialize +from unitree_sdk2py.go2.sport.sport_client import SportClient + + +# --------------------------------------------------------------------------- # +# Option definitions # +# --------------------------------------------------------------------------- # @dataclass class TestOption: name: str id: int + option_list = [ - TestOption(name="damp", id=0), - TestOption(name="stand_up", id=1), - TestOption(name="stand_down", id=2), - TestOption(name="move forward", id=3), - TestOption(name="move lateral", id=4), - TestOption(name="move rotate", id=5), - TestOption(name="stop_move", id=6), - TestOption(name="switch_gait", id=7), - TestOption(name="switch_gait", id=8), - TestOption(name="balanced stand", id=9), - TestOption(name="recovery", id=10), - TestOption(name="recovery", id=10), - TestOption(name="left flip", id=11), - TestOption(name="back flip", id=12), - TestOption(name="free walk", id=13), - TestOption(name="free bound", id=14), - TestOption(name="free avoid", id=15), - TestOption(name="walk stair", id=16), - TestOption(name="walk upright", id=17), - TestOption(name="cross step", id=18), - TestOption(name="free jump", id=19) + # legacy “sport” basic control + TestOption("damp", 0), + TestOption("stand_up", 1), + TestOption("stand_down", 2), + TestOption("move_forward", 3), + TestOption("move_lateral", 4), + TestOption("move_rotate", 5), + TestOption("stop_move", 6), + TestOption("switch_gait_0", 7), + TestOption("switch_gait_1", 8), + TestOption("balanced_stand", 9), + TestOption("recovery", 10), + # legacy flips + TestOption("left_flip", 11), + TestOption("back_flip", 12), + # AI / motion-switcher V2.0 + TestOption("free_walk", 13), + TestOption("free_bound", 14), + TestOption("free_avoid", 15), + TestOption("walk_upright", 17), + TestOption("cross_step", 18), + TestOption("free_jump", 19), + TestOption("hand_stand", 20), + TestOption("classic_walk", 21), + TestOption("static_walk", 22), + TestOption("trot_run", 23), + TestOption("auto_recover_on", 24), + TestOption("auto_recover_off", 25), + TestOption("switch_avoid_mode", 26), ] + +# --------------------------------------------------------------------------- # +# Simple terminal UI helper # +# --------------------------------------------------------------------------- # class UserInterface: - def __init__(self): - self.test_option_ = None + def __init__(self, option_holder: TestOption): + self.option_holder = option_holder - def convert_to_int(self, input_str): + def _to_int(self, s): try: - return int(input_str) + return int(s) except ValueError: return None - def terminal_handle(self): - input_str = input("Enter id or name: \n") + def prompt(self): + user_in = input("Enter command (type 'list' to see all commands): ").strip() - if input_str == "list": - self.test_option_.name = None - self.test_option_.id = None - for option in option_list: - print(f"{option.name}, id: {option.id}") + # show list + if user_in == "list": + print("Available commands:") + for opt in option_list: + print(f" {opt.name} (id {opt.id})") return - for option in option_list: - if input_str == option.name or self.convert_to_int(input_str) == option.id: - self.test_option_.name = option.name - self.test_option_.id = option.id - print(f"Test: {self.test_option_.name}, test_id: {self.test_option_.id}") + # match name or id + for opt in option_list: + if user_in == opt.name or self._to_int(user_in) == opt.id: + self.option_holder.name = opt.name + self.option_holder.id = opt.id + print(f"Selected: {opt.name} (id {opt.id})") return - print("No matching test option found.") + print("No match. Type 'list' to see available commands.") -if __name__ == "__main__": +# --------------------------------------------------------------------------- # +# Main demo # +# --------------------------------------------------------------------------- # +if __name__ == "__main__": + # network interface must be provided if len(sys.argv) < 2: - print(f"Usage: python3 {sys.argv[0]} networkInterface") + print(f"Usage: python3 {sys.argv[0]} ") sys.exit(-1) - print("WARNING: Please ensure there are no obstacles around the robot while running this example.") + print("WARNING: ensure the robot has free space around it.") input("Press Enter to continue...") + # DDS / RPC initialisation ChannelFactoryInitialize(0, sys.argv[1]) - test_option = TestOption(name=None, id=None) - user_interface = UserInterface() - user_interface.test_option_ = test_option + # prepare option holder + UI + current_opt = TestOption("", -1) + ui = UserInterface(current_opt) - sport_client = SportClient() - sport_client.SetTimeout(10.0) - sport_client.Init() - while True: + # initialise SportClient + sport = SportClient() + sport.SetTimeout(10.0) + sport.Init() - user_interface.terminal_handle() - - print(f"Updated Test Option: Name = {test_option.name}, ID = {test_option.id}\n") - - if test_option.id == 0: - sport_client.Damp() - elif test_option.id == 1: - sport_client.StandUp() - elif test_option.id == 2: - sport_client.StandDown() - elif test_option.id == 3: - sport_client.Move(0.3,0,0) - elif test_option.id == 4: - sport_client.Move(0,0.3,0) - elif test_option.id == 5: - sport_client.Move(0,0,0.5) - elif test_option.id == 6: - sport_client.StopMove() - elif test_option.id == 7: - sport_client.SwitchGait(0) - elif test_option.id == 8: - sport_client.SwitchGait(1) - elif test_option.id == 9: - sport_client.BalanceStand() - elif test_option.id == 10: - sport_client.RecoveryStand() - elif test_option.id == 11: - ret = sport_client.LeftFlip() - print("ret: ",ret) - elif test_option.id == 12: - ret = sport_client.BackFlip() - print("ret: ",ret) - elif test_option.id == 13: - ret = sport_client.FreeWalk(True) - print("ret: ",ret) - elif test_option.id == 14: - ret = sport_client.FreeBound(True) - print("ret: ",ret) - time.sleep(2) - ret = sport_client.FreeBound(False) - print("ret: ",ret) - elif test_option.id == 14: - ret = sport_client.FreeBound(True) - print("ret: ",ret) - time.sleep(2) - ret = sport_client.FreeBound(False) - print("ret: ",ret) - elif test_option.id == 15: - ret = sport_client.FreeAvoid(True) - print("ret: ",ret) - time.sleep(2) - ret = sport_client.FreeAvoid(False) - print("ret: ",ret) - elif test_option.id == 16: - ret = sport_client.WalkStair(True) - print("ret: ",ret) - time.sleep(10) - ret = sport_client.WalkStair(False) - print("ret: ",ret) - elif test_option.id == 17: - ret = sport_client.WalkUpright(True) - print("ret: ",ret) - time.sleep(4) - ret = sport_client.WalkUpright(False) - print("ret: ",ret) - elif test_option.id == 18: - ret = sport_client.CrossStep(True) - print("ret: ",ret) - time.sleep(4) - ret = sport_client.CrossStep(False) - print("ret: ",ret) - elif test_option.id == 19: - ret = sport_client.FreeJump(True) - print("ret: ",ret) - time.sleep(4) - ret = sport_client.FreeJump(False) - print("ret: ",ret) + # main loop + while True: + ui.prompt() + cmd = current_opt.id + + # ---------- legacy sport ---------- + if cmd == 0: sport.Damp() + elif cmd == 1: sport.StandUp() + elif cmd == 2: sport.StandDown() + elif cmd == 3: sport.Move(0.3, 0, 0) + elif cmd == 4: sport.Move(0, 0.3, 0) + elif cmd == 5: sport.Move(0, 0, 0.5) + elif cmd == 6: sport.StopMove() + elif cmd == 7: sport.SwitchGait(0) + elif cmd == 8: sport.SwitchGait(1) + elif cmd == 9: sport.BalanceStand() + elif cmd == 10: sport.RecoveryStand() + elif cmd == 11: print("ret:", sport.LeftFlip()) + elif cmd == 12: print("ret:", sport.BackFlip()) + + # ---------- AI / V2.0 switcher ---------- + elif cmd == 13: print("ret:", sport.FreeWalk(True)) + elif cmd == 14: + print("ret:", sport.FreeBound(True)); time.sleep(2) + print("ret:", sport.FreeBound(False)) + elif cmd == 15: + print("ret:", sport.FreeAvoid(True)); time.sleep(2) + print("ret:", sport.FreeAvoid(False)) + elif cmd == 17: + print("ret:", sport.WalkUpright(True)); time.sleep(4) + print("ret:", sport.WalkUpright(False)) + elif cmd == 18: + print("ret:", sport.CrossStep(True)); time.sleep(4) + print("ret:", sport.CrossStep(False)) + elif cmd == 19: + print("ret:", sport.FreeJump(True)); time.sleep(4) + print("ret:", sport.FreeJump(False)) + elif cmd == 20: + print("ret:", sport.HandStand(True)); time.sleep(2) + print("ret:", sport.HandStand(False)) + elif cmd == 21: + print("ret:", sport.ClassicWalk(True)); time.sleep(2) + print("ret:", sport.ClassicWalk(False)) + elif cmd == 22: print("ret:", sport.StaticWalk()) + elif cmd == 23: print("ret:", sport.TrotRun()) + elif cmd == 24: print("ret:", sport.AutoRecoverSet(True)) + elif cmd == 25: print("ret:", sport.AutoRecoverSet(False)) + elif cmd == 26: print("ret:", sport.SwitchAvoidMode()) time.sleep(1) diff --git a/unitree_sdk2py/go2/sport/sport_api.py b/unitree_sdk2py/go2/sport/sport_api.py index bfca62a..265c991 100644 --- a/unitree_sdk2py/go2/sport/sport_api.py +++ b/unitree_sdk2py/go2/sport/sport_api.py @@ -1,74 +1,84 @@ """ -" service name +Service name and API version """ SPORT_SERVICE_NAME = "sport" +SPORT_API_VERSION = "1.0.0.1" +# ------------------------------------------------------------------ # +# High-level / legacy IDs (kept from ≤ V1.1.5) # +# ------------------------------------------------------------------ # +SPORT_API_ID_DAMP = 1001 +SPORT_API_ID_BALANCESTAND = 1002 +SPORT_API_ID_STOPMOVE = 1003 +SPORT_API_ID_STANDUP = 1004 +SPORT_API_ID_STANDDOWN = 1005 +SPORT_API_ID_RECOVERYSTAND = 1006 +SPORT_API_ID_EULER = 1007 +SPORT_API_ID_MOVE = 1008 +SPORT_API_ID_SIT = 1009 +SPORT_API_ID_RISESIT = 1010 +SPORT_API_ID_SWITCHGAIT = 1011 +SPORT_API_ID_TRIGGER = 1012 +SPORT_API_ID_BODYHEIGHT = 1013 +SPORT_API_ID_FOOTRAISEHEIGHT = 1014 +SPORT_API_ID_SPEEDLEVEL = 1015 +SPORT_API_ID_HELLO = 1016 +SPORT_API_ID_STRETCH = 1017 +SPORT_API_ID_TRAJECTORYFOLLOW = 1018 +SPORT_API_ID_CONTINUOUSGAIT = 1019 +SPORT_API_ID_CONTENT = 1020 +SPORT_API_ID_WALLOW = 1021 +SPORT_API_ID_DANCE1 = 1022 +SPORT_API_ID_DANCE2 = 1023 +SPORT_API_ID_GETBODYHEIGHT = 1024 +SPORT_API_ID_GETFOOTRAISEHEIGHT = 1025 +SPORT_API_ID_GETSPEEDLEVEL = 1026 +SPORT_API_ID_SWITCHJOYSTICK = 1027 +SPORT_API_ID_POSE = 1028 +SPORT_API_ID_SCRAPE = 1029 +SPORT_API_ID_FRONTFLIP = 1030 +SPORT_API_ID_FRONTJUMP = 1031 +SPORT_API_ID_FRONTPOUNCE = 1032 +SPORT_API_ID_WIGGLEHIPS = 1033 +SPORT_API_ID_GETSTATE = 1034 +SPORT_API_ID_HEART = 1036 -""" -" service api version -""" -SPORT_API_VERSION = "1.0.0.1" +# ------------------------------------------------------------------ # +# Base gaits moved to 106x in V 1.1.6 # +# ------------------------------------------------------------------ # +SPORT_API_ID_STATICWALK = 1061 +SPORT_API_ID_TROTRUN = 1062 +SPORT_API_ID_ECONOMICGAIT = 1063 +# Aliases with ROBOT_ prefix (needed for RegistApi calls) +ROBOT_SPORT_API_ID_STATICWALK = 1061 +ROBOT_SPORT_API_ID_TROTRUN = 1062 +ROBOT_SPORT_API_ID_ECONOMICGAIT = 1063 -""" -" api id -""" -SPORT_API_ID_DAMP = 1001 -SPORT_API_ID_BALANCESTAND = 1002 -SPORT_API_ID_STOPMOVE = 1003 -SPORT_API_ID_STANDUP = 1004 -SPORT_API_ID_STANDDOWN = 1005 -SPORT_API_ID_RECOVERYSTAND = 1006 -SPORT_API_ID_EULER = 1007 -SPORT_API_ID_MOVE = 1008 -SPORT_API_ID_SIT = 1009 -SPORT_API_ID_RISESIT = 1010 -SPORT_API_ID_SWITCHGAIT = 1011 -SPORT_API_ID_TRIGGER = 1012 -SPORT_API_ID_BODYHEIGHT = 1013 -SPORT_API_ID_FOOTRAISEHEIGHT = 1014 -SPORT_API_ID_SPEEDLEVEL = 1015 -SPORT_API_ID_HELLO = 1016 -SPORT_API_ID_STRETCH = 1017 -SPORT_API_ID_TRAJECTORYFOLLOW = 1018 -SPORT_API_ID_CONTINUOUSGAIT = 1019 -SPORT_API_ID_CONTENT = 1020 -SPORT_API_ID_WALLOW = 1021 -SPORT_API_ID_DANCE1 = 1022 -SPORT_API_ID_DANCE2 = 1023 -SPORT_API_ID_GETBODYHEIGHT = 1024 -SPORT_API_ID_GETFOOTRAISEHEIGHT = 1025 -SPORT_API_ID_GETSPEEDLEVEL = 1026 -SPORT_API_ID_SWITCHJOYSTICK = 1027 -SPORT_API_ID_POSE = 1028 -SPORT_API_ID_SCRAPE = 1029 -SPORT_API_ID_FRONTFLIP = 1030 -SPORT_API_ID_FRONTJUMP = 1031 -SPORT_API_ID_FRONTPOUNCE = 1032 -SPORT_API_ID_WIGGLEHIPS = 1033 -SPORT_API_ID_GETSTATE = 1034 -SPORT_API_ID_ECONOMICGAIT = 1035 -SPORT_API_ID_HEART = 1036 -ROBOT_SPORT_API_ID_DANCE3 = 1037 -ROBOT_SPORT_API_ID_DANCE4 = 1038 -ROBOT_SPORT_API_ID_HOPSPINLEFT = 1039 -ROBOT_SPORT_API_ID_HOPSPINRIGHT = 1040 +# ------------------------------------------------------------------ # +# Legacy flips # +# ------------------------------------------------------------------ # +ROBOT_SPORT_API_ID_LEFTFLIP = 2041 +ROBOT_SPORT_API_ID_BACKFLIP = 2043 -ROBOT_SPORT_API_ID_LEFTFLIP = 1042 -ROBOT_SPORT_API_ID_BACKFLIP = 1044 -ROBOT_SPORT_API_ID_FREEWALK = 1045 -ROBOT_SPORT_API_ID_FREEBOUND = 1046 -ROBOT_SPORT_API_ID_FREEJUMP = 1047 -ROBOT_SPORT_API_ID_FREEAVOID = 1048 -ROBOT_SPORT_API_ID_WALKSTAIR = 1049 -ROBOT_SPORT_API_ID_WALKUPRIGHT = 1050 -ROBOT_SPORT_API_ID_CROSSSTEP = 1051 +# ------------------------------------------------------------------ # +# V2.0 motion-switcher / AI-mode IDs # +# ------------------------------------------------------------------ # +ROBOT_SPORT_API_ID_HANDSTAND = 2044 +ROBOT_SPORT_API_ID_FREEWALK = 2045 +ROBOT_SPORT_API_ID_FREEBOUND = 2046 +ROBOT_SPORT_API_ID_FREEJUMP = 2047 +ROBOT_SPORT_API_ID_FREEAVOID = 2048 +ROBOT_SPORT_API_ID_CLASSICWALK = 2049 +ROBOT_SPORT_API_ID_WALKUPRIGHT = 2050 +ROBOT_SPORT_API_ID_CROSSSTEP = 2051 +ROBOT_SPORT_API_ID_AUTORECOVERY_SET = 2054 +ROBOT_SPORT_API_ID_AUTORECOVERY_GET = 2055 +ROBOT_SPORT_API_ID_SWITCHAVOIDMODE = 2058 -""" -" error code -""" -# client side +# ------------------------------------------------------------------ # +# Error codes # +# ------------------------------------------------------------------ # SPORT_ERR_CLIENT_POINT_PATH = 4101 -# server side -SPORT_ERR_SERVER_OVERTIME = 4201 -SPORT_ERR_SERVER_NOT_INIT = 4202 +SPORT_ERR_SERVER_OVERTIME = 4201 +SPORT_ERR_SERVER_NOT_INIT = 4202 diff --git a/unitree_sdk2py/go2/sport/sport_client.py b/unitree_sdk2py/go2/sport/sport_client.py index d058e51..66072db 100644 --- a/unitree_sdk2py/go2/sport/sport_client.py +++ b/unitree_sdk2py/go2/sport/sport_client.py @@ -1,19 +1,15 @@ import json - from ...rpc.client import Client from .sport_api import * -""" -" SPORT_PATH_POINT_SIZE -""" +# number of points expected by TrajectoryFollow SPORT_PATH_POINT_SIZE = 30 -""" -" class PathPoint -""" class PathPoint: - def __init__(self, timeFromStart: float, x: float, y: float, yaw: float, vx: float, vy: float, vyaw: float): + """Single trajectory point for TrajectoryFollow().""" + def __init__(self, timeFromStart: float, x: float, y: float, + yaw: float, vx: float, vy: float, vyaw: float): self.timeFromStart = timeFromStart self.x = x self.y = y @@ -23,424 +19,131 @@ def __init__(self, timeFromStart: float, x: float, y: float, yaw: float, vx: flo self.vyaw = vyaw -""" -" class SportClient -""" class SportClient(Client): + """ + Python wrapper for Unitree Go2 high-level / AI motion control (SDK ≥ V1.1.6). + """ + def __init__(self, enableLease: bool = False): super().__init__(SPORT_SERVICE_NAME, enableLease) - + # --------------------------------------------------------------------- # + # Init – register every API ID exactly once # + # --------------------------------------------------------------------- # def Init(self): - # set api version self._SetApiVerson(SPORT_API_VERSION) - - # regist api - self._RegistApi(SPORT_API_ID_DAMP, 0) - self._RegistApi(SPORT_API_ID_BALANCESTAND, 0) - self._RegistApi(SPORT_API_ID_STOPMOVE, 0) - self._RegistApi(SPORT_API_ID_STANDUP, 0) - self._RegistApi(SPORT_API_ID_STANDDOWN, 0) - self._RegistApi(SPORT_API_ID_RECOVERYSTAND, 0) - self._RegistApi(SPORT_API_ID_EULER, 0) - self._RegistApi(SPORT_API_ID_MOVE, 0) - self._RegistApi(SPORT_API_ID_SIT, 0) - self._RegistApi(SPORT_API_ID_RISESIT, 0) - self._RegistApi(SPORT_API_ID_SWITCHGAIT, 0) - self._RegistApi(SPORT_API_ID_TRIGGER, 0) - self._RegistApi(SPORT_API_ID_BODYHEIGHT, 0) - self._RegistApi(SPORT_API_ID_FOOTRAISEHEIGHT, 0) - self._RegistApi(SPORT_API_ID_SPEEDLEVEL, 0) - self._RegistApi(SPORT_API_ID_HELLO, 0) - self._RegistApi(SPORT_API_ID_STRETCH, 0) - self._RegistApi(SPORT_API_ID_TRAJECTORYFOLLOW, 0) - self._RegistApi(SPORT_API_ID_CONTINUOUSGAIT, 0) - # self._RegistApi(SPORT_API_ID_CONTENT, 0) - self._RegistApi(SPORT_API_ID_WALLOW, 0) - self._RegistApi(SPORT_API_ID_DANCE1, 0) - self._RegistApi(SPORT_API_ID_DANCE2, 0) - # self._RegistApi(SPORT_API_ID_GETBODYHEIGHT, 0) - # self._RegistApi(SPORT_API_ID_GETFOOTRAISEHEIGHT, 0) - # self._RegistApi(SPORT_API_ID_GETSPEEDLEVEL, 0) - self._RegistApi(SPORT_API_ID_SWITCHJOYSTICK, 0) - self._RegistApi(SPORT_API_ID_POSE, 0) - self._RegistApi(SPORT_API_ID_SCRAPE, 0) - self._RegistApi(SPORT_API_ID_FRONTFLIP, 0) - self._RegistApi(SPORT_API_ID_FRONTJUMP, 0) - self._RegistApi(SPORT_API_ID_FRONTPOUNCE, 0) - self._RegistApi(SPORT_API_ID_WIGGLEHIPS, 0) - self._RegistApi(SPORT_API_ID_GETSTATE, 0) - self._RegistApi(SPORT_API_ID_ECONOMICGAIT, 0) - self._RegistApi(SPORT_API_ID_HEART, 0) + # 1) legacy sport (basic posture, speed, etc.) + legacy_ids = [ + SPORT_API_ID_DAMP, SPORT_API_ID_BALANCESTAND, SPORT_API_ID_STOPMOVE, + SPORT_API_ID_STANDUP, SPORT_API_ID_STANDDOWN, SPORT_API_ID_RECOVERYSTAND, + SPORT_API_ID_EULER, SPORT_API_ID_MOVE, SPORT_API_ID_SIT, SPORT_API_ID_RISESIT, + SPORT_API_ID_SWITCHGAIT, SPORT_API_ID_TRIGGER, SPORT_API_ID_BODYHEIGHT, + SPORT_API_ID_FOOTRAISEHEIGHT, SPORT_API_ID_SPEEDLEVEL, SPORT_API_ID_HELLO, + SPORT_API_ID_STRETCH, SPORT_API_ID_TRAJECTORYFOLLOW, SPORT_API_ID_CONTINUOUSGAIT, + SPORT_API_ID_WALLOW, SPORT_API_ID_DANCE1, SPORT_API_ID_DANCE2, + SPORT_API_ID_SWITCHJOYSTICK, SPORT_API_ID_POSE, SPORT_API_ID_SCRAPE, + SPORT_API_ID_FRONTFLIP, SPORT_API_ID_FRONTJUMP, SPORT_API_ID_FRONTPOUNCE, + SPORT_API_ID_WIGGLEHIPS, SPORT_API_ID_GETSTATE, SPORT_API_ID_ECONOMICGAIT, + SPORT_API_ID_HEART, SPORT_API_ID_STATICWALK, SPORT_API_ID_TROTRUN + ] + for api in legacy_ids: + self._RegistApi(api, 0) + + # flips still exposed as “robot” IDs self._RegistApi(ROBOT_SPORT_API_ID_LEFTFLIP, 0) self._RegistApi(ROBOT_SPORT_API_ID_BACKFLIP, 0) - self._RegistApi(ROBOT_SPORT_API_ID_FREEWALK, 0) - self._RegistApi(ROBOT_SPORT_API_ID_FREEBOUND, 0) - self._RegistApi(ROBOT_SPORT_API_ID_FREEJUMP, 0) - self._RegistApi(ROBOT_SPORT_API_ID_FREEAVOID, 0) - self._RegistApi(ROBOT_SPORT_API_ID_WALKSTAIR, 0) - self._RegistApi(ROBOT_SPORT_API_ID_WALKUPRIGHT, 0) - self._RegistApi(ROBOT_SPORT_API_ID_CROSSSTEP, 0) - - # 1001 - def Damp(self): - p = {} - parameter = json.dumps(p) - code, data = self._Call(SPORT_API_ID_DAMP, parameter) - return code - - # 1002 - def BalanceStand(self): - p = {} - parameter = json.dumps(p) - code, data = self._Call(SPORT_API_ID_BALANCESTAND, parameter) - return code - - # 1003 - def StopMove(self): - p = {} - parameter = json.dumps(p) - code, data = self._Call(SPORT_API_ID_STOPMOVE, parameter) - return code - - # 1004 - def StandUp(self): - p = {} - parameter = json.dumps(p) - code, data = self._Call(SPORT_API_ID_STANDUP, parameter) - return code - - # 1005 - def StandDown(self): - p = {} - parameter = json.dumps(p) - code, data = self._Call(SPORT_API_ID_STANDDOWN, parameter) - return code - - # 1006 - def RecoveryStand(self): - p = {} - parameter = json.dumps(p) - code, data = self._Call(SPORT_API_ID_RECOVERYSTAND, parameter) - return code - - # 1007 - def Euler(self, roll: float, pitch: float, yaw: float): - p = {} - p["x"] = roll - p["y"] = pitch - p["z"] = yaw - parameter = json.dumps(p) - code, data = self._Call(SPORT_API_ID_EULER, parameter) - return code - - # 1008 - def Move(self, vx: float, vy: float, vyaw: float): - p = {} - p["x"] = vx - p["y"] = vy - p["z"] = vyaw - parameter = json.dumps(p) - code = self._CallNoReply(SPORT_API_ID_MOVE, parameter) - return code - - # 1009 - def Sit(self): - p = {} - parameter = json.dumps(p) - code, data = self._Call(SPORT_API_ID_SIT, parameter) - return code - - #1010 - def RiseSit(self): - p = {} - parameter = json.dumps(p) - code, data = self._Call(SPORT_API_ID_RISESIT, parameter) - return code - - # 1011 - def SwitchGait(self, t: int): - p = {} - p["data"] = t - parameter = json.dumps(p) - code, data = self._Call(SPORT_API_ID_SWITCHGAIT, parameter) - return code - - # 1012 - def Trigger(self): - p = {} - parameter = json.dumps(p) - code, data = self._Call(SPORT_API_ID_TRIGGER, parameter) - return code - - # 1013 - def BodyHeight(self, height: float): - p = {} - p["data"] = height - parameter = json.dumps(p) - code, data = self._Call(SPORT_API_ID_BODYHEIGHT, parameter) - return code - - # 1014 - def FootRaiseHeight(self, height: float): - p = {} - p["data"] = height - parameter = json.dumps(p) - code, data = self._Call(SPORT_API_ID_FOOTRAISEHEIGHT, parameter) - return code - - # 1015 - def SpeedLevel(self, level: int): - p = {} - p["data"] = level - parameter = json.dumps(p) - code, data = self._Call(SPORT_API_ID_SPEEDLEVEL, parameter) - return code - - # 1016 - def Hello(self): - p = {} - parameter = json.dumps(p) - code, data = self._Call(SPORT_API_ID_HELLO, parameter) - return code - - # 1017 - def Stretch(self): - p = {} - parameter = json.dumps(p) - code, data = self._Call(SPORT_API_ID_STRETCH, parameter) - return code - - # 1018 - def TrajectoryFollow(self, path: list): - l = len(path) - if l != SPORT_PATH_POINT_SIZE: - return SPORT_ERR_CLIENT_POINT_PATH - - path_p = [] - for i in range(l): - point = path[i] - p = {} - p["t_from_start"] = point.timeFromStart - p["x"] = point.x - p["y"] = point.y - p["yaw"] = point.yaw - p["vx"] = point.vx - p["vy"] = point.vy - p["vyaw"] = point.vyaw - path_p.append(p) - - parameter = json.dumps(path_p) - code = self._CallNoReply(SPORT_API_ID_TRAJECTORYFOLLOW, parameter) - return code - - # 1019 - def ContinuousGait(self, flag: int): - p = {} - p["data"] = flag - parameter = json.dumps(p) - code, data = self._Call(SPORT_API_ID_CONTINUOUSGAIT, parameter) - return code - - # # 1020 - # def Content(self): - # p = {} - # parameter = json.dumps(p) - # code, data = self._Call(SPORT_API_ID_CONTENT, parameter) - # return code - - # 1021 - def Wallow(self): - p = {} - parameter = json.dumps(p) - code, data = self._Call(SPORT_API_ID_WALLOW, parameter) - return code - - # 1022 - def Dance1(self): - p = {} - parameter = json.dumps(p) - code, data = self._Call(SPORT_API_ID_DANCE1, parameter) - return code - - # 1023 - def Dance2(self): - p = {} - parameter = json.dumps(p) - code, data = self._Call(SPORT_API_ID_DANCE2, parameter) - return code - - # 1025 - def GetFootRaiseHeight(self): - p = {} - parameter = json.dumps(p) - - code, data = self._Call(SPORT_API_ID_GETFOOTRAISEHEIGHT, parameter) - - if code == 0: - d = json.loads(data) - return code, d["data"] - else: - return code, None - - - # 1026 - def GetSpeedLevel(self): - p = {} - parameter = json.dumps(p) - - code, data = self._Call(SPORT_API_ID_GETSPEEDLEVEL, parameter) - - if code == 0: - d = json.loads(data) - return code, d["data"] - else: - return code, None - - # 1027 - def SwitchJoystick(self, on: bool): - p = {} - p["data"] = on - parameter = json.dumps(p) - code, data = self._Call(SPORT_API_ID_SWITCHJOYSTICK, parameter) - return code - - # 1028 - def Pose(self, flag: bool): - p = {} - p["data"] = flag - parameter = json.dumps(p) - code, data = self._Call(SPORT_API_ID_POSE, parameter) - return code - - # 1029 - def Scrape(self): - p = {} - parameter = json.dumps(p) - code, data = self._Call(SPORT_API_ID_SCRAPE, parameter) - return code - - # 1030 - def FrontFlip(self): - p = {} - parameter = json.dumps(p) - code, data = self._Call(SPORT_API_ID_FRONTFLIP, parameter) - return code - - # 1031 - def FrontJump(self): - p = {} - parameter = json.dumps(p) - code, data = self._Call(SPORT_API_ID_FRONTJUMP, parameter) - return code - - # 1032 - def FrontPounce(self): - p = {} - parameter = json.dumps(p) - code, data = self._Call(SPORT_API_ID_FRONTPOUNCE, parameter) - return code - - # 1033 - def WiggleHips(self): - p = {} - parameter = json.dumps(p) - code, data = self._Call(SPORT_API_ID_WIGGLEHIPS, parameter) - return code - - # 1034 - def GetState(self, keys: list): - parameter = json.dumps(keys) - code, data = self._Call(SPORT_API_ID_GETSTATE, parameter) - if code == 0: - return code, json.loads(data) - else: - return code, None - - # 1035 - def EconomicGait(self, flag: bool): - p = {} - p["data"] = flag - parameter = json.dumps(p) - code, data = self._Call(SPORT_API_ID_ECONOMICGAIT, parameter) - return code - - # 1036 - def Heart(self): - p = {} - parameter = json.dumps(p) - code, data = self._Call(SPORT_API_ID_HEART, parameter) - return code - - # 1042 - def LeftFlip(self): - p = {} - p["data"] = True - parameter = json.dumps(p) - code, data = self._Call(ROBOT_SPORT_API_ID_LEFTFLIP, parameter) - return code - - # 1044 - def BackFlip(self): - p = {} - p["data"] = True - parameter = json.dumps(p) - code, data = self._Call(ROBOT_SPORT_API_ID_BACKFLIP, parameter) - return code - - # 1045 - def FreeWalk(self, flag: bool): - p = {} - p["data"] = True - parameter = json.dumps(p) - code, data = self._Call(ROBOT_SPORT_API_ID_FREEWALK, parameter) - return code - - # 1046 - def FreeBound(self, flag: bool): - p = {} - p["data"] = flag - parameter = json.dumps(p) - code, data = self._Call(ROBOT_SPORT_API_ID_FREEBOUND, parameter) - return code - - # 1047 - def FreeJump(self, flag: bool): - p = {} - p["data"] = flag - parameter = json.dumps(p) - code, data = self._Call(ROBOT_SPORT_API_ID_FREEJUMP, parameter) - return code - - # 1048 - def FreeAvoid(self, flag: bool): - p = {} - p["data"] = flag - parameter = json.dumps(p) - code, data = self._Call(ROBOT_SPORT_API_ID_FREEAVOID, parameter) - return code - - # 1049 - def WalkStair(self, flag: bool): - p = {} - p["data"] = flag - parameter = json.dumps(p) - code, data = self._Call(ROBOT_SPORT_API_ID_WALKSTAIR, parameter) - return code - - # 1050 - def WalkUpright(self, flag: bool): - p = {} - p["data"] = flag - parameter = json.dumps(p) - code, data = self._Call(ROBOT_SPORT_API_ID_WALKUPRIGHT, parameter) - return code - # 1051 - def CrossStep(self, flag: bool): - p = {} - p["data"] = flag - parameter = json.dumps(p) - code, data = self._Call(ROBOT_SPORT_API_ID_CROSSSTEP, parameter) - return code \ No newline at end of file + # 2) AI / motion-switcher IDs (V2.0) + switcher_ids = [ + ROBOT_SPORT_API_ID_HANDSTAND, ROBOT_SPORT_API_ID_FREEWALK, + ROBOT_SPORT_API_ID_FREEBOUND, ROBOT_SPORT_API_ID_FREEJUMP, + ROBOT_SPORT_API_ID_FREEAVOID, ROBOT_SPORT_API_ID_CLASSICWALK, + ROBOT_SPORT_API_ID_WALKUPRIGHT, ROBOT_SPORT_API_ID_CROSSSTEP, + ROBOT_SPORT_API_ID_AUTORECOVERY_SET, ROBOT_SPORT_API_ID_AUTORECOVERY_GET, + ROBOT_SPORT_API_ID_SWITCHAVOIDMODE + ] + for api in switcher_ids: + self._RegistApi(api, 0) + + # --------------------------------------------------------------------- # + # Legacy high-level wrappers # + # --------------------------------------------------------------------- # + def Damp(self): return self._Call(SPORT_API_ID_DAMP, "{}")[0] + def BalanceStand(self): return self._Call(SPORT_API_ID_BALANCESTAND, "{}")[0] + def StopMove(self): return self._Call(SPORT_API_ID_STOPMOVE, "{}")[0] + def StandUp(self): return self._Call(SPORT_API_ID_STANDUP, "{}")[0] + def StandDown(self): return self._Call(SPORT_API_ID_STANDDOWN, "{}")[0] + def RecoveryStand(self): return self._Call(SPORT_API_ID_RECOVERYSTAND, "{}")[0] + + def Euler(self, roll, pitch, yaw): + return self._Call(SPORT_API_ID_EULER, + json.dumps({"x": roll, "y": pitch, "z": yaw}))[0] + + def Move(self, vx, vy, vyaw): + return self._CallNoReply(SPORT_API_ID_MOVE, + json.dumps({"x": vx, "y": vy, "z": vyaw})) + + def Sit(self): return self._Call(SPORT_API_ID_SIT, "{}")[0] + def RiseSit(self): return self._Call(SPORT_API_ID_RISESIT, "{}")[0] + def SwitchGait(self, t): return self._Call(SPORT_API_ID_SWITCHGAIT, + json.dumps({"data": t}))[0] + + def BodyHeight(self, h): return self._Call(SPORT_API_ID_BODYHEIGHT, + json.dumps({"data": h}))[0] + def FootRaiseHeight(self, h): return self._Call(SPORT_API_ID_FOOTRAISEHEIGHT, + json.dumps({"data": h}))[0] + def SpeedLevel(self, lvl): return self._Call(SPORT_API_ID_SPEEDLEVEL, + json.dumps({"data": lvl}))[0] + def Hello(self): return self._Call(SPORT_API_ID_HELLO, "{}")[0] + def Stretch(self): return self._Call(SPORT_API_ID_STRETCH, "{}")[0] + + def ContinuousGait(self, flag): + return self._Call(SPORT_API_ID_CONTINUOUSGAIT, + json.dumps({"data": flag}))[0] + + def EconomicGait(self, flag): + return self._Call(SPORT_API_ID_ECONOMICGAIT, + json.dumps({"data": flag}))[0] + + # flips + def LeftFlip(self): return self._Call(ROBOT_SPORT_API_ID_LEFTFLIP, + json.dumps({"data": True}))[0] + def BackFlip(self): return self._Call(ROBOT_SPORT_API_ID_BACKFLIP, + json.dumps({"data": True}))[0] + + # moved gaits + def StaticWalk(self): return self._Call(ROBOT_SPORT_API_ID_STATICWALK, "{}")[0] + def TrotRun(self): return self._Call(ROBOT_SPORT_API_ID_TROTRUN, "{}")[0] + + # --------------------------------------------------------------------- # + # Motion-switcher wrappers # + # --------------------------------------------------------------------- # + def FreeWalk(self, f): return self._Call(ROBOT_SPORT_API_ID_FREEWALK, + json.dumps({"data": f}))[0] + def FreeBound(self, f): return self._Call(ROBOT_SPORT_API_ID_FREEBOUND, + json.dumps({"data": f}))[0] + def FreeJump(self, f): return self._Call(ROBOT_SPORT_API_ID_FREEJUMP, + json.dumps({"data": f}))[0] + def FreeAvoid(self, f): return self._Call(ROBOT_SPORT_API_ID_FREEAVOID, + json.dumps({"data": f}))[0] + + def HandStand(self, f): return self._Call(ROBOT_SPORT_API_ID_HANDSTAND, + json.dumps({"data": f}))[0] + def WalkUpright(self, f):return self._Call(ROBOT_SPORT_API_ID_WALKUPRIGHT, + json.dumps({"data": f}))[0] + def CrossStep(self, f): return self._Call(ROBOT_SPORT_API_ID_CROSSSTEP, + json.dumps({"data": f}))[0] + def ClassicWalk(self, f):return self._Call(ROBOT_SPORT_API_ID_CLASSICWALK, + json.dumps({"data": f}))[0] + + def AutoRecoverSet(self, f): + return self._Call(ROBOT_SPORT_API_ID_AUTORECOVERY_SET, + json.dumps({"data": f}))[0] + + def AutoRecoverGet(self): + code, data = self._Call(ROBOT_SPORT_API_ID_AUTORECOVERY_GET, "{}") + return code, json.loads(data)["data"] if code == 0 else (code, None) + + def SwitchAvoidMode(self): + return self._Call(ROBOT_SPORT_API_ID_SWITCHAVOIDMODE, "{}")[0]