Source code for hardware.slew_limiter

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Copyright 2020-2025 by Murray Altheim. All rights reserved. This file is part
# of the Robot Operating System project, released under the MIT License. Please
# see the LICENSE file included as part of this package.
#
# author:   altheim
# created:  2025-06-05
# modified: 2025-06-09
#

from datetime import datetime as dt

# ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
[docs] class SlewLimiter: ''' A slew limiter for the BrushlessMotor, used to limit the rate of change of the motor's target speed, preventing sudden, abrupt changes that could be harmful to the motor and ensuring the changes to the motor's speed are gradual, more elegant, rather than instantaneous. ''' def __init__(self, max_delta_per_sec, safe_threshold=10): ''' :param max_delta_per_sec: Maximum allowed change per second (e.g. RPM/sec or %/sec) :param safe_threshold: Minimum magnitude below which direction changes are allowed ''' self.max_delta_per_sec = float(max_delta_per_sec) self.safe_threshold = float(safe_threshold) self._last_value = None self._last_time = None self.reset()
[docs] def limit(self, value): ''' Returns the limited value based on the time passed since the last call, ''' now = dt.now() value = float(value) if self._last_value is None: self._last_value = value self._last_time = now return value elapsed = (now - self._last_time).total_seconds() if elapsed <= 0.0: return self._last_value # no time has passed # prevent direction change unless speed is low if ( value * self._last_value < 0 and abs(self._last_value) > self.safe_threshold ): return self._last_value # block reversal # calculate allowed delta max_delta = self.max_delta_per_sec * elapsed delta = value - self._last_value if abs(delta) > max_delta: delta = max_delta if delta > 0 else -max_delta value = self._last_value + delta self._last_value = value self._last_time = now return value
[docs] def reset(self, value=None): ''' Resets the limiter to a specific value (or clears it). ''' self._last_value = float(value) if value is not None else None self._last_time = dt.now()
#EOF