SconePy
SconePy is a Python API for SCONE, designed and streamlined for Reinforcement Learning applications with biomechanical simulations.
With SconePy, you'll have access to the following freatures:
- Direct access to biomechanical sensors and actuators via NumPy arrays
- Automatic support for neural delays to sensors and actuators, to enhance biomechanical accuracy
- Easy access to model and simulation components for efficient reward shaping
Prerequisites
In order to use SconePy, you need:
- A system running Windows, Linux or macOS
- Python 3.9
sconegym and depRL
To get started using SCONE with RL, download sconegym, our default Python Gym environment. It has been used for developing the depRL control strategy. Both repositories are open source and freely available.
Please check the project page for more information.
Getting Started
After SCONE is installed, simply open and run <home>/SCONE/SconePy/sconepy_example.py
to see SconePy in action.
The example will run a simple feedback simulation using different simulation engines. SconePy supports simulations with OpenSim3, OpenSim4, and hyfydy (recommended for large optimizations).
Please visit the SCONE User Forum for any questions or feature requests.
API Example
See the SconePy API Reference for more details
- sconepy_example.py
import numpy as np import time from sconetools import sconepy # Reset a model and run a simulation def run_simulation(model, store_data, random_seed, max_time=3, min_com_height=0.3): # reset the model to the initial state model.reset() model.set_store_data(store_data) # initialize the rng rng = np.random.default_rng(random_seed) # Initialize muscle activations to random values muscle_activations = 0.1 + 0.4 * rng.random((len(model.muscles()))) model.init_muscle_activations(muscle_activations) # Tweak the initial pose of the model dof_positions = model.dof_position_array() dof_positions += 0.1 * rng.random(len(dof_positions)) - 0.05 model.set_dof_positions(dof_positions) for d in model.dofs(): if d.name() == 'pelvis_ty': d.set_pos(0.1 + d.pos()) # set the value of a # IMPORTANT: set the actual pose and equilibrates the muscles model.init_state_from_dofs() # Start the simulation, with time t ranging from 0 to 5 for t in np.arange(0, max_time, 0.01): # Set actuator_inputs based on muscle force, length and velocity mus_in = model.muscle_force_array() mus_in += model.muscle_fiber_length_array() - 1 mus_in += 0.2 * model.muscle_fiber_velocity_array() model.set_actuator_inputs(mus_in) # Advance the simulation to time t # Internally, this performs as many simulations steps as required # The internal step size is variable, and determined by the 'accuracy' # setting in the .scone file model.advance_simulation_to(t) # Abort the simulation if the model center of mass falls below 0.3 meter com_y = model.com_pos().y if com_y < min_com_height: print(f'Aborting simulation at t={model.time():.3f} com_y={com_y:.4f}') break # Write results to the SCONE results folder # The resulting .sto file can be openend directly in SCONE Studio for analysis if store_data: dirname = 'sconepy_example_' + model.name() filename = model.name() + f'_{random_seed}_{model.time():0.3f}_{model.com_pos().y:0.3f}' model.write_results(dirname, filename) print(f'Results written to {dirname}/{filename}; please use SCONE Studio to replay the .sto file.', flush=True) def measure_performance(model_file): # load the model start_time = time.perf_counter() model = sconepy.load_model(model_file) load_time = time.perf_counter() - start_time # run a couple of simulations random_seed = 1 model_time = 0.0 duration = 0.0 start_time = time.perf_counter() while duration < 2.0: run_simulation(model, False, random_seed, max_time=2, min_com_height=-10) duration = time.perf_counter() - start_time random_seed += 1 model_time += model.time() # show results real_time_factor = model_time / duration print(f'Loading {model_file} took {load_time*1000:.2f}ms - Simulating took {duration:.2f}s for {model_time:0.2f}s ({real_time_factor:0.2f}x real-time)', flush=True) # Set the SCONE log level between 1-7 (lower is more logging) sconepy.set_log_level(3) print('SCONE Version', sconepy.version()) # change the datatype of returned arrays to 32-bit floats sconepy.set_array_dtype_float32() store_data = True # Run performance benchmarks if sconepy.is_supported('ModelHyfydy'): measure_performance('data/H0918_hfd.scone') if sconepy.is_supported('ModelHyfydy'): measure_performance('data/H0918_hfd_v2.scone') if sconepy.is_supported('ModelOpenSim3'): measure_performance('data/H0918_osim3.scone') if sconepy.is_supported('ModelOpenSim4'): measure_performance('data/H0918_osim4.scone')