def on_run(self, offset, desire_setter, current, default_error, error=None, modulo_error=False, *args, **kwargs): """ Note: This does not 0 the desire when completed. :param offset: A Number or function that when called with no arguments returns a Number that represents the value to be targeted. This offset will be added to the current value. :param desire_setter: A SHM variable (object with a set method) that will be called with a single argument to target. :param current: A Number or function that when called with no arguments returns the current value as a Number. :param error: A Number representing the allowed error before a wrapper is finished. :param modulo_error: a Boolean that is true only if the error calculated should be with respect to modulo 360. """ if error is None: error = default_error offset, current = call_if_function(offset), call_if_function(current) desire_setter(current + offset) if within_deadband(current + offset, current, error, use_mod_error=modulo_error): self.finish()
def on_run(self, velocity, desire_setter, current, target=None, error=-1, modulo_error=False, *args, **kwargs): """ Note: This does not 0 the desire when completed. :param velocity: A Number or function that when called with no arguments returns a Number that represents the value to be targeted. This target will be multiplied with the time in seconds from the last call and be added to the current value. :param desire_setter: A SHM variable (object with a set method) that will be called with a single argument to target. :param current: A Number or function that when called with no arguments returns the current value as a Number. :param target: A Number (or function) that represents the target velocity (units/second). :param error: A Number representing the allowed error before a wrapper is finished. :param modulo_error: a Boolean that is true only if the error calculated should be with respect to modulo 360. """ velocity, current, target = call_if_function(velocity), call_if_function(current), call_if_function(target) target_for_velocity = velocity * (self.this_run_time - self.last_run_time) self.relative_to_current_setter.on_run(offset=target_for_velocity, desire_setter=desire_setter, current=current, error=error, modulo_error=modulo_error) if target is not None or within_deadband(target, current, error, use_mod_error=modulo_error): self.finish() else: desire_setter()
def on_run(self, input_value, output_function, target=0, modulo_error=False, deadband=1, p=1, d=0, i=0, negate=False, *args, **kwargs): # TODO: minimum_output too? input_value = call_if_function(input_value) target = call_if_function(target) output = self.pid.tick(value=input_value, desired=target, p=p, d=d, i=i) output_function(-output if negate else output) if within_deadband(input_value, target, deadband=deadband, use_mod_error=modulo_error): # TODO: Should this zero on finish? Or set to I term? self.finish()
def run(self, input_value, output_function, p=0.2, d=0, i=0, target=0, deadband=0, modulo_error=False, negate=False, debug=False, min_out=None): input_value = evaluate_or_call(input_value) # Don't do anything if the current value (input_value) is within the deadband of the target. if within_deadband(input_value, target, deadband, use_mod_error=modulo_error): # TODO: Should we set the output to the target as we don't know what the current target is? self._finish() return err = (-1 if negate else 1) * (target - input_value) self.error = err # P, I and D loops output_value = p * err self.total_error += err * (self.this_run - self.last_run) output_value += i * self.total_error output_value += d * (self.last_value - input_value) / (self.this_run - self.last_run) if debug: print(output_value) print() if min_out is not None and output_value < min_out: output_function(min_out * (-1 if output_value < 0 else 1)) else: output_function(output_value) self.log({ 'p': p, 'i': i, 'd': d, 'in': input_value, 'out': output_value, 'negate': negate })
def run(self, value, variable, current, error=0, modulo_error=False): """ :param value: A Number that represents the value to be targeted. :param variable: A SHM variable (object with a set method) that will be called with a single argument to target. :param current: A function that when called with no arguments returns the current value as a Number. :param error: A Number representing the allowed error before a wrapper is finished. :param modulo_error: a Boolean that is true only if the error calculated should be with respect to modulo 360. """ value, current = evaluate_or_call(value), evaluate_or_call(current) variable.set(value) if within_deadband(value, current, error, use_mod_error=modulo_error): self._finish()
def on_run(self, velocity, desire_setter, current, default_error, target=None, error=None, modulo_error=False, min_target=None, max_target=None, *args, **kwargs): """ Note: This does not 0 the desire when completed. :param velocity: A Number or function that when called with no arguments returns a Number that represents the value to be targeted. This target will be multiplied with the time in seconds from the last call and be added to the current value. :param desire_setter: A SHM variable (object with a set method) that will be called with a single argument to target. :param current: A Number or function that when called with no arguments returns the current value as a Number. :param target: A Number (or function) that represents the target velocity (units/second). :param error: A Number representing the allowed error before a wrapper is finished. :param modulo_error: a Boolean that is true only if the error calculated should be with respect to modulo 360. """ if error is None: error = default_error velocity, current, target = call_if_function( velocity), call_if_function(current), call_if_function(target) target_for_velocity = velocity * (self.this_run_time - self.last_run_time) self.relative_to_current_setter.on_run(offset=target_for_velocity, desire_setter=desire_setter, current=current, error=error, modulo_error=modulo_error, min_target=min_target, max_target=max_target) if target is not None or within_deadband( target, current, error, use_mod_error=modulo_error): if target is not None: desire_setter() self.finish() else: desire_setter()
def on_run(self, input_value, output_function, target=0, modulo_error=False, deadband=1, p=1, d=0, i=0, negate=False, max_out=None, *args, **kwargs): # TODO: minimum_output too? input_value = call_if_function(input_value) target = call_if_function(target) if max_out is None: max_out = float('inf') output = self.pid.tick(value=input_value, desired=target, p=p, d=d, i=i) output = math.copysign(min(abs(output), max_out), output) output_function(-output if negate else output) if within_deadband(input_value, target, deadband=deadband, use_mod_error=modulo_error): # TODO: Should this zero on finish? Or set to I term? self.finish()
def on_run(self, offset, desire_setter, current, error=-1, modulo_error=False, *args, **kwargs): """ Note: This does not 0 the desire when completed. :param offset: A Number or function that when called with no arguments returns a Number that represents the value to be targeted. This offset will be added to the current value on the first run. :param desire_setter: A SHM variable (object with a set method) that will be called with a single argument to target. :param current: A Number or function that when called with no arguments returns the current value as a Number. :param error: A Number representing the allowed error before a wrapper is finished. :param modulo_error: a Boolean that is true only if the error calculated should be with respect to modulo 360. """ offset, current = call_if_function(offset), call_if_function(current) if within_deadband(self.initial_value + offset, current, error, use_mod_error=modulo_error): self.finish() else: desire_setter(self.initial_value + offset)