123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271 |
- /*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
- #include "Utilities.h"
- #include "Source/ArticulationLinkComponent.h"
- #include "WheelControllerComponent.h"
- #include <AzCore/Component/ComponentApplicationBus.h>
- #include <AzCore/Component/Entity.h>
- #include <AzCore/std/string/string.h>
- #include <HingeJointComponent.h>
- #include <PhysX/Joint/PhysXJointRequestsBus.h>
- #include <Utilities/ArticulationsUtilities.h>
- namespace ROS2Controllers::VehicleDynamics::Utilities
- {
- AxleConfiguration Create2WheelAxle(
- AZ::EntityId leftWheel, AZ::EntityId rightWheel, AZStd::string tag, float wheelRadius, bool steering, bool drive)
- {
- VehicleDynamics::AxleConfiguration axleConfiguration;
- axleConfiguration.m_axleWheels.push_back(leftWheel);
- axleConfiguration.m_axleWheels.push_back(rightWheel);
- axleConfiguration.m_axleTag = AZStd::move(tag);
- axleConfiguration.m_isSteering = steering;
- axleConfiguration.m_isDrive = drive;
- axleConfiguration.m_wheelRadius = wheelRadius;
- return axleConfiguration;
- }
- AxleConfiguration CreateFrontSteerAndDriveAxle(AZ::EntityId leftWheel, AZ::EntityId rightWheel, float wheelRadius)
- {
- return Create2WheelAxle(leftWheel, rightWheel, "Front", wheelRadius, true, true);
- }
- AxleConfiguration CreateRearDriveAxle(AZ::EntityId leftWheel, AZ::EntityId rightWheel, float wheelRadius)
- {
- return Create2WheelAxle(leftWheel, rightWheel, "Rear", wheelRadius, false, true);
- }
- AZStd::vector<VehicleDynamics::SteeringDynamicsData> GetAllSteeringEntitiesData(const VehicleConfiguration& vehicleConfig)
- {
- AZStd::vector<VehicleDynamics::SteeringDynamicsData> steeringEntitiesAndAxis;
- for (const auto& axle : vehicleConfig.m_axles)
- {
- if (!axle.m_isSteering)
- { // Only steering axles will have steering entities
- continue;
- }
- for (const auto& wheel : axle.m_axleWheels)
- {
- if (!wheel.IsValid())
- {
- AZ_Warning("GetAllSteeringEntitiesData", false, "Wheel entity in axle %s is invalid, ignoring", axle.m_axleTag.c_str());
- continue;
- }
- AZ::Entity* wheelEntity = nullptr;
- AZ::ComponentApplicationBus::BroadcastResult(wheelEntity, &AZ::ComponentApplicationRequests::FindEntity, wheel);
- if (!wheelEntity)
- {
- AZ_Warning("GetAllSteeringEntitiesData", false, "Wheel entity in axle %s is null, ignoring", axle.m_axleTag.c_str());
- continue;
- }
- auto* controllerComponent = wheelEntity->FindComponent<WheelControllerComponent>();
- if (!controllerComponent)
- {
- AZ_Warning(
- "GetAllSteeringEntitiesData",
- false,
- "Missing a WheelController in wheel entity %s, ignoring",
- wheel.ToString().c_str());
- continue;
- }
- AZ::EntityId steeringEntity = controllerComponent->m_steeringEntity;
- if (!steeringEntity.IsValid())
- {
- AZ_Warning(
- "GetAllSteeringEntitiesData",
- false,
- "Steering entity specified for WheelController in entity %s is invalid, ignoring",
- wheel.ToString().c_str());
- continue;
- }
- const float steeringScale = controllerComponent->m_steeringScale;
- AZ::Entity* steeringEntityptr{ nullptr };
- AZ::ComponentApplicationBus::BroadcastResult(
- steeringEntityptr, &AZ::ComponentApplicationRequests::FindEntity, steeringEntity);
- AZ_Assert(steeringEntityptr, "Cannot find a steering entity for %s", steeringEntity.ToString().c_str());
- PhysX::HingeJointComponent* hingeComponent{ nullptr };
- hingeComponent = steeringEntityptr->FindComponent<PhysX::HingeJointComponent>();
- PhysX::ArticulationLinkComponent* articulation{ nullptr };
- articulation = steeringEntityptr->FindComponent<PhysX::ArticulationLinkComponent>();
- if (!hingeComponent && !articulation)
- {
- AZ_Warning(
- "GetAllSteeringEntitiesData",
- false,
- "Steering entity specified for WheelController in entity %s does not have either a HingeJointComponent or an "
- "ArticulationLinkComponent, ignoring",
- wheel.ToString().c_str());
- continue;
- }
- if (articulation)
- {
- if (articulation->m_config.m_articulationJointType != PhysX::ArticulationJointType::Hinge)
- {
- AZ_Warning(
- "GetAllSteeringEntitiesData",
- false,
- "Steering entity specified for WheelController in entity %s has an Articulation Link, but it's not a hinge "
- "joint, ignoring",
- wheel.ToString().c_str());
- continue;
- }
- }
- VehicleDynamics::SteeringDynamicsData steeringData;
- steeringData.m_steeringScale = steeringScale;
- steeringData.m_steeringEntity = steeringEntity;
- steeringData.m_isArticulation = articulation;
- if (articulation)
- {
- steeringData.m_steeringJoint = articulation->GetId();
- [[maybe_unused]] const bool hasFreeAxis =
- Utils::TryGetFreeArticulationAxis(steeringData.m_steeringEntity, steeringData.m_axis);
- AZ_Error("VehicleDynamics::Utilities", hasFreeAxis, "Articulation steering has no free axis somehow");
- }
- else
- {
- steeringData.m_steeringJoint = hingeComponent->GetId();
- }
- steeringEntitiesAndAxis.push_back(steeringData);
- }
- }
- return steeringEntitiesAndAxis;
- }
- AZStd::vector<VehicleDynamics::WheelDynamicsData> GetAllDriveWheelsData(const VehicleConfiguration& vehicleConfig)
- {
- AZStd::vector<VehicleDynamics::WheelDynamicsData> driveWheelEntities;
- for (const AxleConfiguration& axle : vehicleConfig.m_axles)
- {
- if (!axle.m_isDrive)
- { // Get only drive wheels, which are attached to a drive axle
- continue;
- }
- for (const AZ::EntityId& wheel : axle.m_axleWheels)
- {
- if (!wheel.IsValid())
- {
- AZ_Warning("GetAllSteeringEntitiesData", false, "Wheel entity in axle %s is invalid, ignoring", axle.m_axleTag.c_str());
- continue;
- }
- AZ::Entity* wheelEntity = nullptr;
- AZ::ComponentApplicationBus::BroadcastResult(wheelEntity, &AZ::ComponentApplicationRequests::FindEntity, wheel);
- if (!wheelEntity)
- {
- AZ_Warning("GetAllSteeringEntitiesData", false, "Wheel entity in axle %s is null, ignoring", axle.m_axleTag.c_str());
- continue;
- }
- auto* controllerComponent = wheelEntity->FindComponent<WheelControllerComponent>();
- if (!controllerComponent)
- {
- AZ_Warning(
- "GetAllDriveWheelsData",
- false,
- "Wheel entity for axle %s is missing a WheelController component, ignoring",
- axle.m_axleTag.c_str());
- continue;
- }
- VehicleDynamics::WheelDynamicsData wheelData = GetWheelData(wheel, axle.m_wheelRadius);
- driveWheelEntities.push_back(wheelData);
- }
- }
- return driveWheelEntities;
- }
- VehicleDynamics::WheelDynamicsData GetWheelData(const AZ::EntityId wheelEntityId, float wheelRadius)
- {
- VehicleDynamics::WheelDynamicsData wheelData;
- wheelData.m_wheelEntity = wheelEntityId;
- wheelData.m_wheelRadius = wheelRadius;
- AZ::Entity* wheelEntity = nullptr;
- AZ::ComponentApplicationBus::BroadcastResult(wheelEntity, &AZ::ComponentApplicationRequests::FindEntity, wheelEntityId);
- if (!wheelEntity)
- {
- AZ_Warning("GetWheelDynamicData", false, "Entity %s was not found", wheelEntityId.ToString().c_str());
- return wheelData;
- }
- PhysX::HingeJointComponent* hingeComponent{ nullptr };
- hingeComponent = wheelEntity->FindComponent<PhysX::HingeJointComponent>();
- PhysX::ArticulationLinkComponent* articulationComponent{ nullptr };
- articulationComponent = wheelEntity->FindComponent<PhysX::ArticulationLinkComponent>();
- if (hingeComponent)
- {
- wheelData.m_isArticulation = false;
- wheelData.m_wheelJoint = hingeComponent->GetId();
- return wheelData;
- }
- if (articulationComponent)
- {
- wheelData.m_isArticulation = true;
- Utils::TryGetFreeArticulationAxis(wheelEntityId, wheelData.m_axis);
- wheelData.m_wheelJoint = articulationComponent->GetId();
- return wheelData;
- }
- AZ_Warning("GetWheelDynamicData", false, "Entity %s has no PhysX::HingeJointComponent", wheelEntityId.ToString().c_str());
- return wheelData;
- }
- float ComputeRampVelocity(float targetVelocity, float lastVelocity, AZ::u64 deltaTimeNs, float acceleration, float maxVelocity)
- {
- const float deltaTimeSec = 1e-9f * static_cast<float>(deltaTimeNs);
- const float deltaAcceleration = deltaTimeSec * acceleration;
- float commandVelocity = 0;
- if (AZStd::abs(lastVelocity - targetVelocity) < deltaAcceleration)
- {
- commandVelocity = targetVelocity;
- }
- else if (targetVelocity > lastVelocity)
- {
- commandVelocity = lastVelocity + deltaAcceleration;
- }
- else if (targetVelocity < lastVelocity)
- {
- commandVelocity = lastVelocity - deltaAcceleration;
- }
- return AZStd::clamp(commandVelocity, -maxVelocity, maxVelocity);
- }
- void SetWheelRotationSpeed(const VehicleDynamics::WheelDynamicsData& data, float wheelRotationSpeed)
- {
- if (data.m_isArticulation)
- {
- PhysX::ArticulationJointRequestBus::Event(
- data.m_wheelEntity, &PhysX::ArticulationJointRequests::SetDriveTargetVelocity, data.m_axis, wheelRotationSpeed);
- }
- else
- {
- PhysX::JointRequestBus::Event(
- AZ::EntityComponentIdPair(data.m_wheelEntity, data.m_wheelJoint), &PhysX::JointRequests::SetVelocity, wheelRotationSpeed);
- }
- }
- AZ::Transform GetJointTransform(const VehicleDynamics::WheelDynamicsData& data)
- {
- AZ::Transform hingeTransform{ AZ::Transform::Identity() };
- if (!data.m_isArticulation)
- {
- PhysX::JointRequestBus::EventResult(
- hingeTransform, AZ::EntityComponentIdPair(data.m_wheelEntity, data.m_wheelJoint), &PhysX::JointRequests::GetTransform);
- }
- return hingeTransform;
- }
- } // namespace ROS2Controllers::VehicleDynamics::Utilities
|