From 118619d47727a36d267540092dfd4cdc9feea756 Mon Sep 17 00:00:00 2001 From: Patrick Fairbank Date: Fri, 4 Jul 2014 17:47:28 -0700 Subject: [PATCH] Don't start a match unless all robots are connected. --- arena.go | 13 +++++++ arena_test.go | 96 +++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 106 insertions(+), 3 deletions(-) diff --git a/arena.go b/arena.go index ed760f0..c0fe60a 100644 --- a/arena.go +++ b/arena.go @@ -67,6 +67,7 @@ func (arena *Arena) AssignTeam(teamId int, station string) error { if _, ok := arena.allianceStations[station]; !ok { return fmt.Errorf("Invalid alliance station '%s'.", station) } + // Do nothing if the station is already assigned to the requested team. dsConn := arena.allianceStations[station].driverStationConnection if dsConn != nil && dsConn.TeamId == teamId { @@ -145,6 +146,18 @@ func (arena *Arena) StartMatch() error { if arena.currentMatch == nil { return fmt.Errorf("Cannot start match when no match is loaded.") } + for _, allianceStation := range arena.allianceStations { + if allianceStation.emergencyStop { + return fmt.Errorf("Cannot start match while an emergency stop is active.") + } + if !allianceStation.bypass { + dsConn := allianceStation.driverStationConnection + if dsConn == nil || !dsConn.DriverStationStatus.RobotLinked { + return fmt.Errorf("Cannot start match until all robots are connected or bypassed.") + } + } + } + arena.matchState = START_MATCH return nil } diff --git a/arena_test.go b/arena_test.go index c1b174e..193f827 100644 --- a/arena_test.go +++ b/arena_test.go @@ -71,8 +71,7 @@ func TestArenaMatchFlow(t *testing.T) { db, err = OpenDatabase(testDbPath) assert.Nil(t, err) defer db.Close() - err = db.CreateTeam(&Team{Id: 254}) - assert.Nil(t, err) + db.CreateTeam(&Team{Id: 254}) mainArena.Setup() err = mainArena.AssignTeam(254, "B3") assert.Nil(t, err) @@ -91,7 +90,14 @@ func TestArenaMatchFlow(t *testing.T) { assert.Equal(t, lastPacketCount+1, mainArena.allianceStations["B3"].driverStationConnection.packetCount) // Check match start, autonomous and transition to teleop. - mainArena.StartMatch() + mainArena.allianceStations["R1"].bypass = true + mainArena.allianceStations["R2"].bypass = true + mainArena.allianceStations["R3"].bypass = true + mainArena.allianceStations["B1"].bypass = true + mainArena.allianceStations["B2"].bypass = true + mainArena.allianceStations["B3"].driverStationConnection.DriverStationStatus.RobotLinked = true + err = mainArena.StartMatch() + assert.Nil(t, err) mainArena.Update() assert.Equal(t, AUTO_PERIOD, mainArena.matchState) assert.Equal(t, true, mainArena.allianceStations["B3"].driverStationConnection.Auto) @@ -176,6 +182,12 @@ func TestArenaMatchFlow(t *testing.T) { func TestArenaStateEnforcement(t *testing.T) { mainArena.Setup() + mainArena.allianceStations["R1"].bypass = true + mainArena.allianceStations["R2"].bypass = true + mainArena.allianceStations["R3"].bypass = true + mainArena.allianceStations["B1"].bypass = true + mainArena.allianceStations["B2"].bypass = true + mainArena.allianceStations["B3"].bypass = true err := mainArena.LoadMatch(new(Match)) assert.Nil(t, err) @@ -268,3 +280,81 @@ func TestArenaStateEnforcement(t *testing.T) { err = mainArena.LoadMatch(new(Match)) assert.Nil(t, err) } + +func TestMatchStartRobotLinkEnforcement(t *testing.T) { + clearDb() + defer clearDb() + var err error + db, err = OpenDatabase(testDbPath) + assert.Nil(t, err) + defer db.Close() + db.CreateTeam(&Team{Id: 101}) + db.CreateTeam(&Team{Id: 102}) + db.CreateTeam(&Team{Id: 103}) + db.CreateTeam(&Team{Id: 104}) + db.CreateTeam(&Team{Id: 105}) + db.CreateTeam(&Team{Id: 106}) + match := Match{Red1: 101, Red2: 102, Red3: 103, Blue1: 104, Blue2: 105, Blue3: 106} + db.CreateMatch(&match) + mainArena.Setup() + + err = mainArena.LoadMatch(&match) + assert.Nil(t, err) + for _, station := range mainArena.allianceStations { + station.driverStationConnection.DriverStationStatus.RobotLinked = true + } + err = mainArena.StartMatch() + assert.Nil(t, err) + mainArena.matchState = PRE_MATCH + + // Check with a single team e-stopped, not linked and bypassed. + mainArena.allianceStations["R1"].emergencyStop = true + err = mainArena.StartMatch() + if assert.NotNil(t, err) { + assert.Contains(t, err.Error(), "while an emergency stop is active") + } + mainArena.allianceStations["R1"].emergencyStop = false + mainArena.allianceStations["R1"].driverStationConnection.DriverStationStatus.RobotLinked = false + err = mainArena.StartMatch() + if assert.NotNil(t, err) { + assert.Contains(t, err.Error(), "until all robots are connected or bypassed") + } + mainArena.allianceStations["R1"].bypass = true + err = mainArena.StartMatch() + assert.Nil(t, err) + mainArena.allianceStations["R1"].bypass = false + mainArena.matchState = PRE_MATCH + + // Check with a team missing. + err = mainArena.AssignTeam(0, "R1") + assert.Nil(t, err) + err = mainArena.StartMatch() + if assert.NotNil(t, err) { + assert.Contains(t, err.Error(), "until all robots are connected or bypassed") + } + mainArena.allianceStations["R1"].bypass = true + err = mainArena.StartMatch() + assert.Nil(t, err) + mainArena.matchState = PRE_MATCH + + // Check with no teams present. + mainArena.LoadMatch(new(Match)) + err = mainArena.StartMatch() + if assert.NotNil(t, err) { + assert.Contains(t, err.Error(), "until all robots are connected or bypassed") + } + mainArena.allianceStations["R1"].bypass = true + mainArena.allianceStations["R2"].bypass = true + mainArena.allianceStations["R3"].bypass = true + mainArena.allianceStations["B1"].bypass = true + mainArena.allianceStations["B2"].bypass = true + mainArena.allianceStations["B3"].bypass = true + mainArena.allianceStations["B3"].emergencyStop = true + err = mainArena.StartMatch() + if assert.NotNil(t, err) { + assert.Contains(t, err.Error(), "while an emergency stop is active") + } + mainArena.allianceStations["B3"].emergencyStop = false + err = mainArena.StartMatch() + assert.Nil(t, err) +}