feat: Add oscillator sensor visualization and data export scripts
- demo_oscillator_simple.py: Visualizes oscillator waveforms in terminal - oscillator_data_export.py: Exports oscillator data as JSON - Supports all waveforms: sine, square, sawtooth, triangle, noise - Real-time visualization with phase tracking - Configurable frequency, sample rate, and duration
This commit is contained in:
111
scripts/oscillator_data_export.py
Normal file
111
scripts/oscillator_data_export.py
Normal file
@@ -0,0 +1,111 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Oscillator Data Export
|
||||
|
||||
Exports oscillator sensor data in JSON format for external use.
|
||||
|
||||
Usage:
|
||||
uv run python scripts/oscillator_data_export.py --waveform sine --frequency 1.0 --duration 5.0
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import time
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from datetime import datetime
|
||||
|
||||
# Add mainline to path
|
||||
sys.path.insert(0, str(Path(__file__).parent.parent))
|
||||
|
||||
from engine.sensors.oscillator import OscillatorSensor, register_oscillator_sensor
|
||||
|
||||
|
||||
def export_oscillator_data(
|
||||
waveform: str = "sine",
|
||||
frequency: float = 1.0,
|
||||
duration: float = 5.0,
|
||||
sample_rate: float = 60.0,
|
||||
output_file: str | None = None,
|
||||
):
|
||||
"""Export oscillator data to JSON."""
|
||||
print(f"Exporting oscillator data: {waveform} wave at {frequency}Hz")
|
||||
print(f"Duration: {duration}s, Sample rate: {sample_rate}Hz")
|
||||
|
||||
# Create oscillator sensor
|
||||
register_oscillator_sensor(
|
||||
name="export_osc", waveform=waveform, frequency=frequency
|
||||
)
|
||||
osc = OscillatorSensor(name="export_osc", waveform=waveform, frequency=frequency)
|
||||
osc.start()
|
||||
|
||||
# Collect data
|
||||
data = {
|
||||
"waveform": waveform,
|
||||
"frequency": frequency,
|
||||
"duration": duration,
|
||||
"sample_rate": sample_rate,
|
||||
"timestamp": datetime.now().isoformat(),
|
||||
"samples": [],
|
||||
}
|
||||
|
||||
sample_interval = 1.0 / sample_rate
|
||||
num_samples = int(duration * sample_rate)
|
||||
|
||||
print(f"Collecting {num_samples} samples...")
|
||||
|
||||
for i in range(num_samples):
|
||||
reading = osc.read()
|
||||
if reading:
|
||||
data["samples"].append(
|
||||
{
|
||||
"index": i,
|
||||
"timestamp": reading.timestamp,
|
||||
"value": reading.value,
|
||||
"phase": osc._phase,
|
||||
}
|
||||
)
|
||||
time.sleep(sample_interval)
|
||||
|
||||
osc.stop()
|
||||
|
||||
# Export to JSON
|
||||
if output_file:
|
||||
with open(output_file, "w") as f:
|
||||
json.dump(data, f, indent=2)
|
||||
print(f"Data exported to {output_file}")
|
||||
else:
|
||||
print(json.dumps(data, indent=2))
|
||||
|
||||
return data
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description="Export oscillator sensor data")
|
||||
parser.add_argument(
|
||||
"--waveform",
|
||||
choices=["sine", "square", "sawtooth", "triangle", "noise"],
|
||||
default="sine",
|
||||
help="Waveform type",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--frequency", type=float, default=1.0, help="Oscillator frequency in Hz"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--duration", type=float, default=5.0, help="Duration to record in seconds"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--sample-rate", type=float, default=60.0, help="Sample rate in Hz"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--output", "-o", type=str, help="Output JSON file (default: print to stdout)"
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
export_oscillator_data(
|
||||
waveform=args.waveform,
|
||||
frequency=args.frequency,
|
||||
duration=args.duration,
|
||||
sample_rate=args.sample_rate,
|
||||
output_file=args.output,
|
||||
)
|
||||
Reference in New Issue
Block a user