def setDataDirectory(): """ Set data directory This is useful so data directory paths don't need to be changed everytime you pull from or push to github. To make this useful, make sure you perform step 2, as defined for your operating system. For Linux or Mac users: Replace bashrc with the shell your using. Could be .zshrc. 1. echo 'export CHRONO_DATA_DIR=<chrono's data directory>' >> ~/.bashrc Ex. echo 'export CHRONO_DATA_DIR=/home/user/chrono/data/' >> ~/.zshrc 2. source ~/.zshrc For Windows users: Link as reference: https://helpdeskgeek.com/how-to/create-custom-environment-variables-in-windows/ 1. Open the System Properties dialog, click on Advanced and then Environment Variables 2. Under User variables, click New... and create a variable as described below Variable name: CHRONO_DATA_DIR Variable value: <chrono's data directory> Ex. Variable value: C:\ Users\ user\ chrono\ data\ """ from pathlib import Path CONDA_PREFIX = os.environ.get('CONDA_PREFIX') CHRONO_DATA_DIR = os.environ.get('CHRONO_DATA_DIR') if CONDA_PREFIX and not CHRONO_DATA_DIR: CHRONO_DATA_DIR = os.path.join(CONDA_PREFIX, "share", "chrono", "data") if not CHRONO_DATA_DIR: CHRONO_DATA_DIR = os.path.join(Path(os.path.dirname(os.path.realpath(__file__))).parents[1], "chrono", "data", "") elif not CHRONO_DATA_DIR: raise Exception('Cannot find the chrono data directory. Please verify that CHRONO_DATA_DIR is set correctly.') chrono.SetChronoDataPath(CHRONO_DATA_DIR) veh.SetDataPath(os.path.join(CHRONO_DATA_DIR, 'vehicle', ''))
def __init__(self): chronopath = os.path.join(os.path.dirname(__file__), 'data') chrono.SetChronoDataPath(chronopath) self.render_setup = False # Will be used by SetNumThreads self.CPU = [1,1,1] return
def __init__(self, render): self.render = render self.observation_space = np.empty([9, 1]) self.action_space = np.empty([ 3, ]) self.info = {} self.timestep = 0.01 # --------------------------------------------------------------------- # # Create the simulation system and add items # self.timeend = 30 # Create the vehicle system chrono.SetChronoDataPath("/home/aaron/chrono/data/") veh.SetDataPath("/home/aaron/chrono/data/vehicle/") # JSON file for vehicle model self.vehicle_file = veh.GetDataPath( ) + "hmmwv/vehicle/HMMWV_Vehicle.json" # JSON files for terrain self.rigidterrain_file = veh.GetDataPath() + "terrain/RigidPlane.json" # JSON file for powertrain (simple) self.simplepowertrain_file = veh.GetDataPath( ) + "generic/powertrain/SimplePowertrain.json" # JSON files tire models (rigid) self.rigidtire_file = veh.GetDataPath( ) + "hmmwv/tire/HMMWV_RigidTire.json" # Initial vehicle position self.initLoc = chrono.ChVectorD(-125, -130, 0.5) # Initial vehicle orientation self.initRot = chrono.ChQuaternionD(1, 0, 0, 0) # Rigid terrain dimensions self.terrainHeight = 0 self.terrainLength = 300.0 # size in X direction self.terrainWidth = 300.0 # size in Y direction # Point on chassis tracked by the camera (Irrlicht only) self.trackPoint = chrono.ChVectorD(0.0, 0.0, 1.75) self.dist = 5.0 self.generator = RandomPathGenerator(width=100, height=100, maxDisplacement=2, steps=1) self.tracknum = 0
def _update_chrono_data_directories(): global _DATA_DIRECTORY, _CHRONO_DATA_DIRECTORY, _CHRONO_VEH_DATA_DIRECTORY if not _OVERRIDE_CHRONO_DIRECTORIES and _DATA_DIRECTORY != get_wa_data_directory( ): _DATA_DIRECTORY = get_wa_data_directory() _CHRONO_DATA_DIRECTORY = str( pathlib.Path(_DATA_DIRECTORY) / "chrono" / " ")[:-1] _CHRONO_VEH_DATA_DIRECTORY = str( pathlib.Path(_DATA_DIRECTORY) / "chrono" / "vehicle" / " ")[:-1] # Update the chrono paths chrono.SetChronoDataPath(_CHRONO_DATA_DIRECTORY) veh.SetDataPath(_CHRONO_VEH_DATA_DIRECTORY)
def set_chrono_data_directory(path: str): """Set the chrono data directory Normally, it is assumed that the chrono data directory is located inside wherever :meth:`~get_wa_data_directory` is set to. Using this method will override that functionality and statically assign the chrono data directory. If you'd like to return to the overriding functionality, call :meth:`~set_chrono_data_directory_override`. Args: path (str): relative (or absolute) path where the data is stored """ global _CHRONO_DATA_DIRECTORY, _OVERRIDE_CHRONO_DIRECTORIES _CHRONO_DATA_DIRECTORY = path _OVERRIDE_CHRONO_DIRECTORIES = True chrono.SetChronoDataPath(_CHRONO_DATA_DIRECTORY)
throttle_controller.Advance(step) driver.Advance(step) vehicle.Advance(step) terrain.Advance(step) vis.Advance(step) # Increment frame number step_number += 1 # ============================================================================= """ !!!! Set this path before running the demo! """ chrono.SetChronoDataPath("/home/aaron/chrono/data/") veh.SetDataPath("/home/aaron/chrono/data/vehicle/") # JSON file for vehicle model vehicle_file = veh.GetDataPath() + "hmmwv/vehicle/HMMWV_Vehicle.json" # JSON files for terrain rigidterrain_file = veh.GetDataPath() + "terrain/RigidPlane.json" # JSON file for powertrain (simple) simplepowertrain_file = veh.GetDataPath( ) + "generic/powertrain/SimplePowertrain.json" # JSON files tire models (rigid) rigidtire_file = veh.GetDataPath() + "hmmwv/tire/HMMWV_RigidTire.json"
import math import time import sys, getopt import pychrono as chrono import pychrono.postprocess as postprocess import pychrono.irrlicht as chronoirr # --------------------------------------------------------------------- m_timestep = 0.01 m_length = 1.0 m_visualization = "pov" m_datapath = "C:/Program Files/chrono_solidworks/data/" # For irrlicht fonts & background. Adjust to your path chrono.SetChronoDataPath(m_datapath) # --------------------------------------------------------------------- # # load the file generated by the SolidWorks CAD plugin # and add it to the ChSystem. # print("Loading C::E scene...") exported_items = chrono.ImportSolidWorksSystem('./engine4c') print("...loading done!") # Print exported items for my_item in exported_items:
# ============================================================================= # # RoboSimian on rigid terrain # # ============================================================================= import os import math import numpy as np import pychrono as chrono import pychrono.robot as robosimian try: from pychrono import irrlicht as chronoirr except: print('Could not import ChronoIrrlicht') chrono.SetChronoDataPath( '/home/hubble-02/miniconda3/envs/isro/share/chrono/data/') time_step = 1e-3 # Drop the robot on rigid terrain drop = True # Robot locomotion mode mode = robosimian.LocomotionMode_WALK # Contact method (system type) contact_method = chrono.ChContactMethod_SMC # Phase durations duration_pose = 1.0 # Interval to assume initial pose duration_settle_robot = 0.5 # Interval to allow robot settling on terrain
# the floor. # # The cable falls under the action of gravity alone, acting in the negative # Y (up) direction. # # The simulation is animated with Irrlicht. # # ============================================================================= import pychrono as chrono import pychrono.fea as fea import pychrono.irrlicht as chronoirr # 0. Set the path to the Chrono data folder CHRONO_DATA_DIR = "C:/codes/Chrono/Chrono_Source/data/" chrono.SetChronoDataPath(CHRONO_DATA_DIR) # 1. Create the physical system that will handle all finite elements and constraints. # NOTE that we need contact in FEA, so we use the ChSystemSMC, that uses SMC penalty in contacts system = chrono.ChSystemSMC() # 2. Create the mesh that will contain the finite elements, and add it to the system mesh = fea.ChMesh() system.Add(mesh) ## ------------------------------------------------------------------------- ## EXERCISE 1 ##
SLEEVE_THICKNESS = 4.215 # in mm # Global -- Optimisation algorithm NEIGHBOURS = 2 INFERRED_RADIUS = 60. # in mm INFERRED_LENGTH = (N_RINGS - 1) * RING_GAP # Constraint of the textile # Global -- Dont touch UNIT_FACTOR = 0.01 metrics = ['mm', 'cm', 'dm', 'm'] metric = metrics[int(math.fabs(round(math.log(UNIT_FACTOR, 10))))] filename = SHAPE_PATH.split('/')[-1].split('.')[0] # --------------------------------------------------------------------------- # Chrono setup chrono.SetChronoDataPath("../data/") mysystem = chrono.ChSystemSMC() mysystem.Set_G_acc(chrono.ChVectorD(0., 0., 0.)) # Remove gravity contact_method = chrono.ChMaterialSurface.SMC # Shape filepath = tool.obj_from_millimeter(chrono.GetChronoDataPath() + SHAPE_PATH, UNIT_FACTOR, f"_{metric}") shape = tool.load_shape(filepath, contact_method, 'textures/skin.jpg') # Get shape bounding box dimensions bbmin, bbmax = chrono.ChVectorD(), chrono.ChVectorD() shape.GetTotalAABB(bbmin, bbmax) bbmin, bbmax = eval(str(bbmin)), eval(str(bbmax)) print(bbmin, bbmax) print(shape.GetPos())
# -*- coding: utf-8 -*- """ Created on Thu Jan 10 11:01:21 2019 @author: SB """ import pychrono as chrono import chtrain_ant import chtrain_pendulum # Properly set path to Chrono data directory, taking into account the location of the chrono-tensorflow # demos relative to the other PyChrono demos. # If running from a different directory, you must change this path accordingly. chrono.SetChronoDataPath('../../' + chrono.GetChronoDataPath()) def Init(env_name, render): if env_name == 'ChronoAnt': return chtrain_ant.Model(render) elif env_name == 'ChronoPendulum': return chtrain_pendulum.Model(render) else: print('Unvalid environment name')
import pychrono as chrono import pychrono.fea as fea import pychrono.mkl as mkl import pychrono.irrlicht as chronoirr import time import random chrono.SetChronoDataPath( '/home/sebastian/miniconda3/pkgs/pychrono-5.0.0-py37_9/share/chrono/data/') writepath = ('/home/sebastian/code/project_name/') class Material(): def __init__(self, name, modulus, poisson, density): self.name = name self.modulus = modulus self.poisson = poisson self.density = density self.shear = self.poisson * self.modulus #def steel_func(): #how to use the Material class # return Material("Mat1",11,12,13) class System(): def __init__(self, name, timestep): self.system = chrono.ChSystemNSC() self.name = name self.system.SetSolver(mkl.ChSolverMKL()) self.timestep = timestep def set_timestep(self, newtimestep):
steering_controller.Advance(step) throttle_controller.Advance(step) driver.Advance(step) vehicle.Advance(step) terrain.Advance(step) # Increment frame number step_number += 1 # ============================================================================= """ !!!! Set this path before running the demo! """ chrono.SetChronoDataPath('/home/aaron/chrono/data/') veh.SetDataPath('/home/aaron/chrono/data/vehicle/') # JSON file for vehicle model vehicle_file = veh.GetDataPath() + "hmmwv/vehicle/HMMWV_Vehicle.json" # JSON files for terrain rigidterrain_file = veh.GetDataPath() + "terrain/RigidPlane.json" # JSON file for powertrain (simple) simplepowertrain_file = veh.GetDataPath( ) + "generic/powertrain/SimplePowertrain.json" # JSON files tire models (rigid) rigidtire_file = veh.GetDataPath() + "hmmwv/tire/HMMWV_RigidTire.json"
# Advance simulation for one timestep for all modules driver.Advance(step_size) vehicle.Advance(step_size) terrain.Advance(step_size) app.Advance(step_size) # Spin in place for real time to catch up realtime_timer.Spin(step_size) # ============================================================================= """ !!!! Set this path before running the demo! """ chrono.SetChronoDataPath('../../../../Library/data/') veh.SetDataPath('../../../../Library/data/vehicle/') # JSON file for vehicle model vehicle_file = veh.GetDataPath() +"hmmwv/vehicle/HMMWV_Vehicle.json" # JSON files for terrain rigidterrain_file = veh.GetDataPath() +"terrain/RigidPlane.json" # JSON file for powertrain (simple) simplepowertrain_file = veh.GetDataPath() + "generic/powertrain/SimplePowertrain.json" # JSON files tire models (rigid) rigidtire_file = veh.GetDataPath() +"hmmwv/tire/HMMWV_RigidTire.json" # Initial vehicle position
def __init__(self, render): self.animate = render self.observation_space = np.empty([ 18, ]) self.action_space = np.zeros([ 6, ]) #TODO: check if targ is reachable self.fingerdist = chrono.ChVectorD(0, 0.1117, 0) #self.d_old = np.linalg.norm(self.Xtarg + self.Ytarg) self.robosystem = chrono.ChSystemNSC() chrono.ChCollisionModel.SetDefaultSuggestedEnvelope(0.001) chrono.ChCollisionModel.SetDefaultSuggestedMargin(0.001) #robosystem.SetSolverType(chrono.ChSolver.Type_BARZILAIBORWEIN) # precise, more slow self.timestep = 0.01 self.info = {} m_filename = "ABB_IRB120" self.timestep = 0.001 m_length = 1.0 self.my_material = chrono.ChMaterialSurfaceNSC() self.my_material.SetFriction(0.5) self.my_material.SetDampingF(0.2) self.my_material.SetCompliance(0.0000001) self.my_material.SetComplianceT(0.0000001) #m_visualization = "irrlicht" self.m_datapath = "../../../../../../codes/Chrono/Chrono_Source/data" chrono.SetChronoDataPath(self.m_datapath) print(" file to load is ", m_filename) print(" timestep is ", self.timestep) print(" length is ", m_length) print(" data path for fonts etc.: ", self.m_datapath) # --------------------------------------------------------------------- # # load the file generated by the SolidWorks CAD plugin # and add it to the ChSystem. # Remove the trailing .py and add / in case of file without ./ #m_absfilename = os.path.abspath(m_filename) #m_modulename = os.path.splitext(m_absfilename)[0] print("Loading C::E scene...") dir_path = os.path.dirname(os.path.realpath(__file__)) self.fpath = os.path.join(dir_path, m_filename) #exported_items = chrono.ImportSolidWorksSystem(self.fpath) #self.exported_items = chrono.ImportSolidWorksSystem(m_modulename) print("...loading done!") # Print exported items #for my_item in exported_items: #print (my_item.GetName()) # Optionally set some solver parameters. #self.robosystem.SetMaxPenetrationRecoverySpeed(1.00) self.robosystem.SetSolverType(chrono.ChSolver.Type_BARZILAIBORWEIN) self.robosystem.SetMaxItersSolverSpeed(600) self.robosystem.SetSolverWarmStarting(True) self.robosystem.Set_G_acc(chrono.ChVectorD(0, -9.8, 0)) """ $$$$$$$$ FIND THE SW DEFINED CONSTRAINTS, GET THEIR self.frames AND GET RID OF EM $$$$$$$$ """ self.con_link = [ "Concentric1", "Concentric2", "Concentric3", "Concentric4", "Concentric5", "Concentric6" ] self.coi_link = [ "Coincident1", "Coincident2", "Coincident3", "Coincident4", "Coincident5", "Coincident6" ] self.bodiesNames = [ "Racer3_p01-1", "Racer3_p02-1", "Racer3_p03-1", "Racer3_p04-1", "Racer3_p05-1", "Racer3_p06-2", "Hand_base_and_p07-3" ] # self.maxSpeed = [430, 450, 500, 600, 600, 900] #°/s -->COMAU self.maxSpeed = [250, 250, 250, 320, 320, 420] #°/s --> ABB # TODO: convert to rads (converted in every operation) #self.limits: # TODO: check signs # TODO: peridodicity ignored # REAL self.limits #self.maxRot = [170, 135, 90, 200, 125, 2700] # ° #self.minRot = [-170, -95, -155, -200, -125, -2700] # ° # MODIFIED self.limits # self.maxRot = [170, 135, 90, 179, 50, 79] # ° --> COMAU # self.minRot = [-170, -95, -155, -179, -50, -79] # ° --> COMAU self.maxRot = [165, 110, 70, 160, 120, 179] # ° --> ABB self.minRot = [-165, -110, -110, -160, -100, -179] # ° --> ABB #self.maxT = np.asarray([28, 28, 28, 7.36, 7.36, 4.41]) self.maxT = np.asarray([100, 100, 50, 7.36, 7.36, 4.41]) # --> LASCIATI UGUALI A COMAU if (self.animate): self.myapplication = chronoirr.ChIrrApp( self.robosystem, 'Test', chronoirr.dimension2du(1280, 720)) self.myapplication.AddShadowAll() self.myapplication.SetStepManage(True) self.myapplication.SetTimestep(self.timestep) self.myapplication.AddTypicalSky(chrono.GetChronoDataPath() + 'skybox/') self.myapplication.AddTypicalLogo(chrono.GetChronoDataPath() + 'logo_pychrono_alpha.png') self.myapplication.AddTypicalCamera( chronoirr.vector3df(1, 1, 1), chronoirr.vector3df(0.0, 0.0, 0.0)) self.myapplication.AddTypicalLights() # angle of FOV
def __init__(self, configuration, visualization: bool = False, output: Optional = None) -> None: # TODO a copy of the configuration is better self._conf = configuration self._visualization = visualization self._output = output self._app = None # TODO not sure about the meaning of theese two parameters, take them from the configuation chrono.ChCollisionInfo.SetDefaultEffectiveCurvatureRadius(1) chrono.ChCollisionModel.SetDefaultSuggestedMargin(0.006) # TODO look into the parameters of the system # e.g. MinBounceSpeed, Gravity self._system = chrono.ChSystemSMC() if self._visualization: # TODO take the data path, the title, the dimension and do_[something] from the configuration chrono.SetChronoDataPath( "/home/gianluca/anaconda3/envs/chrono/share/chrono/data/") self._app = irr.ChIrrApp( self._system, "Artificial Skin", irr.dimension2du(1024, 768), do_fullscreen=False, do_shadows=True, do_antialias=True, ) self._app.AddTypicalSky() self._app.AddTypicalLights() # TODO take the info for the came and lighs from the configuation self._app.AddTypicalCamera(irr.vector3df(-1, -1, 0), irr.vector3df(0, 0, 0)) # TODO this has too many parameters and it is not that important self._app.AddLightWithShadow( irr.vector3df(1.5, 5.5, -2.5), irr.vector3df(0, 0, 0), 3, 2.2, 7.2, 40, 512, irr.SColorf(1, 1, 1), ) self._app.AddShadowAll() self._app.SetTimestep(0.004) self._make_sheets() self._make_sensors() # TODO make the load class -> it takes a node / pair of indexes and time and return the force self._add_forces() # TODO look at all the parameters of the solver and the stepper # TODO consider also mkl.ChSolverMKL # TODO take the parameters from the configuration self._solver = chrono.ChSolverMINRES() self._system.SetSolver(self._solver) self._solver.SetMaxIterations(1000) self._solver.SetTolerance(1e-12) self._solver.EnableDiagonalPreconditioner(True) self._solver.SetVerbose( False) # don't take this from the configuration # HHT implicit integrator for II order systems, adaptive # TODO take the parameters from the configuaration self._stepper = chrono.ChTimestepperHHT(self._system) self._system.SetTimestepper(self._stepper) self._stepper.SetAlpha(-0.2) self._stepper.SetMaxiters(100) self._stepper.SetAbsTolerances(1e-5) self._stepper.SetMode(chrono.ChTimestepperHHT.POSITION) self._stepper.SetScaling(True) # TODO from configuarion # length of the simulation self._life = 5 # seconds
def __init__(self): chronopath = os.path.join(os.path.dirname(__file__), 'data') chrono.SetChronoDataPath(chronopath) self.render_setup = False return
## The crank is connected to ground with a revolute joint and the slider is ## connected to ground through a prismatic joint. A distance constraint models ## a massless link between the crank and the slider. ## ## The mechanism moves under the action of gravity alone, acting in the negative ## Z direction. ## ## The simulation is animated with Irrlicht. ## ## ============================================================================= import pychrono as chrono from pychrono import irrlicht as chronoirr #CHRONO_DATA_DIR = chrono.SetChronoDataPath('C:/codes/Chrono/Chrono_Source/data/') ## 1. Create the physical system that will handle all bodies and constraints. ## Specify the gravitational acceleration vector, consistent with the ## global reference frame having Z up. system = chrono.ChSystemNSC() system.Set_G_acc(chrono.ChVectorD(0, 0, -9.81)) ## 2. Create the rigid bodies of the slider-crank mechanical system. ## For each body, specify: ## - a unique identifier ## - mass and moments of inertia ## - position and orientation of the (centroidal) body frame ## - visualization assets (defined with respect to the body frame)
def main(): # ---------------------- # Set path to data files # ---------------------- # Path to Chrono data files (textures, etc.) chrono.SetChronoDataPath(CHRONO_DATA_DIR) # Path to the data files for this vehicle (JSON specification files) veh.SetDataPath("./data/") # -------------------------- # Create the various modules # -------------------------- # Create and initialize the vehicle system vehicle = veh.WheeledVehicle(veh.GetDataFile(vehicle_file), NSC_SMC) vehicle.Initialize(chrono.ChCoordsysD(initLoc, initRot)) vehicle.SetSuspensionVisualizationType(veh.VisualizationType_PRIMITIVES) vehicle.SetSteeringVisualizationType(veh.VisualizationType_PRIMITIVES) vehicle.SetWheelVisualizationType(veh.VisualizationType_NONE) # Create the terrain terrain = veh.RigidTerrain(vehicle.GetSystem(), veh.GetDataFile(rigidterrain_file)) AddFixedObstacles(vehicle.GetSystem()) AddMovingObstacles(vehicle.GetSystem()) # Create and initialize the powertrain system powertrain = veh.SimplePowertrain(veh.GetDataFile(simplepowertrain_file)) vehicle.InitializePowertrain(powertrain) # Create and initialize the tires for axle in vehicle.GetAxles(): tireL = veh.RigidTire(veh.GetDataFile(rigidtire_file)) tireR = veh.RigidTire(veh.GetDataFile(rigidtire_file)) vehicle.InitializeTire(tireL, axle.m_wheels[0], veh.VisualizationType_MESH) vehicle.InitializeTire(tireR, axle.m_wheels[1], veh.VisualizationType_MESH) # Create the Irrlicht vehicle application app = veh.ChVehicleIrrApp(vehicle, "Vehicle Demo") app.SetSkyBox() app.AddTypicalLights(chronoirr.vector3df(30, -30, 100), chronoirr.vector3df(30, 50, 100), 250, 130) app.SetChaseCamera(trackPoint, 6.0, 0.5) app.SetTimestep(step_size) app.AssetBindAll() app.AssetUpdateAll() # Create the driver system (interactive) driver = veh.ChIrrGuiDriver(app) # Set the time response for steering and throttle keyboard inputs. # NOTE: this is not exact, since we do not render quite at the specified FPS. steering_time = 1.0 # time to go from 0 to +1 (or from 0 to -1) throttle_time = 1.0 # time to go from 0 to +1 braking_time = 0.3 # time to go from 0 to +1 driver.SetSteeringDelta(render_step_size / steering_time) driver.SetThrottleDelta(render_step_size / throttle_time) driver.SetBrakingDelta(render_step_size / braking_time) # ----------------- # Initialize output # ----------------- try: os.mkdir(out_dir) except: print("Error creating directory ") if (povray_output): try: os.mkdir(pov_dir) except: print("Error creating POV directory ") terrain.ExportMeshPovray(out_dir) # --------------- # Simulation loop # --------------- """driveshaft_speed powertrain_torque throttle_input steering_input braking_input""" # Number of simulation steps between two 3D view render frames render_steps = m.ceil(render_step_size / step_size) #Initialize simulation frame counter and simulation time step_number = 0 frame_number = 0 time = 0 realtime_timer = chrono.ChRealtimeStepTimer() while (app.GetDevice().run()): # Render scene if (step_number % render_steps == 0): app.BeginScene(True, True, chronoirr.SColor(255, 140, 161, 192)) app.DrawAll() app.EndScene() #char filename[100]; #sprintf(filename, "%s/data_%03d.dat", pov_dir.c_str(), frame_number + 1); #utils::WriteShapesPovray(vehicle.GetSystem(), filename); frame_number += 1 # Get driver inputs driver_inputs = driver.GetInputs() # Update modules (process inputs from other modules) time = vehicle.GetSystem().GetChTime() driver.Synchronize(time) vehicle.Synchronize(time, driver_inputs, terrain) terrain.Synchronize(time) app.Synchronize(driver.GetInputModeAsString(), driver_inputs) # Advance simulation for one timestep for all modules driver.Advance(step_size) vehicle.Advance(step_size) terrain.Advance(step_size) app.Advance(step_size) # Increment frame number step_number += 1 # Spin in place for real time to catch up realtime_timer.Spin(step_size) return 0