Discover Learn Reference Get OpenPLXSearch Contact

Concepts Vehicle Modeling

This concepts page shows how the Vehicles and MachineModeling bundles can be combined to build a vehicle model from reusable parts, exported rigid bodies, and bundle-level axle/suspension connections.

The structure is inspired by the dump-truck tutorial, but the example below is kept closer to a single working OpenPLX file.

The main pattern is:

  • define reusable tuning traits first
  • define reusable wheel models
  • reuse rigid-body traits exported from Blender
  • assemble the final vehicle using Vehicles interfaces and MachineModeling components

Reusable traits and exported bodies

The Blender plugin can export rigid-body traits with mesh geometry and MateConnectors generated from mates defined in Blender. Those exported connectors are then mapped to the connector roles required by the DumpTruck bundle interfaces.

The code below is intentionally shown as setup material only, so it does not get its own Open in Editor button.

trait Suspension:
    front_axle_connection:
        min_length: 0.4
        stroke_length: 0.4
        rod_diameter: 0.15
        barrel_diameter: 0.20

    rear_axle_connection:
        min_length: 0.45
        stroke_length: 0.4
        rod_diameter: 0.15
        barrel_diameter: 0.20

trait Hydraulic:
    steering:
        min_length: 0.941
        stroke_length: 0.525
        rod_diameter: 0.070
        barrel_diameter: 0.150

ImportedTireVisual is Visuals.Geometries.ExternalTriMeshGeometry:
    path: @"fr_wheel.obj"

Wheel is Vehicles.Wheels.Base:
    rim.radius: 25.00 * 25.4e-3 / 2
    rim.width: 25.00 * 25.4e-3

    rim becomes Vehicles.Wheels.Rim:
        geometry:
            local_transform.rotation: Math.Quat.from_to({1, 0, 0}, {0, 0, 1})
            radius: 1.870/2
        visual is ImportedTireVisual

    connector:
        main_axis: -Math.Vec3.Y_AXIS()
        normal: Math.Vec3.Z_AXIS()

Wheel_L is Wheel:
    connector:
        main_axis: -Math.Vec3.Y_AXIS()
        normal: Math.Vec3.Z_AXIS()

Wheel_R is Wheel:
    connector:
        main_axis: Math.Vec3.Y_AXIS()
        normal: Math.Vec3.Z_AXIS()

trait bodyBody:
    b_frame_c is Physics3D.Interactions.MateConnector:
        position: {0.000000, 0.000000, 0.000000}
        main_axis: {0.000000, -1.000000, -0.000000}
        normal: {0.000000, -0.000000, 1.000000}
    l_lift_cyl_c is Physics3D.Interactions.MateConnector:
        position: {-1.992000, -1.572000, 0.805000}
        main_axis: {-0.366427, -0.930416, 0.007601}
        normal: {0.388944, -0.160589, -0.907157}
    r_lift_cyl_c is Physics3D.Interactions.MateConnector:
        position: {-1.992000, 1.572000, 0.805000}
        main_axis: {-0.366427, 0.930416, 0.007601}
        normal: {-0.388944, -0.160589, 0.907157}
    visual is Visuals.Geometries.ExternalTriMeshGeometry:
        path: @"body.obj"
    geometry is Physics3D.Geometries.ExternalTriMeshGeometry:
        path: visual.path

trait f_axleBody:
    f_frame_c is Physics3D.Interactions.MateConnector:
        position: {0.000000, 0.000000, 0.000000}
        main_axis: {0.000000, -1.000000, -0.000000}
        normal: {0.000000, -0.000000, 1.000000}
    fl_sus_pist_c is Physics3D.Interactions.MateConnector:
        position: {1.345000, -0.680000, 0.200000}
        main_axis: {0.000000, -1.000000, -0.000000}
        normal: {0.000000, -0.000000, 1.000000}
    fl_wheel_c is Physics3D.Interactions.MateConnector:
        position: {1.345000, -1.345000, -0.000000}
        main_axis: {0.000000, -1.000000, -0.000000}
        normal: {0.000000, -0.000000, 1.000000}
    fr_sus_pist_c is Physics3D.Interactions.MateConnector:
        position: {1.345000, 0.680000, 0.200000}
        main_axis: {0.000000, -1.000000, -0.000000}
        normal: {0.000000, -0.000000, 1.000000}
    fr_wheel_c is Physics3D.Interactions.MateConnector:
        position: {1.345000, 1.345000, -0.000000}
        main_axis: {0.000000, -1.000000, -0.000000}
        normal: {0.000000, -0.000000, 1.000000}
    visual is Visuals.Geometries.ExternalTriMeshGeometry:
        path: @"f_axle.obj"
    geometry is Physics3D.Geometries.ExternalTriMeshGeometry:
        path: visual.path

trait f_frameBody:
    kinematics.local_transform.position: {-1.165000, -0.000000, 0.710000}
    f_axle_c is Physics3D.Interactions.MateConnector:
        position: {-2.695000, 0.000000, 0.140000}
        main_axis: {0.000000, -1.000000, -0.000000}
        normal: {0.000000, -0.000000, 1.000000}
    fl_sus_cyl_c is Physics3D.Interactions.MateConnector:
        position: {-1.350000, -0.680000, 0.860000}
        main_axis: {0.000000, -1.000000, -0.000000}
        normal: {0.000000, -0.000000, 1.000000}
    fr_sus_cyl_c is Physics3D.Interactions.MateConnector:
        position: {-1.350000, 0.680000, 0.860000}
        main_axis: {0.000000, -1.000000, -0.000000}
        normal: {0.000000, -0.000000, 1.000000}
    lower_hitch_c is Physics3D.Interactions.MateConnector:
        position: {0.000000, 0.000000, 0.100000}
        main_axis: {0.000000, 0.000000, 1.000000}
        normal: {0.000000, 1.000000, 0.000000}
    upper_hitch_c is Physics3D.Interactions.MateConnector:
        position: {0.000000, 0.000000, 0.700000}
        main_axis: {0.000000, 0.000000, 1.000000}
        normal: {0.000000, 1.000000, 0.000000}
    l_steer_cyl_c is Physics3D.Interactions.MateConnector:
        position: {-1.0285000, -0.44001200, 0.440000}
        main_axis: {0.000000, 0.000000, 1.000000}
        normal: {0.000000, 1.000000, 0.000000}
    r_steer_cyl_c is Physics3D.Interactions.MateConnector:
        position: {-1.0285000, 0.44001200, 0.440000}
        main_axis: {0.000000, 0.000000, 1.000000}
        normal: {0.000000, 1.000000, 0.000000}
    visual is Visuals.Geometries.ExternalTriMeshGeometry:
        path: @"f_frame.obj"
    geometry is Physics3D.Geometries.ExternalTriMeshGeometry:
        path: visual.path

trait b_frameBody:
    b_axle_c is Physics3D.Interactions.MateConnector:
        position: {3.160000, 0.000000, -0.180000}
        main_axis: {0.000000, -1.000000, -0.000000}
        normal: {0.000000, -0.000000, 1.000000}
    body_c is Physics3D.Interactions.MateConnector:
        position: {5.120001, 0.000000, 0.643350}
        main_axis: {0.000000, -1.000000, -0.000000}
        normal: {0.000000, -0.000000, 1.000000}
    c_axle_c is Physics3D.Interactions.MateConnector:
        position: {1.190000, 0.000000, -0.180000}
        main_axis: {0.000000, -1.000000, -0.000000}
        normal: {0.000000, -0.000000, 1.000000}
    upper_hitch_c is Physics3D.Interactions.MateConnector:
        position: {0.000000, 0.000000, 0.300000}
        main_axis: {0.000000, 0.000000, 1.000000}
        normal: {0.000000, 1.000000, 0.000000}
    lower_hitch_c is Physics3D.Interactions.MateConnector:
        position: {0.000000, 0.000000, -0.300000}
        main_axis: {0.000000, 0.000000, 1.000000}
        normal: {0.000000, 1.000000, 0.000000}
    l_equalizer_c is Physics3D.Interactions.MateConnector:
        position: {3.520000, -0.580000, 0.240000}
        main_axis: {0.000000, -1.000000, -0.000000}
        normal: {0.000000, -0.000000, 1.000000}
    r_equalizer_c is Physics3D.Interactions.MateConnector:
        position: {3.520000, 0.580000, 0.240000}
        main_axis: {0.000000, -1.000000, -0.000000}
        normal: {0.000000, -0.000000, 1.000000}
    l_lift_pist_c is Physics3D.Interactions.MateConnector:
        position: {0.586000, -0.535000, 0.150000}
        main_axis: {-0.391978, 0.152884, 0.907182}
        normal: {0.363190, 0.931715, -0.000091}
    r_lift_pist_c is Physics3D.Interactions.MateConnector:
        position: {0.586000, 0.535000, 0.1500000}
        main_axis: {-0.391978, -0.152884, 0.907182}
        normal: {-0.363190, 0.931715, 0.000091}
    l_steer_pist_c is Physics3D.Interactions.MateConnector:
        position: {0.011266, -0.294972, 0.120000}
        main_axis: {0.000000, 0.000000, 1.000000}
        normal: {0.000000, 1.000000, 0.000000}
    r_steer_pist_c is Physics3D.Interactions.MateConnector:
        position: {0.011266, 0.294972, 0.120000}
        main_axis: {0.000000, 0.000000, 1.000000}
        normal: {0.000000, 1.000000, 0.000000}
    visual is Visuals.Geometries.ExternalTriMeshGeometry:
        path: @"b_frame.obj"
    geometry is Physics3D.Geometries.ExternalTriMeshGeometry:
        path: visual.path

The important connector mapping idea is:

  • the Blender-exported MateConnectors preserve the attachment frames from the original CAD/Blender assembly
  • those connector names are then mapped into bundle-required roles like upper_joint_connector, center_a_frame_connector, and left_steering_actuator_connector
  • this lets the vehicle bundle work with authored geometry instead of rebuilding all connector placement by hand

Final dump-truck model

This is the final model block. It depends on the setup traits above, so Open in Editor should copy both the setup section and this final TutorialDumpTruck model into the editor.

TutorialDumpTruck is Vehicles.DumpTruck.Articulated:
    with Vehicles.DumpTruck.Interfaces.FourWheels
    with Hydraulic

    left_front_wheel becomes Wheel_L
    right_front_wheel becomes Wheel_R
    left_rear_wheel becomes Wheel_L
    right_rear_wheel becomes Wheel_R

    chassis becomes Vehicles.Chassis.Articulated.DualPivot:
        front_frame becomes MachineModeling.Components.Primitive.Base with Vehicles.Chassis.Articulated.Interfaces.DualJoint, Vehicles.Chassis.Articulated.Interfaces.DualSteeringActuators, Vehicles.DumpTruck.Interfaces.Chassis.AFrame:
            body becomes Physics3D.Bodies.RigidBody with f_frameBody

            upper_joint_connector: chassis.front_frame.body.upper_hitch_c
            lower_joint_connector: chassis.front_frame.body.lower_hitch_c
            left_steering_actuator_connector: chassis.front_frame.body.l_steer_cyl_c
            right_steering_actuator_connector: chassis.front_frame.body.r_steer_cyl_c
            center_a_frame_connector: chassis.front_frame.body.f_axle_c

        rear_frame becomes MachineModeling.Components.Primitive.Base with Vehicles.Chassis.Articulated.Interfaces.DualJoint, Vehicles.DumpTruck.Interfaces.Chassis.AFrame, Vehicles.DumpTruck.Interfaces.CargoBed.SingleJoint, Vehicles.DumpTruck.Interfaces.CargoBed.DualActuator, Vehicles.Chassis.Articulated.Interfaces.DualSteeringActuators:
            body becomes Physics3D.Bodies.RigidBody with b_frameBody
            upper_joint_connector: chassis.rear_frame.body.upper_hitch_c
            lower_joint_connector: chassis.rear_frame.body.lower_hitch_c
            center_a_frame_connector: chassis.rear_frame.body.b_axle_c
            cargo_bed_connector: chassis.rear_frame.body.body_c
            left_steering_actuator_connector: chassis.rear_frame.body.l_steer_pist_c
            right_steering_actuator_connector: chassis.rear_frame.body.r_steer_pist_c

    front_wheel_axle:
        body becomes Physics3D.Bodies.RigidBody with f_axleBody
        center_a_frame_connector: front_wheel_axle.body.f_frame_c
        left_wheel_connector: front_wheel_axle.body.fl_wheel_c
        right_wheel_connector: front_wheel_axle.body.fr_wheel_c

    rear_wheel_axle:
        body becomes Physics3D.Bodies.RigidBody with f_axleBody
        center_a_frame_connector: rear_wheel_axle.body.f_frame_c
        left_wheel_connector: rear_wheel_axle.body.fl_wheel_c
        right_wheel_connector: rear_wheel_axle.body.fr_wheel_c

    steering:
        left_steering_actuator becomes MachineModeling.Actuators.Linear.Cylinder with MachineModeling.Actuators.Linear.Traits.VelocityMotor
        right_steering_actuator becomes MachineModeling.Actuators.Linear.Cylinder with MachineModeling.Actuators.Linear.Traits.VelocityMotor

    front_axle_connection becomes Vehicles.DumpTruck.Connections.AFrame.Base:
        chassis_frame: chassis.front_frame
        a_frame: front_wheel_axle
        left_axle_connector: front_wheel_axle.left_wheel_connector
        right_axle_connector: front_wheel_axle.right_wheel_connector

    rear_axle_connection becomes Vehicles.DumpTruck.Connections.AFrame.Base:
        chassis_frame: chassis.rear_frame
        a_frame: rear_wheel_axle
        left_axle_connector: rear_wheel_axle.left_wheel_connector
        right_axle_connector: rear_wheel_axle.right_wheel_connector

    cargo_bed becomes MachineModeling.Components.Primitive.Base with Vehicles.DumpTruck.Interfaces.CargoBed.SingleJoint:
        body becomes Physics3D.Bodies.RigidBody with bodyBody
        cargo_bed_connector: cargo_bed.body.b_frame_c

    cargo_bed_connection becomes Vehicles.DumpTruck.Connections.CargoBed.Fixed:
        chassis_frame: chassis.rear_frame
        cargo_bed: cargo_bed

This model is intentionally simpler than the full tutorial, but it keeps the same bundle-level idea:

  • Vehicles provides the vehicle interfaces and ready-made axle connection abstractions
  • MachineModeling provides the component structure for the articulated chassis
  • Blender-exported rigid-body traits provide geometry and connector frames
  • the final truck model just maps those parts together
OpenPLX is a work in progress. This draft version will evolve with user feedback and experience. We welcome your input and collaboration.
X