Modular Vehicles Tutorial 4: Adding Driving Logic
In this tutorial, we're going through the final steps needed so that our vehicle can be driven by a controller with a camera attached to the driver's point of view.
Prerequisites
Modular Vehicles Tutorial 3: Adding Tire Models
Setting up the Vehicle Controller
In this section, we will create a Python script that receives the inputs of our hardware (in this case, a gamepad) to convert them to inputs of our vehicle system.
- From the Script section of the Toolbox, add a Dynamics Script. Close the following window.
- Rename (F2) the script "LAVÂ Controller".
- Create a Scripts folder in you vehicle folder structure.
Create a file text file and rename it LAV Controller.py. Add the following code to it and save it.
LAV Controllerfrom Vortex import Types MAX_GEAR = 8 MIN_GEAR = -6 DIFF_LOCK_TORQUE = 1000 def on_simulation_start(self): self.engine = create_input(self, 'Engine Start', Types.Type_Bool, default_value=False) self.gearUp = create_input(self, 'Gear Up', Types.Type_Bool, default_value=False) self.gearDown = create_input(self, 'Gear Down', Types.Type_Bool, default_value=False) self.lock = create_input(self, 'Diff Lock', Types.Type_Bool, default_value=False) self.park = create_input(self, 'Park', Types.Type_Bool, default_value=False) self.engineON = create_output(self, 'Engine On', Types.Type_Bool, default_value=False) self.parkON = create_output(self, 'Park On', Types.Type_Bool, default_value=False) self.lockTorque = create_output(self, 'Lock Torque', Types.Type_Double, default_value=False) self.gear = create_output(self, 'Gear Value', Types.Type_Int, default_value=0) self.last_engine = False self.last_gearUp = False self.last_gearDown = False self.last_lock = False self.lockON = False self.last_park = False def pre_step(self): if self.engine.value and not self.last_engine: self.engineON.value = not self.engineON.value self.last_engine = True elif not self.engine.value: self.last_engine = False if self.park.value and not self.last_park: self.parkON.value = not self.parkON.value self.last_park = True elif not self.park.value: self.last_park = False if self.lock.value and not self.last_lock: self.lockON = not self.lockON self.last_lock = True elif not self.lock.value: self.last_lock = False self.lockTorque.value = DIFF_LOCK_TORQUE * self.lockON if self.gearUp.value and not self.last_gearUp: self.gear.value += 1 if self.gear.value > MAX_GEAR: self.gear.value = MAX_GEAR self.last_gearUp = True elif not self.gearUp.value: self.last_gearUp = False if self.gearDown.value and not self.last_gearDown: self.gear.value -= 1 if self.gear.value < MIN_GEAR: self.gear.value = MIN_GEAR self.last_gearDown = True elif not self.gearDown.value: self.last_gearDown = False def create_output(extension, name, o_type, default_value=None): """Create output field with optional default value, reset on every simulation run.""" if extension.getOutput(name) is None: extension.addOutput(name, o_type) if default_value is not None: extension.getOutput(name).value = default_value return extension.getOutput(name) def create_parameter(extension, name, p_type, default_value=None): """Create parameter field with optional default value set only when the field is created.""" if extension.getParameter(name) is None: field = extension.addParameter(name, p_type) if default_value is not None: field.value = default_value return extension.getParameter(name) def create_input(extension, name, i_type, default_value=None): """Create input field with optional default value set only when the field is created.""" if extension.getInput(name) is None: field = extension.addInput(name, i_type) if default_value is not None: field.value = default_value return extension.getInput(name)
- From the LAV Controller script extension properties, assign the Script Path to the newly created LAV Controller.py.
- Step (F8) the simulation once for the Inputs and Outputs to appear in the script properties.
- From the Input Devices section of the Toolbox, insert a Joystick.
- From the Basics section of the Toolbox, add a Connection Container. Rename it "LAVÂ Controller Connections".
- Insert all field from the Vehicle Control VHL and the LAV Controller script.
- Insert the following Outputs from the Joystick:
- Button2
- Button4
- Button5
- Button6
- Button8
- AxisX
- AxisZ
- AxisZRot
- Make the following connections:
- Test (F7) the simulation and drive the vehicle with your gamepad.
Adding a Driver Camera
- From the Cameras section of the Toolbox, insert a Perspective camera. Rename it Driver Camera
- Open the Skin connection container.
- Insert the Parent Transform and connect it to the World Transform of the Chassis part.