Skip to content

Commit 194943a

Browse files
aZira371Gui-FernandesBR
authored andcommitted
DOC: updating 3 dof documentation and corresponding index.rst
- DOC: added 3 dof and 6 dof comparison analysis to three_dof_simulation.rst - DOC: updated iusers/index.rst to build three_dof_simulation.rst - MNT: deleted the bella_lui_3dof_vs_6dof_comparison.ipynb as the doc now covers this section
1 parent ef1d003 commit 194943a

3 files changed

Lines changed: 318 additions & 1197 deletions

File tree

docs/examples/bella_lui_3dof_vs_6dof_comparison.ipynb

Lines changed: 0 additions & 1188 deletions
This file was deleted.

docs/user/index.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ RocketPy's User Guide
2828
Air Brakes Example <airbrakes.rst>
2929
../notebooks/sensors.ipynb
3030
../matlab/matlab.rst
31-
31+
3 DOF Simulations and comparison<three_dof_simulation.rst>
3232
.. toctree::
3333
:maxdepth: 2
3434
:caption: Monte Carlo Simulations

docs/user/three_dof_simulation.rst

Lines changed: 317 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,316 @@ Here's a complete 3-DOF simulation from start to finish:
340340

341341
flight.plots.trajectory_3d()
342342

343+
Weathercocking Model
344+
--------------------
345+
346+
RocketPy's 3-DOF simulation mode includes a weathercocking model that allows
347+
the rocket's attitude to evolve during flight. This feature simulates how a
348+
statically stable rocket naturally aligns with the relative wind direction.
349+
350+
Understanding Weathercocking
351+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
352+
353+
Weathercocking is the tendency of a rocket to align its body axis with the
354+
direction of the relative wind. In reality, this occurs due to aerodynamic
355+
restoring moments from fins and other stabilizing surfaces. The 3-DOF
356+
weathercocking model provides a simplified representation of this behavior
357+
without requiring full 6-DOF rotational dynamics.
358+
359+
The ``weathercock_coeff`` Parameter
360+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
361+
362+
The weathercocking behavior is controlled by the ``weathercock_coeff`` parameter
363+
in the :class:`rocketpy.Flight` class:
364+
365+
.. jupyter-execute::
366+
367+
from rocketpy import Environment, PointMassMotor, PointMassRocket, Flight
368+
369+
env = Environment(
370+
latitude=32.990254,
371+
longitude=-106.974998,
372+
elevation=1400
373+
)
374+
env.set_atmospheric_model(type="StandardAtmosphere")
375+
376+
motor = PointMassMotor(
377+
thrust_source=1500,
378+
dry_mass=1.5,
379+
propellant_initial_mass=2.5,
380+
burn_time=3.5,
381+
)
382+
383+
rocket = PointMassRocket(
384+
radius=0.078,
385+
mass=15.0,
386+
center_of_mass_without_motor=0.0,
387+
power_off_drag=0.43,
388+
power_on_drag=0.43,
389+
)
390+
rocket.add_motor(motor, position=0)
391+
392+
# Flight with weathercocking enabled
393+
flight = Flight(
394+
rocket=rocket,
395+
environment=env,
396+
rail_length=4.2,
397+
inclination=85,
398+
heading=45,
399+
simulation_mode="3 DOF",
400+
weathercock_coeff=1.0, # Default value
401+
)
402+
403+
print(f"Apogee: {flight.apogee - env.elevation:.2f} m")
404+
405+
The ``weathercock_coeff`` parameter controls the rate at which the rocket
406+
aligns with the relative wind:
407+
408+
- ``weathercock_coeff=0``: No weathercocking (original fixed-attitude behavior)
409+
- ``weathercock_coeff=1.0``: Default moderate alignment rate
410+
- ``weathercock_coeff>1.0``: Faster alignment (more stable rocket)
411+
412+
Effect of Weathercocking Coefficient
413+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
414+
415+
Higher values of ``weathercock_coeff`` result in faster alignment with the
416+
relative wind. This affects the lateral motion and impact point:
417+
418+
.. list-table:: Weathercocking Coefficient Effects
419+
:header-rows: 1
420+
:widths: 25 25 50
421+
422+
* - Coefficient
423+
- Alignment Speed
424+
- Typical Use Case
425+
* - 0
426+
- None (fixed attitude)
427+
- Original 3-DOF behavior
428+
* - 1.0
429+
- Moderate
430+
- Default, general purpose
431+
* - 2.0-5.0
432+
- Fast
433+
- Highly stable rockets
434+
* - >5.0
435+
- Very fast
436+
- Rockets with large fins
437+
438+
3-DOF vs 6-DOF Comparison Results
439+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
440+
441+
The following example compares a 6-DOF simulation using the full Bella Lui rocket
442+
with 3-DOF simulations using ``PointMassRocket`` and different weathercocking
443+
coefficients. This demonstrates the trade-off between computational speed and
444+
accuracy.
445+
446+
**Setup the simulations:**
447+
448+
.. jupyter-execute::
449+
450+
import numpy as np
451+
import time
452+
from rocketpy import Environment, Flight, Rocket, SolidMotor
453+
from rocketpy.rocket.point_mass_rocket import PointMassRocket
454+
from rocketpy.motors.point_mass_motor import PointMassMotor
455+
456+
# Environment
457+
env = Environment(
458+
gravity=9.81,
459+
latitude=47.213476,
460+
longitude=9.003336,
461+
elevation=407,
462+
)
463+
env.set_atmospheric_model(type="StandardAtmosphere")
464+
env.max_expected_height = 2000
465+
466+
# Full 6-DOF Motor
467+
motor_6dof = SolidMotor(
468+
thrust_source="../data/motors/aerotech/AeroTech_K828FJ.eng",
469+
burn_time=2.43,
470+
dry_mass=1,
471+
dry_inertia=(0, 0, 0),
472+
center_of_dry_mass_position=0,
473+
grains_center_of_mass_position=-1,
474+
grain_number=3,
475+
grain_separation=0.003,
476+
grain_density=782.4,
477+
grain_outer_radius=0.042799,
478+
grain_initial_inner_radius=0.033147,
479+
grain_initial_height=0.1524,
480+
nozzle_radius=0.04445,
481+
throat_radius=0.0214376,
482+
nozzle_position=-1.1356,
483+
)
484+
485+
# Full 6-DOF Rocket
486+
rocket_6dof = Rocket(
487+
radius=0.078,
488+
mass=17.227,
489+
inertia=(0.78267, 0.78267, 0.064244),
490+
power_off_drag=0.43,
491+
power_on_drag=0.43,
492+
center_of_mass_without_motor=0,
493+
)
494+
rocket_6dof.set_rail_buttons(0.1, -0.5)
495+
rocket_6dof.add_motor(motor_6dof, -1.1356)
496+
rocket_6dof.add_nose(length=0.242, kind="tangent", position=1.542)
497+
rocket_6dof.add_trapezoidal_fins(3, span=0.200, root_chord=0.280, tip_chord=0.125, position=-0.75)
498+
499+
# Point Mass Motor for 3-DOF
500+
motor_3dof = PointMassMotor(
501+
thrust_source="../data/motors/aerotech/AeroTech_K828FJ.eng",
502+
dry_mass=1.0,
503+
propellant_initial_mass=1.373,
504+
)
505+
506+
# Point Mass Rocket for 3-DOF
507+
rocket_3dof = PointMassRocket(
508+
radius=0.078,
509+
mass=17.227,
510+
center_of_mass_without_motor=0,
511+
power_off_drag=0.43,
512+
power_on_drag=0.43,
513+
)
514+
rocket_3dof.add_motor(motor_3dof, -1.1356)
515+
516+
**Run simulations and compare results:**
517+
518+
.. jupyter-execute::
519+
520+
# 6-DOF Flight
521+
start = time.time()
522+
flight_6dof = Flight(
523+
rocket=rocket_6dof,
524+
environment=env,
525+
rail_length=4.2,
526+
inclination=89,
527+
heading=45,
528+
terminate_on_apogee=True,
529+
)
530+
time_6dof = time.time() - start
531+
532+
# 3-DOF with no weathercocking
533+
start = time.time()
534+
flight_3dof_0 = Flight(
535+
rocket=rocket_3dof,
536+
environment=env,
537+
rail_length=4.2,
538+
inclination=89,
539+
heading=45,
540+
terminate_on_apogee=True,
541+
simulation_mode="3 DOF",
542+
weathercock_coeff=0.0,
543+
)
544+
time_3dof_0 = time.time() - start
545+
546+
# 3-DOF with default weathercocking
547+
start = time.time()
548+
flight_3dof_1 = Flight(
549+
rocket=rocket_3dof,
550+
environment=env,
551+
rail_length=4.2,
552+
inclination=89,
553+
heading=45,
554+
terminate_on_apogee=True,
555+
simulation_mode="3 DOF",
556+
weathercock_coeff=1.0,
557+
)
558+
time_3dof_1 = time.time() - start
559+
560+
# 3-DOF with high weathercocking
561+
start = time.time()
562+
flight_3dof_5 = Flight(
563+
rocket=rocket_3dof,
564+
environment=env,
565+
rail_length=4.2,
566+
inclination=89,
567+
heading=45,
568+
terminate_on_apogee=True,
569+
simulation_mode="3 DOF",
570+
weathercock_coeff=5.0,
571+
)
572+
time_3dof_5 = time.time() - start
573+
574+
# Print comparison table
575+
print("=" * 80)
576+
print("SIMULATION RESULTS COMPARISON")
577+
print("=" * 80)
578+
print("\n{:<30} {:>12} {:>12} {:>12} {:>12}".format(
579+
"Parameter", "6-DOF", "3DOF(wc=0)", "3DOF(wc=1)", "3DOF(wc=5)"
580+
))
581+
print("-" * 80)
582+
print("{:<30} {:>12.2f} {:>12.2f} {:>12.2f} {:>12.2f}".format(
583+
"Apogee (m AGL)",
584+
flight_6dof.apogee - env.elevation,
585+
flight_3dof_0.apogee - env.elevation,
586+
flight_3dof_1.apogee - env.elevation,
587+
flight_3dof_5.apogee - env.elevation,
588+
))
589+
print("{:<30} {:>12.2f} {:>12.2f} {:>12.2f} {:>12.2f}".format(
590+
"Apogee Time (s)",
591+
flight_6dof.apogee_time,
592+
flight_3dof_0.apogee_time,
593+
flight_3dof_1.apogee_time,
594+
flight_3dof_5.apogee_time,
595+
))
596+
print("{:<30} {:>12.2f} {:>12.2f} {:>12.2f} {:>12.2f}".format(
597+
"Max Speed (m/s)",
598+
flight_6dof.max_speed,
599+
flight_3dof_0.max_speed,
600+
flight_3dof_1.max_speed,
601+
flight_3dof_5.max_speed,
602+
))
603+
print("{:<30} {:>12.3f} {:>12.3f} {:>12.3f} {:>12.3f}".format(
604+
"Runtime (s)",
605+
time_6dof,
606+
time_3dof_0,
607+
time_3dof_1,
608+
time_3dof_5,
609+
))
610+
print("-" * 80)
611+
print("Speedup vs 6-DOF: {:>12} {:>12.1f}x {:>12.1f}x {:>12.1f}x".format(
612+
"-",
613+
time_6dof / time_3dof_0 if time_3dof_0 > 0 else 0,
614+
time_6dof / time_3dof_1 if time_3dof_1 > 0 else 0,
615+
time_6dof / time_3dof_5 if time_3dof_5 > 0 else 0,
616+
))
617+
618+
**3D Trajectory Comparison:**
619+
620+
.. jupyter-execute::
621+
622+
import matplotlib.pyplot as plt
623+
from mpl_toolkits.mplot3d import Axes3D
624+
625+
fig = plt.figure(figsize=(12, 8))
626+
ax = fig.add_subplot(111, projection="3d")
627+
628+
# Plot all trajectories
629+
ax.plot(flight_6dof.x[:, 1], flight_6dof.y[:, 1], flight_6dof.z[:, 1] - env.elevation,
630+
"b-", linewidth=2, label="6-DOF")
631+
ax.plot(flight_3dof_0.x[:, 1], flight_3dof_0.y[:, 1], flight_3dof_0.z[:, 1] - env.elevation,
632+
"r--", linewidth=2, label="3-DOF (wc=0)")
633+
ax.plot(flight_3dof_1.x[:, 1], flight_3dof_1.y[:, 1], flight_3dof_1.z[:, 1] - env.elevation,
634+
"g--", linewidth=2, label="3-DOF (wc=1)")
635+
ax.plot(flight_3dof_5.x[:, 1], flight_3dof_5.y[:, 1], flight_3dof_5.z[:, 1] - env.elevation,
636+
"m--", linewidth=2, label="3-DOF (wc=5)")
637+
638+
ax.set_xlabel("X (m)")
639+
ax.set_ylabel("Y (m)")
640+
ax.set_zlabel("Altitude AGL (m)")
641+
ax.set_title("3-DOF vs 6-DOF Trajectory Comparison with Weathercocking")
642+
ax.legend()
643+
plt.tight_layout()
644+
plt.show()
645+
646+
The results show that:
647+
648+
- **3-DOF is 5-7x faster** than 6-DOF simulations
649+
- **Apogee prediction** is within 1-3% of 6-DOF
650+
- **Weathercocking** improves trajectory accuracy by aligning the rocket with relative wind
651+
- **Higher weathercock_coeff** values result in trajectories closer to 6-DOF
652+
343653
Comparison: 3-DOF vs 6-DOF
344654
---------------------------
345655

@@ -353,10 +663,10 @@ Understanding the differences between simulation modes:
353663
- 3-DOF
354664
- 6-DOF
355665
* - Computational Speed
356-
- Fast
357-
- Slower
666+
- 5-7x faster
667+
- Slower (more accurate)
358668
* - Rocket Orientation
359-
- Fixed (no rotation)
669+
- Weathercocking model
360670
- Full attitude dynamics
361671
* - Stability Analysis
362672
- ❌ Not available
@@ -371,10 +681,10 @@ Understanding the differences between simulation modes:
371681
- ❌ Not needed
372682
- ✅ Required
373683
* - Use Cases
374-
- Quick estimates, education
684+
- Quick estimates, Monte Carlo
375685
- Detailed design, stability
376686
* - Trajectory Accuracy
377-
- Good for stable rockets
687+
- Good (~1.5% error)
378688
- Highly accurate
379689

380690
Best Practices
@@ -401,8 +711,7 @@ Limitations and Warnings
401711

402712
- **No stability checking** - The simulation cannot detect unstable rockets
403713
- **No attitude control** - Air brakes and thrust vectoring are not supported
404-
- **Assumes perfect alignment** - Rocket always points along velocity vector
405-
- **No wind weathercocking** - Wind effects on orientation are ignored
714+
- **Simplified weathercocking** - Uses proportional alignment model, not full dynamics
406715

407716
.. warning::
408717

@@ -428,4 +737,4 @@ For more information about point mass trajectory simulations:
428737

429738
- `Trajectory Optimization <https://en.wikipedia.org/wiki/Trajectory_optimization>`_
430739
- `Equations of Motion <https://en.wikipedia.org/wiki/Equations_of_motion>`_
431-
- `Point Mass Model <https://www.grc.nasa.gov/www/k-12/airplane/flteqs.html>`_
740+
- `Point Mass Model <https://www.grc.nasa.gov/www/k-12/airplane/flteqs.html>`_

0 commit comments

Comments
 (0)