Skip to content

Commit 831a6ab

Browse files
committed
Add a test client for the CI interface
1 parent 51cfa5a commit 831a6ab

File tree

3 files changed

+157
-0
lines changed

3 files changed

+157
-0
lines changed

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ There are some reference clients:
2727
* [ssl-ref-client](./cmd/ssl-ref-client): A client that receives referee messages
2828
* [ssl-auto-ref-client](./cmd/ssl-auto-ref-client/README.md): A client that connects to the controller as an autoRef
2929
* [ssl-team-client](./cmd/ssl-team-client/README.md): A client that connects to the controller as a team
30+
* [ssl-ci-test-client](./cmd/ssl-ci-test-client/README.md): A client that connects to the CI interface of the controller
3031

3132
### Comparison to ssl-refbox
3233
The ssl-game-controller replaces the ssl-refbox. With the introduction of automatic referees, there was demand for several new features. To accommodate these, the ssl-refbox has been rewritten to take advantage of modern technologies.
@@ -164,3 +165,8 @@ go get github.com/gobuffalo/packr/packr
164165
cd cmd/ssl-game-controller
165166
packr install
166167
```
168+
169+
### Update generated protobuf code
170+
Generate the code for the `.proto` files with [./generateProto.sh](./generateProto.sh),
171+
after you've changed anything in a `.proto` file.
172+

cmd/ssl-ci-test-client/README.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# ssl-ci-test-client
2+
3+
This folder contains a sample client that connects to the CI interface of the game-controller.
4+
5+
## Protocol
6+
The communication is established with a bidirectional TCP connection. Messages are encoded with [Protocol Buffers](https://developers.google.com/protocol-buffers/). Each message is preceded by an uvarint containing the message size in bytes, see https://cwiki.apache.org/confluence/display/GEODE/Delimiting+Protobuf+Messages for details.
7+
8+
The protobuf files can be found in [../../proto](../../proto/).
9+
The main protobuf file is `ssl_gc_ci.proto`.
10+
11+
The default port is `10009`.
12+
13+
## Sample client
14+
The sample client, that is included in this folder, can be used to test the connection. It can be run with
15+
```bash
16+
go run cmd/ssl-ci-test-client/main.go
17+
```
18+
Pass it the `-h` parameter to get the available options.

cmd/ssl-ci-test-client/main.go

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
package main
2+
3+
import (
4+
"bufio"
5+
"flag"
6+
"fmt"
7+
"github.com/RoboCup-SSL/ssl-game-controller/internal/app/ci"
8+
"github.com/RoboCup-SSL/ssl-game-controller/internal/app/geom"
9+
"github.com/RoboCup-SSL/ssl-game-controller/internal/app/tracker"
10+
"github.com/RoboCup-SSL/ssl-go-tools/pkg/sslconn"
11+
"github.com/odeke-em/go-uuid"
12+
"log"
13+
"net"
14+
"os"
15+
"strconv"
16+
"strings"
17+
"time"
18+
)
19+
20+
var address = flag.String("address", "localhost:10009", "The address of the ssl-game-controller CI interface")
21+
22+
var id = uuid.New()
23+
var name = "Test client"
24+
var trackerPacket = createTrackerPacket()
25+
26+
func main() {
27+
flag.Parse()
28+
29+
conn, err := net.Dial("tcp", *address)
30+
if err != nil {
31+
log.Fatal("could not connect to game-controller at ", *address)
32+
}
33+
defer func() {
34+
if err := conn.Close(); err != nil {
35+
log.Printf("Could not close connection: %v", err)
36+
}
37+
}()
38+
log.Printf("Connected to game-controller at %v", *address)
39+
40+
go receive(conn)
41+
send(conn)
42+
43+
commands := map[string]func([]string){}
44+
commands["ball"] = func(args []string) {
45+
trackerPacket.TrackedFrame.Balls = []*tracker.TrackedBall{createBall(args)}
46+
}
47+
48+
reader := bufio.NewReader(os.Stdin)
49+
for {
50+
fmt.Print("-> ")
51+
text, err := reader.ReadString('\n')
52+
if err != nil {
53+
log.Print("Can not read from stdin: ", err)
54+
for {
55+
time.Sleep(1 * time.Second)
56+
}
57+
}
58+
// convert CRLF to LF
59+
text = strings.Replace(text, "\n", "", -1)
60+
cmd := strings.Split(text, " ")
61+
if fn, ok := commands[cmd[0]]; ok {
62+
fn(cmd[1:])
63+
} else {
64+
fmt.Println("Available commands:")
65+
for cmd := range commands {
66+
fmt.Printf(" %-20s\n", cmd)
67+
}
68+
}
69+
}
70+
}
71+
72+
func createBall(args []string) (ball *tracker.TrackedBall) {
73+
ball = new(tracker.TrackedBall)
74+
var pos, vel *geom.Vector3
75+
if len(args) >= 2 {
76+
pos = new(geom.Vector3)
77+
pos.X = new(float32)
78+
pos.Y = new(float32)
79+
pos.Z = new(float32)
80+
x, _ := strconv.ParseFloat(args[0], 64)
81+
*pos.X = float32(x)
82+
y, _ := strconv.ParseFloat(args[1], 64)
83+
*pos.Y = float32(y)
84+
if len(args) >= 3 {
85+
z, _ := strconv.ParseFloat(args[2], 64)
86+
*pos.Z = float32(z)
87+
}
88+
}
89+
if len(args) >= 5 {
90+
vel = new(geom.Vector3)
91+
vel.X = new(float32)
92+
vel.Y = new(float32)
93+
x, _ := strconv.ParseFloat(args[3], 64)
94+
y, _ := strconv.ParseFloat(args[4], 64)
95+
*vel.X = float32(x)
96+
*vel.Y = float32(y)
97+
}
98+
ball.Pos = pos
99+
ball.Vel = vel
100+
return
101+
}
102+
103+
func createTrackerPacket() (p tracker.TrackerWrapperPacket) {
104+
p.Uuid = &id
105+
p.SourceName = &name
106+
p.TrackedFrame = new(tracker.TrackedFrame)
107+
p.TrackedFrame.Timestamp = new(float64)
108+
p.TrackedFrame.FrameNumber = new(uint32)
109+
return
110+
}
111+
112+
func send(conn net.Conn) {
113+
for {
114+
timestamp := time.Now().UnixNano()
115+
*trackerPacket.TrackedFrame.Timestamp = float64(timestamp / 1e9)
116+
*trackerPacket.TrackedFrame.FrameNumber++
117+
input := ci.CiInput{Timestamp: &timestamp, TrackerPacket: &trackerPacket}
118+
if err := sslconn.SendMessage(conn, &input); err != nil {
119+
log.Println("Could not send message: ", err)
120+
}
121+
time.Sleep(time.Millisecond * 25)
122+
}
123+
}
124+
125+
func receive(conn net.Conn) {
126+
for {
127+
output := ci.CiOutput{}
128+
if err := sslconn.ReceiveMessage(conn, &output); err != nil {
129+
log.Println("Could not receive message: ", err)
130+
}
131+
log.Println("RefereeMsg: ", output.RefereeMsg)
132+
}
133+
}

0 commit comments

Comments
 (0)