Add pre- and post-match LED modes to indicate field status.

This commit is contained in:
Patrick Fairbank
2018-07-21 23:26:44 -07:00
parent 738b5a0e7b
commit cd050d4e18
6 changed files with 74 additions and 12 deletions

View File

@@ -53,6 +53,7 @@ type Arena struct {
RedRealtimeScore *RealtimeScore
BlueRealtimeScore *RealtimeScore
lastDsPacketTime time.Time
FieldVolunteers bool
FieldReset bool
AudienceDisplayScreen string
SavedMatch *model.Match
@@ -83,6 +84,8 @@ type Arena struct {
RedSwitchLeds led.Controller
BlueSwitchLeds led.Controller
warmupLedMode led.Mode
lastRedAllianceReady bool
lastBlueAllianceReady bool
}
type ArenaStatus struct {
@@ -227,6 +230,7 @@ func (arena *Arena) LoadMatch(match *model.Match) error {
// Reset the realtime scores.
arena.RedRealtimeScore = NewRealtimeScore()
arena.BlueRealtimeScore = NewRealtimeScore()
arena.FieldVolunteers = false
arena.FieldReset = false
arena.Scale = &game.Seesaw{Kind: game.NeitherAlliance}
arena.RedSwitch = &game.Seesaw{Kind: game.RedAlliance}
@@ -249,6 +253,13 @@ func (arena *Arena) LoadMatch(match *model.Match) error {
arena.AllianceStationDisplayScreen = "match"
arena.AllianceStationDisplayNotifier.Notify(nil)
// Set the initial state of the lights.
arena.ScaleLeds.SetMode(led.OffMode, led.OffMode)
arena.RedSwitchLeds.SetMode(led.RedMode, led.RedMode)
arena.BlueSwitchLeds.SetMode(led.BlueMode, led.BlueMode)
arena.lastRedAllianceReady = false
arena.lastBlueAllianceReady = false
return nil
}
@@ -607,15 +618,10 @@ func (arena *Arena) checkCanStartMatch() error {
if arena.MatchState != PreMatch {
return fmt.Errorf("Cannot start match while there is a match still in progress or with results pending.")
}
for _, allianceStation := range arena.AllianceStations {
if allianceStation.Estop {
return fmt.Errorf("Cannot start match while an emergency stop is active.")
}
if !allianceStation.Bypass {
if allianceStation.DsConn == nil || !allianceStation.DsConn.RobotLinked {
return fmt.Errorf("Cannot start match until all robots are connected or bypassed.")
}
}
err := arena.checkAllianceStationsReady("R1", "R2", "R3", "B1", "B2", "B3")
if err != nil {
return err
}
if arena.EventSettings.PlcAddress != "" {
@@ -630,6 +636,22 @@ func (arena *Arena) checkCanStartMatch() error {
return nil
}
func (arena *Arena) checkAllianceStationsReady(stations ...string) error {
for _, station := range stations {
allianceStation := arena.AllianceStations[station]
if allianceStation.Estop {
return fmt.Errorf("Cannot start match while an emergency stop is active.")
}
if !allianceStation.Bypass {
if allianceStation.DsConn == nil || !allianceStation.DsConn.RobotLinked {
return fmt.Errorf("Cannot start match until all robots are connected or bypassed.")
}
}
}
return nil
}
func (arena *Arena) sendDsPacket(auto bool, enabled bool) {
for _, allianceStation := range arena.AllianceStations {
dsConn := allianceStation.DsConn
@@ -752,6 +774,22 @@ func (arena *Arena) handlePlcOutput() {
func (arena *Arena) handleLeds() {
switch arena.MatchState {
case PreMatch:
// Turn off each alliance switch if all teams become ready.
if arena.checkAllianceStationsReady("R1", "R2", "R3") == nil && !arena.lastRedAllianceReady {
arena.RedSwitchLeds.SetMode(led.OffMode, led.OffMode)
arena.lastRedAllianceReady = true
} else if arena.checkAllianceStationsReady("R1", "R2", "R3") != nil && arena.lastRedAllianceReady {
arena.RedSwitchLeds.SetMode(led.RedMode, led.RedMode)
arena.lastRedAllianceReady = false
}
if arena.checkAllianceStationsReady("B1", "B2", "B3") == nil && !arena.lastBlueAllianceReady {
arena.BlueSwitchLeds.SetMode(led.OffMode, led.OffMode)
arena.lastBlueAllianceReady = true
} else if arena.checkAllianceStationsReady("B1", "B2", "B3") != nil && arena.lastBlueAllianceReady {
arena.BlueSwitchLeds.SetMode(led.BlueMode, led.BlueMode)
arena.lastBlueAllianceReady = false
}
case WarmupPeriod:
arena.ScaleLeds.SetMode(arena.warmupLedMode, arena.warmupLedMode)
arena.RedSwitchLeds.SetMode(arena.warmupLedMode, arena.warmupLedMode)
@@ -769,9 +807,15 @@ func (arena *Arena) handleLeds() {
arena.RedSwitchLeds.SetMode(led.OffMode, led.OffMode)
arena.BlueSwitchLeds.SetMode(led.OffMode, led.OffMode)
case PostMatch:
arena.ScaleLeds.SetMode(led.FadeSingleMode, led.FadeSingleMode)
arena.RedSwitchLeds.SetMode(led.FadeSingleMode, led.FadeSingleMode)
arena.BlueSwitchLeds.SetMode(led.FadeSingleMode, led.FadeSingleMode)
mode := led.FadeSingleMode
if arena.FieldReset {
mode = led.GreenMode
} else if arena.FieldVolunteers {
mode = led.PurpleMode
}
arena.ScaleLeds.SetMode(mode, mode)
arena.RedSwitchLeds.SetMode(mode, mode)
arena.BlueSwitchLeds.SetMode(mode, mode)
}
arena.ScaleLeds.Update()

View File

@@ -13,6 +13,7 @@ const (
GreenMode
BlueMode
WhiteMode
PurpleMode
ChaseMode
WarmupMode
Warmup2Mode
@@ -35,6 +36,7 @@ var ModeNames = map[Mode]string{
GreenMode: "Green",
BlueMode: "Blue",
WhiteMode: "White",
PurpleMode: "Purple",
ChaseMode: "Chase",
WarmupMode: "Warmup",
Warmup2Mode: "Warmup Purple",

View File

@@ -30,6 +30,8 @@ func (strip *strip) updatePixels() {
strip.updateSingleColorMode(blue)
case WhiteMode:
strip.updateSingleColorMode(white)
case PurpleMode:
strip.updateSingleColorMode(purple)
case ChaseMode:
strip.updateChaseMode()
case WarmupMode:

View File

@@ -79,6 +79,11 @@ var cycleCard = function(cardButton) {
$(cardButton).attr("data-card", newCard);
};
// Signals to the volunteers that they may enter the field.
var signalVolunteers = function() {
websocket.send("signalVolunteers");
};
// Signals to the teams that they may enter the field.
var signalReset = function() {
websocket.send("signalReset");

View File

@@ -72,6 +72,8 @@
onclick="commitFoul();">Add Foul</button>
</div>
<div class="row text-center">
<a class="btn btn-sm btn-warning btn-referee btn-referee-wide"
onclick="signalVolunteers();">Signal Volunteers</a>
<a class="btn btn-sm btn-success btn-referee btn-referee-wide"
onclick="signalReset();">Signal Reset</a>
<a class="btn btn-sm btn-info btn-referee btn-referee-wide"

View File

@@ -213,6 +213,13 @@ func (web *Web) refereeDisplayWebsocketHandler(w http.ResponseWriter, r *http.Re
}
cards[strconv.Itoa(args.TeamId)] = args.Card
continue
case "signalVolunteers":
if web.arena.MatchState != field.PostMatch {
// Don't allow clearing the field until the match is over.
continue
}
web.arena.FieldVolunteers = true
continue // Don't reload.
case "signalReset":
if web.arena.MatchState != field.PostMatch {
// Don't allow clearing the field until the match is over.