add: modify project param

This commit is contained in:
robinson
2026-09-03 15:44:54 +08:00
parent e901fa9579
commit 120df4f805
8 changed files with 103 additions and 23 deletions

View File

@@ -5,7 +5,7 @@ mode = "geometric"
max_tilt = 0.35 # rad仅 linear 外环限幅
[position.linear]
kp = 0.8
kp = 8.8
ki = 0.2
kd = 0.9

View File

@@ -42,6 +42,8 @@ from uavcatch.eval import (
evaluate_maneuver,
plot_control_performance,
plot_maneuver_report,
plot_summary_comparison,
@@ -290,13 +292,23 @@ def main() -> int:
out_file = args.output / f"{spec.name}.png"
plot_maneuver_report(data, metrics, save_path=out_file, show=args.show)
plot_maneuver_report(data, metrics, save_path=out_file, show=args.show, show_actuator=False)
ctrl_file = args.output / f"{spec.name}_control.png"
plot_control_performance(
data,
metrics,
omega_max=uav_cfg.rotor.omega_max,
save_path=ctrl_file,
show=args.show,
)
import matplotlib.pyplot as plt
plt.close("all")
print(f" -> saved {out_file}")
print(f" -> saved {ctrl_file}")

Binary file not shown.

Before

Width:  |  Height:  |  Size: 211 KiB

After

Width:  |  Height:  |  Size: 167 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 182 KiB

View File

@@ -4,7 +4,7 @@ from __future__ import annotations
from uavcatch.eval.maneuvers import ManeuverSpec, default_maneuver_suite
from uavcatch.eval.metrics import ManeuverMetrics, evaluate_maneuver
from uavcatch.eval.plots import plot_maneuver_report, plot_summary_comparison
from uavcatch.eval.plots import plot_control_performance, plot_maneuver_report, plot_summary_comparison
from uavcatch.eval.recorder import SimRecorder
__all__ = [
@@ -13,6 +13,7 @@ __all__ = [
"SimRecorder",
"default_maneuver_suite",
"evaluate_maneuver",
"plot_control_performance",
"plot_maneuver_report",
"plot_summary_comparison",
]

View File

@@ -15,17 +15,17 @@ def plot_maneuver_report(
metrics: ManeuverMetrics,
save_path: Path | None = None,
show: bool = False,
show_actuator: bool = True,
) -> plt.Figure:
time = data["time"]
pos = data["position"]
target = data["target_position"]
err = data["tracking_error"]
euler = np.degrees(data["euler"])
omega = data["omega"]
fig = plt.figure(figsize=(12, 10))
nrows = 4 if show_actuator else 3
fig = plt.figure(figsize=(12, 10 if show_actuator else 8))
fig.suptitle(f"{metrics.name} [{metrics.mode}] - {metrics.description}", fontsize=11)
gs = fig.add_gridspec(4, 3, hspace=0.35, wspace=0.28)
gs = fig.add_gridspec(nrows, 3, hspace=0.35, wspace=0.28)
labels = ("x", "y", "z")
colors = ("#2563eb", "#16a34a", "#dc2626")
@@ -48,24 +48,29 @@ def plot_maneuver_report(
ax.set_xlabel("Time (s)")
ax.grid(alpha=0.3)
ax_att = fig.add_subplot(gs[2, 0])
att_labels = ("roll", "pitch", "yaw")
for i, (lab, c) in enumerate(zip(att_labels, colors)):
ax_att.plot(time, euler[:, i], color=c, linewidth=1.2, label=lab)
ax_att.set_ylabel("Attitude (deg)")
ax_att.set_xlabel("Time (s)")
ax_att.legend(fontsize=8)
ax_att.grid(alpha=0.3)
if show_actuator:
euler = np.degrees(data["euler"])
omega = data["omega"]
ax_om = fig.add_subplot(gs[2, 1:])
for i in range(omega.shape[1]):
ax_om.plot(time, omega[:, i], linewidth=1.0, alpha=0.85, label=f"m{i + 1}")
ax_om.set_ylabel("Motor ω (rad/s)")
ax_om.set_xlabel("Time (s)")
ax_om.legend(fontsize=7, ncol=2)
ax_om.grid(alpha=0.3)
ax_att = fig.add_subplot(gs[2, 0])
att_labels = ("roll", "pitch", "yaw")
for i, (lab, c) in enumerate(zip(att_labels, colors)):
ax_att.plot(time, euler[:, i], color=c, linewidth=1.2, label=lab)
ax_att.set_ylabel("Attitude (deg)")
ax_att.set_xlabel("Time (s)")
ax_att.legend(fontsize=8)
ax_att.grid(alpha=0.3)
ax_txt = fig.add_subplot(gs[3, :])
ax_om = fig.add_subplot(gs[2, 1:])
for i in range(omega.shape[1]):
ax_om.plot(time, omega[:, i], linewidth=1.0, alpha=0.85, label=f"m{i + 1}")
ax_om.set_ylabel("Motor ω (rad/s)")
ax_om.set_xlabel("Time (s)")
ax_om.legend(fontsize=7, ncol=2)
ax_om.grid(alpha=0.3)
txt_row = 3 if show_actuator else 2
ax_txt = fig.add_subplot(gs[txt_row, :])
ax_txt.axis("off")
lines = [
f"3D RMSE = {metrics.tracking.rmse_3d:.4f} m | Max error = {metrics.tracking.max_error_3d:.4f} m",
@@ -91,6 +96,68 @@ def plot_maneuver_report(
return fig
def plot_control_performance(
data: dict[str, np.ndarray],
metrics: ManeuverMetrics,
omega_max: float | None = None,
save_path: Path | None = None,
show: bool = False,
) -> plt.Figure:
"""Supplementary figure focused on velocity tracking and motor control."""
time = data["time"]
vel = data["velocity"]
tgt_vel = data["target_velocity"]
omega = data["omega"]
vel_err = tgt_vel - vel
fig = plt.figure(figsize=(12, 9))
fig.suptitle(f"{metrics.name} — Control Performance", fontsize=11, fontweight="bold")
gs = fig.add_gridspec(3, 3, hspace=0.35, wspace=0.28)
labels = ("x", "y", "z")
colors = ("#2563eb", "#16a34a", "#dc2626")
# --- Velocity tracking ---
ax_vel = fig.add_subplot(gs[0, :])
for i, (lab, c) in enumerate(zip(labels, colors)):
ax_vel.plot(time, tgt_vel[:, i], "--", color=c, alpha=0.5, linewidth=1.0, label=f"{lab} ref")
ax_vel.plot(time, vel[:, i], "-", color=c, linewidth=1.5, label=f"{lab} act")
ax_vel.set_ylabel("Velocity (m/s)")
ax_vel.set_xlabel("Time (s)")
ax_vel.legend(loc="upper right", ncol=3, fontsize=8)
ax_vel.grid(alpha=0.3)
# --- Velocity error per axis ---
for i, (lab, c) in enumerate(zip(labels, colors)):
ax = fig.add_subplot(gs[1, i])
ax.plot(time, vel_err[:, i], color=c, linewidth=1.3)
ax.axhline(0.0, color="k", linewidth=0.6, alpha=0.4)
rmse = float(np.sqrt(np.mean(vel_err[:, i] ** 2)))
ax.set_title(f"Vel Error {lab} RMSE={rmse:.3f} m/s")
ax.set_ylabel("Error (m/s)")
ax.set_xlabel("Time (s)")
ax.grid(alpha=0.3)
# --- Motor speeds ---
ax_om = fig.add_subplot(gs[2, :])
for i in range(omega.shape[1]):
ax_om.plot(time, omega[:, i], linewidth=1.0, alpha=0.85, label=f"m{i + 1}")
if omega_max is not None:
ax_om.axhline(omega_max, color="red", linewidth=0.8, linestyle="--", alpha=0.6, label=f"ω_max={omega_max:.0f}")
ax_om.set_ylabel("Motor ω (rad/s)")
ax_om.set_xlabel("Time (s)")
ax_om.legend(fontsize=7, ncol=4)
ax_om.grid(alpha=0.3)
if save_path is not None:
save_path.parent.mkdir(parents=True, exist_ok=True)
fig.savefig(save_path, dpi=140, bbox_inches="tight")
if show:
plt.show()
return fig
def plot_summary_comparison(
all_metrics: list[ManeuverMetrics],
save_path: Path | None = None,