-
Notifications
You must be signed in to change notification settings - Fork 57
/
Copy pathFSM_State_Locomotion.py
139 lines (112 loc) · 5.21 KB
/
FSM_State_Locomotion.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
from math import fabs
from numpy.linalg import norm
# from MPC_Controller.deprecated.ConvexMPCLocomotion_copy import ConvexMPCLocomotion
from MPC_Controller.Parameters import Parameters
from MPC_Controller.common.Quadruped import RobotType
from MPC_Controller.FSM_states.ControlFSMData import ControlFSMData
from MPC_Controller.FSM_states.FSM_State import FSM_State, FSM_StateName
from MPC_Controller.convex_MPC.ConvexMPCLocomotion import ConvexMPCLocomotion
from MPC_Controller.math_utils.orientation_tools import deg2rad, rad2deg
class FSM_State_Locomotion(FSM_State):
"""
* FSM State for robot locomotion. Manages the contact specific logic
* and handles calling the interfaces to the controllers. This state
* should be independent of controller, gait, and desired trajectory.
"""
def __init__(self, _controlFSMData:ControlFSMData):
super().__init__(_controlFSMData, FSM_StateName.LOCOMOTION, "LOCOMOTION")
self.cMPC = ConvexMPCLocomotion(Parameters.controller_dt,
27/(1000.0*Parameters.controller_dt))
self.turnOnAllSafetyChecks()
# Turn off Foot pos command since it is set in WBC as operational task
# self.checkPDesFoot = False
# Initialize GRF and footstep locations to 0s
# self.footFeedForwardForces = np.zeros((3,4), dtype=DTYPE)
# self.footstepLocations = np.zeros((3,4), dtype=DTYPE)
self.iter = 0
def onEnter(self):
# Default is to not transition
self.nextStateName = self.stateName
# Reset the transition data
self.transitionDone = False
self.cMPC.initialize(self._data)
self._data._desiredStateCommand.reset()
self._data._stateEstimator.reset()
if Parameters.FSM_print_info:
print("[FSM LOCOMOTION] On Enter")
def run(self):
"""
* Calls the functions to be executed on each control loop iteration.
"""
# # Call the locomotion control logic for this iteration
self.LocomotionControlStep()
def onExit(self):
self.iter = 0
def checkTransition(self):
"""
* Manages which states can be transitioned into either by the user
* commands or state event triggers.
*
* @return the enumerated FSM state name to transition into
"""
self.iter += 1
if self.locomotionSafe():
if Parameters.control_mode is FSM_StateName.LOCOMOTION:
pass
elif Parameters.control_mode is FSM_StateName.PASSIVE:
# Requested change to PASSIVE
self.nextStateName = FSM_StateName.PASSIVE
elif Parameters.control_mode is FSM_StateName.RECOVERY_STAND:
self.nextStateName = FSM_StateName.RECOVERY_STAND
else:
print("[CONTROL FSM] Bad Request: Cannot transition from "
+ self.stateName.name
+ " to "
+ Parameters.control_mode.name)
else:
self.nextStateName = FSM_StateName.RECOVERY_STAND
# TODO change to an individual indicator may be better
Parameters.locomotionUnsafe = True
return self.nextStateName
def transition(self):
"""
* Handles the actual transition for the robot between states.
* Returns true when the transition is completed.
*
* @return true if transition is complete
"""
if self.nextStateName is FSM_StateName.PASSIVE:
self.turnOffAllSafetyChecks()
self.transitionDone = True
elif self.nextStateName is FSM_StateName.RECOVERY_STAND:
self.transitionDone = True
else:
print("[CONTROL FSM] Something went wrong in transition")
return self.transitionDone
def locomotionSafe(self):
if not Parameters.FSM_check_safety:
return True
seResult = self._data._stateEstimator.getResult()
max_roll = 40
max_pitch = 40
if fabs(seResult.rpy[0]>deg2rad(max_roll)):
print("[FSM LOCOMOTION] Unsafe locomotion: roll is %.3f degrees (max %.3f)"%(rad2deg(seResult.rpy[0]), max_roll))
return False
if fabs(seResult.rpy[1]) > deg2rad(max_pitch):
print("[FSM LOCOMOTION] Unsafe locomotion: pitch is %.3f degrees (max %.3f)\n"% (rad2deg(seResult.rpy[1]), max_pitch))
return False
for leg in range(4):
p_leg = self._data._legController.datas[leg].p
if p_leg[2]>0:
print("[FSM LOCOMOTION] Unsafe locomotion: leg %d is above hip (%.3f m)"%(leg, p_leg[2]))
return False
if fabs(p_leg[1]>0.18):
print("[FSM LOCOMOTION] Unsafe locomotion: leg %d's y-position is bad (%.3f m)"%(leg, p_leg[1]))
return False
# v_leg = norm(self._data._legController.datas[leg].v)
# if fabs(v_leg) > 11.0:
# print("[FSM LOCOMOTION] Unsafe locomotion: leg %d is moving too quickly (%.3f m/s)"%(leg, v_leg))
# return False
return True
def LocomotionControlStep(self):
self.cMPC.run(self._data)