utils.spark_max_callbacks
1# Third-party imports 2import rev 3 4 5class SparkMaxCallbacks: 6 """ 7 Wraps a REV SparkMax motor and encoder into a dict of callbacks 8 for PositionCalibration. 9 10 You usually don't need to use this class directly. Pass 11 ``motor=`` to PositionCalibration and it creates these 12 callbacks for you automatically. 13 14 Direct usage (if you want to customize one callback):: 15 16 # Start from SparkMax defaults, then override one 17 cbs = SparkMaxCallbacks(motor, encoder).as_dict() 18 cbs['on_limit_detected'] = my_custom_handler 19 cal = PositionCalibration(name="Turret", ..., **cbs) 20 21 Returned callbacks and what they wrap: 22 23 ============================ ====================================== 24 Callback name SparkMax call 25 ============================ ====================================== 26 ``set_motor_output`` ``motor.set(pct)`` 27 ``stop_motor`` ``motor.stopMotor()`` 28 ``set_position`` ``encoder.setPosition(value)`` 29 ``get_position`` ``encoder.getPosition()`` 30 ``get_velocity`` ``encoder.getVelocity()`` 31 ``get_forward_limit_switch`` ``motor.getForwardLimitSwitch().get()`` 32 ``get_reverse_limit_switch`` ``motor.getReverseLimitSwitch().get()`` 33 ``set_current_limit`` ``motor.configure(smartCurrentLimit)`` 34 ``set_soft_limits`` ``motor.configure(softLimit ...)`` 35 ``disable_soft_limits`` ``motor.configure(softLimit ...)`` 36 ``save_config`` reads ``motor.configAccessor`` 37 ``restore_config`` ``motor.configure(...)`` 38 ``set_conversion_factor`` ``motor.configure(encoder ...)`` 39 ============================ ====================================== 40 """ 41 42 def __init__(self, motor: rev.SparkMax, encoder=None): 43 self._motor = motor 44 self._encoder = encoder or motor.getEncoder() 45 46 def as_dict(self) -> dict: 47 """Return all callbacks as a dict for PositionCalibration(**kwargs).""" 48 return { 49 'get_position': lambda: self._encoder.getPosition(), 50 'get_velocity': lambda: self._encoder.getVelocity(), 51 'set_position': lambda v: self._encoder.setPosition(v), 52 'set_motor_output': lambda p: self._motor.set(p), 53 'stop_motor': lambda: self._motor.stopMotor(), 54 'set_current_limit': self._make_set_current_limit(), 55 'set_soft_limits': self._make_set_soft_limits(), 56 'disable_soft_limits': self._make_disable_soft_limits(), 57 'save_config': self._make_save_config(), 58 'restore_config': self._make_restore_config(), 59 'get_forward_limit_switch': ( 60 lambda: self._motor.getForwardLimitSwitch().get() 61 ), 62 'get_reverse_limit_switch': ( 63 lambda: self._motor.getReverseLimitSwitch().get() 64 ), 65 'set_conversion_factor': ( 66 self._make_set_conversion_factor() 67 ), 68 } 69 70 def _make_set_current_limit(self): 71 motor = self._motor 72 73 def set_current_limit(amps): 74 cfg = rev.SparkMaxConfig() 75 cfg.smartCurrentLimit(int(amps)) 76 motor.configure( 77 cfg, 78 rev.ResetMode.kNoResetSafeParameters, 79 rev.PersistMode.kNoPersistParameters 80 ) 81 return set_current_limit 82 83 def _make_set_soft_limits(self): 84 motor = self._motor 85 86 def set_soft_limits(min_limit, max_limit): 87 cfg = rev.SparkMaxConfig() 88 ( 89 cfg.softLimit 90 .forwardSoftLimit(max_limit) 91 .forwardSoftLimitEnabled(True) 92 .reverseSoftLimit(min_limit) 93 .reverseSoftLimitEnabled(True) 94 ) 95 motor.configure( 96 cfg, 97 rev.ResetMode.kNoResetSafeParameters, 98 rev.PersistMode.kNoPersistParameters 99 ) 100 return set_soft_limits 101 102 def _make_disable_soft_limits(self): 103 motor = self._motor 104 105 def disable_soft_limits(forward, reverse): 106 cfg = rev.SparkMaxConfig() 107 if forward: 108 cfg.softLimit.forwardSoftLimitEnabled(False) 109 if reverse: 110 cfg.softLimit.reverseSoftLimitEnabled(False) 111 motor.configure( 112 cfg, 113 rev.ResetMode.kNoResetSafeParameters, 114 rev.PersistMode.kNoPersistParameters 115 ) 116 return disable_soft_limits 117 118 def _make_save_config(self): 119 motor = self._motor 120 121 def save_config(): 122 ca = motor.configAccessor 123 return { 124 'current_limit': ca.getSmartCurrentLimit(), 125 'current_free_limit': ca.getSmartCurrentFreeLimit(), 126 'current_rpm_limit': ca.getSmartCurrentRPMLimit(), 127 'fwd_soft_limit_enabled': ( 128 ca.softLimit.getForwardSoftLimitEnabled() 129 ), 130 'rev_soft_limit_enabled': ( 131 ca.softLimit.getReverseSoftLimitEnabled() 132 ), 133 'fwd_soft_limit': ca.softLimit.getForwardSoftLimit(), 134 'rev_soft_limit': ca.softLimit.getReverseSoftLimit(), 135 } 136 return save_config 137 138 def _make_restore_config(self): 139 motor = self._motor 140 141 def restore_config(saved): 142 cfg = rev.SparkMaxConfig() 143 cfg.smartCurrentLimit( 144 int(saved['current_limit']), 145 int(saved['current_free_limit']), 146 int(saved['current_rpm_limit']) 147 ) 148 ( 149 cfg.softLimit 150 .forwardSoftLimitEnabled(saved['fwd_soft_limit_enabled']) 151 .reverseSoftLimitEnabled(saved['rev_soft_limit_enabled']) 152 ) 153 motor.configure( 154 cfg, 155 rev.ResetMode.kNoResetSafeParameters, 156 rev.PersistMode.kNoPersistParameters 157 ) 158 return restore_config 159 160 def _make_set_conversion_factor(self): 161 motor = self._motor 162 163 def set_conversion_factor(factor): 164 # Velocity factor mirrors the position factor scaled by 1/60 165 # so that getVelocity() reads user-units per second. 166 velocity_factor = factor / 60.0 167 cfg = rev.SparkMaxConfig() 168 ( 169 cfg.encoder 170 .positionConversionFactor(factor) 171 .velocityConversionFactor(velocity_factor) 172 ) 173 motor.configure( 174 cfg, 175 rev.ResetMode.kNoResetSafeParameters, 176 rev.PersistMode.kNoPersistParameters 177 ) 178 return set_conversion_factor
6class SparkMaxCallbacks: 7 """ 8 Wraps a REV SparkMax motor and encoder into a dict of callbacks 9 for PositionCalibration. 10 11 You usually don't need to use this class directly. Pass 12 ``motor=`` to PositionCalibration and it creates these 13 callbacks for you automatically. 14 15 Direct usage (if you want to customize one callback):: 16 17 # Start from SparkMax defaults, then override one 18 cbs = SparkMaxCallbacks(motor, encoder).as_dict() 19 cbs['on_limit_detected'] = my_custom_handler 20 cal = PositionCalibration(name="Turret", ..., **cbs) 21 22 Returned callbacks and what they wrap: 23 24 ============================ ====================================== 25 Callback name SparkMax call 26 ============================ ====================================== 27 ``set_motor_output`` ``motor.set(pct)`` 28 ``stop_motor`` ``motor.stopMotor()`` 29 ``set_position`` ``encoder.setPosition(value)`` 30 ``get_position`` ``encoder.getPosition()`` 31 ``get_velocity`` ``encoder.getVelocity()`` 32 ``get_forward_limit_switch`` ``motor.getForwardLimitSwitch().get()`` 33 ``get_reverse_limit_switch`` ``motor.getReverseLimitSwitch().get()`` 34 ``set_current_limit`` ``motor.configure(smartCurrentLimit)`` 35 ``set_soft_limits`` ``motor.configure(softLimit ...)`` 36 ``disable_soft_limits`` ``motor.configure(softLimit ...)`` 37 ``save_config`` reads ``motor.configAccessor`` 38 ``restore_config`` ``motor.configure(...)`` 39 ``set_conversion_factor`` ``motor.configure(encoder ...)`` 40 ============================ ====================================== 41 """ 42 43 def __init__(self, motor: rev.SparkMax, encoder=None): 44 self._motor = motor 45 self._encoder = encoder or motor.getEncoder() 46 47 def as_dict(self) -> dict: 48 """Return all callbacks as a dict for PositionCalibration(**kwargs).""" 49 return { 50 'get_position': lambda: self._encoder.getPosition(), 51 'get_velocity': lambda: self._encoder.getVelocity(), 52 'set_position': lambda v: self._encoder.setPosition(v), 53 'set_motor_output': lambda p: self._motor.set(p), 54 'stop_motor': lambda: self._motor.stopMotor(), 55 'set_current_limit': self._make_set_current_limit(), 56 'set_soft_limits': self._make_set_soft_limits(), 57 'disable_soft_limits': self._make_disable_soft_limits(), 58 'save_config': self._make_save_config(), 59 'restore_config': self._make_restore_config(), 60 'get_forward_limit_switch': ( 61 lambda: self._motor.getForwardLimitSwitch().get() 62 ), 63 'get_reverse_limit_switch': ( 64 lambda: self._motor.getReverseLimitSwitch().get() 65 ), 66 'set_conversion_factor': ( 67 self._make_set_conversion_factor() 68 ), 69 } 70 71 def _make_set_current_limit(self): 72 motor = self._motor 73 74 def set_current_limit(amps): 75 cfg = rev.SparkMaxConfig() 76 cfg.smartCurrentLimit(int(amps)) 77 motor.configure( 78 cfg, 79 rev.ResetMode.kNoResetSafeParameters, 80 rev.PersistMode.kNoPersistParameters 81 ) 82 return set_current_limit 83 84 def _make_set_soft_limits(self): 85 motor = self._motor 86 87 def set_soft_limits(min_limit, max_limit): 88 cfg = rev.SparkMaxConfig() 89 ( 90 cfg.softLimit 91 .forwardSoftLimit(max_limit) 92 .forwardSoftLimitEnabled(True) 93 .reverseSoftLimit(min_limit) 94 .reverseSoftLimitEnabled(True) 95 ) 96 motor.configure( 97 cfg, 98 rev.ResetMode.kNoResetSafeParameters, 99 rev.PersistMode.kNoPersistParameters 100 ) 101 return set_soft_limits 102 103 def _make_disable_soft_limits(self): 104 motor = self._motor 105 106 def disable_soft_limits(forward, reverse): 107 cfg = rev.SparkMaxConfig() 108 if forward: 109 cfg.softLimit.forwardSoftLimitEnabled(False) 110 if reverse: 111 cfg.softLimit.reverseSoftLimitEnabled(False) 112 motor.configure( 113 cfg, 114 rev.ResetMode.kNoResetSafeParameters, 115 rev.PersistMode.kNoPersistParameters 116 ) 117 return disable_soft_limits 118 119 def _make_save_config(self): 120 motor = self._motor 121 122 def save_config(): 123 ca = motor.configAccessor 124 return { 125 'current_limit': ca.getSmartCurrentLimit(), 126 'current_free_limit': ca.getSmartCurrentFreeLimit(), 127 'current_rpm_limit': ca.getSmartCurrentRPMLimit(), 128 'fwd_soft_limit_enabled': ( 129 ca.softLimit.getForwardSoftLimitEnabled() 130 ), 131 'rev_soft_limit_enabled': ( 132 ca.softLimit.getReverseSoftLimitEnabled() 133 ), 134 'fwd_soft_limit': ca.softLimit.getForwardSoftLimit(), 135 'rev_soft_limit': ca.softLimit.getReverseSoftLimit(), 136 } 137 return save_config 138 139 def _make_restore_config(self): 140 motor = self._motor 141 142 def restore_config(saved): 143 cfg = rev.SparkMaxConfig() 144 cfg.smartCurrentLimit( 145 int(saved['current_limit']), 146 int(saved['current_free_limit']), 147 int(saved['current_rpm_limit']) 148 ) 149 ( 150 cfg.softLimit 151 .forwardSoftLimitEnabled(saved['fwd_soft_limit_enabled']) 152 .reverseSoftLimitEnabled(saved['rev_soft_limit_enabled']) 153 ) 154 motor.configure( 155 cfg, 156 rev.ResetMode.kNoResetSafeParameters, 157 rev.PersistMode.kNoPersistParameters 158 ) 159 return restore_config 160 161 def _make_set_conversion_factor(self): 162 motor = self._motor 163 164 def set_conversion_factor(factor): 165 # Velocity factor mirrors the position factor scaled by 1/60 166 # so that getVelocity() reads user-units per second. 167 velocity_factor = factor / 60.0 168 cfg = rev.SparkMaxConfig() 169 ( 170 cfg.encoder 171 .positionConversionFactor(factor) 172 .velocityConversionFactor(velocity_factor) 173 ) 174 motor.configure( 175 cfg, 176 rev.ResetMode.kNoResetSafeParameters, 177 rev.PersistMode.kNoPersistParameters 178 ) 179 return set_conversion_factor
Wraps a REV SparkMax motor and encoder into a dict of callbacks for PositionCalibration.
You usually don't need to use this class directly. Pass
motor= to PositionCalibration and it creates these
callbacks for you automatically.
Direct usage (if you want to customize one callback)::
# Start from SparkMax defaults, then override one
cbs = SparkMaxCallbacks(motor, encoder).as_dict()
cbs['on_limit_detected'] = my_custom_handler
cal = PositionCalibration(name="Turret", ..., **cbs)
Returned callbacks and what they wrap:
============================ ======================================
Callback name SparkMax call
============================ ======================================
set_motor_output motor.set(pct)
stop_motor motor.stopMotor()
set_position encoder.setPosition(value)
get_position encoder.getPosition()
get_velocity encoder.getVelocity()
get_forward_limit_switch motor.getForwardLimitSwitch().get()
get_reverse_limit_switch motor.getReverseLimitSwitch().get()
set_current_limit motor.configure(smartCurrentLimit)
set_soft_limits motor.configure(softLimit ...)
disable_soft_limits motor.configure(softLimit ...)
save_config reads motor.configAccessor
restore_config motor.configure(...)
set_conversion_factor motor.configure(encoder ...)
============================ ======================================
47 def as_dict(self) -> dict: 48 """Return all callbacks as a dict for PositionCalibration(**kwargs).""" 49 return { 50 'get_position': lambda: self._encoder.getPosition(), 51 'get_velocity': lambda: self._encoder.getVelocity(), 52 'set_position': lambda v: self._encoder.setPosition(v), 53 'set_motor_output': lambda p: self._motor.set(p), 54 'stop_motor': lambda: self._motor.stopMotor(), 55 'set_current_limit': self._make_set_current_limit(), 56 'set_soft_limits': self._make_set_soft_limits(), 57 'disable_soft_limits': self._make_disable_soft_limits(), 58 'save_config': self._make_save_config(), 59 'restore_config': self._make_restore_config(), 60 'get_forward_limit_switch': ( 61 lambda: self._motor.getForwardLimitSwitch().get() 62 ), 63 'get_reverse_limit_switch': ( 64 lambda: self._motor.getReverseLimitSwitch().get() 65 ), 66 'set_conversion_factor': ( 67 self._make_set_conversion_factor() 68 ), 69 }
Return all callbacks as a dict for PositionCalibration(**kwargs).