Icarus
Vehicle Simulation as a Transformable Computational Graph, built on Vulcan and Janus
Loading...
Searching...
No Matches
PhysicalComponent.hpp
Go to the documentation of this file.
1#pragma once
2
11
13#include "janus/math/Quaternion.hpp"
14#include <cmath>
15
16namespace icarus {
17
77template <typename Scalar> class PhysicalComponent : public Component<Scalar> {
78 protected:
80 Vec3<Scalar> body_position_ = Vec3<Scalar>::Zero();
81
83 janus::Quaternion<Scalar> body_orientation_;
84
87
110 const auto &config = this->GetConfig();
111
112 // Read position (default to origin)
113 body_position_ = this->read_param_vec3("body_position", Vec3<Scalar>::Zero());
114
115 // Check for Euler angles first (more user-friendly format)
116 if (config.template Has<std::vector<double>>("body_orientation_euler_zyx")) {
117 auto euler_deg = config.template Get<std::vector<double>>("body_orientation_euler_zyx",
118 {0.0, 0.0, 0.0});
119
120 if (euler_deg.size() != 3) {
121 throw ConfigError(
122 "body_orientation_euler_zyx must have 3 elements [yaw, pitch, roll]");
123 }
124
125 // Convert degrees to radians
126 constexpr double deg2rad = M_PI / 180.0;
127 double yaw_rad = euler_deg[0] * deg2rad;
128 double pitch_rad = euler_deg[1] * deg2rad;
129 double roll_rad = euler_deg[2] * deg2rad;
130
131 // Build quaternion from ZYX Euler angles
132 // Note: Janus from_euler() takes (roll, pitch, yaw) order for ZYX sequence
133 body_orientation_ = janus::Quaternion<Scalar>::from_euler(
134 static_cast<Scalar>(roll_rad), static_cast<Scalar>(pitch_rad),
135 static_cast<Scalar>(yaw_rad));
136 } else if (config.template Has<std::vector<double>>("body_orientation")) {
137 // Quaternion format: [w, x, y, z]
138 auto q =
139 config.template Get<std::vector<double>>("body_orientation", {1.0, 0.0, 0.0, 0.0});
140
141 if (q.size() != 4) {
142 throw ConfigError("body_orientation must have 4 elements [w, x, y, z]");
143 }
144
145 body_orientation_ = janus::Quaternion<Scalar>{
146 static_cast<Scalar>(q[0]), // w
147 static_cast<Scalar>(q[1]), // x
148 static_cast<Scalar>(q[2]), // y
149 static_cast<Scalar>(q[3]) // z
150 };
151
152 // Normalize to ensure unit quaternion
154 }
155 // else: keep default identity orientation
156
158 }
159
166 void SetBodyAttachment(const Vec3<Scalar> &position,
167 const janus::Quaternion<Scalar> &orientation) {
168 body_position_ = position;
169 body_orientation_ = orientation;
171 }
172
177 void SetBodyPosition(const Vec3<Scalar> &position) {
178 body_position_ = position;
180 }
181
182 public:
183 // ===== Override Base Class Virtual Methods =====
184
185 [[nodiscard]] bool HasBodyAttachment() const override { return has_body_attachment_; }
186
187 [[nodiscard]] Vec3<Scalar> GetBodyPosition() const override { return body_position_; }
188
189 [[nodiscard]] janus::Quaternion<Scalar> GetBodyOrientation() const override {
190 return body_orientation_;
191 }
192
193 // ===== Additional Accessors =====
194
203 [[nodiscard]] janus::Quaternion<Scalar> GetComponentToBodyRotation() const {
204 return body_orientation_.conjugate();
205 }
206
212 [[nodiscard]] Vec3<Scalar> TransformToBodyFrame(const Vec3<Scalar> &v_local) const {
213 return body_orientation_.conjugate().rotate(v_local);
214 }
215
221 [[nodiscard]] Vec3<Scalar> TransformToLocalFrame(const Vec3<Scalar> &v_body) const {
222 return body_orientation_.rotate(v_body);
223 }
224};
225
226} // namespace icarus
Base class for all simulation components.
Base class for all simulation components.
Definition Component.hpp:47
const ComponentConfig & GetConfig() const
Get component configuration.
Definition Component.hpp:227
Vec3< Scalar > read_param_vec3(const std::string &key, const Vec3< Scalar > &default_val) const
Read a Vec3 config parameter with automatic double→Scalar conversion.
Definition Component.hpp:272
Configuration/parsing errors with optional file context.
Definition Error.hpp:185
Intermediate class for components with physical body attachment.
Definition PhysicalComponent.hpp:77
janus::Quaternion< Scalar > GetBodyOrientation() const override
Get the component's mounting orientation (body-to-component rotation).
Definition PhysicalComponent.hpp:189
void SetBodyAttachment(const Vec3< Scalar > &position, const janus::Quaternion< Scalar > &orientation)
Set body attachment programmatically (for testing or dynamic mounting).
Definition PhysicalComponent.hpp:166
void ReadAttachmentFromConfig()
Read body attachment from component config.
Definition PhysicalComponent.hpp:109
janus::Quaternion< Scalar > GetComponentToBodyRotation() const
Get rotation from component frame to body frame.
Definition PhysicalComponent.hpp:203
bool has_body_attachment_
True after ReadAttachmentFromConfig() is called.
Definition PhysicalComponent.hpp:86
bool HasBodyAttachment() const override
Whether this component has a body attachment (position/orientation).
Definition PhysicalComponent.hpp:185
Vec3< Scalar > TransformToBodyFrame(const Vec3< Scalar > &v_local) const
Transform a vector from component local frame to body frame.
Definition PhysicalComponent.hpp:212
Vec3< Scalar > GetBodyPosition() const override
Get the component's mounting position in vehicle body frame.
Definition PhysicalComponent.hpp:187
Vec3< Scalar > TransformToLocalFrame(const Vec3< Scalar > &v_body) const
Transform a vector from body frame to component local frame.
Definition PhysicalComponent.hpp:221
void SetBodyPosition(const Vec3< Scalar > &position)
Set body position only (orientation defaults to identity).
Definition PhysicalComponent.hpp:177
Vec3< Scalar > body_position_
Mounting position in vehicle body frame [m].
Definition PhysicalComponent.hpp:80
janus::Quaternion< Scalar > body_orientation_
Rotation from body frame to component local frame (identity by default).
Definition PhysicalComponent.hpp:83
Definition AggregationTypes.hpp:13