Skip to content

Commit 31b9162

Browse files
committed
[feature] Receive geometry from vision
1 parent bc734e2 commit 31b9162

File tree

5 files changed

+125
-22
lines changed

5 files changed

+125
-22
lines changed

config/ssl-game-controller.yaml

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
publish:
2-
address: 224.5.23.1:10003
1+
network:
2+
publish-address: 224.5.23.1:10003
3+
vision-address: 224.5.23.2:10006
34
server:
45
auto-ref:
56
address: :10007
@@ -30,17 +31,17 @@ game:
3031
DivA:
3132
field-length: 12.0
3233
field-width: 9.0
33-
penalty-area-depth: 1.2
34-
penalty-area-width: 2.4
34+
defense-area-depth: 1.2
35+
defense-area-width: 2.4
3536
placement-offset-touch-line: 0.2
3637
placement-offset-goal-line: 0.2
3738
placement-offset-goal-line-goal-kick: 1.0
3839
placement-offset-defense-area: 1.0
3940
DivB:
4041
field-length: 9.0
4142
field-width: 6.0
42-
penalty-area-depth: 1.0
43-
penalty-area-width: 2.0
43+
defense-area-depth: 1.0
44+
defense-area-width: 2.0
4445
placement-offset-touch-line: 0.2
4546
placement-offset-goal-line: 0.2
4647
placement-offset-goal-line-goal-kick: 1.0

internal/app/controller/config.go

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ type ConfigSpecial struct {
1919
type ConfigGeometry struct {
2020
FieldLength float64 `yaml:"field-length"`
2121
FieldWidth float64 `yaml:"field-width"`
22-
PenaltyAreaDepth float64 `yaml:"penalty-area-depth"`
23-
PenaltyAreaWidth float64 `yaml:"penalty-area-width"`
22+
DefenseAreaDepth float64 `yaml:"defense-area-depth"`
23+
DefenseAreaWidth float64 `yaml:"defense-area-width"`
2424
PlacementOffsetTouchLine float64 `yaml:"placement-offset-touch-line"`
2525
PlacementOffsetGoalLine float64 `yaml:"placement-offset-goal-line"`
2626
PlacementOffsetGoalLineGoalKick float64 `yaml:"placement-offset-goal-line-goal-kick"`
@@ -40,9 +40,10 @@ type ConfigGame struct {
4040
MultiplePlacementFailures int `yaml:"multiple-placement-failures"`
4141
}
4242

43-
// ConfigPublish holds configs for publishing the state and commands to the teams
44-
type ConfigPublish struct {
45-
Address string `yaml:"address"`
43+
// ConfigNetwork holds configs for network communication
44+
type ConfigNetwork struct {
45+
PublishAddress string `yaml:"publish-address"`
46+
VisionAddress string `yaml:"vision-address"`
4647
}
4748

4849
// ConfigServer holds configs for the available server services
@@ -65,7 +66,7 @@ type ConfigServerTeam struct {
6566

6667
// Config structure for the game controller
6768
type Config struct {
68-
Publish ConfigPublish `yaml:"publish"`
69+
Network ConfigNetwork `yaml:"network"`
6970
Game ConfigGame `yaml:"game"`
7071
Server ConfigServer `yaml:"server"`
7172
}
@@ -95,7 +96,8 @@ func LoadConfig(fileName string) (config Config, err error) {
9596

9697
// DefaultConfig creates a config with default values
9798
func DefaultConfig() (c Config) {
98-
c.Publish.Address = "224.5.23.1:10003"
99+
c.Network.PublishAddress = "224.5.23.1:10003"
100+
c.Network.VisionAddress = "224.5.23.2:10006"
99101
c.Game.YellowCardDuration = 2 * time.Minute
100102
c.Game.MultipleCardStep = 3
101103
c.Game.MultipleFoulStep = 3
@@ -124,8 +126,8 @@ func DefaultConfig() (c Config) {
124126
c.Game.DefaultGeometry[DivA] = new(ConfigGeometry)
125127
c.Game.DefaultGeometry[DivA].FieldLength = 12
126128
c.Game.DefaultGeometry[DivA].FieldWidth = 9
127-
c.Game.DefaultGeometry[DivA].PenaltyAreaDepth = 1.2
128-
c.Game.DefaultGeometry[DivA].PenaltyAreaWidth = 2.4
129+
c.Game.DefaultGeometry[DivA].DefenseAreaDepth = 1.2
130+
c.Game.DefaultGeometry[DivA].DefenseAreaWidth = 2.4
129131
c.Game.DefaultGeometry[DivA].PlacementOffsetGoalLine = 0.2
130132
c.Game.DefaultGeometry[DivA].PlacementOffsetGoalLineGoalKick = 1.0
131133
c.Game.DefaultGeometry[DivA].PlacementOffsetTouchLine = 0.2
@@ -134,8 +136,8 @@ func DefaultConfig() (c Config) {
134136
c.Game.DefaultGeometry[DivB] = new(ConfigGeometry)
135137
c.Game.DefaultGeometry[DivB].FieldLength = 9
136138
c.Game.DefaultGeometry[DivB].FieldWidth = 6
137-
c.Game.DefaultGeometry[DivB].PenaltyAreaDepth = 1
138-
c.Game.DefaultGeometry[DivB].PenaltyAreaWidth = 2
139+
c.Game.DefaultGeometry[DivB].DefenseAreaDepth = 1
140+
c.Game.DefaultGeometry[DivB].DefenseAreaWidth = 2
139141
c.Game.DefaultGeometry[DivB].PlacementOffsetGoalLine = 0.2
140142
c.Game.DefaultGeometry[DivB].PlacementOffsetGoalLineGoalKick = 1.0
141143
c.Game.DefaultGeometry[DivB].PlacementOffsetTouchLine = 0.2

internal/app/controller/controller.go

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@ import (
44
"github.com/RoboCup-SSL/ssl-game-controller/internal/app/rcon"
55
"github.com/RoboCup-SSL/ssl-game-controller/pkg/refproto"
66
"github.com/RoboCup-SSL/ssl-game-controller/pkg/timer"
7+
"github.com/RoboCup-SSL/ssl-go-tools/pkg/sslproto"
78
"github.com/pkg/errors"
89
"log"
10+
"math"
911
"sync"
1012
"time"
1113
)
@@ -25,6 +27,7 @@ type GameController struct {
2527
numRefereeEventsLastPublish int
2628
outstandingTeamChoice *TeamChoice
2729
Mutex sync.Mutex
30+
VisionReceiver *VisionReceiver
2831
}
2932

3033
type TeamChoice struct {
@@ -42,6 +45,9 @@ func NewGameController() (c *GameController) {
4245
c.ApiServer = ApiServer{}
4346
c.ApiServer.Consumer = c
4447

48+
c.VisionReceiver = NewVisionReceiver(c.Config.Network.VisionAddress)
49+
c.VisionReceiver.GeometryCallback = c.ProcessGeometry
50+
4551
c.AutoRefServer = rcon.NewAutoRefServer()
4652
c.AutoRefServer.LoadTrustedKeys(c.Config.Server.AutoRef.TrustedKeysDir)
4753
c.AutoRefServer.ProcessRequest = c.ProcessAutoRefRequests
@@ -59,6 +65,34 @@ func NewGameController() (c *GameController) {
5965
return
6066
}
6167

68+
func (c *GameController) ProcessGeometry(data *sslproto.SSL_GeometryData) {
69+
if int32(math.Round(c.Engine.Geometry.FieldWidth*1000.0)) != *data.Field.FieldWidth {
70+
newFieldWidth := float64(*data.Field.FieldWidth) / 1000.0
71+
log.Printf("FieldWidth changed from %v to %v", c.Engine.Geometry.FieldWidth, newFieldWidth)
72+
c.Engine.Geometry.FieldWidth = newFieldWidth
73+
}
74+
if int32(math.Round(c.Engine.Geometry.FieldLength*1000)) != *data.Field.FieldLength {
75+
newFieldLength := float64(*data.Field.FieldLength) / 1000.0
76+
log.Printf("FieldLength changed from %v to %v", c.Engine.Geometry.FieldLength, newFieldLength)
77+
c.Engine.Geometry.FieldLength = newFieldLength
78+
}
79+
for _, line := range data.Field.FieldLines {
80+
if *line.Name == "LeftFieldLeftPenaltyStretch" {
81+
defenseAreaDepth := math.Abs(float64(*line.P1.X-*line.P2.X)) / 1000.0
82+
if math.Abs(defenseAreaDepth-c.Engine.Geometry.DefenseAreaDepth) > 1e-3 {
83+
log.Printf("DefenseAreaDepth changed from %v to %v", c.Engine.Geometry.DefenseAreaDepth, defenseAreaDepth)
84+
c.Engine.Geometry.DefenseAreaDepth = defenseAreaDepth
85+
}
86+
} else if *line.Name == "LeftPenaltyStretch" {
87+
defenseAreaWidth := math.Abs(float64(*line.P1.Y-*line.P2.Y)) / 1000.0
88+
if math.Abs(defenseAreaWidth-c.Engine.Geometry.DefenseAreaWidth) > 1e-3 {
89+
log.Printf("DefenseAreaDepth changed from %v to %v", c.Engine.Geometry.DefenseAreaWidth, defenseAreaWidth)
90+
c.Engine.Geometry.DefenseAreaWidth = defenseAreaWidth
91+
}
92+
}
93+
}
94+
}
95+
6296
func (c *GameController) ProcessAutoRefRequests(request refproto.AutoRefToControllerRequest) error {
6397
c.Mutex.Lock()
6498
defer c.Mutex.Unlock()
@@ -211,9 +245,9 @@ func (c *GameController) timeoutTeamChoice() {
211245
}
212246

213247
func loadPublisher(config Config) Publisher {
214-
publisher, err := NewPublisher(config.Publish.Address)
248+
publisher, err := NewPublisher(config.Network.PublishAddress)
215249
if err != nil {
216-
log.Printf("Could not start publisher on %v. %v", config.Publish.Address, err)
250+
log.Printf("Could not start publisher on %v. %v", config.Network.PublishAddress, err)
217251
}
218252
return publisher
219253
}

internal/app/controller/placementPos.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ func (e *Engine) BallPlacementPos() *Location {
7272
case GameEventDefenderInDefenseArea:
7373
teamInFavor := event.ByTeam().Opposite()
7474
location := Location{}
75-
location.X = (e.Geometry.FieldLength / 2.0) - e.Geometry.PenaltyAreaDepth
75+
location.X = (e.Geometry.FieldLength / 2.0) - e.Geometry.DefenseAreaDepth
7676
if e.State.TeamState[teamInFavor].OnPositiveHalf {
7777
location.X *= -1
7878
}
@@ -128,8 +128,8 @@ func (e *Engine) validateLocation(location *Location) *Location {
128128
}
129129

130130
func (e *Engine) movePositionOutOfDefenseArea(location *Location) {
131-
maxX := e.Geometry.FieldLength/2 - e.Geometry.PenaltyAreaDepth - e.Geometry.PlacementOffsetDefenseArea
132-
minY := e.Geometry.PenaltyAreaWidth + e.Geometry.PlacementOffsetDefenseArea
131+
maxX := e.Geometry.FieldLength/2 - e.Geometry.DefenseAreaDepth - e.Geometry.PlacementOffsetDefenseArea
132+
minY := e.Geometry.DefenseAreaWidth + e.Geometry.PlacementOffsetDefenseArea
133133
if math.Abs(location.X) > maxX && math.Abs(location.Y) < minY {
134134
if math.Abs(maxX-math.Abs(location.X)) < math.Abs(minY-math.Abs(location.Y)) {
135135
location.X = math.Copysign(maxX, location.X)
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package controller
2+
3+
import (
4+
"github.com/RoboCup-SSL/ssl-go-tools/pkg/sslproto"
5+
"github.com/golang/protobuf/proto"
6+
"log"
7+
"net"
8+
"time"
9+
)
10+
11+
type VisionReceiver struct {
12+
DetectionCallback func(*sslproto.SSL_DetectionFrame)
13+
GeometryCallback func(*sslproto.SSL_GeometryData)
14+
}
15+
16+
func NewVisionReceiver(address string) (v *VisionReceiver) {
17+
v = new(VisionReceiver)
18+
v.DetectionCallback = func(*sslproto.SSL_DetectionFrame) {}
19+
v.GeometryCallback = func(data *sslproto.SSL_GeometryData) {}
20+
21+
addr, err := net.ResolveUDPAddr("udp", address)
22+
if err != nil {
23+
log.Print(err)
24+
return
25+
}
26+
conn, err := net.ListenMulticastUDP("udp", nil, addr)
27+
if err != nil {
28+
log.Print(err)
29+
return
30+
}
31+
32+
if err := conn.SetReadBuffer(maxDatagramSize); err != nil {
33+
log.Printf("Could not set read buffer to %v.", maxDatagramSize)
34+
}
35+
log.Println("Receiving vision from", address)
36+
37+
go v.receive(conn)
38+
return
39+
}
40+
41+
func (v *VisionReceiver) receive(conn *net.UDPConn) {
42+
b := make([]byte, maxDatagramSize)
43+
for {
44+
n, err := conn.Read(b)
45+
if err != nil {
46+
log.Print("Could not read", err)
47+
time.Sleep(1 * time.Second)
48+
continue
49+
}
50+
if n >= maxDatagramSize {
51+
log.Fatal("Buffer size too small")
52+
}
53+
wrapper := sslproto.SSL_WrapperPacket{}
54+
if err := proto.Unmarshal(b[0:n], &wrapper); err != nil {
55+
log.Println("Could not unmarshal referee message")
56+
continue
57+
}
58+
59+
if wrapper.Geometry != nil {
60+
v.GeometryCallback(wrapper.Geometry)
61+
}
62+
if wrapper.Detection != nil {
63+
v.DetectionCallback(wrapper.Detection)
64+
}
65+
}
66+
}

0 commit comments

Comments
 (0)