Differences
This shows you the differences between two versions of the page.
Previous revision | |||
— | tutorials:script [2023/12/14 16:11] (current) – thomas | ||
---|---|---|---|
Line 1: | Line 1: | ||
+ | ====== Script Examples ====== | ||
+ | <callout type=" | ||
+ | This tutorial demonstrates the use of custom scripts using [[ref: | ||
+ | </ | ||
+ | ==== Maximizing the Height of a Body ==== | ||
+ | This example uses both a [[ref: | ||
+ | <code python> | ||
+ | CmaOptimizer { | ||
+ | signature_prefix = DATE_TIME | ||
+ | |||
+ | SimulationObjective { | ||
+ | max_duration = 2 | ||
+ | |||
+ | # Model used in simulation | ||
+ | ModelOpenSim3 { | ||
+ | model_file = models/ | ||
+ | state_init_file = init/ | ||
+ | initial_load = 1 | ||
+ | fixed_control_step_size = 0.005 # larger step sizes give better performance | ||
+ | } | ||
+ | |||
+ | # Controller based on lua script | ||
+ | ScriptController { | ||
+ | script_file = " | ||
+ | } | ||
+ | |||
+ | # Measure based on lua script | ||
+ | ScriptMeasure { | ||
+ | minimize = 0 # let the optimizer know we want to maximize this measure | ||
+ | target_body = " | ||
+ | script_file = " | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==== FeedForward Controller ==== | ||
+ | The actual controller is defined in '' | ||
+ | * '' | ||
+ | * '' | ||
+ | |||
+ | <code lua> | ||
+ | -- SCONE script for a simple feed-forward controller. | ||
+ | -- See Tutorial 6a - Script - High Jump | ||
+ | |||
+ | function init( model, par, side ) | ||
+ | -- keep a list of offsets and slopes to compute the excitation | ||
+ | offset = {} | ||
+ | slope = {} | ||
+ | |||
+ | -- keep a list of all actuators | ||
+ | actuators = {} | ||
+ | |||
+ | -- iterate over all actuators in the model | ||
+ | for i = 1, model: | ||
+ | -- store the actuator in the list | ||
+ | actuators[ i ] = model: | ||
+ | |||
+ | -- create parameters for both slope and offset | ||
+ | local name = actuators[ i ]:name() | ||
+ | offset[ i ] = par: | ||
+ | slope[ i ] = par: | ||
+ | end | ||
+ | end | ||
+ | |||
+ | function update( model ) | ||
+ | -- get the current simulation time | ||
+ | local t = model: | ||
+ | |||
+ | -- iterate over all actuators | ||
+ | for i = 1, #actuators do | ||
+ | local excitation = offset[ i ] + t * slope[ i ] | ||
+ | actuators[ i ]: | ||
+ | end | ||
+ | |||
+ | return false | ||
+ | end | ||
+ | </ | ||
+ | |||
+ | ==== Jump Measure ==== | ||
+ | The actual measure is defined in '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | |||
+ | The actual measure is defined in '' | ||
+ | <code lua> | ||
+ | -- SCONE script for a high-jump measure. | ||
+ | -- See Tutorial 6a - Script - High Jump | ||
+ | |||
+ | function init( model, par, side ) | ||
+ | -- get the ' | ||
+ | target_body = scone.target_body or " | ||
+ | |||
+ | -- find the actual body with the same name | ||
+ | body = model: | ||
+ | |||
+ | -- body height integral, used to compute average height | ||
+ | body_H = 0 | ||
+ | end | ||
+ | |||
+ | function update( model ) | ||
+ | -- get current vertical position and velocity | ||
+ | local body_height = body: | ||
+ | |||
+ | -- update best_height | ||
+ | body_H = body_H + model: | ||
+ | |||
+ | -- stop simulation if com pos is below 0.5 | ||
+ | if model: | ||
+ | return true -- terminate the simulation | ||
+ | else | ||
+ | return false -- keep simulating | ||
+ | end | ||
+ | end | ||
+ | |||
+ | function result( model ) | ||
+ | -- this is called at the end of the simulation | ||
+ | -- fitness corresponds to average body height | ||
+ | local fitness = body_H / model: | ||
+ | |||
+ | return fitness | ||
+ | end | ||
+ | |||
+ | function store_data( frame ) | ||
+ | -- store some values for analysis | ||
+ | frame: | ||
+ | end | ||
+ | </ | ||
+ | |||
+ | ==== Balance Device ==== | ||
+ | This example demonstrates a possible implementation of a ' | ||
+ | |||
+ | The SCONE scenario uses a Geyer & Herr gait controller in combination with a [[ref: | ||
+ | <code python> | ||
+ | CmaOptimizer { | ||
+ | signature_prefix = DATE_TIME | ||
+ | |||
+ | SimulationObjective { | ||
+ | max_duration = 10 | ||
+ | |||
+ | # Model used in simulation | ||
+ | OpenSimModel { | ||
+ | model_file = data/ | ||
+ | fixed_control_step_size = 0.005 # higher step sizes give better performance | ||
+ | enable_external_forces = 1 # Required when applying external forces | ||
+ | |||
+ | # Optimize initial state parameters | ||
+ | state_init_file = data/ | ||
+ | initial_state_offset = 0~0.01< | ||
+ | initial_state_offset_exclude = " | ||
+ | } | ||
+ | |||
+ | CompositeController { | ||
+ | # Controller for gait, based on [Geyer & Herr 2010] | ||
+ | << data/ | ||
+ | |||
+ | ScriptController { | ||
+ | name = BalanceDevice | ||
+ | target_body = torso | ||
+ | min_deg = -20~2 # optimize this parameter | ||
+ | max_deg = 5~0.5 # optimize this parameter | ||
+ | moment = 50 | ||
+ | duration = 0.2 | ||
+ | script_file = " | ||
+ | } | ||
+ | } | ||
+ | |||
+ | # Measure for gait | ||
+ | << data/ | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | The actual control script is defined in '' | ||
+ | <code lua> | ||
+ | -- SCONE script that simulates a device that generates an external moment at a specific condition. | ||
+ | -- See Tutorial 6b - Script - Balance Device | ||
+ | |||
+ | function init( model, par ) | ||
+ | -- get the ' | ||
+ | target_body = model: | ||
+ | |||
+ | -- get ' | ||
+ | if ( scone.min_deg and scone.min_deg ) then | ||
+ | body_min = par: | ||
+ | body_max = par: | ||
+ | else | ||
+ | -- produce an error and abort the simulation | ||
+ | error( "Must set min_deg and max_deg parameters!" | ||
+ | end | ||
+ | |||
+ | -- get ' | ||
+ | device_moment_mag = scone.moment and par: | ||
+ | device_duration = scone.duration and par: | ||
+ | |||
+ | -- initialize global variables that keep track of the device state | ||
+ | device_start = 0 | ||
+ | device_moment = 0 | ||
+ | end | ||
+ | |||
+ | function update( model ) | ||
+ | local t = model: | ||
+ | |||
+ | -- check if the device is currently active | ||
+ | if device_moment ~= 0 then | ||
+ | -- check if the device should deactivate | ||
+ | if t - device_start > device_duration then | ||
+ | -- add opposite external moment to deactivate device | ||
+ | target_body: | ||
+ | device_moment = 0 | ||
+ | -- print a message to the scone messages window | ||
+ | scone.debug( " | ||
+ | end | ||
+ | -- device is not active, check if we activate it | ||
+ | elseif device_start == 0 then -- device was not activated before | ||
+ | -- get the current body orientation in degrees and check with body_min / body_max | ||
+ | local ori = 57.3 * target_body: | ||
+ | if ori < body_min then | ||
+ | device_moment = device_moment_mag | ||
+ | elseif ori > body_max then | ||
+ | device_moment = -device_moment_mag | ||
+ | end | ||
+ | |||
+ | -- check if device_moment was set | ||
+ | if device_moment ~= 0 then | ||
+ | device_start = t | ||
+ | target_body: | ||
+ | |||
+ | -- print a message to the scone messages window | ||
+ | scone.debug( " | ||
+ | end | ||
+ | end | ||
+ | |||
+ | -- return false to keep going | ||
+ | return false; | ||
+ | end | ||
+ | </ |