tutorials:standing_balance

Standing Balance

About

This tutorial demonstrates how to use a ReflexController to perform a standing balance test.
  • Open the scenario Tutorials/Tutorial 3a - Balance.scone

You may notice that the file is pretty short, but that it does contain the following lines:

# Controller for reflex based balance (different file)
<< data/ControllerReflexBalance.scone >>
 
# Measure for standing balance (different file)
<< data/MeasureBalance.scone >>

What happens here is that both the controller and the measure are defined in another file. This is great for reusing algorithms, and also makes the main file a little cleaner.

  • Evaluate the scenario by pressing Ctrl + E

You'll that with the initial parameter settings, the human model falls pretty quickly.

  • Optimize the scenario by pressing Ctrl + F5

While SCONE is optimizing the scenario in the background, we can have a close look at what's going on.

  • Open the file Tutorials/data/ControllerReflexBalance.scone

In this file, you will find a controller of type ReflexController:

# Some predefined variables we use later on
$L0 = ~0.5
$KL = ~1
$KP = 0~0.1
$KV = 0~0.1
$VDELAY = 0.1
$OFS = [ 0 0.5 0 ]
$DIR = [ 1 0 0 ]
 
ReflexController {
	name = Balance
	symmetric = 1
 
	# Muscle length reflexes
	MuscleReflex { target = iliopsoas L0 = $L0 KL = $KL delay = 0.010 }
	MuscleReflex { target = glut_max L0 = $L0 KL = $KL delay = 0.010 }
	MuscleReflex { target = rect_fem L0 = $L0 KL = $KL delay = 0.010 }
	MuscleReflex { target = hamstrings L0 = $L0 KL = $KL delay = 0.010 }
	MuscleReflex { target = vasti L0 = $L0 KL = $KL delay = 0.020 }
	MuscleReflex { target = gastroc L0 = $L0 KL = $KL delay = 0.020 }
	MuscleReflex { target = soleus L0 = $L0 KL = $KL delay = 0.035 }
	MuscleReflex { target = tib_ant L0 = $L0 KL = $KL delay = 0.035 }
 
	# Vestibular reflexes
	BodyPointReflex { target = iliopsoas source = torso
		KP = $KP KV = $KV delay = $VDELAY offset = $OFS direction = $DIR }
	BodyPointReflex { target = rect_fem source = torso
		KP = $KP KV = $KV delay = $VDELAY offset = $OFS direction = $DIR }
	BodyPointReflex { target = vasti source = torso 
		KP = $KP KV = $KV delay = $VDELAY offset = $OFS direction = $DIR }
	BodyPointReflex { target = tib_ant source = torso 
		KP = $KP KV = $KV delay = $VDELAY offset = $OFS direction = $DIR }
	BodyPointReflex { target = glut_max source = torso 
		KP = $KP KV = $KV delay = $VDELAY offset = $OFS direction = $DIR }
	BodyPointReflex { target = hamstrings source = torso 
		KP = $KP KV = $KV delay = $VDELAY offset = $OFS direction = $DIR }
	BodyPointReflex { target = gastroc source = torso 
		KP = $KP KV = $KV delay = $VDELAY offset = $OFS direction = $DIR }
	BodyPointReflex { target = soleus source = torso 
		KP = $KP KV = $KV delay = $VDELAY offset = $OFS direction = $DIR }
}

Controllers of type ReflexController contain one or more Reflex entries, each of which defines a reflex arc, with a specific gains, offsets and delay. In our example, we use MuscleReflex to simulate proprioceptive reflexes, and BodyPointReflex to simulate vestibular reflexes.

In the Parameters window, you can see all the optimization parameters defined by this controller. These include the muscle length reflex gains and offsets defined in MuscleReflex (ending with .KL and .L0), as well as the parameters from the BodyPointReflex (ending with .KP and .KD).

Finally, we define the objective function in the file Tutorials/data/MeasureBalance.scone.

  • Open the file Tutorials/data/MeasureBalance.scone

You will find a CompositeMeasure that contains terms for not falling, minimizing effort and penalizing locked knees:

# Measure for standing balance
CompositeMeasure {
	# Penalize falling
	BalanceMeasure {
		termination_height = 0.8
		weight = 100
	}
 
	# Minimize effort
	EffortMeasure {
		name = Effort
		weight = 0.01
		measure_type = Wang2012
	}
 
	# Penalize locked knees
	DofMeasure {
		dof = knee_angle_r
		position { min = -30 max = 0 abs_penalty = 10 }
	}
}

Our measure combines a BalanceMeasure to detect falling and an EffortMeasure to minimize energy. In addition, we use DofMeasure to penalize upper body sway and locked knees.

After a while, you'll notice that the optimization results get better. In this case, we are penalizing falling, which means a lower value indicates a better result.

  • Check the results by clicking on the most recent item in Optimization Results

After playing back the results, it's possible to analyze the contribution of each of the feedback paths using the analysis tool. They can be best found by typing a capital RL in the filter box:

When optimizing balance, you might notice that the results aren't entirely realistic. One way to improve this is to add motor noise:

  • Open the file Tutorial 3b - Motor Noise Balance.scone

You will find that the controller has been adjusted to add include motor noise, using a motor_noise controller.

# CompositeController with multiple sub-controllers
CompositeController {
	# Controller for reflex based balance (different file)
	<< data/ControllerReflexBalance.scone >>
 
	# Motor noise controller
	NoiseController {
		base_noise = 0.01
		proportional_noise = 0.1
	}
}
  • Optimize the scenario by pressing Ctrl + F5

Now, compare the results to the previous optimization. You'll find quite a difference in both the muscle excitation patterns, as well as in the resulting balance strategy!