Differences
This shows you the differences between two versions of the page.
Previous revision | |||
— | tutorials:standing_balance [2022/09/28 10:52] (current) – thomas | ||
---|---|---|---|
Line 1: | Line 1: | ||
+ | ====== Standing Balance ====== | ||
+ | <callout type=" | ||
+ | ==== Balance Control ==== | ||
+ | * Open the scenario '' | ||
+ | |||
+ | You may notice that the file is pretty short, but that it does contain the following lines: | ||
+ | <code python> | ||
+ | # Controller for reflex based balance (different file) | ||
+ | << data/ | ||
+ | |||
+ | # Measure for standing balance (different file) | ||
+ | << data/ | ||
+ | </ | ||
+ | |||
+ | 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 '' | ||
+ | |||
+ | You'll that with the initial parameter settings, the human model falls pretty quickly. | ||
+ | |||
+ | * Optimize the scenario by pressing '' | ||
+ | |||
+ | While SCONE is optimizing the scenario in the background, we can have a close look at what's going on. | ||
+ | |||
+ | ==== Reflex Balance Controller ==== | ||
+ | * Open the file '' | ||
+ | |||
+ | In this file, you will find a controller of type [[ref: | ||
+ | <code python> | ||
+ | # 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 [[ref: | ||
+ | |||
+ | In the // | ||
+ | |||
+ | ==== Balance Objective ==== | ||
+ | Finally, we define the objective function in the file '' | ||
+ | |||
+ | * Open the file '' | ||
+ | |||
+ | You will find a [[ref: | ||
+ | <code python> | ||
+ | # 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 [[ref: | ||
+ | |||
+ | ==== Analyzing the Results ==== | ||
+ | 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 '' | ||
+ | |||
+ | 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 '' | ||
+ | |||
+ | {{ :: | ||
+ | |||
+ | ==== Adding Motor Noise ==== | ||
+ | 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 '' | ||
+ | |||
+ | You will find that the controller has been adjusted to add include motor noise, using a [[ref: | ||
+ | <code python> | ||
+ | # CompositeController with multiple sub-controllers | ||
+ | CompositeController { | ||
+ | # Controller for reflex based balance (different file) | ||
+ | << data/ | ||
+ | |||
+ | # Motor noise controller | ||
+ | NoiseController { | ||
+ | base_noise = 0.01 | ||
+ | proportional_noise = 0.1 | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | * Optimize the scenario by pressing '' | ||
+ | |||
+ | 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! |