Skip to content

Advanced Usage Tutorial

This tutorial covers advanced features of SoftRealtimeLoop

Sensor Data Acquisition

Example of reading from a simulated sensor at precise intervals:

class SimpleSensorSimulator:
    def __init__(self):
        self.start_time = time.monotonic()

    def read(self, t):
        # Simulate a 0.5 Hz sine wave sensor reading
        return 100 * sin(2 * pi * 0.5 * t)


def sensor_example():
    # Create a 20Hz loop (0.05 second period)
    rt_loop = SoftRealtimeLoop(dt=0.05)

    # Initialize sensor and data storage
    sensor = SimpleSensorSimulator()
    readings = []

    print("Recording simulated sensor data for 2 seconds...")

    for t in rt_loop:
        reading = sensor.read(t)
        readings.append(reading)
        print(f"Time: {t:.2f}s, Sensor value: {reading:.1f}")

        if t > 2.0:  # Stop after 2 seconds
            rt_loop.stop()

    print(f"\nCollected {len(readings)} samples at 20Hz")
    print(f"Average sampling period: {2.0 / len(readings):.3f} seconds")

Graceful Shutdown with Fade-out

Demonstration of the fade-out feature for a smooth shutdown:

def fade_example():
    # Create a 10Hz loop with 1-second fade-out
    rt_loop = SoftRealtimeLoop(dt=0.1, fade=1.0)

    print("Running loop with fade-out...")
    print("Press Ctrl+C to test graceful shutdown!")

    try:
        for t in rt_loop:
            fade_value = rt_loop.fade
            print(f"Time: {t:.1f}s, Fade value: {fade_value:.2f}")

            if t > 10.0:  # Auto-stop after 10 seconds if no Ctrl+C
                rt_loop.stop()

    except KeyboardInterrupt:
        print("\nCtrl+C detected - demonstrating fade-out...")
        # The loop will automatically handle the fade-out

    print("\nLoop completed with graceful shutdown!")

Understanding Performance Statistics

When a SoftRealtimeLoop completes (either through normal termination or interruption), it prints detailed timing statistics if reporting is enabled (default). Let's understand what these metrics mean and how to use them:

Available Statistics

The loop reports three key metrics:

# Example output:
In 1000 cycles at 100.00 Hz:
    avg error: 0.123 milliseconds
    stddev error: 0.045 milliseconds
    percent of time sleeping: 85.2 %
  1. Average Error: Shows how far off your timing is from the target on average

    • Values under 1ms are typically good for most applications
    • Higher values indicate your loop might be overloaded
  2. Standard Deviation Error: Shows how consistent your timing is

    • Lower values mean more consistent timing
    • High variance might indicate interference from other processes
  3. Percent Time Sleeping: Shows how much CPU headroom you have

    • Higher values (>50%) indicate your loop has plenty of processing time
    • Low values suggest your loop might be struggling to keep up

Improving Performance

If your statistics show timing issues, here are some general ways to improve your real-time performance:

  • Reduce other system load
  • Increase process priority
  • Move computationally intensive operations outside the loop

Monitoring Performance

You can access timing statistics programmatically:

rt_loop = SoftRealtimeLoop(dt=0.001)
# ... run your loop ...
avg_error = rt_loop.sum_err / rt_loop.n if rt_loop.n > 0 else 0
sleep_percentage = (rt_loop.sleep_t_agg / rt_loop.time_since_start) * 100 if rt_loop.time_since_start > 0 else 0

By monitoring these statistics, you can ensure your real-time applications maintain precise timing and reliable performance. The statistics help identify when your loop needs tuning or when system resources are becoming constrained.

Best Practices

  1. Choose Appropriate Time Steps:

    • Faster loops (smaller dt) require more CPU resources
    • Balance between control requirements and system capabilities
  2. Monitor Resource Usage:

    • Watch for sleep percentages below 20%
    • Consider operating at a lower frequency if the system is struggling
  3. Use Fade-out for Clean Graceful Shutdown:

    rt_loop = SoftRealtimeLoop(dt=0.01, fade=1.0)  # 1-second fade-out
    
  4. Reset for Multiple Uses:

    rt_loop.reset()  # Clears statistics for new measurements
    

If you have any questions or need further assistance, please post on the Open Source Leg community forum.