[wpilib] Publish AllianceStationID (#8856)

Glass now internally uses the AllianceStationID enum, but the two
separate topics remain for simple use cases. The Invalid alliance is now
published as Red, Station 0, instead of 3.

Fixes #6488 and fixes #8725.
This commit is contained in:
Gold856
2026-07-02 02:07:51 -04:00
committed by GitHub
parent 9dabcb99f3
commit 5a06b81673
4 changed files with 28 additions and 24 deletions

View File

@@ -32,10 +32,9 @@ NTFMSModel::NTFMSModel(wpi::nt::NetworkTableInstance inst,
: m_inst{inst},
m_gameDataSubscriber{
inst.GetStringTopic(fmt::format("{}/GameData", path)).Subscribe("")},
m_alliance{inst.GetBooleanTopic(fmt::format("{}/IsRedAlliance", path))
.Subscribe(false)},
m_station{inst.GetIntegerTopic(fmt::format("{}/StationNumber", path))
.Subscribe(0)},
m_allianceStation{
inst.GetIntegerTopic(fmt::format("{}/AllianceStationID", path))
.Subscribe(0)},
m_controlWord{inst.GetRawTopic(fmt::format("{}/ControlWord", path))
.Subscribe("struct:ControlWord", {})},
m_fmsAttached{fmt::format("NT_FMS:FMSAttached:{}", path)},
@@ -47,18 +46,8 @@ NTFMSModel::NTFMSModel(wpi::nt::NetworkTableInstance inst,
m_gameData{fmt::format("NT_FMS:GameData:{}", path)} {}
void NTFMSModel::Update() {
for (auto&& v : m_alliance.ReadQueue()) {
int allianceStationId = m_allianceStationId.GetValue();
allianceStationId %= 3;
// true if red
allianceStationId += 3 * (v.value ? 0 : 1);
m_allianceStationId.SetValue(allianceStationId, v.time);
}
for (auto&& v : m_station.ReadQueue()) {
int allianceStationId = m_allianceStationId.GetValue();
bool isRed = (allianceStationId < 3);
// the NT value is 1-indexed
m_allianceStationId.SetValue(v.value - 1 + 3 * (isRed ? 0 : 1), v.time);
for (auto&& v : m_allianceStation.ReadQueue()) {
m_allianceStationId.SetValue(v.value, v.time);
}
for (auto&& v : m_controlWord.ReadQueue()) {
if (v.value.size() != sizeof(uint64_t)) {

View File

@@ -53,8 +53,7 @@ class NTFMSModel : public FMSModel {
private:
wpi::nt::NetworkTableInstance m_inst;
wpi::nt::StringSubscriber m_gameDataSubscriber;
wpi::nt::BooleanSubscriber m_alliance;
wpi::nt::IntegerSubscriber m_station;
wpi::nt::IntegerSubscriber m_allianceStation;
wpi::nt::RawSubscriber m_controlWord;
BooleanSource m_fmsAttached;

View File

@@ -107,6 +107,8 @@ struct MatchDataSender {
true};
MatchDataSenderEntry<wpi::nt::IntegerTopic> station{table, "StationNumber",
1};
MatchDataSenderEntry<wpi::nt::IntegerTopic> allianceStation{
table, "AllianceStationID", 0};
wpi::nt::StructPublisher<wpi::hal::ControlWord> controlWord;
wpi::nt::StringPublisher opMode;
wpi::hal::ControlWord prevControlWord;
@@ -931,10 +933,14 @@ void SendMatchData() {
isRedAlliance = true;
stationNumber = 2;
break;
default:
case HAL_ALLIANCE_STATION_RED_3:
isRedAlliance = true;
stationNumber = 3;
break;
default:
isRedAlliance = true;
stationNumber = 0;
break;
}
HAL_MatchInfo tmpDataStore;
@@ -944,14 +950,15 @@ void SendMatchData() {
HAL_GetGameData(&tmpGameData);
auto& inst = GetInstance();
inst.matchDataSender.alliance.Set(isRedAlliance);
inst.matchDataSender.station.Set(stationNumber);
inst.matchDataSender.eventName.Set(tmpDataStore.eventName);
inst.matchDataSender.gameData.Set(
std::string(reinterpret_cast<char*>(tmpGameData.gameData)));
inst.matchDataSender.matchNumber.Set(tmpDataStore.matchNumber);
inst.matchDataSender.replayNumber.Set(tmpDataStore.replayNumber);
inst.matchDataSender.matchType.Set(static_cast<int>(tmpDataStore.matchType));
inst.matchDataSender.alliance.Set(isRedAlliance);
inst.matchDataSender.station.Set(stationNumber);
inst.matchDataSender.allianceStation.Set(alliance);
hal::ControlWord ctlWord = hal::GetControlWord();
if (ctlWord != inst.matchDataSender.prevControlWord) {

View File

@@ -161,15 +161,17 @@ public final class DriverStationBackend {
final IntegerPublisher matchType;
final BooleanPublisher alliance;
final IntegerPublisher station;
final IntegerPublisher allianceStation;
final StructPublisher<ControlWord> controlWord;
final StringPublisher opMode;
boolean oldIsRedAlliance = true;
int oldStationNumber = 1;
String oldEventName = "";
String oldGameData = "";
int oldMatchNumber;
int oldReplayNumber;
int oldMatchType;
boolean oldIsRedAlliance = true;
int oldStationNumber = 1;
int oldAllianceStation = 0;
final ControlWord oldControlWord = new ControlWord();
final ControlWord currentControlWord = new ControlWord();
@@ -194,6 +196,8 @@ public final class DriverStationBackend {
alliance.set(true);
station = table.getIntegerTopic("StationNumber").publish();
station.set(1);
allianceStation = table.getIntegerTopic("AllianceStationID").publish();
allianceStation.set(0);
controlWord = table.getStructTopic("ControlWord", ControlWord.struct).publish();
controlWord.set(oldControlWord);
opMode = table.getStringTopic("OpMode").publish();
@@ -207,7 +211,8 @@ public final class DriverStationBackend {
switch (allianceID) {
case BLUE_1, RED_1 -> 1;
case BLUE_2, RED_2 -> 2;
case BLUE_3, RED_3, UNKNOWN -> 3;
case BLUE_3, RED_3 -> 3;
case UNKNOWN -> 0;
};
final boolean isRedAlliance =
switch (allianceID) {
@@ -240,6 +245,10 @@ public final class DriverStationBackend {
station.set(stationNumber);
oldStationNumber = stationNumber;
}
if (oldAllianceStation != allianceID.ordinal()) {
allianceStation.set(allianceID.ordinal());
oldAllianceStation = allianceID.ordinal();
}
if (!oldEventName.equals(currentEventName)) {
eventName.set(currentEventName);
oldEventName = currentEventName;