@@ -258,15 +258,33 @@ def update_control(ctrl_mat: PreviewControllerMatrices, current_zmp, zmp_ref, x,
258258
259259
260260class WalkingState (Enum ):
261- INIT = 0
262- DS = 1
263- SS_LEFT = 2
264- SS_RIGHT = 3
265- END = 4
261+ """Enumeration of the high-level walking phases."""
262+
263+ INIT = 0 # Initialization (pre-walk)
264+ DS = 1 # Double support phase
265+ SS_LEFT = 2 # Single support, left foot stance
266+ SS_RIGHT = 3 # Single support, right foot stance
267+ END = 4 # End of walking sequence
266268
267269
268270@dataclass
269271class WalkingStateMachineParams :
272+ """Timing and contact parameters for the walking state machine.
273+
274+ Attributes
275+ ----------
276+ t_init : float
277+ Duration of the initial phase before starting walking [s].
278+ t_end : float
279+ Duration of the final phase after the last step [s].
280+ t_ss : float
281+ Nominal duration of a single support phase [s].
282+ t_ds : float
283+ Nominal duration of a double support phase [s].
284+ force_threshold : float
285+ Contact force threshold used to detect foot contact [N].
286+ """
287+
270288 t_init : float = 2.0 # [s]
271289 t_end : float = 2.0 # [s]
272290 t_ss : float = 0.8 # [s]
@@ -275,7 +293,26 @@ class WalkingStateMachineParams:
275293
276294
277295class WalkingStateMachine :
278- def __init__ (self , params : WalkingStateMachineParams , initial_state = WalkingState .INIT ):
296+ """Finite state machine controlling walking phases.
297+
298+ The state machine advances through INIT, DS, SS_LEFT, SS_RIGHT, and END
299+ based on elapsed time and measured foot contact forces.
300+ """
301+
302+ def __init__ (
303+ self ,
304+ params : WalkingStateMachineParams ,
305+ initial_state : WalkingState = WalkingState .INIT ,
306+ ):
307+ """Initialize the walking state machine.
308+
309+ Parameters
310+ ----------
311+ params : WalkingStateMachineParams
312+ Timing and contact parameters for the state machine.
313+ initial_state : WalkingState, optional
314+ Initial state of the machine, by default WalkingState.INIT.
315+ """
279316 self .params = params
280317 self .state = initial_state
281318 self .next_ss_state = WalkingState .SS_RIGHT
@@ -284,6 +321,14 @@ def __init__(self, params: WalkingStateMachineParams, initial_state=WalkingState
284321 self .step_idx = None
285322
286323 def update_steps (self , steps_pose ):
324+ """Set the planned sequence of steps.
325+
326+ Parameters
327+ ----------
328+ steps_pose :
329+ Container describing the planned footsteps (e.g. list/array of poses).
330+ Only its length is used here to know when the last step is reached.
331+ """
287332 self .steps = steps_pose
288333 self .step_idx = 0
289334
@@ -293,6 +338,22 @@ def update(
293338 rf_contact_force : float ,
294339 lf_contact_force : float ,
295340 ):
341+ """Update the state machine given time and contact forces.
342+
343+ Parameters
344+ ----------
345+ t : float
346+ Current time [s].
347+ rf_contact_force : float
348+ Measured contact force under the right foot [N].
349+ lf_contact_force : float
350+ Measured contact force under the left foot [N].
351+
352+ Notes
353+ -----
354+ This method updates the internal state of the machine in-place.
355+ If no steps have been provided with `update_steps`, it returns immediately.
356+ """
296357 if self .steps is None :
297358 return
298359
@@ -315,23 +376,72 @@ def update(
315376 self .steps = None
316377
317378 def get_current_state (self ) -> WalkingState :
379+ """Return the current walking state.
380+
381+ Returns
382+ -------
383+ WalkingState
384+ Current state of the finite state machine.
385+ """
318386 return self .state
319387
320388 def _switch_single_support_leg (self , t : float ):
389+ """Switch to the next single-support state and reset the phase timer.
390+
391+ Parameters
392+ ----------
393+ t : float
394+ Current time [s], used as the new phase start time.
395+ """
321396 self .t_start = t
322397 self .state = self .next_ss_state
323398 self .next_ss_state = (
324399 WalkingState .SS_LEFT if self .state == WalkingState .SS_RIGHT else WalkingState .SS_RIGHT
325400 )
326401
327402 def _try_transition_to_single_support (self , t : float , duration : float ):
403+ """Transition from INIT/DS to the next single-support state if duration elapsed.
404+
405+ Parameters
406+ ----------
407+ t : float
408+ Current time [s].
409+ duration : float
410+ Required time spent in the current phase before switching [s].
411+ """
328412 if t - self .t_start > duration :
329413 self ._switch_single_support_leg (t )
330414
331415 def _is_last_step (self ) -> bool :
416+ """Check whether the current step is the last one.
417+
418+ Returns
419+ -------
420+ bool
421+ True if the current step index corresponds to the last planned step,
422+ False otherwise.
423+ """
332424 return self .step_idx == len (self .steps ) - 2
333425
334426 def _try_transition_to_ds_or_end (self , t : float , contact_force : float ):
427+ """Transition from single support to double support or END.
428+
429+ Parameters
430+ ----------
431+ t : float
432+ Current time [s].
433+ contact_force : float
434+ Measured contact force of the swing foot [N].
435+
436+ Notes
437+ -----
438+ The transition is triggered when:
439+ - at least half of `t_ss` has elapsed since `t_start`, and
440+ - the swing foot contact force exceeds `force_threshold`.
441+
442+ If the current step is the last one, the next state is END.
443+ Otherwise the state transitions to DS and the step index is incremented.
444+ """
335445 if (
336446 t - self .t_start > 0.5 * self .params .t_ss
337447 and contact_force > self .params .force_threshold
0 commit comments