Program Listing for include/vehicle2/drivetrain/PxVehicleDrivetrainComponents.h

↰ Return to documentation for include/vehicle2/drivetrain/PxVehicleDrivetrainComponents.h

// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//  * Redistributions of source code must retain the above copyright
//    notice, this list of conditions and the following disclaimer.
//  * Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in the
//    documentation and/or other materials provided with the distribution.
//  * Neither the name of NVIDIA CORPORATION nor the names of its
//    contributors may be used to endorse or promote products derived
//    from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2022 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.

#pragma once

#include "vehicle2/PxVehicleFunctions.h"
#include "vehicle2/PxVehicleParams.h"
#include "vehicle2/PxVehicleComponent.h"

#include "vehicle2/braking/PxVehicleBrakingFunctions.h"
#include "vehicle2/commands/PxVehicleCommandHelpers.h"
#include "vehicle2/rigidBody/PxVehicleRigidBodyStates.h"
#include "vehicle2/steering/PxVehicleSteeringFunctions.h"
#include "vehicle2/steering/PxVehicleSteeringParams.h"
#include "vehicle2/wheel/PxVehicleWheelStates.h"
#include "vehicle2/wheel/PxVehicleWheelParams.h"
#include "vehicle2/tire/PxVehicleTireStates.h"

#include "PxVehicleDrivetrainStates.h"
#include "PxVehicleDrivetrainFunctions.h"

#include "common/PxProfileZone.h"

#if !PX_DOXYGEN
namespace physx
{
namespace vehicle2
{
#endif

struct PxVehicleBrakeCommandResponseParams;
struct PxVehicleDirectDriveThrottleCommandResponseParams;

class PxVehicleDirectDriveCommandResponseComponent : public PxVehicleComponent
{
public:

    PxVehicleDirectDriveCommandResponseComponent() : PxVehicleComponent() {}
    virtual ~PxVehicleDirectDriveCommandResponseComponent() {}

    virtual void getDataForDirectDriveCommandResponseComponent(
        const PxVehicleAxleDescription*& axleDescription,
        PxVehicleSizedArrayData<const PxVehicleBrakeCommandResponseParams>& brakeResponseParams,
        const PxVehicleDirectDriveThrottleCommandResponseParams*& throttleResponseParams,
        const PxVehicleSteerCommandResponseParams*& steerResponseParams,
        PxVehicleSizedArrayData<const PxVehicleAckermannParams>& ackermannParams,
        const PxVehicleCommandState*& commands, const PxVehicleDirectDriveTransmissionCommandState*& transmissionCommands,
        const PxVehicleRigidBodyState*& rigidBodyState,
        PxVehicleArrayData<PxReal>& brakeResponseStates,
        PxVehicleArrayData<PxReal>& throttleResponseStates,
        PxVehicleArrayData<PxReal>& steerResponseStates) = 0;

    virtual bool update(const PxReal dt, const PxVehicleSimulationContext& context)
    {
        PX_UNUSED(dt);
        PX_UNUSED(context);

        PX_PROFILE_ZONE("PxVehicleDirectDriveCommandResponseComponent::update", 0);

        const PxVehicleAxleDescription* axleDescription;
        PxVehicleSizedArrayData<const PxVehicleBrakeCommandResponseParams> brakeResponseParams;
        const PxVehicleDirectDriveThrottleCommandResponseParams* throttleResponseParams;
        const PxVehicleSteerCommandResponseParams* steerResponseParams;
        PxVehicleSizedArrayData<const PxVehicleAckermannParams> ackermannParams;
        const PxVehicleCommandState* commands;
        const PxVehicleDirectDriveTransmissionCommandState* transmissionCommands;
        const PxVehicleRigidBodyState* rigidBodyState;
        PxVehicleArrayData<PxReal> brakeResponseStates;
        PxVehicleArrayData<PxReal> throttleResponseStates;
        PxVehicleArrayData<PxReal> steerResponseStates;

        getDataForDirectDriveCommandResponseComponent(axleDescription,
            brakeResponseParams,  throttleResponseParams, steerResponseParams, ackermannParams,
            commands, transmissionCommands,
            rigidBodyState,
            brakeResponseStates, throttleResponseStates, steerResponseStates);

        const PxReal longitudinalSpeed = rigidBodyState->getLongitudinalSpeed(context.frame);

        for (PxU32 i = 0; i < axleDescription->nbWheels; i++)
        {
            const PxU32 wheelId = axleDescription->wheelIdsInAxleOrder[i];

            PxVehicleBrakeCommandResponseUpdate(
                commands->brakes, commands->nbBrakes, longitudinalSpeed,
                wheelId, brakeResponseParams,
                brakeResponseStates[wheelId]);

            PxVehicleDirectDriveThrottleCommandResponseUpdate(
                commands->throttle, *transmissionCommands, longitudinalSpeed,
                wheelId, *throttleResponseParams,
                throttleResponseStates[wheelId]);

            PxVehicleSteerCommandResponseUpdate(
                commands->steer, longitudinalSpeed,
                wheelId, *steerResponseParams,
                steerResponseStates[wheelId]);
        }
        if (ackermannParams.size > 0)
            PxVehicleAckermannSteerUpdate(
                commands->steer,
                *steerResponseParams, ackermannParams,
                steerResponseStates);

        return true;
    }
};


class PxVehicleDirectDriveActuationStateComponent : public PxVehicleComponent
{
public:

    PxVehicleDirectDriveActuationStateComponent() : PxVehicleComponent() {}
    virtual ~PxVehicleDirectDriveActuationStateComponent() {}


    virtual void getDataForDirectDriveActuationStateComponent(
        const PxVehicleAxleDescription*& axleDescription,
        PxVehicleArrayData<const PxReal>& brakeResponseStates,
        PxVehicleArrayData<const PxReal>& throttleResponseStates,
        PxVehicleArrayData<PxVehicleWheelActuationState>& actuationStates) = 0;

    virtual bool update(const PxReal dt, const PxVehicleSimulationContext& context)
    {
        PX_UNUSED(dt);
        PX_UNUSED(context);

        PX_PROFILE_ZONE("PxVehicleDirectDriveActuationStateComponent::update", 0);

        const PxVehicleAxleDescription* axleDescription;
        PxVehicleArrayData<const PxReal> brakeResponseStates;
        PxVehicleArrayData<const PxReal> throttleResponseStates;
        PxVehicleArrayData<PxVehicleWheelActuationState> actuationStates;

        getDataForDirectDriveActuationStateComponent(
            axleDescription,
            brakeResponseStates, throttleResponseStates,
            actuationStates);

        for (PxU32 i = 0; i < axleDescription->nbWheels; i++)
        {
            const PxU32 wheelId = axleDescription->wheelIdsInAxleOrder[i];
            PxVehicleDirectDriveActuationStateUpdate(
                brakeResponseStates[wheelId], throttleResponseStates[wheelId],
                actuationStates[wheelId]);
        }

        return true;
    }
};

class PxVehicleDirectDrivetrainComponent : public PxVehicleComponent
{
public:

    PxVehicleDirectDrivetrainComponent() : PxVehicleComponent() {}
    virtual ~PxVehicleDirectDrivetrainComponent() {}

    virtual void getDataForDirectDrivetrainComponent(
        const PxVehicleAxleDescription*& axleDescription,
        PxVehicleArrayData<const PxReal>& brakeResponseStates,
        PxVehicleArrayData<const PxReal>& throttleResponseStates,
        PxVehicleArrayData<const PxVehicleWheelParams>& wheelParams,
        PxVehicleArrayData<const PxVehicleWheelActuationState>& actuationStates,
        PxVehicleArrayData<const PxVehicleTireForce>& tireForces,
        PxVehicleArrayData<PxVehicleWheelRigidBody1dState>& wheelRigidBody1dStates) = 0;

    virtual bool update(const PxReal dt, const PxVehicleSimulationContext& context)
    {
        PX_UNUSED(context);

        PX_PROFILE_ZONE("PxVehicleDirectDrivetrainComponent::update", 0);

        const PxVehicleAxleDescription* axleDescription;
        PxVehicleArrayData<const PxReal> brakeResponseStates;
        PxVehicleArrayData<const PxReal> throttleResponseStates;
        PxVehicleArrayData<const PxVehicleWheelParams> wheelParams;
        PxVehicleArrayData<const PxVehicleWheelActuationState> actuationStates;
        PxVehicleArrayData<const PxVehicleTireForce> tireForces;
        PxVehicleArrayData<PxVehicleWheelRigidBody1dState> wheelRigidBody1dStates;

        getDataForDirectDrivetrainComponent(axleDescription,
            brakeResponseStates, throttleResponseStates,
            wheelParams, actuationStates, tireForces,
            wheelRigidBody1dStates);

        for (PxU32 i = 0; i < axleDescription->nbWheels; i++)
        {
            const PxU32 wheelId = axleDescription->wheelIdsInAxleOrder[i];

            PxVehicleDirectDriveUpdate(
                wheelParams[wheelId], actuationStates[wheelId],
                brakeResponseStates[wheelId], throttleResponseStates[wheelId],
                tireForces[wheelId],
                dt,
                wheelRigidBody1dStates[wheelId]);
        }

        return true;
    }
};

class PxVehicleEngineDriveCommandResponseComponent : public PxVehicleComponent
{
public:

    PxVehicleEngineDriveCommandResponseComponent() : PxVehicleComponent() {}
    virtual ~PxVehicleEngineDriveCommandResponseComponent() {}

    virtual void getDataForEngineDriveCommandResponseComponent(
        const PxVehicleAxleDescription*& axleDescription,
        PxVehicleSizedArrayData<const PxVehicleBrakeCommandResponseParams>& brakeResponseParams,
        const PxVehicleSteerCommandResponseParams*& steerResponseParams,
        PxVehicleSizedArrayData<const PxVehicleAckermannParams>& ackermannParams,
        const PxVehicleGearboxParams*& gearboxParams,
        const PxVehicleClutchCommandResponseParams*& clutchResponseParams,
        const PxVehicleEngineParams*& engineParams,
        const PxVehicleRigidBodyState*& rigidBodyState,
        const PxVehicleEngineState*& engineState,
        const PxVehicleAutoboxParams*& autoboxParams,
        const PxVehicleCommandState*& commands,
        const PxVehicleEngineDriveTransmissionCommandState*& transmissionCommands,
        PxVehicleArrayData<PxReal>& brakeResponseStates,
        PxVehicleEngineDriveThrottleCommandResponseState*& throttleResponseState,
        PxVehicleArrayData<PxReal>& steerResponseStates,
        PxVehicleGearboxState*& gearboxResponseState,
        PxVehicleClutchCommandResponseState*& clutchResponseState,
        PxVehicleAutoboxState*& autoboxState) = 0;

    virtual bool update(const PxReal dt, const PxVehicleSimulationContext& context)
    {
        PX_UNUSED(dt);
        PX_UNUSED(context);

        PX_PROFILE_ZONE("PxVehicleEngineDriveCommandResponseComponent::update", 0);

        const PxVehicleAxleDescription* axleDescription;
        PxVehicleSizedArrayData<const PxVehicleBrakeCommandResponseParams> brakeResponseParams;
        const PxVehicleSteerCommandResponseParams* steerResponseParams;
        PxVehicleSizedArrayData<const PxVehicleAckermannParams> ackermannParams;
        const PxVehicleGearboxParams* gearboxParams;
        const PxVehicleClutchCommandResponseParams* clutchResponseParams;
        const PxVehicleEngineParams* engineParams;
        const PxVehicleRigidBodyState* rigidBodyState;
        const PxVehicleEngineState* engineState;
        const PxVehicleAutoboxParams* autoboxParams;
        const PxVehicleCommandState* commands;
        const PxVehicleEngineDriveTransmissionCommandState* transmissionCommands;
        PxVehicleArrayData<PxReal> brakeResponseStates;
        PxVehicleEngineDriveThrottleCommandResponseState* throttleResponseState;
        PxVehicleArrayData<PxReal> steerResponseStates;
        PxVehicleGearboxState* gearboxResponseState;
        PxVehicleClutchCommandResponseState* clutchResponseState;
        PxVehicleAutoboxState* autoboxState;

        getDataForEngineDriveCommandResponseComponent(axleDescription,
            brakeResponseParams, steerResponseParams, ackermannParams,
            gearboxParams, clutchResponseParams, engineParams, rigidBodyState,
            engineState, autoboxParams,
            commands, transmissionCommands,
            brakeResponseStates, throttleResponseState,
            steerResponseStates,
            gearboxResponseState, clutchResponseState, autoboxState);

        //The autobox can modify commands like throttle and target gear. Since the user defined
        //values should not be overwritten, a copy is used to compute the response.
        PxVehicleCommandState commandsTmp = *commands;
        PxVehicleEngineDriveTransmissionCommandState transmissionCommandsTmp = *transmissionCommands;

        const PxReal longitudinalSpeed = rigidBodyState->getLongitudinalSpeed(context.frame);

        //Let the autobox set the target gear, unless the user defined target gear requests
        //a shift already
        if (autoboxParams)
        {
            PX_ASSERT(engineParams);
            PX_ASSERT(engineState);
            PX_ASSERT(autoboxState);

            PxVehicleAutoBoxUpdate(
                *engineParams, *gearboxParams, *autoboxParams,
                *engineState, *gearboxResponseState, dt,
                transmissionCommandsTmp.targetGear, *autoboxState, commandsTmp.throttle);
        }
        else if (transmissionCommandsTmp.targetGear == PxVehicleEngineDriveTransmissionCommandState::eAUTOMATIC_GEAR)
        {
            //If there is no autobox but eAUTOMATIC_GEAR was specified, use the current target gear
            transmissionCommandsTmp.targetGear = gearboxResponseState->targetGear;
        }

        //Distribute brake torque to the wheels across each axle.
        for (PxU32 i = 0; i < axleDescription->nbWheels; i++)
        {
            const PxU32 wheelId = axleDescription->wheelIdsInAxleOrder[i];
            PxVehicleBrakeCommandResponseUpdate(
                commandsTmp.brakes, commandsTmp.nbBrakes, longitudinalSpeed,
                wheelId, brakeResponseParams,
                brakeResponseStates[i]);
        }

        //Update target gear as required.
        PxVehicleGearCommandResponseUpdate(
            transmissionCommandsTmp.targetGear,
            *gearboxParams,
            *gearboxResponseState);

        //Compute the response to the clutch command.
        PxVehicleClutchCommandResponseLinearUpdate(
            transmissionCommandsTmp.clutch,
            *clutchResponseParams,
            *clutchResponseState);

        //Compute the response to the throttle command.
        PxVehicleEngineDriveThrottleCommandResponseLinearUpdate(
            commandsTmp,
            *throttleResponseState);

        //Update the steer angles and Ackermann correction.
        for (PxU32 i = 0; i < axleDescription->nbWheels; i++)
        {
            const PxU32 wheelId = axleDescription->wheelIdsInAxleOrder[i];
            PxVehicleSteerCommandResponseUpdate(commandsTmp.steer, longitudinalSpeed, wheelId, *steerResponseParams, steerResponseStates[i]);
        }
        if (ackermannParams.size > 0)
            PxVehicleAckermannSteerUpdate(commandsTmp.steer, *steerResponseParams, ackermannParams, steerResponseStates);

        return true;
    }
};

class PxVehicleMultiWheelDriveDifferentialStateComponent : public PxVehicleComponent
{
public:

    PxVehicleMultiWheelDriveDifferentialStateComponent() : PxVehicleComponent() {}
    virtual ~PxVehicleMultiWheelDriveDifferentialStateComponent() {}

    virtual void getDataForMultiWheelDriveDifferentialStateComponent(
        const PxVehicleAxleDescription*& axleDescription,
        const PxVehicleMultiWheelDriveDifferentialParams*& differentialParams,
        PxVehicleDifferentialState*& differentialState) = 0;

    virtual bool update(const PxReal dt, const PxVehicleSimulationContext& context)
    {
        PX_UNUSED(dt);
        PX_UNUSED(context);

        PX_PROFILE_ZONE("PxVehicleMultiWheelDriveDifferentialStateComponent::update", 0);

        const PxVehicleAxleDescription* axleDescription;
        const PxVehicleMultiWheelDriveDifferentialParams* differentialParams;
        PxVehicleDifferentialState* differentialState;

        getDataForMultiWheelDriveDifferentialStateComponent(axleDescription,
            differentialParams, differentialState);

        PxVehicleDifferentialStateUpdate(
            *axleDescription,
            *differentialParams,
            *differentialState);

        return true;
    }
};

class PxVehicleFourWheelDriveDifferentialStateComponent : public PxVehicleComponent
{
public:

    PxVehicleFourWheelDriveDifferentialStateComponent() : PxVehicleComponent() {}
    virtual ~PxVehicleFourWheelDriveDifferentialStateComponent() {}

    virtual void getDataForFourWheelDriveDifferentialStateComponent(
        const PxVehicleAxleDescription*& axleDescription,
        const PxVehicleFourWheelDriveDifferentialParams*& differentialParams,
        PxVehicleArrayData<const PxVehicleWheelRigidBody1dState>& wheelRigidbody1dStates,
        PxVehicleDifferentialState*& differentialState,
        PxVehicleWheelConstraintGroupState*& wheelConstraintGroupState) = 0;

    virtual bool update(const PxReal dt, const PxVehicleSimulationContext& context)
    {
        PX_UNUSED(dt);
        PX_UNUSED(context);

        PX_PROFILE_ZONE("PxVehicleFourWheelDriveDifferentialStateComponent::update", 0);

        const PxVehicleAxleDescription* axleDescription;
        const PxVehicleFourWheelDriveDifferentialParams* differentialParams;
        PxVehicleArrayData<const PxVehicleWheelRigidBody1dState> wheelRigidbody1dStates;
        PxVehicleDifferentialState* differentialState;
        PxVehicleWheelConstraintGroupState* wheelConstraintGroupState;

        getDataForFourWheelDriveDifferentialStateComponent(axleDescription, differentialParams,
            wheelRigidbody1dStates,
            differentialState, wheelConstraintGroupState);

        PxVehicleDifferentialStateUpdate(
            *axleDescription, *differentialParams,
            wheelRigidbody1dStates, dt,
            *differentialState, *wheelConstraintGroupState);

        return true;
    }
};

class PxVehicleTankDriveDifferentialStateComponent : public PxVehicleComponent
{
public:

    PxVehicleTankDriveDifferentialStateComponent() : PxVehicleComponent() {}
    virtual ~PxVehicleTankDriveDifferentialStateComponent() {}

    virtual void getDataForTankDriveDifferentialStateComponent(
        const PxVehicleAxleDescription*& axleDescription,
        const PxVehicleTankDriveTransmissionCommandState*& transmissionCommands,
        PxVehicleArrayData<const PxVehicleWheelParams>& wheelParams,
        const PxVehicleTankDriveDifferentialParams*& differentialParams,
        PxVehicleDifferentialState*& differentialState,
        PxVehicleWheelConstraintGroupState*& constraintGroupState) = 0;

    virtual bool update(const PxReal dt, const PxVehicleSimulationContext& context)
    {
        PX_UNUSED(dt);
        PX_UNUSED(context);

        PX_PROFILE_ZONE("PxVehicleTankDriveDifferentialStateComponent::update", 0);

        const PxVehicleAxleDescription* axleDescription;
        const PxVehicleTankDriveTransmissionCommandState* transmissionCommands;
        PxVehicleArrayData<const PxVehicleWheelParams> wheelParams;
        const PxVehicleTankDriveDifferentialParams* differentialParams;
        PxVehicleDifferentialState* differentialState;
        PxVehicleWheelConstraintGroupState* constraintGroupState;

        getDataForTankDriveDifferentialStateComponent(
            axleDescription,
            transmissionCommands,
            wheelParams,
            differentialParams,
            differentialState, constraintGroupState);

        PxVehicleDifferentialStateUpdate(
            *axleDescription,
            wheelParams, *differentialParams,
            transmissionCommands->thrusts[0], transmissionCommands->thrusts[1],
            *differentialState, *constraintGroupState);

        return true;
    }
};

class PX_DEPRECATED PxVehicleLegacyFourWheelDriveDifferentialStateComponent : public PxVehicleComponent
{
public:

    PxVehicleLegacyFourWheelDriveDifferentialStateComponent() : PxVehicleComponent() {}
    virtual ~PxVehicleLegacyFourWheelDriveDifferentialStateComponent() {}

    virtual void getDataForLegacyFourWheelDriveDifferentialStateComponent(
        const PxVehicleAxleDescription*& axleDescription,
        const PxVehicleFourWheelDriveDifferentialLegacyParams*& differentialParams,
        PxVehicleArrayData<const PxVehicleWheelRigidBody1dState>& wheelRigidbody1dStates,
        PxVehicleDifferentialState*& differentialState) = 0;

    virtual bool update(const PxReal dt, const PxVehicleSimulationContext& context)
    {
        PX_UNUSED(dt);
        PX_UNUSED(context);

        PX_PROFILE_ZONE("PxVehicleLegacyFourWheelDriveDifferentialStateComponent::update", 0);

        const PxVehicleAxleDescription* axleDescription;
        const PxVehicleFourWheelDriveDifferentialLegacyParams* differentialParams;
        PxVehicleArrayData<const PxVehicleWheelRigidBody1dState> wheelRigidbody1dStates;
        PxVehicleDifferentialState* differentialState;

        getDataForLegacyFourWheelDriveDifferentialStateComponent(axleDescription, differentialParams,
            wheelRigidbody1dStates,
            differentialState);

        PxVehicleDifferentialStateUpdate(
            *differentialParams, wheelRigidbody1dStates,
            *differentialState);

        return true;
    }
};

class PxVehicleEngineDriveActuationStateComponent : public PxVehicleComponent
{
public:

    PxVehicleEngineDriveActuationStateComponent() : PxVehicleComponent() {}
    virtual ~PxVehicleEngineDriveActuationStateComponent() {}

    virtual void getDataForEngineDriveActuationStateComponent(
        const PxVehicleAxleDescription*& axleDescription,
        const PxVehicleGearboxParams*& gearboxParams,
        PxVehicleArrayData<const PxReal>& brakeResponseStates,
        const PxVehicleEngineDriveThrottleCommandResponseState*& throttleResponseState,
        const PxVehicleGearboxState*& gearboxState,
        const PxVehicleDifferentialState*& differentialState,
        const PxVehicleClutchCommandResponseState*& clutchResponseState,
        PxVehicleArrayData<PxVehicleWheelActuationState>& actuationStates) = 0;

    virtual bool update(const PxReal dt, const PxVehicleSimulationContext& context)
    {
        PX_UNUSED(dt);
        PX_UNUSED(context);

        PX_PROFILE_ZONE("PxVehicleEngineDriveActuationStateComponent::update", 0);

        const PxVehicleAxleDescription* axleDescription;
        const PxVehicleGearboxParams* gearboxParams;
        PxVehicleArrayData<const PxReal> brakeResponseStates;
        const PxVehicleEngineDriveThrottleCommandResponseState* throttleResponseState;
        const PxVehicleGearboxState* gearboxState;
        const PxVehicleDifferentialState* differentialState;
        const PxVehicleClutchCommandResponseState* clutchResponseState;
        PxVehicleArrayData<PxVehicleWheelActuationState> actuationStates;

        getDataForEngineDriveActuationStateComponent(axleDescription, gearboxParams,
            brakeResponseStates, throttleResponseState,
            gearboxState, differentialState, clutchResponseState,
            actuationStates);

        PxVehicleEngineDriveActuationStateUpdate(
            *axleDescription,
            *gearboxParams,
            brakeResponseStates,
            *throttleResponseState,
            *gearboxState, *differentialState, *clutchResponseState,
            actuationStates);

        return true;
    }
};

class PxVehicleEngineDrivetrainComponent : public PxVehicleComponent
{
public:

    PxVehicleEngineDrivetrainComponent() : PxVehicleComponent() {}
    virtual ~PxVehicleEngineDrivetrainComponent() {}

    virtual void getDataForEngineDrivetrainComponent(
        const PxVehicleAxleDescription*& axleDescription,
        PxVehicleArrayData<const PxVehicleWheelParams>& wheelParams,
        const PxVehicleEngineParams*& engineParams,
        const PxVehicleClutchParams*& clutchParams,
        const PxVehicleGearboxParams*& gearboxParams,
        PxVehicleArrayData<const PxReal>& brakeResponseStates,
        PxVehicleArrayData<const PxVehicleWheelActuationState>& actuationStates,
        PxVehicleArrayData<const PxVehicleTireForce>& tireForces,
        const PxVehicleEngineDriveThrottleCommandResponseState*& throttleResponseState,
        const PxVehicleClutchCommandResponseState*& clutchResponseState,
        const PxVehicleDifferentialState*& differentialState,
        const PxVehicleWheelConstraintGroupState*& constraintGroupState,
        PxVehicleArrayData<PxVehicleWheelRigidBody1dState>& wheelRigidBody1dStates,
        PxVehicleEngineState*& engineState,
        PxVehicleGearboxState*& gearboxState,
        PxVehicleClutchSlipState*& clutchState) = 0;

    virtual bool update(const PxReal dt, const PxVehicleSimulationContext& context)
    {
        PX_UNUSED(context);

        PX_PROFILE_ZONE("PxVehicleEngineDrivetrainComponent::update", 0);

        const PxVehicleAxleDescription* axleDescription;
        PxVehicleArrayData<const PxVehicleWheelParams> wheelParams;
        const PxVehicleEngineParams* engineParams;
        const PxVehicleClutchParams* clutchParams;
        const PxVehicleGearboxParams* gearboxParams;
        PxVehicleArrayData<const PxReal> brakeResponseStates;
        PxVehicleArrayData<const PxVehicleWheelActuationState> actuationStates;
        PxVehicleArrayData<const PxVehicleTireForce> tireForces;
        const PxVehicleEngineDriveThrottleCommandResponseState* throttleResponseState;
        const PxVehicleClutchCommandResponseState* clutchResponseState;
        const PxVehicleDifferentialState* differentialState;
        const PxVehicleWheelConstraintGroupState* constraintGroupState;
        PxVehicleArrayData<PxVehicleWheelRigidBody1dState> wheelRigidBody1dStates;
        PxVehicleEngineState* engineState;
        PxVehicleGearboxState* gearboxState;
        PxVehicleClutchSlipState* clutchState;

        getDataForEngineDrivetrainComponent(axleDescription, wheelParams,
            engineParams, clutchParams, gearboxParams,
            brakeResponseStates, actuationStates, tireForces,
            throttleResponseState, clutchResponseState, differentialState, constraintGroupState,
            wheelRigidBody1dStates, engineState, gearboxState, clutchState);

        PxVehicleGearboxUpdate(*gearboxParams, dt, *gearboxState);

        PxVehicleEngineDrivetrainUpdate(
            *axleDescription,
            wheelParams,
            *engineParams, *clutchParams, *gearboxParams,
            brakeResponseStates, actuationStates,
            tireForces,
            *gearboxState, *throttleResponseState, *clutchResponseState, *differentialState, constraintGroupState,
            dt,
            wheelRigidBody1dStates, *engineState, *clutchState);

        return true;
    }
};

#if !PX_DOXYGEN
} // namespace vehicle2
} // namespace physx
#endif