Skip to content

Commit f6dd040

Browse files
committed
DOC: improve generic_surfaces rst
1 parent 63cad27 commit f6dd040

2 files changed

Lines changed: 187 additions & 2 deletions

File tree

docs/user/rocket/generic_surface.rst

Lines changed: 186 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,72 @@ Where:
111111
Commonly the rocket's diameter is used as the reference length.
112112

113113

114+
Wind-frame and body-frame force coefficients
115+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
116+
117+
The three force coefficients above are given in the **aerodynamic (wind) frame**,
118+
relative to the velocity vector:
119+
120+
- :math:`C_L` (lift), :math:`C_Q` (side force) and :math:`C_D` (drag).
121+
122+
The same force can be expressed in the **body frame**, relative to the rocket's
123+
axes, which is what tools such as Missile DATCOM, wind tunnels and Barrowman
124+
report:
125+
126+
- :math:`C_N` (normal force, perpendicular to the body axis),
127+
- :math:`C_Y` (body side force),
128+
- :math:`C_A` (axial force, along the body axis).
129+
130+
The two sets are the same force in different frames, related by the
131+
angle-of-attack/sideslip rotation :math:`\mathbf{M}_{BA}`:
132+
133+
.. math::
134+
\begin{aligned}
135+
C_N &= \cos\alpha\, C_L + \sin\alpha\,(\sin\beta\, C_Q + \cos\beta\, C_D) \\
136+
C_Y &= \cos\beta\, C_Q - \sin\beta\, C_D \\
137+
C_A &= -\sin\alpha\, C_L + \cos\alpha\,(\sin\beta\, C_Q + \cos\beta\, C_D)
138+
\end{aligned}
139+
140+
At small angles these reduce to :math:`C_N \approx C_L`, :math:`C_Y \approx C_Q`
141+
and :math:`C_A \approx C_D`.
142+
143+
Every aerodynamic surface exposes **all nine** coefficients as attributes
144+
(``cL``, ``cQ``, ``cD``, ``cN``, ``cY``, ``cA``, ``cm``, ``cn``, ``cl``). The
145+
coefficients you did not provide are computed on demand from the ones you did,
146+
so you can always read a surface's forces in whichever frame you need, for
147+
example ``surface.cN`` for the normal-force coefficient.
148+
149+
**Choosing the input frame.** Because rocket aerodynamic data (DATCOM, wind
150+
tunnel, CFD, Barrowman) is usually reported in the body frame, you can supply
151+
your coefficients in either frame and RocketPy converts them for you. Provide the
152+
wind-frame names (``cL``/``cQ``/``cD``) or the body-frame names
153+
(``cN``/``cY``/``cA``); the moment coefficients (``cm``/``cn``/``cl``) are the
154+
same in both.
155+
156+
Moment reference point
157+
~~~~~~~~~~~~~~~~~~~~~~~~
158+
159+
The moment coefficients :math:`C_m`, :math:`C_n` and :math:`C_l` are taken about
160+
the surface's own reference point (its ``center_of_pressure``). When the rocket
161+
assembles the total aerodynamic moment it transports each surface's force from
162+
that point to the rocket's **center of dry mass**, adding the
163+
:math:`\vec{r}_{\text{cp} \to \text{cdm}} \times \vec{F}` term, so the rocket's
164+
reported pitch/yaw moment and static margin are about the center of dry mass.
165+
166+
This matters when your coefficients come from a source that uses a different
167+
reference. Aerodynamic decks frequently give the pitch moment **about the nose
168+
tip** (or another fixed station) rather than about the center of dry mass. A
169+
pitch-moment coefficient referenced to a point a distance :math:`d` ahead of the
170+
surface's center of pressure must be shifted before use:
171+
172+
.. math::
173+
C_{m,\,\text{cp}} = C_{m,\,\text{ref}} + \frac{d}{L_{ref}}\, C_N
174+
175+
Provide the coefficient about the surface's center of pressure (or set
176+
``center_of_pressure`` so the transport lands the moment at the intended point);
177+
otherwise the static margin will be off by the reference-point offset.
178+
179+
114180
Aerodynamic angles
115181
~~~~~~~~~~~~~~~~~~
116182

@@ -263,7 +329,18 @@ independent variables:
263329
- ``yaw_rate``: Yaw rate.
264330
- ``roll_rate``: Roll rate.
265331

266-
The last column must be the coefficient value, and must contain a header,
332+
When the surface is created with ``unsteady_aero=True``, the coefficients may
333+
additionally depend on the time derivatives of the flow angles, appended after
334+
``roll_rate``:
335+
336+
- ``alpha_dot``: Rate of change of the angle of attack.
337+
- ``beta_dot``: Rate of change of the side slip angle.
338+
339+
Callables must then accept the two extra trailing arguments
340+
(``coefficient(alpha, beta, Ma, Re, q, r, p, alpha_dot, beta_dot)``) and
341+
``.csv`` files may include ``alpha_dot``/``beta_dot`` columns.
342+
343+
The last column must be the coefficient value, and must contain a header,
267344
though the header name can be anything.
268345

269346
.. important::
@@ -451,3 +528,111 @@ shown below:
451528
rocket.add_surfaces(linear_generic_surface, position=(0,0,0))
452529
453530
531+
.. _generic_surface_interpolation:
532+
533+
Interpolation and Extrapolation of Tabulated Coefficients
534+
---------------------------------------------------------
535+
536+
When a coefficient is provided as tabulated data (a ``.csv`` file or a list of
537+
points), RocketPy stores it as a :class:`rocketpy.Function` and must decide two
538+
things: how to **interpolate** *between* the tabulated points, and how to
539+
**extrapolate** *outside* the tabulated range. Both :class:`rocketpy.GenericSurface`
540+
and :class:`rocketpy.LinearGenericSurface` (and
541+
:class:`rocketpy.ControllableGenericSurface`) expose these as the
542+
``interpolation`` and ``extrapolation`` arguments.
543+
544+
.. note::
545+
Interpolation and extrapolation only apply to **tabulated** coefficients.
546+
A coefficient given as a constant or a callable is evaluated directly, so
547+
these settings have no effect on it (a callable is assumed valid over its
548+
whole domain).
549+
550+
Each argument accepts either:
551+
552+
- a **single string**, applied to every coefficient of the surface; or
553+
- a **dictionary** keyed by coefficient name, setting the method per
554+
coefficient. Coefficients omitted from the dictionary keep the default.
555+
556+
.. code-block:: python
557+
558+
from rocketpy import GenericSurface
559+
560+
radius = 0.0635
561+
generic_surface = GenericSurface(
562+
reference_area=np.pi * radius**2,
563+
reference_length=2 * radius,
564+
coefficients={
565+
"cD": "cD.csv",
566+
"cL": "cL.csv",
567+
},
568+
# A single method applied to every coefficient:
569+
extrapolation="constant",
570+
# ... or per coefficient (unlisted ones keep the default):
571+
interpolation={"cD": "linear", "cL": "akima"},
572+
)
573+
574+
Choosing an interpolation method
575+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
576+
577+
Interpolation controls the behavior *between* tabulated points. For 1-D tables
578+
the options are ``"linear"``, ``"akima"``, ``"spline"`` and ``"polynomial"``.
579+
580+
- ``"linear"`` (**default**) is the safe choice. It never overshoots and
581+
introduces no spurious oscillations, which matters most across the
582+
**transonic drag rise** (:math:`Ma \approx 0.8`–:math:`1.2`), where a spline
583+
will oscillate and invent non-physical wiggles in :math:`C_D`. Prefer it for
584+
coarse tables and for anything with a sharp feature.
585+
- ``"akima"`` gives continuous first derivatives (smoother
586+
:math:`C_{m_\alpha}`, cleaner stability curves) while resisting the overshoot
587+
of a natural cubic spline near kinks. It is the best "smooth" option for
588+
**dense, smooth** data, such as lift/moment slopes in the attached-flow
589+
region.
590+
- ``"spline"`` produces the smoothest derivatives but overshoots near sharp
591+
features (stall, :math:`Ma = 1`). Use it only for genuinely smooth,
592+
well-resolved data.
593+
594+
A practical rule of thumb: use ``"linear"`` against Mach (transonic kinks) and
595+
``"akima"`` against angle of attack / sideslip when you have fine data and care
596+
about smooth derivatives.
597+
598+
.. note::
599+
Multi-dimensional CSV tables that form a strict Cartesian grid are read with
600+
a :class:`scipy.interpolate.RegularGridInterpolator`. The ``interpolation``
601+
argument still applies: it is mapped onto the interpolator's method, with
602+
``"spline"`` becoming ``"cubic"`` and ``"akima"`` becoming the
603+
shape-preserving ``"pchip"`` (``"linear"`` stays linear). Smooth methods need
604+
enough samples per axis (``"cubic"`` needs at least 4), otherwise SciPy
605+
raises.
606+
607+
Choosing an extrapolation method
608+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
609+
610+
Extrapolation controls the behavior *outside* the tabulated range. The options
611+
are ``"constant"``, ``"natural"`` and ``"zero"``. This choice matters more than
612+
interpolation, because a bad one fails silently, precisely when the rocket is at
613+
an extreme condition beyond your data.
614+
615+
- ``"constant"`` holds the value at the nearest edge of the data. This is the
616+
**default for tabulated coefficients**, and the right choice for essentially
617+
all of them: a rocket can briefly exceed your tabulated Mach/angle range, and
618+
holding the last value is bounded and physically conservative.
619+
- ``"zero"`` returns 0 outside the range. Occasionally reasonable for force or
620+
moment *slopes* if you want contributions to vanish past the modeled envelope,
621+
but it introduces a discontinuity at the edge.
622+
- ``"natural"`` continues the fitted curve past the data. **Avoid this for
623+
tabulated coefficients**: extrapolating a linear or spline fit can send
624+
:math:`C_D` or a moment slope to large, non-physical values right when the
625+
rocket is at an extreme condition.
626+
627+
.. tip::
628+
Tabulated coefficients default to ``extrapolation="constant"`` so they never
629+
run to non-physical values past the tabulated envelope. Override it only when
630+
you have a specific reason (e.g. ``"zero"`` to make a contribution vanish
631+
outside the modeled range).
632+
633+
.. seealso::
634+
These arguments are forwarded to each :class:`rocketpy.Function`; see
635+
:meth:`rocketpy.Function.set_interpolation` and
636+
:meth:`rocketpy.Function.set_extrapolation` for the full list of methods.
637+
638+

requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
numpy>=1.13
2-
scipy>=1.0
2+
scipy>=1.13.0 # RegularGridInterpolator "pchip"/spline methods (Apr 2024)
33
matplotlib>=3.9.0 # Released May 15th 2024
44
netCDF4>=1.6.4
55
requests

0 commit comments

Comments
 (0)