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