from math import floor import numpy as np from MPC_Controller.FSM_states.ControlFSMData import ControlFSMData from MPC_Controller.FSM_states.FSM_State import FSM_State, FSM_StateName from MPC_Controller.Parameters import Parameters from MPC_Controller.utils import DTYPE StandUp = 0 FoldLegs = 1 RollOver = 2 class FSM_State_RecoveyrStand(FSM_State): def __init__(self, _controlFSMData: ControlFSMData): super().__init__(_controlFSMData, FSM_StateName.RECOVERY_STAND, "RECOVERY_STAND") # Set the pre controls safety checks self.checkSafeOrientation = False # Post control safety checks self.checkPDesFoot = False self.checkForceFeedForward = False self.iter = 0 self._state_iter = 0 self._motion_start_iter = 0 self._flag = FoldLegs self.zero_vec3 = np.zeros((3,1), dtype=DTYPE) # goal configuration # Folding # * test passed self.fold_ramp_iter = int(45 / (Parameters.controller_dt*100)) self.fold_settle_iter = int(75 / (Parameters.controller_dt*100)) self.fold_jpos = np.array([0.0, 1.4, -2.7, -0.0, 1.4, -2.7, 0.0, 1.4, -2.7, -0.0, 1.4, -2.7], dtype=DTYPE).reshape((4,3,1)) # Stand Up # * test passed self.standup_ramp_iter = int(30 / (Parameters.controller_dt*100)) self.standup_settle_iter = int(30 / (Parameters.controller_dt*100)) self.stand_jpos = np.array([0., 0.8, -1.6, 0., 0.8, -1.6, 0., 0.8, -1.6, 0., 0.8, -1.6], dtype=DTYPE).reshape((4,3,1)) # Rolling # * test passed self.rollover_ramp_iter = int(13 / (Parameters.controller_dt*100)) self.rollover_settle_iter = int(15 / (Parameters.controller_dt*100)) self.rolling_jpos = np.array([1.3, 3.1, -2.77, 0.0, 1.6, -2.77, 1.3, 3.1, -2.77, 0.0, 1.6, -2.77], dtype=DTYPE).reshape((4,3,1)) self.initial_jpos = np.zeros((4,3,1), dtype=DTYPE) def onEnter(self): # Default is to not transition self.nextStateName = self.stateName # Reset the transition data self.transitionDone = False # Reset iteration counter self.iter = 0 self._state_iter = 0 # initial configuration, position for leg in range(4): self.initial_jpos[leg] = self._data._legController.datas[leg].q body_height = self._data._stateEstimator.getResult().position[2] self._flag = FoldLegs if not self._UpsideDown(): if 0.2 floor(self.standup_ramp_iter*0.7) and something_wrong: # If body height is too low because of some reason # even after the stand up motion is almost over for leg in range(4): self.initial_jpos[leg] = self._data._legController.datas[leg].q self._flag = FoldLegs self._motion_start_iter = self._state_iter + 1 print("[Recovery Balance - Warning] body height is still too low (%f) or UpsideDown (%d); Folding legs" %(body_height, self._UpsideDown())) else: for leg in range(4): self._SetJPosInterPts(curr_iter, self.standup_ramp_iter, leg, self.initial_jpos[leg], self.stand_jpos[leg]) # setContactPhase = np.array([0.5,0.5,0.5,0.5], dtype=DTYPE).reshape((4,1)) # self._data._stateEstimator.setContactPhase(setContactPhase) def _FoldLegs(self, curr_iter:int): for leg in range(4): self._SetJPosInterPts(curr_iter, self.rollover_ramp_iter, leg, self.initial_jpos[leg], self.fold_jpos[leg]) if curr_iter >= self.fold_ramp_iter + self.fold_settle_iter: if self._UpsideDown(): self._flag = RollOver for leg in range(4): self.initial_jpos[leg] = self.fold_jpos[leg] else: self._flag = StandUp for leg in range(4): self.initial_jpos[leg] = self.fold_jpos[leg] self._motion_start_iter = self._state_iter + 1 def _RollOver(self, curr_iter:int): for leg in range(4): self._SetJPosInterPts(curr_iter, self.rollover_ramp_iter, leg, self.initial_jpos[leg], self.rolling_jpos[leg]) if curr_iter > self.rollover_ramp_iter + self.rollover_settle_iter: self._flag = FoldLegs for leg in range(4): self.initial_jpos[leg] = self.rolling_jpos[leg] self._motion_start_iter = self._state_iter + 1