874 auto driveName = drive->
GetName();
876 module->SetupTelemetry(driveName);
879 auto inst = wpi::nt::NetworkTableInstance::GetDefault();
880 m_dataTable = inst.GetTable(
"Mechanisms")->GetSubTable(driveName);
881 m_tuningTable = inst.GetTable(
"Tuning")->GetSubTable(driveName);
891 if (translationPID) {
892 doubleFields.at(DoubleTelemetryField::TranslationP)
893 .SetDefaultValue(translationPID->get().GetP());
894 doubleFields.at(DoubleTelemetryField::TranslationI)
895 .SetDefaultValue(translationPID->get().GetI());
896 doubleFields.at(DoubleTelemetryField::TranslationD)
897 .SetDefaultValue(translationPID->get().GetD());
899 doubleFields.at(DoubleTelemetryField::TranslationP).Disable();
900 doubleFields.at(DoubleTelemetryField::TranslationI).Disable();
901 doubleFields.at(DoubleTelemetryField::TranslationD).Disable();
904 doubleFields.at(DoubleTelemetryField::RotationP).SetDefaultValue(rotationPID->get().GetP());
905 doubleFields.at(DoubleTelemetryField::RotationI).SetDefaultValue(rotationPID->get().GetI());
906 doubleFields.at(DoubleTelemetryField::RotationD).SetDefaultValue(rotationPID->get().GetD());
908 doubleFields.at(DoubleTelemetryField::RotationP).Disable();
909 doubleFields.at(DoubleTelemetryField::RotationI).Disable();
910 doubleFields.at(DoubleTelemetryField::RotationD).Disable();
913 if (!translationPID || !rotationPID) {
914 doubleFields.at(DoubleTelemetryField::AutoAlignPoseX).Disable();
915 doubleFields.at(DoubleTelemetryField::AutoAlignPoseY).Disable();
916 doubleFields.at(DoubleTelemetryField::AutoAlignPoseRotation).Disable();
917 m_config.
GetBoolFields().at(BooleanTelemetryField::AutoAlignEnabled).Disable();
921 if (!modules.empty()) {
922 auto* driveMotor = modules[0]->GetDriveMotorController();
924 driveMotor->GetConfig().GetSlotGains(driveMotor->GetClosedLoopControllerSlot());
926 .at(DoubleTelemetryField::ModulesDriveP)
927 .SetDefaultValue(driveGains.kP);
929 .at(DoubleTelemetryField::ModulesDriveI)
930 .SetDefaultValue(driveGains.kI);
932 .at(DoubleTelemetryField::ModulesDriveD)
933 .SetDefaultValue(driveGains.kD);
935 .at(DoubleTelemetryField::ModulesDriveKs)
936 .SetDefaultValue(driveGains.kS);
938 .at(DoubleTelemetryField::ModulesDriveKv)
939 .SetDefaultValue(driveGains.kV);
941 .at(DoubleTelemetryField::ModulesDriveKa)
942 .SetDefaultValue(driveGains.kA);
944 auto* azimuthMotor = modules[0]->GetAzimuthMotorController();
946 azimuthMotor->GetConfig().GetSlotGains(azimuthMotor->GetClosedLoopControllerSlot());
948 .at(DoubleTelemetryField::ModulesAzimuthP)
949 .SetDefaultValue(azimuthGains.kP);
951 .at(DoubleTelemetryField::ModulesAzimuthI)
952 .SetDefaultValue(azimuthGains.kI);
954 .at(DoubleTelemetryField::ModulesAzimuthD)
955 .SetDefaultValue(azimuthGains.kD);
957 .at(DoubleTelemetryField::ModulesAzimuthKs)
958 .SetDefaultValue(azimuthGains.kS);
960 .at(DoubleTelemetryField::ModulesAzimuthKv)
961 .SetDefaultValue(azimuthGains.kV);
963 .at(DoubleTelemetryField::ModulesAzimuthKa)
964 .SetDefaultValue(azimuthGains.kA);
969 if (!dt.IsEnabled())
continue;
970 if (nt4Enabled) dt.SetupNetworkTables(m_dataTable, m_tuningTable);
971 if (dataLogName) dt.SetupDataLog(*dataLogName);
974 if (!bt.IsEnabled())
continue;
975 if (nt4Enabled) bt.SetupNetworkTables(m_dataTable, m_tuningTable);
976 if (dataLogName) bt.SetupDataLog(*dataLogName);
979 if (!stt.IsEnabled())
continue;
980 if (nt4Enabled) stt.SetupNetworkTables(m_dataTable, m_tuningTable);
981 if (dataLogName) stt.SetupDataLog(*dataLogName);
984 if (!stt.IsEnabled())
continue;
985 if (nt4Enabled) stt.SetupNetworkTables(m_dataTable, m_tuningTable);
986 if (dataLogName) stt.SetupDataLog(*dataLogName);
989 if (!stat.IsEnabled())
continue;
990 if (nt4Enabled) stat.SetupNetworkTables(m_dataTable, m_tuningTable);
991 if (dataLogName) stat.SetupDataLog(*dataLogName);
1059 std::optional<wpi::math::PIDController> translationPID;
1061 std::optional<wpi::math::PIDController> rotationPID;
1069 std::set<TuningMode> modes;
1070 for (
auto& [field, bt] : boolFields) {
1071 if (!bt.IsEnabled() || !bt.Get())
continue;
1073 case BooleanTelemetryField::AutoAlignEnabled:
1074 modes.insert(TuningMode::AutoAlign);
1075 modes.erase(TuningMode::Drive);
1076 modes.erase(TuningMode::Azimuth);
1077 boolFields.at(BooleanTelemetryField::ModulesDriveTuningEnabled).ForceSet(
false);
1078 boolFields.at(BooleanTelemetryField::ModulesAzimuthTuningEnabled).ForceSet(
false);
1080 case BooleanTelemetryField::ModulesDriveTuningEnabled:
1081 if (!modes.contains(TuningMode::AutoAlign)) {
1082 modes.insert(TuningMode::Drive);
1083 modes.erase(TuningMode::Azimuth);
1084 boolFields.at(BooleanTelemetryField::ModulesAzimuthTuningEnabled).ForceSet(
false);
1087 case BooleanTelemetryField::ModulesDriveInPlace:
1088 modes.insert(TuningMode::DriveInPlace);
1090 case BooleanTelemetryField::ModulesDriveVoltageEnabled:
1091 modes.insert(TuningMode::DriveVoltage);
1093 case BooleanTelemetryField::ModulesAzimuthTuningEnabled:
1094 if (!modes.contains(TuningMode::AutoAlign) && !modes.contains(TuningMode::Drive)) {
1095 modes.insert(TuningMode::Azimuth);
1098 case BooleanTelemetryField::ModulesAzimuthVoltageEnabled:
1099 modes.insert(TuningMode::AzimuthVoltage);
1104 if (!modes.contains(TuningMode::Drive)) {
1105 modes.erase(TuningMode::DriveInPlace);
1106 modes.erase(TuningMode::DriveVoltage);
1108 if (!modes.contains(TuningMode::Azimuth)) modes.erase(TuningMode::AzimuthVoltage);
1112 wpi::util::array<wpi::math::Rotation2d, NumModules> driveAngles{wpi::util::empty_array};
1113 for (
size_t i = 0; i < NumModules; ++i) {
1114 driveAngles[i] = wpi::math::Rotation2d{};
1115 if (modes.contains(TuningMode::DriveInPlace)) {
1116 auto moduleLocation = *modules[i]->GetConfig().GetLocation();
1117 driveAngles[i] = moduleLocation.Angle().value_or(wpi::math::Rotation2d{}) +
1118 wpi::math::Rotation2d{wpi::units::degree_t{90}};
1123 if (modes.contains(TuningMode::AutoAlign)) {
1124 wpi::math::Pose2d targetPose{
1125 wpi::units::meter_t{doubleFields.at(DoubleTelemetryField::AutoAlignPoseX).Get()},
1126 wpi::units::meter_t{doubleFields.at(DoubleTelemetryField::AutoAlignPoseY).Get()},
1127 wpi::math::Rotation2d{
1128 wpi::units::degree_t{doubleFields.at(DoubleTelemetryField::AutoAlignPoseRotation).Get()}}};
1134 if (modes != m_lastModes) {
1135 const std::set<TuningMode> lastModes = m_lastModes.value_or(std::set<TuningMode>{});
1136 m_lastModes = modes;
1138 for (
auto* module : modules) {
1139 if (lastModes.contains(TuningMode::DriveVoltage) && !modes.contains(TuningMode::DriveVoltage)) {
1140 module->GetDriveMotorController()->StartClosedLoopController();
1142 if (lastModes.contains(TuningMode::AzimuthVoltage) &&
1143 !modes.contains(TuningMode::AzimuthVoltage)) {
1144 module->GetAzimuthMotorController()->StartClosedLoopController();
1147 wpi::util::array<wpi::math::SwerveModuleVelocity, NumModules> states{wpi::util::empty_array};
1148 if (modes.empty()) {
1151 for (
size_t i = 0; i < NumModules; ++i) {
1152 states[i] = wpi::math::SwerveModuleVelocity{wpi::units::meters_per_second_t{0},
1153 modules[i]->GetState().angle};
1157 for (
auto mode : modes) {
1159 case TuningMode::AutoAlign:
1162 case TuningMode::DriveInPlace:
1165 case TuningMode::Drive:
1166 if (!modes.contains(TuningMode::DriveVoltage)) {
1167 for (
size_t i = 0; i < NumModules; ++i) {
1168 states[i] = wpi::math::SwerveModuleVelocity{
1169 wpi::units::meters_per_second_t{
1170 doubleFields.at(DoubleTelemetryField::ModulesDriveVelocity).Get()},
1176 case TuningMode::DriveVoltage:
1177 for (
size_t i = 0; i < NumModules; ++i) {
1179 if (!lastModes.contains(TuningMode::DriveVoltage)) {
1180 modules[i]->GetDriveMotorController()->StopClosedLoopController();
1183 modules[i]->GetDriveMotorController()->SetVoltage(
1184 wpi::units::volt_t{doubleFields.at(DoubleTelemetryField::ModulesDriveVoltage).Get()});
1185 modules[i]->GetAzimuthMotorController()->SetPosition(
1186 wpi::units::degree_t{driveAngles[i].Degrees()});
1189 case TuningMode::Azimuth:
1190 if (!modes.contains(TuningMode::AzimuthVoltage)) {
1194 doubleFields.at(DoubleTelemetryField::ModulesAzimuthAngle).Get()}});
1197 case TuningMode::AzimuthVoltage:
1198 for (
auto* module : modules) {
1200 if (!lastModes.contains(TuningMode::AzimuthVoltage)) {
1201 module->GetAzimuthMotorController()->StopClosedLoopController();
1204 module->GetDriveMotorController()->SetVelocity(wpi::units::meters_per_second_t{0} +
1205 module->GetCouplingVelocity());
1206 module->GetAzimuthMotorController()->SetVoltage(wpi::units::volt_t{
1207 doubleFields.at(DoubleTelemetryField::ModulesAzimuthVoltage).Get()});
1215 for (
auto field : {DoubleTelemetryField::TranslationP,
1216 DoubleTelemetryField::TranslationI,
1217 DoubleTelemetryField::TranslationD,
1218 DoubleTelemetryField::RotationP,
1219 DoubleTelemetryField::RotationI,
1220 DoubleTelemetryField::RotationD,
1221 DoubleTelemetryField::AutoAlignPoseX,
1222 DoubleTelemetryField::AutoAlignPoseY,
1223 DoubleTelemetryField::AutoAlignPoseRotation,
1224 DoubleTelemetryField::ModulesDriveP,
1225 DoubleTelemetryField::ModulesDriveI,
1226 DoubleTelemetryField::ModulesDriveD,
1227 DoubleTelemetryField::ModulesDriveKs,
1228 DoubleTelemetryField::ModulesDriveKv,
1229 DoubleTelemetryField::ModulesDriveKa,
1230 DoubleTelemetryField::ModulesDriveVelocity,
1231 DoubleTelemetryField::ModulesDriveVoltage,
1232 DoubleTelemetryField::ModulesAzimuthP,
1233 DoubleTelemetryField::ModulesAzimuthI,
1234 DoubleTelemetryField::ModulesAzimuthD,
1235 DoubleTelemetryField::ModulesAzimuthKs,
1236 DoubleTelemetryField::ModulesAzimuthKv,
1237 DoubleTelemetryField::ModulesAzimuthKa,
1238 DoubleTelemetryField::ModulesAzimuthAngle,
1239 DoubleTelemetryField::ModulesAzimuthVoltage}) {
1240 auto& dt = doubleFields.at(field);
1241 if (!dt.IsEnabled() || !dt.IsTunable())
continue;
1243 case DoubleTelemetryField::TranslationP:
1244 if (translationPID) {
1245 translationPID->SetP(dt.Get());
1249 case DoubleTelemetryField::TranslationI:
1250 if (translationPID) {
1251 translationPID->SetI(dt.Get());
1255 case DoubleTelemetryField::TranslationD:
1256 if (translationPID) {
1257 translationPID->SetD(dt.Get());
1261 case DoubleTelemetryField::RotationP:
1263 rotationPID->SetP(dt.Get());
1267 case DoubleTelemetryField::RotationI:
1269 rotationPID->SetI(dt.Get());
1273 case DoubleTelemetryField::RotationD:
1275 rotationPID->SetD(dt.Get());
1279 case DoubleTelemetryField::AutoAlignPoseX:
1280 case DoubleTelemetryField::AutoAlignPoseY:
1281 case DoubleTelemetryField::AutoAlignPoseRotation:
1284 case DoubleTelemetryField::ModulesDriveP:
1285 for (
auto* module : modules) module->GetDriveMotorController()->SetKp(dt.Get());
1287 case DoubleTelemetryField::ModulesDriveI:
1288 for (
auto* module : modules) module->GetDriveMotorController()->SetKi(dt.Get());
1290 case DoubleTelemetryField::ModulesDriveD:
1291 for (
auto* module : modules) module->GetDriveMotorController()->SetKd(dt.Get());
1293 case DoubleTelemetryField::ModulesDriveKs:
1294 for (
auto* module : modules) module->GetDriveMotorController()->SetKs(dt.Get());
1296 case DoubleTelemetryField::ModulesDriveKv:
1297 for (
auto* module : modules) module->GetDriveMotorController()->SetKv(dt.Get());
1299 case DoubleTelemetryField::ModulesDriveKa:
1300 for (
auto* module : modules) module->GetDriveMotorController()->SetKa(dt.Get());
1302 case DoubleTelemetryField::ModulesAzimuthP:
1303 for (
auto* module : modules) module->GetAzimuthMotorController()->SetKp(dt.Get());
1305 case DoubleTelemetryField::ModulesAzimuthI:
1306 for (
auto* module : modules) module->GetAzimuthMotorController()->SetKi(dt.Get());
1308 case DoubleTelemetryField::ModulesAzimuthD:
1309 for (
auto* module : modules) module->GetAzimuthMotorController()->SetKd(dt.Get());
1311 case DoubleTelemetryField::ModulesAzimuthKs:
1312 for (
auto* module : modules) module->GetAzimuthMotorController()->SetKs(dt.Get());
1314 case DoubleTelemetryField::ModulesAzimuthKv:
1315 for (
auto* module : modules) module->GetAzimuthMotorController()->SetKv(dt.Get());
1317 case DoubleTelemetryField::ModulesAzimuthKa:
1318 for (
auto* module : modules) module->GetAzimuthMotorController()->SetKa(dt.Get());
1320 case DoubleTelemetryField::ModulesDriveVelocity:
1321 if (modes.contains(TuningMode::Drive) && !modes.contains(TuningMode::DriveVoltage)) {
1322 wpi::util::array<wpi::math::SwerveModuleVelocity, NumModules> states{
1323 wpi::util::empty_array};
1324 for (
size_t i = 0; i < NumModules; ++i) {
1325 states[i] = wpi::math::SwerveModuleVelocity{wpi::units::meters_per_second_t{dt.Get()},
1331 case DoubleTelemetryField::ModulesDriveVoltage:
1332 if (modes.contains(TuningMode::DriveVoltage)) {
1333 for (
size_t i = 0; i < NumModules; ++i) {
1335 modules[i]->GetDriveMotorController()->SetVoltage(wpi::units::volt_t{dt.Get()});
1336 modules[i]->GetAzimuthMotorController()->SetPosition(
1337 wpi::units::degree_t{driveAngles[i].Degrees()});
1341 case DoubleTelemetryField::ModulesAzimuthAngle:
1342 if (modes.contains(TuningMode::Azimuth) && !modes.contains(TuningMode::AzimuthVoltage)) {
1345 drive->
SetAzimuthAngles(wpi::math::Rotation2d{wpi::units::degree_t{dt.Get()}});
1348 case DoubleTelemetryField::ModulesAzimuthVoltage:
1349 if (modes.contains(TuningMode::AzimuthVoltage)) {
1350 for (
auto* module : modules) {
1352 module->GetDriveMotorController()->SetVelocity(wpi::units::meters_per_second_t{0} +
1353 module->GetCouplingVelocity());
1354 module->GetAzimuthMotorController()->SetVoltage(wpi::units::volt_t{dt.Get()});