trajectory / app.py
typ11
''
caffd6c
Raw History Blame Contribute Delete
11.2 kB
import gradio as gr
import numpy as np
import matplotlib.pyplot as plt
import math
from typing import Tuple, Optional
import requests
import json
class BulletDistanceCalculator:
"""A comprehensive bullet distance calculator with physics modeling."""
def __init__(self):
self.gravity = 9.81 # m/sΒ²
self.air_density = 1.225 # kg/mΒ³ at sea level
def calculate_trajectory(self,
initial_velocity: float,
angle: float,
bullet_mass: float = 0.01,
drag_coefficient: float = 0.3,
bullet_diameter: float = 0.007) -> Tuple[np.ndarray, np.ndarray, dict]:
"""
Calculate bullet trajectory with air resistance.
Args:
initial_velocity: Initial velocity in m/s
angle: Launch angle in degrees
bullet_mass: Mass of bullet in kg
drag_coefficient: Drag coefficient
bullet_diameter: Bullet diameter in meters
Returns:
Tuple of (x_coords, y_coords, results_dict)
"""
angle_rad = math.radians(angle)
vx = initial_velocity * math.cos(angle_rad)
vy = initial_velocity * math.sin(angle_rad)
# Calculate cross-sectional area
area = math.pi * (bullet_diameter / 2) ** 2
# Time step for numerical integration
dt = 0.01
max_time = 20 # seconds
x_coords = [0]
y_coords = [0]
t = 0
while t < max_time and y_coords[-1] >= 0:
# Calculate drag force
velocity = math.sqrt(vx**2 + vy**2)
if velocity > 0:
drag_force = 0.5 * self.air_density * velocity**2 * drag_coefficient * area
drag_x = -drag_force * (vx / velocity)
drag_y = -drag_force * (vy / velocity)
else:
drag_x = drag_y = 0
# Update velocities
vx += (drag_x / bullet_mass) * dt
vy += ((drag_y / bullet_mass) - self.gravity) * dt
# Update positions
x = x_coords[-1] + vx * dt
y = y_coords[-1] + vy * dt
if y < 0: # Ground impact
# Linear interpolation to find exact impact point
y_prev = y_coords[-1]
x_prev = x_coords[-1]
t_impact = t - dt + dt * (-y_prev) / (y - y_prev)
x_impact = x_prev + vx * (t_impact - t + dt)
x_coords.append(x_impact)
y_coords.append(0)
break
x_coords.append(x)
y_coords.append(y)
t += dt
# Calculate results
max_height = max(y_coords)
range_distance = x_coords[-1]
flight_time = t
results = {
'range': range_distance,
'max_height': max_height,
'flight_time': flight_time,
'final_velocity': math.sqrt(vx**2 + vy**2),
'impact_angle': math.degrees(math.atan2(vy, vx))
}
return np.array(x_coords), np.array(y_coords), results
def create_trajectory_plot(x_coords: np.ndarray, y_coords: np.ndarray, results: dict) -> str:
"""Create a matplotlib plot of the trajectory."""
plt.figure(figsize=(10, 6))
plt.plot(x_coords, y_coords, 'b-', linewidth=2, label='Trajectory')
plt.scatter([0], [0], color='green', s=100, label='Launch Point', zorder=5)
plt.scatter([x_coords[-1]], [y_coords[-1]], color='red', s=100, label='Impact Point', zorder=5)
plt.xlabel('Distance (m)')
plt.ylabel('Height (m)')
plt.title(f'Bullet Trajectory\nRange: {results["range"]:.1f}m, Max Height: {results["max_height"]:.1f}m')
plt.grid(True, alpha=0.3)
plt.legend()
plt.axis('equal')
# Save plot
plot_path = "trajectory_plot.png"
plt.savefig(plot_path, dpi=150, bbox_inches='tight')
plt.close()
return plot_path
def calculate_bullet_distance(velocity: float,
angle: float,
mass: float,
drag_coeff: float,
diameter: float) -> Tuple[str, str, str]:
"""
Main function for Gradio interface.
Returns:
Tuple of (results_text, plot_path, detailed_info)
"""
try:
calculator = BulletDistanceCalculator()
x_coords, y_coords, results = calculator.calculate_trajectory(
velocity, angle, mass, drag_coeff, diameter
)
# Create plot
plot_path = create_trajectory_plot(x_coords, y_coords, results)
# Format results
results_text = f"""
🎯 **Bullet Distance Calculation Results**
πŸ“ **Range**: {results['range']:.2f} meters
πŸ“ˆ **Maximum Height**: {results['max_height']:.2f} meters
⏱️ **Flight Time**: {results['flight_time']:.2f} seconds
πŸš€ **Final Velocity**: {results['final_velocity']:.2f} m/s
πŸ“ **Impact Angle**: {results['impact_angle']:.1f}Β°
"""
detailed_info = f"""
**Physics Parameters:**
- Initial Velocity: {velocity} m/s
- Launch Angle: {angle}Β°
- Bullet Mass: {mass} kg
- Drag Coefficient: {drag_coeff}
- Bullet Diameter: {diameter} m
**Environmental Conditions:**
- Gravity: {calculator.gravity} m/sΒ²
- Air Density: {calculator.air_density} kg/mΒ³
"""
return results_text, plot_path, detailed_info
except Exception as e:
error_msg = f"❌ Error in calculation: {str(e)}"
return error_msg, None, error_msg
def get_huggingface_model_info(model_name: str) -> str:
"""Get information about a Hugging Face model."""
try:
api_url = f"https://huggingface.co/api/models/{model_name}"
response = requests.get(api_url, timeout=10)
if response.status_code == 200:
model_data = response.json()
info = f"""
πŸ€— **Hugging Face Model Information**
**Model**: {model_data.get('modelId', 'Unknown')}
**Downloads**: {model_data.get('downloads', 0):,}
**Tags**: {', '.join(model_data.get('tags', []))}
**Pipeline Tag**: {model_data.get('pipeline_tag', 'N/A')}
**Library**: {model_data.get('library_name', 'N/A')}
**Last Modified**: {model_data.get('lastModified', 'N/A')}
"""
return info
else:
return f"❌ Error fetching model info: HTTP {response.status_code}"
except Exception as e:
return f"❌ Error connecting to Hugging Face: {str(e)}"
# Create Gradio interface
with gr.Blocks(title="Bullet Distance Calculator", theme=gr.themes.Soft()) as demo:
gr.Markdown("""
# 🎯 Bullet Distance Calculator
Calculate bullet trajectory with realistic physics including air resistance, drag, and gravity.
This app interfaces with Hugging Face and provides comprehensive ballistics calculations.
""")
with gr.Tabs():
with gr.TabItem("🎯 Ballistics Calculator"):
with gr.Row():
with gr.Column(scale=1):
gr.Markdown("### Input Parameters")
velocity = gr.Slider(
minimum=100, maximum=1000, value=300, step=10,
label="Initial Velocity (m/s)",
info="Typical rifle: 300-800 m/s"
)
angle = gr.Slider(
minimum=0, maximum=90, value=30, step=1,
label="Launch Angle (degrees)",
info="0Β° = horizontal, 90Β° = vertical"
)
mass = gr.Slider(
minimum=0.001, maximum=0.1, value=0.01, step=0.001,
label="Bullet Mass (kg)",
info="Typical: 0.005-0.02 kg"
)
drag_coeff = gr.Slider(
minimum=0.1, maximum=1.0, value=0.3, step=0.01,
label="Drag Coefficient",
info="Typical: 0.2-0.5"
)
diameter = gr.Slider(
minimum=0.005, maximum=0.02, value=0.007, step=0.001,
label="Bullet Diameter (m)",
info="Typical: 0.005-0.01 m"
)
calculate_btn = gr.Button("πŸš€ Calculate Trajectory", variant="primary")
with gr.Column(scale=2):
gr.Markdown("### Results")
results_output = gr.Markdown()
gr.Markdown("### Trajectory Plot")
plot_output = gr.Image(label="Trajectory Visualization")
gr.Markdown("### Detailed Information")
detailed_output = gr.Markdown()
with gr.TabItem("πŸ€— Hugging Face Integration"):
gr.Markdown("### Hugging Face Model Information")
with gr.Row():
model_input = gr.Textbox(
label="Model Name",
placeholder="e.g., microsoft/DialoGPT-medium",
value="microsoft/DialoGPT-medium"
)
fetch_btn = gr.Button("πŸ” Get Model Info", variant="secondary")
hf_output = gr.Markdown()
with gr.TabItem("πŸ“š About"):
gr.Markdown("""
## About This App
This Bullet Distance Calculator provides:
- **Realistic Physics**: Includes air resistance, drag, and gravity
- **Interactive Visualization**: Real-time trajectory plotting
- **Hugging Face Integration**: Access to model information
- **Comprehensive Results**: Range, height, flight time, and more
### Physics Model
The calculator uses numerical integration to solve the equations of motion:
- Accounts for air resistance using drag coefficient
- Considers bullet mass and cross-sectional area
- Models realistic environmental conditions
### Hugging Face Features
- Fetch model information and statistics
- Access model metadata and tags
- Real-time API integration
Built with Gradio and designed for Hugging Face Spaces deployment.
""")
# Event handlers
calculate_btn.click(
fn=calculate_bullet_distance,
inputs=[velocity, angle, mass, drag_coeff, diameter],
outputs=[results_output, plot_output, detailed_output]
)
fetch_btn.click(
fn=get_huggingface_model_info,
inputs=[model_input],
outputs=[hf_output]
)
if __name__ == "__main__":
demo.launch(share=True,mcp_server=True)