Skip to content

Commit 73024c5

Browse files
committed
docs(readme): dark theme plots, move examples to end section
- formatter.py: dark background (#1a1a2e) for PID and FFT plots with matching text/axis colors - README: move PID examples to new 'Examples' section at end - Add terminal output example showing diagnostic format - Replace example images with dark-themed versions
1 parent 349659d commit 73024c5

4 files changed

Lines changed: 67 additions & 17 deletions

File tree

‎README.md‎

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -181,16 +181,6 @@ stune pid -i flight.bin -a roll # Single axis
181181
stune pid -i flight.bbl --visual # Betaflight
182182
```
183183

184-
### PID Step Response Examples
185-
186-
**ArduPilot** (DataFlash `.bin` log):
187-
188-
![ArduPilot PID step response](assets/pid_ardupilot_example.png)
189-
190-
**Betaflight** (Blackbox `.bbl` log):
191-
192-
![Betaflight PID step response](assets/pid_betaflight_example.png)
193-
194184
### `stune fft`
195185

196186
Frequency-domain vibration analysis with notch filter suggestions.
@@ -371,6 +361,46 @@ Agents call `stune`, get structured tuning recommendations, and can act on them.
371361

372362
---
373363

364+
## Examples
365+
366+
### Terminal Output
367+
368+
```text
369+
Platform: Betaflight
370+
╭──────────────────────────────────────────────────────────────────╮
371+
│ PID Step Response Analysis │
372+
╰──────────────────────────────────────────────────────────────────╯
373+
374+
PITCH: MARGINAL (steps: 4)
375+
ROLL: MARGINAL (steps: 1)
376+
YAW: MARGINAL (steps: 1)
377+
Overall: MARGINAL
378+
379+
╭──────────────────────────────────────────────────────────────────╮
380+
│ FFT Vibration Analysis │
381+
╰──────────────────────────────────────────────────────────────────╯
382+
Vibration: MARGINAL (10.0 m/s²)
383+
Freq (Hz) Amplitude (dB) Source
384+
93.7 -46.5 motor
385+
→ gyro_notch1_hz: 93.7
386+
→ gyro_lowpass_hz: 40
387+
→ acc_lpf_hz: 10
388+
389+
✓ Analysis complete!
390+
```
391+
392+
### PID Step Response
393+
394+
**ArduPilot** (DataFlash `.bin` log):
395+
396+
![ArduPilot PID step response](assets/pid_ardupilot_example.png)
397+
398+
**Betaflight** (Blackbox `.bbl` log):
399+
400+
![Betaflight PID step response](assets/pid_betaflight_example.png)
401+
402+
---
403+
374404
## For Humans
375405

376406
Yes, the terminal output is also beautiful. Rich-powered tables, progress bars, color-coded diagnostics — everything you'd expect from a modern CLI. But the architecture underneath is agent-first.

‎assets/pid_ardupilot_example.png‎

34.8 KB
Loading

‎assets/pid_betaflight_example.png‎

-3.12 KB
Loading

‎smarttune/output/formatter.py‎

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -490,6 +490,16 @@ def _generate_pid_plot(self, results: Any) -> Optional[str]:
490490

491491
n = len(axes_data)
492492
fig, axes_plots = plt.subplots(n, 1, figsize=(10, 4 * n), squeeze=False)
493+
fig.patch.set_facecolor("#1a1a2e")
494+
plt.rcParams.update({
495+
"text.color": "#e0e0e0",
496+
"axes.labelcolor": "#e0e0e0",
497+
"axes.facecolor": "#16213e",
498+
"axes.edgecolor": "#4a4a6a",
499+
"xtick.color": "#e0e0e0",
500+
"ytick.color": "#e0e0e0",
501+
"grid.color": "#3a3a5a",
502+
})
493503

494504
for i, (axis_name, axis_data) in enumerate(axes_data.items()):
495505
fft_step = axis_data.get("fft_step", {})
@@ -510,13 +520,13 @@ def _generate_pid_plot(self, results: Any) -> Optional[str]:
510520
resp = np.array(step_resp)
511521

512522
# Plot step response
513-
ax.plot(t, resp, "b-", linewidth=1.5, alpha=0.9, label="Response")
523+
ax.plot(t, resp, color="#4fc3f7", linewidth=1.5, alpha=0.9, label="Response")
514524

515525
# Reference lines
516-
ax.axhline(0, color="black", linestyle="-", linewidth=0.5, alpha=0.5)
517-
ax.axhline(1, color="black", linestyle="--", linewidth=1.0, alpha=0.8, label="Target")
518-
ax.axhline(0.1, color="gray", linestyle=":", linewidth=0.8, alpha=0.5)
519-
ax.axhline(0.9, color="gray", linestyle=":", linewidth=0.8, alpha=0.5)
526+
ax.axhline(0, color="#888888", linestyle="-", linewidth=0.5, alpha=0.5)
527+
ax.axhline(1, color="#ff7043", linestyle="--", linewidth=1.0, alpha=0.8, label="Target")
528+
ax.axhline(0.1, color="#666666", linestyle=":", linewidth=0.8, alpha=0.5)
529+
ax.axhline(0.9, color="#666666", linestyle=":", linewidth=0.8, alpha=0.5)
520530

521531
# Axes limits
522532
max_time_ms = max(t) if len(t) > 0 else 500
@@ -533,7 +543,7 @@ def _generate_pid_plot(self, results: Any) -> Optional[str]:
533543

534544
plt.tight_layout()
535545
out_path = self._plot_save("pid_analysis.png")
536-
plt.savefig(out_path, dpi=150)
546+
plt.savefig(out_path, dpi=150, facecolor=fig.get_facecolor())
537547
plt.close(fig)
538548
return out_path
539549

@@ -559,6 +569,16 @@ def _generate_fft_plot(
559569
return None
560570

561571
fig, ax = plt.subplots(figsize=(10, 5))
572+
fig.patch.set_facecolor("#1a1a2e")
573+
ax.set_facecolor("#16213e")
574+
plt.rcParams.update({
575+
"text.color": "#e0e0e0",
576+
"axes.labelcolor": "#e0e0e0",
577+
"axes.edgecolor": "#4a4a6a",
578+
"xtick.color": "#e0e0e0",
579+
"ytick.color": "#e0e0e0",
580+
"grid.color": "#3a3a5a",
581+
})
562582

563583
# Full spectrum curve
564584
if raw_spectrum and raw_spectrum.get("freqs"):
@@ -629,7 +649,7 @@ def _generate_fft_plot(
629649

630650
plt.tight_layout()
631651
out_path = self._plot_save("fft_spectrum.png")
632-
plt.savefig(out_path, dpi=150)
652+
plt.savefig(out_path, dpi=150, facecolor=fig.get_facecolor())
633653
plt.close(fig)
634654
return out_path
635655

0 commit comments

Comments
 (0)