Healthy Gait

About

This tutorial shows how to optimize gait controllers, based on the model by [Geyer & Herr 2010].
  • Open the scenario Tutorials/Tutorial 4a - Gait

As you can see, the scone file is fairly short and doesn't contain a Controller or a Measure. However, there is a section in the middle that says:

# Controller for gait, based on [Geyer & Herr 2010]
<< data/ControllerGH2010.scone >>
		
# Measure for gait
<< data/MeasureGait10.scone >>

What this means is, we have moved the controller and measure code to different files, in order to keep things tidy. Before we look into any details, start the optimization (this will take a while).

  • Click Scenario → Optimize Scenario or press Ctrl + F5

Controller [Geyer & Herr 2010]

The actual Controller is inside the file Tutorials/data/ControllerGH2010.scone, which implements the controller defined by [Geyer & Herr 2010]:

# Gait controller adapted from [Geyer & Herr 2010] by Thomas Geijtenbeek 
GaitStateController {
	signature_postfix = "GH2010v8"
	stance_load_threshold = ~0.1<0.001,1>
	leg_load_sensor_delay = 0
	symmetric = 1
	ConditionalControllers {
		# TA stretch reflexes [Geyer & Herr 2010]
		ConditionalController {
			states = "EarlyStance LateStance Liftoff Swing Landing"
			ReflexController {
				MuscleReflex {
					target = tib_ant
					delay = 0.020
					KL = ~1.1<-10,10>
					L0 = ~0.71<0,2>
				}
				MuscleReflex {
					target = tib_ant
					source = soleus
					delay = 0.020
					KF = ~-0.3<-10,10>
				}
			}
		}
 
		# GAS and SOL F+ reflexes [Geyer & Herr 2010]
		ConditionalController {
			states = "EarlyStance LateStance Liftoff"
			ReflexController {
				MuscleReflex {
					target = soleus
					delay = 0.020
					KF = ~1.2<-10,10>
				}
				MuscleReflex {
					target = gastroc
					delay = 0.020
					KF = ~1.1<-10,10>
				}
			}
		}
 
		# Stance reflexes
		ConditionalController {
			states = "EarlyStance LateStance"
			ReflexController {
				Reflexes {
					# F+ VAS
					ConditionalMuscleReflex {
						target = vasti
						delay = 0.010
						KF = ~1.15<-10,10> # G_VAS
						C0 = ~0.09<-1,1> # S_0,VAS
						dof = knee_angle
						pos_max = ~-0.175<-1,0>
					}
					# Root stability
					DofReflex {
						target = hamstrings
						source = pelvis_tilt
						delay = 0.005
						KP = ~1.91<-10,10> # k_p
						KV = ~0.25<-10,10> # k_d
						P0 = -0.105 # theta_ref, not optimized because of C0
						C0 = ~0.05<-1,1> # S_0,BAL
					}
					DofReflex {
						target = glut_max
						source = pelvis_tilt
						delay = 0.005
						KP = ~1.91<-10,10> # k_p
						KV = ~0.25<-10,10> # k_d
						P0 = -0.105 # theta_ref, not optimized because of C0
						C0 = ~0.05<-1,1> # S_0,BAL
					}
					DofReflex {
						target = iliopsoas
						source = pelvis_tilt
						delay = 0.005
						KP = ~-1.91<-10,10> # -k_p
						KV = ~-0.25<-10,10> # -k_d
						P0 = -0.105 # theta_ref, not optimized because of C0
						C0 = ~0.05<-1,1> # S_0,BAL
					}
				}
			}
		}
 
		# Double support reflexes
		ConditionalController {
			states = "Liftoff"
			ReflexController {
				MuscleReflex {
					target = iliopsoas
					delay = 0.005
					C0 = ~0.25<-1,1> # DELTA_S
				}
				MuscleReflex {
					target = glut_max
					delay = 0.005
					C0 = ~-0.25<-1,1> # DELTA_S
				}
			}
		}
 
		# Swing reflexes
		ConditionalController {
			states = "Swing Landing"
			ReflexController {
				# HFL excitation [Geyer & Herr 2010]
				MuscleReflex {
					target = iliopsoas
					delay = 0.005
					KL = ~0.35<-10,10> # G_HFL
					L0 = ~0.6<0,2> # l_off_HFL
				}
				DofReflex {
					target = iliopsoas
					source = pelvis_tilt
					delay = 0.005
					KP = ~1.15<-10,10> # k_lean
					KV = ~0.25<-10,10> # not in [GH2010]
					P0 = ~-0.105<-1,1> # theta_ref
				}
				# late-swing HFL inhibition [Geyer & Herr 2010]
				MuscleReflex {
					target = iliopsoas
					source = hamstrings
					delay = 0.005
					KL = ~-4.0<-10,10>
					L0 = ~0.85<0,2>
				}
				# late-swing HAM and GLU reflexes [Geyer & Herr 2010]
				MuscleReflex {
					target = hamstrings
					delay = 0.005
					KF = ~0.65<-10,10>
				}
				MuscleReflex {
					target = glut_max
					delay = 0.005
					KF = ~0.4<-10,10>
				}
			}
		}
	}
}

Gait at Different Speeds

  • Open the file Tutorials/Tutorial 4b - Gait at Different Speeds.scone

To optimize gait for different target speeds, we can simply change the optimization criterion. In this case, we define the optimization criterion in the file Tutorials/data/MeasureGait15.scone:

# Measure for gait, minimum speed = 1.5 m/s
CompositeMeasure {
	GaitMeasure {
		name = Gait
		weight = 100
		threshold = 0.05
		termination_height = 0.85
		min_velocity = 1.5
	}
	EffortMeasure {
		name = Effort
		weight = 0.1
		measure_type = Wang2012
		use_cost_of_transport = 1
	}
	CompositeMeasure {
		name = DofLimits
		symmetric = 1
		DofMeasure {
			weight = 0.1
			dof = ankle_angle
			position { min = -60 max = 60 squared_penalty = 1 }
		}
		DofMeasure {
			weight = 0.01
			threshold = 5
			dof = knee_angle
			force { min = 0 max = 0 abs_penalty = 1 }
		}
	}
}

The target speed is set by the min_velocity tag in the GaitMeasure section. In addition, and EffortMeasure is used to minimize cost of transport, and DofMeasure is used to prevent knee and ankle hyper-extension.

Perturbed Gait

  • Open the file Tutorials/Tutorial 4c - Perturbed Gait.scone

Here you will see that we use a CompositeController that consists of our Geyer and Herr controller, in combination with a couple of PerturbationController entries:

CompositeController {
	# Controller for gait, based on [Geyer & Herr 2010]
	<< data/ControllerGH2010.scone >>
 
	# Perturbation backwards every 4 seconds
	PerturbationController {
		start_time = 3
		duration = 0.2
		interval = 4
		force = [ -100 0 0 ]
		body = pelvis
		position_offset = [ -0.15 0.35 0 ]
	}
 
	# Perturbation forwards every other 4 seconds
	PerturbationController {
		start_time = 5
		duration = 0.2
		interval = 4
		force = [ 100 0 0 ]
		body = pelvis
		position_offset = [ -0.15 0.35 0 ]
	}
}

Note that inside SCONE, a PerturbationController is a controller just like anything else, even though it does not work on internal actuators. A SCONE Controller is simply any entity that can generate actuator inputs in the simulation.

  • Test the optimization by pressing Ctrl + T

You'll see that, once the first perturbation kicks in, the model falls over immediately. The control parameters of the model have not yet been optimized to be robust against external perturbations.

  • Start the optimization with Ctrl + F5

After a while, you'll find that the gait controller will become more robust against perturbations. Note that we have increased the simulation time 30 seconds: can you think of a reason why?

Walking on Ice

To simulate walking on ice, we need to adjust the friction defined in the contact force. For this tutorial, we have created a separate model in which we have done exactly that (see Tutorials/data/Human0914Ice.osim):

<HuntCrossleyForce name="foot_r">
	<!--Flag indicating whether the force is disabled or not. Disabled means that the force is not active in subsequent dynamics realizations.-->
	<isDisabled>false</isDisabled>
	<!--Material properties.-->
	<HuntCrossleyForce::ContactParametersSet name="contact_parameters">
		<objects>
			<HuntCrossleyForce::ContactParameters>
				<!--Names of geometry objects affected by these parameters.-->
				<geometry>platform r_heel r_toe</geometry>
				<stiffness>2e6</stiffness>
				<dissipation>1</dissipation>
				<static_friction>0.15</static_friction>
				<dynamic_friction>0.15</dynamic_friction>
				<viscous_friction>0.15</viscous_friction>
			</HuntCrossleyForce::ContactParameters>
		</objects>
		<groups />
	</HuntCrossleyForce::ContactParametersSet>
	<!--Slip velocity (creep) at which peak static friction occurs.-->
	<transition_velocity>0.1</transition_velocity>
</HuntCrossleyForce>

The tags to look for are called static_friction and dynamic_friction.

  • Open the file Tutorials/Tutorial 4d - Walking on Ice

In our SCONE scenario, we simply assign the new model file:

model_file = data/Human0914Ice.osim

We also change the objective function to allow for a lower minimum velocity:

<< data/MeasureGait05.scone >>
  • Optimize the scenario with the modified OpenSim model (Ctrl + F5)

Eventually, this will produce a controller that is robust against walking on ice. Be sure to check the intermediate results in the Optimization Results panel!

  • by tgeijten