3i/Atlas Closest

 avatar
unknown
python
5 months ago
6.9 kB
31
Indexable
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

# Orbital elements for 3I/ATLAS (from search results)
# Using JPL solution from July 2025
atlas_e = 6.143  # eccentricity
atlas_q = 1.357  # perihelion distance (AU)
atlas_i = 175.1  # inclination (degrees) - retrograde
atlas_omega = 0  # argument of perihelion (approximated)
atlas_Omega = 0  # longitude of ascending node (approximated)
atlas_v_inf = 58  # velocity at infinity (km/s)

# New Horizons trajectory data (from search results)
# Post-Jupiter trajectory characteristics
nh_inclination = 2.3  # degrees (after Jupiter flyby)
nh_eccentricity = 1.40  # hyperbolic orbit
nh_perihelion = 2.2  # AU

# Convert angles to radians
atlas_i_rad = np.radians(atlas_i)
atlas_omega_rad = np.radians(atlas_omega)
atlas_Omega_rad = np.radians(atlas_Omega)
nh_i_rad = np.radians(nh_inclination)


def calculate_position(a, e, i, omega, Omega, true_anomaly, mu=1.0):
    """
    Calculate 3D position from orbital elements
    Using simplified two-body problem
    """
    # Distance from focus
    r = a * (1 - e**2) / (1 + e * np.cos(true_anomaly))

    # Position in orbital plane
    x_orb = r * np.cos(true_anomaly)
    y_orb = r * np.sin(true_anomaly)
    z_orb = 0

    # Rotation matrices to transform to heliocentric ecliptic frame
    # Rotate by argument of periapsis
    cos_omega = np.cos(omega)
    sin_omega = np.sin(omega)

    # Rotate by inclination
    cos_i = np.cos(i)
    sin_i = np.sin(i)

    # Rotate by longitude of ascending node
    cos_Omega = np.cos(Omega)
    sin_Omega = np.sin(Omega)

    # Combined rotation matrix
    x = x_orb * (cos_omega * cos_Omega - sin_omega * sin_Omega * cos_i) - y_orb * (
        sin_omega * cos_Omega + cos_omega * sin_Omega * cos_i
    )

    y = x_orb * (cos_omega * sin_Omega + sin_omega * cos_Omega * cos_i) + y_orb * (
        cos_omega * cos_Omega * cos_i - sin_omega * sin_Omega
    )

    z = x_orb * sin_omega * sin_i + y_orb * cos_omega * sin_i

    return np.array([x, y, z])


def hyperbolic_trajectory_points(e, q, i, omega, Omega, n_points=100):
    """Generate points along hyperbolic trajectory"""
    a = q / (1 - e)  # semi-major axis (negative for hyperbola)

    # For hyperbolic orbits, true anomaly is limited
    max_true_anomaly = np.arccos(-1 / e)  # Maximum physical true anomaly
    true_anomalies = np.linspace(
        -max_true_anomaly * 0.99, max_true_anomaly * 0.99, n_points
    )

    positions = []
    for ta in true_anomalies:
        pos = calculate_position(abs(a), e, i, omega, Omega, ta)
        positions.append(pos)

    return np.array(positions)


# Generate trajectory points for 3I/ATLAS
print("Calculating 3I/ATLAS trajectory...")
atlas_a = atlas_q / (1 - atlas_e)  # semi-major axis
atlas_positions = hyperbolic_trajectory_points(
    atlas_e, atlas_q, atlas_i_rad, atlas_omega_rad, atlas_Omega_rad
)

# For New Horizons, approximate as a straight line trajectory
# Since it's been traveling for ~20 years since launch
print("Calculating New Horizons trajectory...")

# New Horizons approximate position progression
# Started near Earth, passed Jupiter in 2007, now ~62 AU out
# Simplified trajectory: starts near 1 AU, goes to ~62+ AU

# Time points (years since 2006 launch)
time_years = np.linspace(0, 25, 100)
nh_distances = 1 + time_years * 2.5  # Rough approximation: ~2.5 AU per year average

# New Horizons travels roughly in ecliptic plane with small inclination
nh_positions = []
for i, dist in enumerate(nh_distances):
    # Approximate trajectory direction (roughly toward constellation Sagittarius)
    # Using simplified coordinates
    x = dist * np.cos(np.radians(270))  # Roughly toward galactic center
    y = dist * np.sin(np.radians(270))
    z = dist * np.sin(nh_i_rad) * 0.1  # Small inclination effect
    nh_positions.append([x, y, z])

nh_positions = np.array(nh_positions)

# Calculate closest approach
print("Finding closest approach...")
min_distance = float("inf")
closest_atlas_idx = 0
closest_nh_idx = 0

for i, atlas_pos in enumerate(atlas_positions):
    for j, nh_pos in enumerate(nh_positions):
        distance = np.linalg.norm(atlas_pos - nh_pos)
        if distance < min_distance:
            min_distance = distance
            closest_atlas_idx = i
            closest_nh_idx = j

# Results
closest_atlas_pos = atlas_positions[closest_atlas_idx]
closest_nh_pos = nh_positions[closest_nh_idx]

print(f"\nRESULTS:")
print(f"Minimum distance: {min_distance:.2f} AU")
print(f"Minimum distance: {min_distance * 149.6:.0f} million km")

print(f"\n3I/ATLAS position at closest approach:")
print(f"  X: {closest_atlas_pos[0]:.2f} AU")
print(f"  Y: {closest_atlas_pos[1]:.2f} AU")
print(f"  Z: {closest_atlas_pos[2]:.2f} AU")
print(f"  Distance from Sun: {np.linalg.norm(closest_atlas_pos):.2f} AU")

print(f"\nNew Horizons position at closest approach:")
print(f"  X: {closest_nh_pos[0]:.2f} AU")
print(f"  Y: {closest_nh_pos[1]:.2f} AU")
print(f"  Z: {closest_nh_pos[2]:.2f} AU")
print(f"  Distance from Sun: {np.linalg.norm(closest_nh_pos):.2f} AU")

# Create 3D visualization
fig = plt.figure(figsize=(12, 10))
ax = fig.add_subplot(111, projection="3d")

# Plot Sun at origin
ax.scatter([0], [0], [0], color="yellow", s=100, label="Sun")

# Plot trajectories
ax.plot(
    atlas_positions[:, 0],
    atlas_positions[:, 1],
    atlas_positions[:, 2],
    "r-",
    label="3I/ATLAS trajectory",
    alpha=0.7,
)
ax.plot(
    nh_positions[:, 0],
    nh_positions[:, 1],
    nh_positions[:, 2],
    "b-",
    label="New Horizons trajectory",
    alpha=0.7,
)

# Mark closest approach points
ax.scatter(
    closest_atlas_pos[0],
    closest_atlas_pos[1],
    closest_atlas_pos[2],
    color="red",
    s=100,
    label=f"3I/ATLAS closest",
)
ax.scatter(
    closest_nh_pos[0],
    closest_nh_pos[1],
    closest_nh_pos[2],
    color="blue",
    s=100,
    label=f"New Horizons closest",
)

# Draw line between closest points
ax.plot(
    [closest_atlas_pos[0], closest_nh_pos[0]],
    [closest_atlas_pos[1], closest_nh_pos[1]],
    [closest_atlas_pos[2], closest_nh_pos[2]],
    "k--",
    alpha=0.5,
    linewidth=2,
    label=f"Min distance: {min_distance:.1f} AU",
)

ax.set_xlabel("X (AU)")
ax.set_ylabel("Y (AU)")
ax.set_zlabel("Z (AU)")
ax.set_title("3I/ATLAS vs New Horizons Trajectories\nClosest Approach Calculation")
ax.legend()

# Set equal aspect ratio
max_range = 70
ax.set_xlim([-max_range, max_range])
ax.set_ylim([-max_range, max_range])
ax.set_zlim([-10, 10])

plt.tight_layout()
plt.show()

print(f"\nNOTE: This is an approximation based on:")
print(f"- Limited orbital element data for both objects")
print(f"- Simplified New Horizons trajectory model")
print(f"- Two-body orbital mechanics (ignoring planetary perturbations)")
print(f"- The actual minimum distance could vary significantly from this estimate")
Editor is loading...
Leave a Comment