Skip to main content
Glama

rocket_3dof_trajectory

Calculate 3DOF rocket trajectory using numerical integration for flight planning and aerospace analysis. Input rocket geometry and launch conditions to get trajectory results.

Instructions

Calculate 3DOF rocket trajectory using numerical integration.

Args: rocket_geometry: Rocket geometry parameters launch_conditions: Launch conditions (launch_angle_deg, launch_site, etc.) simulation_options: Optional simulation settings

Returns: Formatted string with trajectory analysis results

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
rocket_geometryYes
launch_conditionsYes
simulation_optionsNo

Implementation Reference

  • MCP tool handler function that processes input parameters (rocket_geometry dict, launch_conditions dict, simulation_options dict), creates RocketGeometry object, delegates to core trajectory analysis, and formats results into readable text with performance summary, key trajectory points, and JSON performance data.
    def rocket_3dof_trajectory(
        rocket_geometry: dict,
        launch_conditions: dict,
        simulation_options: dict | None = None,
    ) -> str:
        """Calculate 3DOF rocket trajectory using numerical integration.
    
        Args:
            rocket_geometry: Rocket geometry parameters
            launch_conditions: Launch conditions (launch_angle_deg, launch_site, etc.)
            simulation_options: Optional simulation settings
    
        Returns:
            Formatted string with trajectory analysis results
        """
        try:
            from ..integrations.rockets import (
                RocketGeometry,
            )
            from ..integrations.rockets import (
                rocket_3dof_trajectory as _trajectory_analysis,
            )
    
            # Create geometry object
            geometry = RocketGeometry(**rocket_geometry)
    
            # Run trajectory analysis
            result = _trajectory_analysis(geometry, launch_conditions, simulation_options)
    
            # Format response
            result_lines = [
                "3DOF Rocket Trajectory Analysis",
                "=" * 50,
                f"Rocket: {geometry.length_m:.1f}m long, {geometry.diameter_m:.2f}m dia",
                f"Mass: {geometry.dry_mass_kg:.1f} kg dry + {geometry.propellant_mass_kg:.1f} kg prop",
                f"Launch Angle: {launch_conditions.get('launch_angle_deg', 90):.1f}°",
                "",
                "Performance Summary:",
                f"  Max Altitude: {result.performance.max_altitude_m:.0f} m ({result.performance.max_altitude_m / 1000:.2f} km)",
                f"  Max Velocity: {result.performance.max_velocity_ms:.1f} m/s (Mach {result.performance.max_mach:.2f})",
                f"  Apogee Time: {result.performance.apogee_time_s:.1f} s",
                f"  Burnout Time: {result.performance.burnout_time_s:.1f} s",
                f"  Max Q: {result.performance.max_q_pa / 1000:.1f} kPa",
                f"  Total Impulse: {result.performance.total_impulse_ns:.0f} N⋅s",
                f"  Specific Impulse: {result.performance.specific_impulse_s:.1f} s",
            ]
    
            # Add trajectory points summary
            if hasattr(result, "trajectory") and result.trajectory:
                result_lines.extend(
                    [
                        "",
                        "Key Trajectory Points:",
                        f"{'Time (s)':>8} {'Alt (m)':>8} {'Vel (m/s)':>10} {'Accel (m/s²)':>12}",
                    ]
                )
                result_lines.append("-" * 45)
    
                # Sample key points
                trajectory = result.trajectory
                sample_indices = [
                    0,
                    len(trajectory) // 4,
                    len(trajectory) // 2,
                    3 * len(trajectory) // 4,
                    -1,
                ]
    
                for i in sample_indices:
                    if i < len(trajectory):
                        point = trajectory[i]
                        result_lines.append(
                            f"{point.time_s:8.1f} {point.altitude_m:8.0f} {point.velocity_ms:10.1f} "
                            f"{point.acceleration_ms2:12.1f}"
                        )
    
            # Add JSON data
            json_data = json.dumps(
                {
                    "performance": {
                        "max_altitude_m": result.performance.max_altitude_m,
                        "max_velocity_ms": result.performance.max_velocity_ms,
                        "apogee_time_s": result.performance.apogee_time_s,
                        "burnout_time_s": result.performance.burnout_time_s,
                        "max_q_pa": result.performance.max_q_pa,
                        "total_impulse_ns": result.performance.total_impulse_ns,
                        "specific_impulse_s": result.performance.specific_impulse_s,
                    }
                },
                indent=2,
            )
            result_lines.extend(["", "JSON Performance Data:", json_data])
    
            return "\n".join(result_lines)
    
        except ImportError:
            return "Rocket trajectory analysis not available - install rocketry packages"
        except Exception as e:
            logger.error(f"Rocket trajectory error: {str(e)}", exc_info=True)
            return f"Rocket trajectory error: {str(e)}"
  • Explicit schema definition for the rocket_3dof_trajectory tool as a ToolReference, including name, description, parameters (geometry dict, dt_s, max_time_s, launch_angle_deg), and examples.
    ToolReference(
        name="rocket_3dof_trajectory",
        description="Simulate 3DOF rocket trajectory with atmospheric effects",
        parameters={
            "geometry": "dict - Rocket geometry with mass_kg, thrust_n, burn_time_s, drag_coeff, reference_area_m2",
            "dt_s": "float - Time step in seconds (default 0.1)",
            "max_time_s": "float - Maximum simulation time in seconds (default 300)",
            "launch_angle_deg": "float - Launch angle in degrees from vertical (default 0)",
        },
        examples=[
            'rocket_3dof_trajectory({"mass_kg": 500, "thrust_n": 8000, "burn_time_s": 60, "drag_coeff": 0.3, "reference_area_m2": 0.5}, 0.1, 300, 15)'
        ],
    ),
  • Explicit registration of the rocket_3dof_trajectory tool with FastMCP server via mcp.tool(rocket_3dof_trajectory).
    mcp.tool(rocket_3dof_trajectory)
  • Core physics implementation: 3DOF rocket trajectory simulator using numerical Euler integration, handling thrust curves, atmospheric density, drag forces, gravity, propellant mass flow, and returning list of trajectory points.
    def rocket_3dof_trajectory(
        geometry: RocketGeometry,
        dt_s: float = 0.1,
        max_time_s: float = 300.0,
        launch_angle_deg: float = 90.0,
    ) -> list[RocketTrajectoryPoint]:
        """
        Calculate 3DOF rocket trajectory using numerical integration.
    
        Args:
            geometry: Rocket geometry and mass properties
            dt_s: Time step for integration (seconds)
            max_time_s: Maximum simulation time (seconds)
            launch_angle_deg: Launch angle from horizontal (degrees)
    
        Returns:
            List of trajectory points
        """
        # Initial conditions
        trajectory = []
        time = 0.0
        altitude = 0.0  # m above sea level
        velocity_vertical = 0.0  # m/s
        velocity_horizontal = 0.0  # m/s
        mass = geometry.dry_mass_kg + geometry.propellant_mass_kg
    
        # Launch angle in radians
        launch_angle_rad = math.radians(launch_angle_deg)
    
        # Constants
        g0 = 9.80665  # m/s² standard gravity
    
        # Get atmosphere profile for drag calculations
        max_alt_m = 50000  # 50km max altitude for atmosphere
        alt_points = list(range(0, max_alt_m + 1000, 1000))
        atm_profile = get_atmosphere_profile(alt_points, "ISA")
        atm_dict = {point.altitude_m: point for point in atm_profile}
    
        while time <= max_time_s and altitude >= 0:
            # Get current thrust
            thrust = (
                get_thrust_at_time(geometry.thrust_curve, time)
                if geometry.thrust_curve
                else 0.0
            )
    
            # Get atmospheric properties at current altitude
            atm_alt = min(max_alt_m, max(0, int(altitude // 1000) * 1000))
            if atm_alt in atm_dict:
                atm = atm_dict[atm_alt]
                rho = atm.density_kg_m3
                speed_of_sound = atm.speed_of_sound_mps
            else:
                # Fallback for extreme altitudes
                rho = 1.225 * math.exp(-altitude / 8400)  # Simple exponential model
                speed_of_sound = 343.0 * math.sqrt(
                    max(0.1, (288.15 - 0.0065 * altitude) / 288.15)
                )
    
            # Total velocity
            velocity_total = math.sqrt(velocity_vertical**2 + velocity_horizontal**2)
    
            # Mach number
            mach = velocity_total / speed_of_sound if speed_of_sound > 0 else 0.0
    
            # Dynamic pressure
            dynamic_pressure = 0.5 * rho * velocity_total**2
    
            # Drag force (opposing velocity direction)
            drag_area = math.pi * (geometry.diameter_m / 2) ** 2
            drag_force = geometry.cd * drag_area * dynamic_pressure
    
            # Drag acceleration components
            if velocity_total > 0:
                drag_accel_vertical = (
                    -drag_force * (velocity_vertical / velocity_total) / mass
                )
                drag_accel_horizontal = (
                    -drag_force * (velocity_horizontal / velocity_total) / mass
                )
            else:
                drag_accel_vertical = 0.0
                drag_accel_horizontal = 0.0
    
            # Thrust acceleration (in launch direction initially, then vertical)
            if time < 5.0:  # First 5 seconds follow launch angle
                thrust_accel_vertical = thrust * math.sin(launch_angle_rad) / mass
                thrust_accel_horizontal = thrust * math.cos(launch_angle_rad) / mass
            else:  # After 5 seconds, thrust is vertical only
                thrust_accel_vertical = thrust / mass
                thrust_accel_horizontal = 0.0
    
            # Total acceleration
            accel_vertical = thrust_accel_vertical - g0 + drag_accel_vertical
            accel_horizontal = thrust_accel_horizontal + drag_accel_horizontal
    
            # Record current state
            trajectory.append(
                RocketTrajectoryPoint(
                    time_s=time,
                    altitude_m=altitude,
                    velocity_ms=velocity_total,
                    acceleration_ms2=math.sqrt(accel_vertical**2 + accel_horizontal**2),
                    mass_kg=mass,
                    thrust_n=thrust,
                    drag_n=drag_force,
                    mach=mach,
                    dynamic_pressure_pa=dynamic_pressure,
                )
            )
    
            # Integration (Euler method)
            velocity_vertical += accel_vertical * dt_s
            velocity_horizontal += accel_horizontal * dt_s
            altitude += velocity_vertical * dt_s
    
            # Update mass (simple propellant consumption)
            if thrust > 0 and geometry.thrust_curve:
                # Estimate mass flow rate from thrust curve
                # For a simplified model, assume constant mass flow rate during burn
                burn_time_total = max(
                    (point[0] for point in geometry.thrust_curve if point[1] > 0),
                    default=1.0,
                )
                if burn_time_total > 0:
                    mass_flow_rate = geometry.propellant_mass_kg / burn_time_total
                    mass = max(geometry.dry_mass_kg, mass - mass_flow_rate * dt_s)
    
            time += dt_s
    
            # Stop if apogee reached and descending
            if altitude > 0 and velocity_vertical < -1.0:
                break
    
        return trajectory
  • Dataclass RocketGeometry defining structure for rocket parameters: dry_mass_kg, propellant_mass_kg, diameter_m, length_m, cd, thrust_curve.
    @dataclass
    class RocketGeometry:
        """Rocket geometry parameters."""
    
        dry_mass_kg: float  # Rocket dry mass
        propellant_mass_kg: float  # Initial propellant mass
        diameter_m: float  # Rocket diameter
        length_m: float  # Total rocket length
        cd: float = 0.3  # Drag coefficient
        thrust_curve: list[list[float]] = (
            None  # [[time_s, thrust_N], ...] or constant thrust
        )

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/cheesejaguar/aerospace-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server