Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
def setupPeriodicStatus(self):
"""Enables periodic status updates from the Jaguar
"""
# Message 0 returns bus voltage, output voltage, output current, and
# temperature.
kMessage0Data = [
_cj.LM_PSTAT_VOLTBUS_B0, _cj.LM_PSTAT_VOLTBUS_B1,
_cj.LM_PSTAT_VOLTOUT_B0, _cj.LM_PSTAT_VOLTOUT_B1,
_cj.LM_PSTAT_CURRENT_B0, _cj.LM_PSTAT_CURRENT_B1,
_cj.LM_PSTAT_TEMP_B0, _cj.LM_PSTAT_TEMP_B1]
# Message 1 returns position and speed
kMessage1Data = [
_cj.LM_PSTAT_POS_B0, _cj.LM_PSTAT_POS_B1,
_cj.LM_PSTAT_POS_B2, _cj.LM_PSTAT_POS_B3,
_cj.LM_PSTAT_SPD_B0, _cj.LM_PSTAT_SPD_B1,
_cj.LM_PSTAT_SPD_B2, _cj.LM_PSTAT_SPD_B3]
# Message 2 returns limits and faults
kMessage2Data = [
_cj.LM_PSTAT_LIMIT_CLR,
_cj.LM_PSTAT_FAULT,
_cj.LM_PSTAT_END,
0, 0, 0, 0, 0]
def disableControl(self):
"""Disable the closed loop controller.
Stop driving the output based on the feedback.
"""
# Disable all control modes.
self.sendMessage(_cj.LM_API_VOLT_DIS, None)
self.sendMessage(_cj.LM_API_SPD_DIS, None)
self.sendMessage(_cj.LM_API_POS_DIS, None)
self.sendMessage(_cj.LM_API_ICTRL_DIS, None)
self.sendMessage(_cj.LM_API_VCOMP_DIS, None)
# Stop all periodic setpoints
self.sendMessage(_cj.LM_API_VOLT_T_SET, None,
frccan.CAN_SEND_PERIOD_STOP_REPEATING)
self.sendMessage(_cj.LM_API_SPD_T_SET, None,
frccan.CAN_SEND_PERIOD_STOP_REPEATING)
self.sendMessage(_cj.LM_API_POS_T_SET, None,
frccan.CAN_SEND_PERIOD_STOP_REPEATING)
self.sendMessage(_cj.LM_API_ICTRL_T_SET, None,
frccan.CAN_SEND_PERIOD_STOP_REPEATING)
self.sendMessage(_cj.LM_API_VCOMP_T_SET, None,
frccan.CAN_SEND_PERIOD_STOP_REPEATING)
except frccan.CANMessageNotFound:
# Verification is needed but not available - request it again.
self.requestMessage(_cj.LM_API_SPD_REF)
if not self.posRefVerified:
try:
data = self.getMessage(_cj.LM_API_POS_REF, _cj.CAN_MSGID_FULL_M)
posRef = data[0]
if self.positionReference == posRef:
self.posRefVerified = True
else:
# It's wrong - set it again
self.setPositionReference(self.positionReference)
except frccan.CANMessageNotFound:
# Verification is needed but not available - request it again.
self.requestMessage(_cj.LM_API_POS_REF)
if not self.pVerified:
message = 0
if self.controlMode == self.ControlMode.Speed:
message = _cj.LM_API_SPD_PC
elif self.controlMode == self.ControlMode.Position:
message = _cj.LM_API_POS_PC
elif self.controlMode == self.ControlMode.Current:
message = _cj.LM_API_ICTRL_PC
if message != 0:
try:
data = self.getMessage(message, _cj.CAN_MSGID_FULL_M)
p = _unpackFXP16_16(data)
if _FXP16_EQ(self.p, p):
self.pVerified = True
def updateSyncGroup(syncGroup):
"""Update all the motors that have pending sets in the syncGroup.
:param syncGroup: A bitmask of groups to generate synchronous output.
"""
_sendMessageHelper(_cj.CAN_MSGID_API_SYNC, [syncGroup],
frccan.CAN_SEND_PERIOD_NO_REPEAT)
_cj.LM_PSTAT_VOLTBUS_B0, _cj.LM_PSTAT_VOLTBUS_B1,
_cj.LM_PSTAT_VOLTOUT_B0, _cj.LM_PSTAT_VOLTOUT_B1,
_cj.LM_PSTAT_CURRENT_B0, _cj.LM_PSTAT_CURRENT_B1,
_cj.LM_PSTAT_TEMP_B0, _cj.LM_PSTAT_TEMP_B1]
# Message 1 returns position and speed
kMessage1Data = [
_cj.LM_PSTAT_POS_B0, _cj.LM_PSTAT_POS_B1,
_cj.LM_PSTAT_POS_B2, _cj.LM_PSTAT_POS_B3,
_cj.LM_PSTAT_SPD_B0, _cj.LM_PSTAT_SPD_B1,
_cj.LM_PSTAT_SPD_B2, _cj.LM_PSTAT_SPD_B3]
# Message 2 returns limits and faults
kMessage2Data = [
_cj.LM_PSTAT_LIMIT_CLR,
_cj.LM_PSTAT_FAULT,
_cj.LM_PSTAT_END,
0, 0, 0, 0, 0]
data = _packINT16(int(self.kSendMessagePeriod))
self.sendMessage(_cj.LM_API_PSTAT_PER_EN_S0, data)
self.sendMessage(_cj.LM_API_PSTAT_PER_EN_S1, data)
self.sendMessage(_cj.LM_API_PSTAT_PER_EN_S2, data)
self.sendMessage(_cj.LM_API_PSTAT_CFG_S0, kMessage0Data)
self.sendMessage(_cj.LM_API_PSTAT_CFG_S1, kMessage1Data)
self.sendMessage(_cj.LM_API_PSTAT_CFG_S2, kMessage2Data)
class CANJaguar(LiveWindowSendable, MotorSafety):
"""Texas Instruments Jaguar Speed Controller as a CAN device."""
kMaxMessageDataSize = 8
# The internal PID control loop in the Jaguar runs at 1kHz.
kControllerRate = 1000
kApproxBusVoltage = 12.0
kReceiveStatusAttempts = 50
allocated = Resource(63)
kFullMessageIDMask = \
_cj.CAN_MSGID_API_M | _cj.CAN_MSGID_MFR_M | _cj.CAN_MSGID_DTYPE_M
kSendMessagePeriod = 20
kTrustedMessages = set([
_cj.LM_API_VOLT_T_EN, _cj.LM_API_VOLT_T_SET, _cj.LM_API_SPD_T_EN,
_cj.LM_API_SPD_T_SET, _cj.LM_API_VCOMP_T_EN, _cj.LM_API_VCOMP_T_SET,
_cj.LM_API_POS_T_EN, _cj.LM_API_POS_T_SET, _cj.LM_API_ICTRL_T_EN,
_cj.LM_API_ICTRL_T_SET])
class Mode:
"""Control Mode."""
#: Sets an encoder as the speed reference only.
kEncoder = 0
#: Sets a quadrature encoder as the position and speed reference.
kQuadEncoder = 1
# Verify periodic status messages again
self.receivedStatusMessage0 = False
self.receivedStatusMessage1 = False
self.receivedStatusMessage2 = False
# Remove any old values from netcomms. Otherwise, parameters
# are incorrectly marked as verified based on stale messages.
messages = [
_cj.LM_API_SPD_REF, _cj.LM_API_POS_REF,
_cj.LM_API_SPD_PC, _cj.LM_API_POS_PC,
_cj.LM_API_ICTRL_PC, _cj.LM_API_SPD_IC,
_cj.LM_API_POS_IC, _cj.LM_API_ICTRL_IC,
_cj.LM_API_SPD_DC, _cj.LM_API_POS_DC,
_cj.LM_API_ICTRL_DC, _cj.LM_API_CFG_ENC_LINES,
_cj.LM_API_CFG_POT_TURNS, _cj.LM_API_CFG_BRAKE_COAST,
_cj.LM_API_CFG_LIMIT_MODE, _cj.LM_API_CFG_LIMIT_REV,
_cj.LM_API_CFG_MAX_VOUT, _cj.LM_API_VOLT_SET_RAMP,
_cj.LM_API_VCOMP_COMP_RAMP, _cj.LM_API_CFG_FAULT_TIME,
_cj.LM_API_CFG_LIMIT_FWD]
for message in messages:
try:
data = self.getMessage(message, _cj.CAN_MSGID_FULL_M)
except frccan.CANMessageNotFound:
pass
except frccan.CANMessageNotFound:
self.requestMessage(_cj.LM_API_STATUS_POWER)
# Verify that any recently set parameters are correct
if not self.controlModeVerified and self.controlEnabled:
try:
data = self.getMessage(_cj.LM_API_STATUS_CMODE,
else:
self.pVerified = False
self.iVerified = False
self.dVerified = False
# Verify periodic status messages again
self.receivedStatusMessage0 = False
self.receivedStatusMessage1 = False
self.receivedStatusMessage2 = False
# Remove any old values from netcomms. Otherwise, parameters
# are incorrectly marked as verified based on stale messages.
messages = [
_cj.LM_API_SPD_REF, _cj.LM_API_POS_REF,
_cj.LM_API_SPD_PC, _cj.LM_API_POS_PC,
_cj.LM_API_ICTRL_PC, _cj.LM_API_SPD_IC,
_cj.LM_API_POS_IC, _cj.LM_API_ICTRL_IC,
_cj.LM_API_SPD_DC, _cj.LM_API_POS_DC,
_cj.LM_API_ICTRL_DC, _cj.LM_API_CFG_ENC_LINES,
_cj.LM_API_CFG_POT_TURNS, _cj.LM_API_CFG_BRAKE_COAST,
_cj.LM_API_CFG_LIMIT_MODE, _cj.LM_API_CFG_LIMIT_REV,
_cj.LM_API_CFG_MAX_VOUT, _cj.LM_API_VOLT_SET_RAMP,
_cj.LM_API_VCOMP_COMP_RAMP, _cj.LM_API_CFG_FAULT_TIME,
_cj.LM_API_CFG_LIMIT_FWD]
for message in messages:
try:
data = self.getMessage(message, _cj.CAN_MSGID_FULL_M)
except frccan.CANMessageNotFound:
pass
except frccan.CANMessageNotFound:
self.requestMessage(_cj.LM_API_STATUS_POWER)
def setupPeriodicStatus(self):
"""Enables periodic status updates from the Jaguar
"""
# Message 0 returns bus voltage, output voltage, output current, and
# temperature.
kMessage0Data = [
_cj.LM_PSTAT_VOLTBUS_B0, _cj.LM_PSTAT_VOLTBUS_B1,
_cj.LM_PSTAT_VOLTOUT_B0, _cj.LM_PSTAT_VOLTOUT_B1,
_cj.LM_PSTAT_CURRENT_B0, _cj.LM_PSTAT_CURRENT_B1,
_cj.LM_PSTAT_TEMP_B0, _cj.LM_PSTAT_TEMP_B1]
# Message 1 returns position and speed
kMessage1Data = [
_cj.LM_PSTAT_POS_B0, _cj.LM_PSTAT_POS_B1,
_cj.LM_PSTAT_POS_B2, _cj.LM_PSTAT_POS_B3,
_cj.LM_PSTAT_SPD_B0, _cj.LM_PSTAT_SPD_B1,
_cj.LM_PSTAT_SPD_B2, _cj.LM_PSTAT_SPD_B3]
# Message 2 returns limits and faults
kMessage2Data = [
_cj.LM_PSTAT_LIMIT_CLR,
_cj.LM_PSTAT_FAULT,
_cj.LM_PSTAT_END,
0, 0, 0, 0, 0]
try:
data = self.getMessage(_cj.LM_API_PSTAT_DATA_S0,
_cj.CAN_MSGID_FULL_M)
self.busVoltage = _unpackFXP8_8(data[0:2])
self.outputVoltage = _unpackPercentage(data[2:4]) * self.busVoltage
self.outputCurrent = _unpackFXP8_8(data[4:6])
self.temperature = _unpackFXP8_8(data[6:8])
self.receivedStatusMessage0 = True
except frccan.CANMessageNotFound:
pass
# Check if a new position/speed message has arrived and do the same
try:
data = self.getMessage(_cj.LM_API_PSTAT_DATA_S1,
_cj.CAN_MSGID_FULL_M)
self.position = _unpackFXP16_16(data[0:4])
self.speed = _unpackFXP16_16(data[4:8])
self.receivedStatusMessage1 = True
except frccan.CANMessageNotFound:
pass
# Check if a new limits/faults message has arrived and do the same
try:
data = self.getMessage(_cj.LM_API_PSTAT_DATA_S2,
_cj.CAN_MSGID_FULL_M)
self.limits = data[0]
self.faults = data[1]