JointsMaker.cpp 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include "JointsMaker.h"
  9. #include "PrefabMakerUtils.h"
  10. #include <AzToolsFramework/Entity/EditorEntityHelpers.h>
  11. #include <RobotImporter/Utils/TypeConversions.h>
  12. #include <Source/EditorColliderComponent.h>
  13. #include <Source/EditorFixedJointComponent.h>
  14. #include <Source/EditorHingeJointComponent.h>
  15. #include <Source/EditorPrismaticJointComponent.h>
  16. #include <Source/EditorRigidBodyComponent.h>
  17. namespace ROS2RobotImporter
  18. {
  19. JointsMaker::JointsMakerResult JointsMaker::AddJointComponent(
  20. const sdf::Joint* joint, AZ::EntityId followColliderEntityId, AZ::EntityId leadColliderEntityId) const
  21. {
  22. AZ::Entity* followColliderEntity = AzToolsFramework::GetEntityById(followColliderEntityId);
  23. PhysX::EditorJointComponent* jointComponent = nullptr;
  24. // URDF/SDF has a joint axis configurable by a normalized vector - that is given by the 'axis' sub-element in the joint element.
  25. // The o3de has a slightly different way of configuring the axis of the joint. The o3de has an axis around positive `X` and rotation
  26. // with Euler angles can be applied to configure the desirable direction of the joint. A quaternion that transforms a unit vector X
  27. // {1,0,0} to a vector given by the URDF/SDF joint need to be found. Heavily suboptimal element in this conversion is needed of
  28. // converting the unit quaternion to Euler vector.
  29. const AZ::Vector3 o3deJointDir{ 1.0, 0.0, 0.0 };
  30. const sdf::JointAxis* jointAxis = joint->Axis();
  31. AZ::Vector3 jointCoordinateAxis = AZ::Vector3::CreateZero();
  32. auto quaternion = AZ::Quaternion::CreateIdentity();
  33. if (jointAxis != nullptr)
  34. {
  35. jointCoordinateAxis = URDF::TypeConversions::ConvertVector3(jointAxis->Xyz());
  36. quaternion = jointCoordinateAxis.IsZero() ? AZ::Quaternion::CreateIdentity()
  37. : AZ::Quaternion::CreateShortestArc(o3deJointDir, jointCoordinateAxis);
  38. }
  39. AZ_Printf(
  40. "JointsMaker",
  41. "Quaternion from URDF/SDF to o3de %f, %f, %f, %f",
  42. quaternion.GetX(),
  43. quaternion.GetY(),
  44. quaternion.GetZ(),
  45. quaternion.GetW());
  46. const AZ::Vector3 rotation = quaternion.GetEulerDegrees();
  47. switch (joint->Type())
  48. {
  49. case sdf::JointType::FIXED:
  50. {
  51. jointComponent = followColliderEntity->CreateComponent<PhysX::EditorFixedJointComponent>();
  52. }
  53. break;
  54. case sdf::JointType::PRISMATIC:
  55. {
  56. jointComponent = followColliderEntity->CreateComponent<PhysX::EditorPrismaticJointComponent>();
  57. followColliderEntity->Activate();
  58. PhysX::EditorJointRequestBus::Event(
  59. AZ::EntityComponentIdPair(followColliderEntityId, jointComponent->GetId()),
  60. &PhysX::EditorJointRequests::SetVector3Value,
  61. PhysX::JointsComponentModeCommon::ParameterNames::Rotation,
  62. rotation);
  63. if (jointAxis != nullptr)
  64. {
  65. PhysX::EditorJointRequestBus::Event(
  66. AZ::EntityComponentIdPair(followColliderEntityId, jointComponent->GetId()),
  67. &PhysX::EditorJointRequests::SetLinearValuePair,
  68. PhysX::JointsComponentModeCommon::ParameterNames::LinearLimits,
  69. PhysX::AngleLimitsFloatPair(jointAxis->Upper(), jointAxis->Lower()));
  70. }
  71. followColliderEntity->Deactivate();
  72. }
  73. break;
  74. case sdf::JointType::CONTINUOUS:
  75. { // Implemented as Hinge with angular limit disabled
  76. jointComponent = followColliderEntity->CreateComponent<PhysX::EditorHingeJointComponent>();
  77. followColliderEntity->Activate();
  78. PhysX::EditorJointRequestBus::Event(
  79. AZ::EntityComponentIdPair(followColliderEntityId, jointComponent->GetId()),
  80. [&rotation](PhysX::EditorJointRequests* editorJointRequest)
  81. {
  82. editorJointRequest->SetVector3Value(PhysX::JointsComponentModeCommon::ParameterNames::Rotation, rotation);
  83. editorJointRequest->SetLinearValuePair(
  84. PhysX::JointsComponentModeCommon::ParameterNames::TwistLimits,
  85. PhysX::AngleLimitsFloatPair(AZ::RadToDeg(AZ::Constants::TwoPi), -AZ::RadToDeg(AZ::Constants::TwoPi)));
  86. editorJointRequest->SetBoolValue(PhysX::JointsComponentModeCommon::ParameterNames::EnableLimits, false);
  87. });
  88. followColliderEntity->Deactivate();
  89. }
  90. break;
  91. case sdf::JointType::REVOLUTE:
  92. { // Hinge
  93. jointComponent = followColliderEntity->CreateComponent<PhysX::EditorHingeJointComponent>();
  94. followColliderEntity->Activate();
  95. if (jointAxis != nullptr)
  96. {
  97. using LimitType = decltype(jointAxis->Upper());
  98. const bool enableJointLimits = jointAxis->Upper() != AZStd::numeric_limits<LimitType>::infinity() ||
  99. jointAxis->Lower() != -AZStd::numeric_limits<LimitType>::infinity();
  100. const double limitUpper = jointAxis->Upper() != AZStd::numeric_limits<LimitType>::infinity()
  101. ? AZ::RadToDeg(jointAxis->Upper())
  102. : AZ::RadToDeg(AZ::Constants::TwoPi);
  103. const double limitLower = jointAxis->Lower() != -AZStd::numeric_limits<LimitType>::infinity()
  104. ? AZ::RadToDeg(jointAxis->Lower())
  105. : -AZ::RadToDeg(AZ::Constants::TwoPi);
  106. AZ_Printf(
  107. "JointsMaker",
  108. "Setting limits : upper: %.1f lower: %.1f (URDF/SDF:%f,%f)",
  109. limitUpper,
  110. limitLower,
  111. jointAxis->Upper(),
  112. jointAxis->Lower());
  113. PhysX::EditorJointRequestBus::Event(
  114. AZ::EntityComponentIdPair(followColliderEntityId, jointComponent->GetId()),
  115. [&rotation, enableJointLimits, &limitLower, &limitUpper](PhysX::EditorJointRequests* editorJointRequest)
  116. {
  117. editorJointRequest->SetVector3Value(PhysX::JointsComponentModeCommon::ParameterNames::Rotation, rotation);
  118. editorJointRequest->SetLinearValuePair(
  119. PhysX::JointsComponentModeCommon::ParameterNames::TwistLimits,
  120. PhysX::AngleLimitsFloatPair(limitUpper, limitLower));
  121. editorJointRequest->SetBoolValue(
  122. PhysX::JointsComponentModeCommon::ParameterNames::EnableLimits, enableJointLimits);
  123. });
  124. }
  125. followColliderEntity->Deactivate();
  126. }
  127. break;
  128. default:
  129. AZ_Warning(
  130. "AddJointComponent",
  131. false,
  132. "Unknown or unsupported joint type %d for joint %s",
  133. static_cast<int>(joint->Type()),
  134. joint->Name().c_str());
  135. return AZ::Failure(AZStd::string::format("unsupported joint type : %d", static_cast<int>(joint->Type())));
  136. }
  137. followColliderEntity->Activate();
  138. PhysX::EditorJointRequestBus::Event(
  139. AZ::EntityComponentIdPair(followColliderEntityId, jointComponent->GetId()),
  140. &PhysX::EditorJointRequests::SetEntityIdValue,
  141. PhysX::JointsComponentModeCommon::ParameterNames::LeadEntity,
  142. leadColliderEntityId);
  143. followColliderEntity->Deactivate();
  144. return AZ::Success(jointComponent->GetId());
  145. }
  146. } // namespace ROS2RobotImporter