Skip to content

Commit

Permalink
aero page to dashboard
Browse files Browse the repository at this point in the history
  • Loading branch information
Natsoulas committed Feb 12, 2025
1 parent 64c0ea2 commit b860a17
Show file tree
Hide file tree
Showing 2 changed files with 112 additions and 43 deletions.
54 changes: 30 additions & 24 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,13 @@ fn main() -> Result<(), Box<dyn Error>> {
// Modify CSV header to include UTC time
writer.write_record(&[
"UTC Time",
"Time (s)", // Changed from "Mission Elapsed Time (s)" for viz compatibility
"Time (s)",
"Position X (km)",
"Position Y (km)",
"Position Z (km)",
"Velocity X (km/s)",
"Velocity Y (km/s)",
"Velocity Z (km/s)",
"Longitude (deg)",
"Latitude (deg)",
"Altitude (km)",
Expand Down Expand Up @@ -179,29 +182,32 @@ fn main() -> Result<(), Box<dyn Error>> {

// Write data to CSV with attitude state
writer.write_record(&[
format!("{}", current_epoch),
format!("{:.1}", current_time),
format!("{:.3}", state.position[0] / 1000.0),
format!("{:.3}", state.position[1] / 1000.0),
format!("{:.3}", state.position[2] / 1000.0),
format!("{:.6}", longitude),
format!("{:.6}", latitude),
format!("{:.3}", altitude / 1000.0), // Convert to km
format!("{:.6}", state.quaternion.scalar()),
format!("{:.6}", state.quaternion.vector()[0]),
format!("{:.6}", state.quaternion.vector()[1]),
format!("{:.6}", state.quaternion.vector()[2]),
format!("{:.6}", state.angular_velocity[0]),
format!("{:.6}", state.angular_velocity[1]),
format!("{:.6}", state.angular_velocity[2]),
format!("{:.6e}", energy_error),
format!("{:.6e}", angular_momentum_error),
format!("{:.6e}", control_torque[0]),
format!("{:.6e}", control_torque[1]),
format!("{:.6e}", control_torque[2]),
format!("{:.6e}", thrust[0]),
format!("{:.6e}", thrust[1]),
format!("{:.6e}", thrust[2]),
&current_epoch.to_string(),
&current_time.to_string(),
&(state.position.x / 1000.0).to_string(),
&(state.position.y / 1000.0).to_string(),
&(state.position.z / 1000.0).to_string(),
&(state.velocity.x / 1000.0).to_string(),
&(state.velocity.y / 1000.0).to_string(),
&(state.velocity.z / 1000.0).to_string(),
&longitude.to_string(),
&latitude.to_string(),
&(altitude / 1000.0).to_string(), // Convert to km
&state.quaternion.scalar().to_string(),
&state.quaternion.vector()[0].to_string(),
&state.quaternion.vector()[1].to_string(),
&state.quaternion.vector()[2].to_string(),
&state.angular_velocity[0].to_string(),
&state.angular_velocity[1].to_string(),
&state.angular_velocity[2].to_string(),
&energy_error.to_string(),
&angular_momentum_error.to_string(),
&control_torque[0].to_string(),
&control_torque[1].to_string(),
&control_torque[2].to_string(),
&thrust[0].to_string(),
&thrust[1].to_string(),
&thrust[2].to_string(),
])?;
}
state = integrator.integrate(&state, dt);
Expand Down
101 changes: 82 additions & 19 deletions viz/plotMissionDashboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -218,11 +218,11 @@ def create_orbit_tab(event=None):
ax_map.legend()

# 3D Trajectory (bottom left)
ax = fig.add_subplot(gs[1, 0], projection='3d')
ax = fig.add_subplot(gs[1, 0], projection="3d")

# Create Earth sphere
r = 6378.137 # Earth radius in km (WGS84)
phi = np.linspace(0, 2*np.pi, 100)
phi = np.linspace(0, 2 * np.pi, 100)
theta = np.linspace(0, np.pi, 100)
phi, theta = np.meshgrid(phi, theta)

Expand All @@ -234,33 +234,38 @@ def create_orbit_tab(event=None):
ax.plot_surface(x, y, z, cmap=cm.Blues, alpha=0.3)

# Create colored trajectory
points = np.array([df["Position X (km)"], df["Position Y (km)"], df["Position Z (km)"]]).T.reshape(-1, 1, 3)
points = np.array(
[df["Position X (km)"], df["Position Y (km)"], df["Position Z (km)"]]
).T.reshape(-1, 1, 3)
segments = np.concatenate([points[:-1], points[1:]], axis=1)

# Create line collection for 3D
from mpl_toolkits.mplot3d.art3d import Line3DCollection

colors = df["Time (s)"][:-1]
norm = plt.Normalize(colors.min(), colors.max())
lc = Line3DCollection(segments, cmap='plasma', norm=norm)
lc = Line3DCollection(segments, cmap="plasma", norm=norm)
lc.set_array(colors)
ax.add_collection3d(lc)

# Add colorbar
cbar = plt.colorbar(
lc,
lc,
ax=ax,
orientation="horizontal",
pad=0.08,
fraction=0.015,
)
cbar.set_label("Mission Elapsed Time [hours]")
cbar.ax.xaxis.set_major_formatter(plt.FuncFormatter(lambda x, p: f"{x / 3600:.1f}"))
cbar.ax.xaxis.set_major_formatter(
plt.FuncFormatter(lambda x, p: f"{x / 3600:.1f}")
)

# Set equal aspect ratio and limits
max_range = max(
df["Position X (km)"].abs().max(),
df["Position Y (km)"].abs().max(),
df["Position Z (km)"].abs().max()
df["Position Z (km)"].abs().max(),
)
max_range = max_range * 1.1 # Add 10% margin
ax.set_xlim([-max_range, max_range])
Expand All @@ -269,10 +274,10 @@ def create_orbit_tab(event=None):
ax.set_box_aspect([1, 1, 1]) # This makes it perfectly cubic

# Labels
ax.set_xlabel('X [km]')
ax.set_ylabel('Y [km]')
ax.set_zlabel('Z [km]')
ax.set_title('Orbital Trajectory')
ax.set_xlabel("X [km]")
ax.set_ylabel("Y [km]")
ax.set_zlabel("Z [km]")
ax.set_title("Orbital Trajectory")

# Orbital Altitudes (bottom right)
ax_alt = fig.add_subplot(gs[1, 1])
Expand All @@ -284,16 +289,18 @@ def create_orbit_tab(event=None):

# Clear old buttons and create new ones
buttons.clear()
for i, name in enumerate(["Orbit", "Attitude", "Controls"]):
button_ax = fig.add_axes([0.35 + i * 0.12, 0.95, 0.10, 0.03])
for i, name in enumerate(["Orbit", "Attitude", "Controls", "Aero"]):
button_ax = fig.add_axes([0.30 + i * 0.12, 0.95, 0.10, 0.03])
btn = Button(button_ax, name, color="#2d2d2d", hovercolor="#4d4d4d")
btn.label.set_color("white")
if name == "Orbit":
btn.on_clicked(lambda x: create_orbit_tab())
elif name == "Attitude":
btn.on_clicked(lambda x: create_attitude_tab())
else:
elif name == "Controls":
btn.on_clicked(lambda x: create_controls_tab())
else:
btn.on_clicked(lambda x: create_aero_tab())
buttons.append(btn)

plt.draw()
Expand Down Expand Up @@ -346,16 +353,18 @@ def create_attitude_tab(event=None):

# Clear old buttons and create new ones
buttons.clear()
for i, name in enumerate(["Orbit", "Attitude", "Controls"]):
button_ax = fig.add_axes([0.35 + i * 0.12, 0.95, 0.10, 0.03])
for i, name in enumerate(["Orbit", "Attitude", "Controls", "Aero"]):
button_ax = fig.add_axes([0.30 + i * 0.12, 0.95, 0.10, 0.03])
btn = Button(button_ax, name, color="#2d2d2d", hovercolor="#4d4d4d")
btn.label.set_color("white")
if name == "Orbit":
btn.on_clicked(lambda x: create_orbit_tab())
elif name == "Attitude":
btn.on_clicked(lambda x: create_attitude_tab())
else:
elif name == "Controls":
btn.on_clicked(lambda x: create_controls_tab())
else:
btn.on_clicked(lambda x: create_aero_tab())
buttons.append(btn)

plt.draw()
Expand Down Expand Up @@ -403,16 +412,70 @@ def create_controls_tab(event=None):

# Add buttons
buttons.clear()
for i, name in enumerate(["Orbit", "Attitude", "Controls"]):
button_ax = fig.add_axes([0.35 + i * 0.12, 0.95, 0.10, 0.03])
for i, name in enumerate(["Orbit", "Attitude", "Controls", "Aero"]):
button_ax = fig.add_axes([0.30 + i * 0.12, 0.95, 0.10, 0.03])
btn = Button(button_ax, name, color="#2d2d2d", hovercolor="#4d4d4d")
btn.label.set_color("white")
if name == "Orbit":
btn.on_clicked(lambda x: create_orbit_tab())
elif name == "Attitude":
btn.on_clicked(lambda x: create_attitude_tab())
elif name == "Controls":
btn.on_clicked(lambda x: create_controls_tab())
else:
btn.on_clicked(lambda x: create_aero_tab())
buttons.append(btn)

plt.draw()

def create_aero_tab(event=None):
global buttons
fig.clear()
gs = fig.add_gridspec(1, 1, top=0.9)

# Altitude vs Velocity plot
ax = fig.add_subplot(gs[0, 0])
velocity_magnitude = np.sqrt(
df["Velocity X (km/s)"] ** 2
+ df["Velocity Y (km/s)"] ** 2
+ df["Velocity Z (km/s)"] ** 2
)

# Create scatter plot with time-based coloring
scatter = ax.scatter(
velocity_magnitude,
df["Altitude (km)"],
c=df["Time (s)"],
cmap="plasma",
alpha=0.6,
)

# Add colorbar
cbar = plt.colorbar(scatter)
cbar.set_label("Mission Elapsed Time [hours]")
cbar.ax.yaxis.set_major_formatter(
plt.FuncFormatter(lambda x, p: f"{x / 3600:.1f}")
)

ax.set_xlabel("Velocity Magnitude [km/s]")
ax.set_ylabel("Altitude [km]")
ax.set_title("Altitude vs Velocity")
ax.grid(True)

# Clear old buttons and create new ones
buttons.clear()
for i, name in enumerate(["Orbit", "Attitude", "Controls", "Aero"]):
button_ax = fig.add_axes([0.30 + i * 0.12, 0.95, 0.10, 0.03])
btn = Button(button_ax, name, color="#2d2d2d", hovercolor="#4d4d4d")
btn.label.set_color("white")
if name == "Orbit":
btn.on_clicked(lambda x: create_orbit_tab())
elif name == "Attitude":
btn.on_clicked(lambda x: create_attitude_tab())
elif name == "Controls":
btn.on_clicked(lambda x: create_controls_tab())
else:
btn.on_clicked(lambda x: create_aero_tab())
buttons.append(btn)

plt.draw()
Expand Down

0 comments on commit b860a17

Please sign in to comment.