Vulcan
Aerospace Engineering Utilities Built on Janus
Loading...
Searching...
No Matches
RailLaunch.hpp
Go to the documentation of this file.
1// Vulcan Rail Launch Dynamics
2// Pure stateless functions for rail-constrained motion
3#pragma once
4
6
7#include <janus/janus.hpp>
8
9namespace vulcan::dynamics {
10
11// =============================================================================
12// Rail Direction Utilities
13// =============================================================================
14
20template <typename Scalar>
21Vec3<Scalar> rail_direction_ned(const Scalar &azimuth,
22 const Scalar &elevation) {
23 // In NED: North=+X, East=+Y, Down=+Z
24 // Azimuth from North, elevation from horizontal
25 Scalar cos_elev = janus::cos(elevation);
26 Scalar sin_elev = janus::sin(elevation);
27 Scalar cos_az = janus::cos(azimuth);
28 Scalar sin_az = janus::sin(azimuth);
29
30 return Vec3<Scalar>{
31 cos_elev * cos_az, // North component
32 cos_elev * sin_az, // East component
33 -sin_elev // Down component (negative because up is -Z)
34 };
35}
36
37// =============================================================================
38// Rail Launch Dynamics (1-DOF)
39// =============================================================================
40
59template <typename Scalar>
60Scalar rail_acceleration(const Scalar &s_dot, const Scalar &force_along,
61 const Scalar &force_perp_mag, const Scalar &mass,
62 const Scalar &gravity, const Scalar &elevation,
63 const Scalar &friction_coeff) {
64 // Gravity component along rail (positive opposes motion for uphill)
65 Scalar gravity_along = gravity * janus::sin(elevation);
66
67 // Friction force (Coulomb friction opposing motion direction)
68 Scalar friction_sign =
69 janus::where(s_dot > Scalar(0), Scalar(1),
70 janus::where(s_dot < Scalar(0), Scalar(-1), Scalar(0)));
71 Scalar friction_force = friction_coeff * force_perp_mag * friction_sign;
72
73 // Net acceleration along rail
74 return (force_along - friction_force) / mass - gravity_along;
75}
76
88template <typename Scalar>
89Scalar
90rail_acceleration_body(const Scalar &s_dot, const Vec3<Scalar> &force_body,
91 const Scalar &mass, const Scalar &gravity,
92 const Scalar &elevation, const Scalar &friction_coeff) {
93 // Force along rail (body X)
94 Scalar force_along = force_body(0);
95
96 // Perpendicular force magnitude (body Y and Z)
97 Scalar force_perp_mag = janus::sqrt(force_body(1) * force_body(1) +
98 force_body(2) * force_body(2));
99
100 return rail_acceleration(s_dot, force_along, force_perp_mag, mass, gravity,
101 elevation, friction_coeff);
102}
103
109template <typename Scalar>
110Scalar on_rail(const Scalar &s, const Scalar &rail_length) {
111 return janus::where(s < rail_length,
112 janus::where(s >= Scalar(0), Scalar(1), Scalar(0)),
113 Scalar(0));
114}
115
116// =============================================================================
117// Position/Velocity from Rail State
118// =============================================================================
119
126template <typename Scalar>
127Vec3<Scalar> rail_position(const Scalar &s, const Vec3<Scalar> &origin,
128 const Vec3<Scalar> &direction) {
129 return origin + s * direction;
130}
131
137template <typename Scalar>
138Vec3<Scalar> rail_velocity(const Scalar &s_dot, const Vec3<Scalar> &direction) {
139 return s_dot * direction;
140}
141
142// =============================================================================
143// Attitude for Rail-Aligned Body
144// =============================================================================
145
154template <typename Scalar>
155janus::Quaternion<Scalar> rail_aligned_attitude(const Scalar &azimuth,
156 const Scalar &elevation) {
157 // Construct rotation: first rotate about Z by azimuth, then about Y by
158 // pitch This aligns body +X with rail direction in NED frame
159
160 // Yaw (azimuth rotation about NED Z-axis)
161 Scalar half_az = azimuth / Scalar(2);
162 janus::Quaternion<Scalar> q_yaw(janus::cos(half_az), Scalar(0), Scalar(0),
163 janus::sin(half_az));
164
165 // Pitch (elevation rotation about body Y-axis)
166 // Positive elevation = pitch up = body X toward NED -Z
167 Scalar half_pitch = elevation / Scalar(2);
168 janus::Quaternion<Scalar> q_pitch(janus::cos(half_pitch), Scalar(0),
169 janus::sin(half_pitch), Scalar(0));
170
171 // Combined rotation: yaw then pitch
172 return q_yaw * q_pitch;
173}
174
179template <typename Scalar>
180Vec3<Scalar> rail_reaction_force(const Vec3<Scalar> &force_body) {
181 // Rail reacts perpendicular components (Y and Z in body frame)
182 return Vec3<Scalar>{Scalar(0), -force_body(1), -force_body(2)};
183}
184
185} // namespace vulcan::dynamics
Definition Guided5Dof.hpp:13
Vec3< Scalar > rail_direction_ned(const Scalar &azimuth, const Scalar &elevation)
Definition RailLaunch.hpp:21
Definition GravityTypes.hpp:7
Definition MassProperties.hpp:12