Skip to content

Commit 7c67c8a

Browse files
committed
Implement a common reset mechanism when simulator restart was detected
1 parent cbc865b commit 7c67c8a

File tree

5 files changed

+92
-22
lines changed

5 files changed

+92
-22
lines changed

internal/simctl/geometry.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,18 @@ type GeometrySetter struct {
2323
timeLastSent *time.Time
2424
}
2525

26-
func (r *GeometrySetter) LoadGeometry() {
26+
func NewGeometrySetter(c *SimulationController) (r *GeometrySetter) {
27+
r = new(GeometrySetter)
28+
r.c = c
29+
r.loadGeometry()
30+
return r
31+
}
32+
33+
func (r *GeometrySetter) Reset() {
34+
r.timeLastSent = nil
35+
}
36+
37+
func (r *GeometrySetter) loadGeometry() {
2738
r.geometryDivA = new(vision.SSL_GeometryData)
2839
if err := proto.UnmarshalText(geometryConfigDivA, r.geometryDivA); err != nil {
2940
log.Println("Could not unmarshal geometry file: ", err)

internal/simctl/maintain_robot_count.go

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,15 @@ type RobotCountMaintainer struct {
1616

1717
lastTimeSendCommand time.Time
1818
robotCountMismatchSince map[referee.Team]time.Time
19-
lastUpdate time.Time
2019
}
2120

22-
func (r *RobotCountMaintainer) init() {
21+
func NewRobotCountMaintainer(c *SimulationController) (r *RobotCountMaintainer) {
22+
r = new(RobotCountMaintainer)
23+
r.c = c
24+
return r
25+
}
26+
27+
func (r *RobotCountMaintainer) Reset() {
2328
r.lastTimeSendCommand = time.Now()
2429
r.robotCountMismatchSince = map[referee.Team]time.Time{}
2530
r.robotCountMismatchSince[referee.Team_BLUE] = time.Time{}
@@ -28,13 +33,6 @@ func (r *RobotCountMaintainer) init() {
2833

2934
func (r *RobotCountMaintainer) handleRobotCount() {
3035

31-
preLastUpdate := r.lastUpdate
32-
r.lastUpdate = time.Now()
33-
if r.lastUpdate.Sub(preLastUpdate) > time.Second {
34-
// First update since a second, probably a simulator restart
35-
r.init()
36-
}
37-
3836
if time.Now().Sub(r.lastTimeSendCommand) < 500*time.Millisecond {
3937
// Placed ball just recently
4038
return

internal/simctl/replace_ball.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,17 @@ type BallReplacer struct {
1515
haltTime *time.Time
1616
}
1717

18+
func NewBallReplacer(c *SimulationController) (r *BallReplacer) {
19+
r = new(BallReplacer)
20+
r.c = c
21+
return r
22+
}
23+
24+
func (r *BallReplacer) Reset() {
25+
r.lastTimePlacedBall = time.Time{}
26+
r.haltTime = nil
27+
}
28+
1829
func (r *BallReplacer) handleReplaceBall() {
1930
if *r.c.lastRefereeMsg.Command != referee.Referee_HALT {
2031
// Only during HALT

internal/simctl/robot_specs.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,14 +46,24 @@ type RobotSpecSetter struct {
4646
appliedTeams map[referee.Team]string
4747
}
4848

49-
func (r *RobotSpecSetter) LoadRobotSpecs(configFile string) {
49+
func NewRobotSpecSetter(c *SimulationController, configFile string) (r *RobotSpecSetter) {
50+
r = new(RobotSpecSetter)
51+
r.c = c
52+
r.loadRobotSpecs(configFile)
53+
return r
54+
}
55+
56+
func (r *RobotSpecSetter) Reset() {
57+
r.appliedTeams = map[referee.Team]string{}
58+
}
59+
60+
func (r *RobotSpecSetter) loadRobotSpecs(configFile string) {
5061
data, err := ioutil.ReadFile(configFile)
5162
if err != nil {
5263
log.Println("Could not read robot spec file: ", err)
5364
} else if err := yaml.Unmarshal(data, &r.teamRobotSpecs); err != nil {
5465
log.Println("Could not unmarshal robot spec file: ", err)
5566
}
56-
r.appliedTeams = map[referee.Team]string{}
5767
}
5868

5969
func (r *RobotSpecSetter) handleRobotSpecs() {

internal/simctl/simctl.go

Lines changed: 50 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,25 +7,30 @@ import (
77
"github.com/RoboCup-SSL/ssl-simulation-controller/internal/vision"
88
"github.com/golang/protobuf/proto"
99
"log"
10+
"math"
1011
"net"
12+
"sync"
1113
)
1214

1315
type SimulationController struct {
1416
visionServer *sslnet.MulticastServer
1517
refereeServer *sslnet.MulticastServer
1618
trackerServer *sslnet.MulticastServer
1719
simControlClient *sslnet.UdpClient
20+
mutex sync.Mutex
1821

19-
simControlPort string
22+
simControlPort string
23+
simulatorRestarted bool
2024

21-
lastTrackedFrame *tracker.TrackerWrapperPacket
22-
lastRefereeMsg *referee.Referee
23-
fieldSize *vision.SSL_GeometryFieldSize
25+
lastTrackedFrame *tracker.TrackerWrapperPacket
26+
lastRefereeMsg *referee.Referee
27+
fieldSize *vision.SSL_GeometryFieldSize
28+
lastVisionFrameIds map[uint32]uint32
2429

25-
ballReplacer BallReplacer
26-
robotCountMaintainer RobotCountMaintainer
27-
robotSpecsSetter RobotSpecSetter
28-
geometrySetter GeometrySetter
30+
ballReplacer *BallReplacer
31+
robotCountMaintainer *RobotCountMaintainer
32+
robotSpecsSetter *RobotSpecSetter
33+
geometrySetter *GeometrySetter
2934
}
3035

3136
func NewSimulationController(visionAddress, refereeAddress, trackerAddress, simControlPort, robotSpecConfig string) (c *SimulationController) {
@@ -34,12 +39,18 @@ func NewSimulationController(visionAddress, refereeAddress, trackerAddress, simC
3439
c.refereeServer = sslnet.NewMulticastServer(refereeAddress, c.onNewRefereeData)
3540
c.trackerServer = sslnet.NewMulticastServer(trackerAddress, c.onNewTrackerData)
3641
c.simControlPort = simControlPort
42+
c.simulatorRestarted = true
43+
c.lastVisionFrameIds = map[uint32]uint32{}
44+
45+
c.ballReplacer = NewBallReplacer(c)
46+
c.robotCountMaintainer = NewRobotCountMaintainer(c)
47+
c.robotSpecsSetter = NewRobotSpecSetter(c, robotSpecConfig)
48+
c.geometrySetter = NewGeometrySetter(c)
49+
3750
c.ballReplacer.c = c
3851
c.robotCountMaintainer.c = c
3952
c.robotSpecsSetter.c = c
40-
c.robotSpecsSetter.LoadRobotSpecs(robotSpecConfig)
4153
c.geometrySetter.c = c
42-
c.geometrySetter.LoadGeometry()
4354
return
4455
}
4556

@@ -51,7 +62,24 @@ func (c *SimulationController) onNewVisionData(data []byte, remoteAddr *net.UDPA
5162
}
5263

5364
if wrapper.Geometry != nil && wrapper.Geometry.Field != nil {
65+
c.mutex.Lock()
5466
c.fieldSize = wrapper.Geometry.Field
67+
c.mutex.Unlock()
68+
}
69+
70+
if wrapper.Detection != nil {
71+
c.mutex.Lock()
72+
frameId := *wrapper.Detection.FrameNumber
73+
lastFrameId, lastFrameIdPresent := c.lastVisionFrameIds[*wrapper.Detection.CameraId]
74+
if lastFrameIdPresent && math.Abs(float64(frameId-lastFrameId)) > 100 {
75+
// large frame id change: Simulator probably restarted
76+
c.simulatorRestarted = true
77+
c.lastVisionFrameIds = map[uint32]uint32{}
78+
log.Printf("Simulator restart detected due to high frame id change (%d -> %d)",
79+
lastFrameId, frameId)
80+
}
81+
c.lastVisionFrameIds[*wrapper.Detection.CameraId] = frameId
82+
c.mutex.Unlock()
5583
}
5684

5785
if c.simControlClient == nil {
@@ -68,7 +96,9 @@ func (c *SimulationController) onNewRefereeData(data []byte, _ *net.UDPAddr) {
6896
log.Println("Could not unmarshal referee packet", err)
6997
return
7098
}
99+
c.mutex.Lock()
71100
c.lastRefereeMsg = refereeMsg
101+
c.mutex.Unlock()
72102
}
73103

74104
func (c *SimulationController) onNewTrackerData(data []byte, _ *net.UDPAddr) {
@@ -81,8 +111,10 @@ func (c *SimulationController) onNewTrackerData(data []byte, _ *net.UDPAddr) {
81111
*c.lastTrackedFrame.Uuid == *frame.Uuid || // frame from same origin
82112
// new frame is significantly newer than last frame
83113
(*frame.TrackedFrame.Timestamp-*c.lastTrackedFrame.TrackedFrame.Timestamp) > 5 {
114+
c.mutex.Lock()
84115
c.lastTrackedFrame = frame
85116
c.handle()
117+
c.mutex.Unlock()
86118
}
87119
}
88120

@@ -105,6 +137,14 @@ func (c *SimulationController) handle() {
105137
return
106138
}
107139

140+
if c.simulatorRestarted {
141+
c.ballReplacer.Reset()
142+
c.robotCountMaintainer.Reset()
143+
c.robotSpecsSetter.Reset()
144+
c.geometrySetter.Reset()
145+
c.simulatorRestarted = false
146+
}
147+
108148
c.ballReplacer.handleReplaceBall()
109149
c.robotCountMaintainer.handleRobotCount()
110150
c.robotSpecsSetter.handleRobotSpecs()

0 commit comments

Comments
 (0)