Vehicle Presets 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
Vehicle Presets Tutorial 3 : Adding Tire Models to a Wheeled Vehicle
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 def on_simulation_start(self): self.throttle_input = create_input(self, 'Throttle', Types.Type_Double, default_value=0) self.brake_input = create_input(self, 'Brake', Types.Type_Double, default_value=0) 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.throttle_output = create_output(self, 'Throttle', Types.Type_Double, default_value=0) self.brake_output = create_output(self, 'Brake', Types.Type_Double, default_value=0) self.engineON = create_output(self, 'Engine On', Types.Type_Bool, default_value=False) self.lockON = create_output(self, 'Lock On', Types.Type_Bool, default_value=False) self.gear = create_output(self, 'Gear Value', Types.Type_String, default_value='P') self.last_engine = False self.last_gearUp = False self.last_gearDown = False self.last_lock = False self.last_park = False self.parkON = False self.gear_number = 0 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 = not self.parkON self.last_park = True elif not self.park.value: self.last_park = False if self.lock.value and not self.last_lock: self.lockON.value = not self.lockON.value self.last_lock = True elif not self.lock.value: self.last_lock = False if self.gearUp.value and not self.last_gearUp: self.gear_number += 1 if self.gear_number > MAX_GEAR: self.gear_number = 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_number -= 1 if self.gear_number < MIN_GEAR: self.gear_number = MIN_GEAR self.last_gearDown = True elif not self.gearDown.value: self.last_gearDown = False if self.parkON: self.gear.value = 'P' self.gear_number = 0 else: if self.gear_number == 0: self.gear.value = 'N' elif self.gear_number > 0: self.gear.value = 'D' + str(self.gear_number) elif self.gear_number < 0: self.gear.value = 'R' + str(abs(self.gear_number)) self.throttle_output.value = max(0, self.throttle_input.value) self.brake_output.value = abs(self.brake_input.value) 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
- Button3
- 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.