Fawkes API  Fawkes Development Version
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
spl.cpp
1 
2 /***************************************************************************
3  * spl.cpp - Fawkes SPL refbox repeater
4  *
5  * Created: Tue Jul 08 13:50:06 2008
6  * Copyright 2008 Tim Niemueller [www.niemueller.de]
7  * 2009 Tobias Kellner
8  *
9  ****************************************************************************/
10 
11 /* This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU Library General Public License for more details.
20  *
21  * Read the full text in the LICENSE.GPL file in the doc directory.
22  */
23 
24 #include "spl.h"
25 #include "state_handler.h"
26 #include <core/exception.h>
27 #include <netcomm/socket/datagram.h>
28 #include <logging/logger.h>
29 
30 #ifdef USE_SPL_GC6
31 # include <interfaces/SoccerPenaltyInterface.h>
32 #endif
33 
34 #include <cstring>
35 #include <cstdio>
36 #include <unistd.h>
37 #include <cerrno>
38 // it it was defined, Exception::errno() could not be called...
39 #ifdef errno
40 # undef errno
41 #endif
42 using namespace fawkes;
43 
44 #ifdef USE_SPL_GC6
45 static const uint32_t SPL_STRUCT_VERSION = 6;
46 #else
47 static const uint32_t SPL_STRUCT_VERSION = 7;
48 #endif
49 
50 static const uint8_t SPL_STATE_INITIAL = 0;
51 static const uint8_t SPL_STATE_READY = 1;
52 static const uint8_t SPL_STATE_SET = 2;
53 static const uint8_t SPL_STATE_PLAYING = 3;
54 static const uint8_t SPL_STATE_FINISHED = 4;
55 
56 static const uint8_t SPL_STATE2_NORMAL = 0;
57 static const uint8_t SPL_STATE2_PENALTYSHOOT = 1;
58 
59 static const uint8_t SPL_PENALTY_NONE = 0;
60 #ifdef USE_SPL_GC6
61 static const uint8_t SPL_PENALTY_BALL_HOLDING = 1;
62 static const uint8_t SPL_PENALTY_GOALIE_PUSHING = 2;
63 static const uint8_t SPL_PENALTY_PLAYER_PUSHING = 3;
64 static const uint8_t SPL_PENALTY_ILLEGAL_DEFENDER = 4;
65 static const uint8_t SPL_PENALTY_ILLEGAL_DEFENSE = 5;
66 static const uint8_t SPL_PENALTY_OBSTRUCTION = 6;
67 static const uint8_t SPL_PENALTY_REQ_FOR_PICKUP = 7;
68 static const uint8_t SPL_PENALTY_LEAVING = 8;
69 static const uint8_t SPL_PENALTY_DAMAGE = 9;
70 static const uint8_t SPL_PENALTY_MANUAL = 10;
71 #else
72 static const uint8_t SPL_PENALTY_BALL_HOLDING = 1;
73 static const uint8_t SPL_PENALTY_PLAYER_PUSHING = 2;
74 static const uint8_t SPL_PENALTY_OBSTRUCTION = 3;
75 static const uint8_t SPL_PENALTY_INACTIVE_PLAYER = 4;
76 static const uint8_t SPL_PENALTY_ILLEGAL_DEFENDER = 5;
77 static const uint8_t SPL_PENALTY_LEAVING_THE_FIELD = 6;
78 static const uint8_t SPL_PENALTY_PLAYING_WITH_HANDS = 7;
79 static const uint8_t SPL_PENALTY_REQ_FOR_PICKUP = 8;
80 static const uint8_t SPL_PENALTY_MANUAL = 15;
81 #endif
82 
83 // team numbers
84 static const uint8_t SPL_TEAM_BLUE = 0;
85 static const uint8_t SPL_TEAM_RED = 1;
86 
87 static const uint8_t SPL_GOAL_BLUE = 0;
88 static const uint8_t SPL_GOAL_YELLOW = 1;
89 
90 static const char SPL_GAMECONTROL_HEADER[SPL_HEADER_SIZE] = {'R','G','m','e'};
91 
92 
93 /** @class SplRefBoxProcessor "processor/spl.h"
94  * SPL league refbox repeater.
95  * This class will listen to SPL refbox commands and derive matching
96  * game states from the communication stream and send this via the world info.
97  * @author Tim Niemueller
98  */
99 
100 /** Constructor.
101  * @param logger Logger
102  * @param broadcast_port Broadcast port
103  * @param team_number our team number
104  * @param player_number individual player number
105  */
107  unsigned short int broadcast_port,
108  unsigned int team_number,
109  unsigned int player_number)
110 {
111  __player_number = player_number;
112  __team_number = team_number;
113  __logger = logger;
114  __quit = false;
115  __s = new DatagramSocket(0.0000000001);
116  __s->bind(broadcast_port);
117 
118  __penalty = SPL_PENALTY_NONE;
119 }
120 
121 
122 /** Destructor. */
124 {
125  __s->close();
126  delete __s;
127 }
128 
129 
130 /** Process received struct. */
131 void
132 SplRefBoxProcessor::process_struct(spl_gamecontrol_t *msg)
133 {
135  //fawkes::worldinfo_gamestate_goalcolor_t our_goal;
136 
137  int team_index;
138  if (msg->teams[0].team_number == __team_number) team_index = 0;
139  else if (msg->teams[1].team_number == __team_number) team_index = 1;
140  else return; //Message doesn't concern us
141 
142  switch (msg->teams[team_index].team_color) {
143  case SPL_TEAM_BLUE:
144  our_team = TEAM_CYAN;
145  break;
146  case SPL_TEAM_RED:
147  our_team = TEAM_MAGENTA;
148  break;
149  default:
150  printf("Ignoring faulty packet\n");
151  return;
152  }
153 
154  _rsh->set_score(msg->teams[team_index].score, msg->teams[(team_index == 1 ? 0 : 1)].score);
155  _rsh->set_team_goal(our_team, (our_team == TEAM_CYAN ? GOAL_BLUE : GOAL_YELLOW)); //blue team defends blue goal
156 
157  for (unsigned int pl_num = 0; pl_num < SPL_MAX_NUM_PLAYERS; ++pl_num)
158  {
159  if ((pl_num + 1) == __player_number)
160  {
161  if ((msg->teams[team_index].players[pl_num].penalty != __penalty) ||
162  (msg->teams[team_index].players[pl_num].penalty != PENALTY_NONE))
163  {
164  __penalty = msg->teams[team_index].players[pl_num].penalty;
165 
166 #ifdef USE_SPL_GC6
167  // convert GC6 codes to new GC7 codes, "closest match"
168  switch (__penalty) {
169  case SPL_PENALTY_BALL_HOLDING:
171  case SPL_PENALTY_GOALIE_PUSHING:
172  case SPL_PENALTY_PLAYER_PUSHING:
174  case SPL_PENALTY_ILLEGAL_DEFENDER:
175  case SPL_PENALTY_ILLEGAL_DEFENSE:
177  case SPL_PENALTY_OBSTRUCTION:
179  case SPL_PENALTY_REQ_FOR_PICKUP:
181  case SPL_PENALTY_LEAVING:
183  case SPL_PENALTY_DAMAGE:
184  case SPL_PENALTY_MANUAL:
186  default:
187  __penalty = SoccerPenaltyInterface::SPL_PENALTY_NONE; break;
188  }
189 #endif
190 
191  _rsh->add_penalty(__penalty,
192  msg->teams[team_index].players[pl_num].secs_till_unpenalized);
193  }
194  break;
195  }
196  }
197 
198  switch (msg->state) {
199  case SPL_STATE_INITIAL:
200  _rsh->set_gamestate(GS_SPL_INITIAL, TEAM_BOTH);
201  break;
202  case SPL_STATE_READY:
203  _rsh->set_gamestate(GS_SPL_READY, TEAM_BOTH);
204  break;
205  case SPL_STATE_SET:
206  _rsh->set_gamestate(GS_SPL_SET, TEAM_BOTH);
207  break;
208  case SPL_STATE_PLAYING:
209  _rsh->set_gamestate(GS_SPL_PLAY, TEAM_BOTH);
210  break;
211  case SPL_STATE_FINISHED:
212  _rsh->set_gamestate(GS_SPL_FINISHED, TEAM_BOTH);
213  break;
214  default:
215  _rsh->set_gamestate(GS_SPL_FINISHED, TEAM_BOTH);
216  break;
217  }
218 
219  _rsh->set_half((msg->first_half == 1) ? HALF_FIRST : HALF_SECOND,
220  msg->kick_off_team == team_index);
221 }
222 
223 
224 void
226 {
227  try {
228  spl_gamecontrol_t ctrlmsg;
229  size_t bytes_read = __s->recv((void *)&ctrlmsg, sizeof(ctrlmsg));
230  if ( bytes_read == sizeof(ctrlmsg) ) {
231  if ((strncmp(ctrlmsg.header, SPL_GAMECONTROL_HEADER, SPL_HEADER_SIZE) == 0) &&
232  (ctrlmsg.version == SPL_STRUCT_VERSION) ) {
233  process_struct(&ctrlmsg);
234  }
235  }
236  } catch (fawkes::Exception &e) {
237  if ( e.get_errno() != EAGAIN ) {
238  __logger->log_warn("SplRefBoxProcessor", "Receiving failed, exception follows");
239  __logger->log_warn("SplRefBoxProcessor", e);
240  } // else just no data available this time
241  }
242 }
243 
244 bool
246 {
247  return true;
248 }
249 
250 
251 /** Run.
252  * Reads messages from the network, processes them and calls the refbox state sender.
253  */
254 void
256 {
257  spl_gamecontrol_t ctrlmsg;
258  while ( ! __quit ) {
259  size_t bytes_read = __s->recv((void *)&ctrlmsg, sizeof(ctrlmsg));
260  if ( bytes_read == sizeof(ctrlmsg) ) {
261  if ( (strncmp(ctrlmsg.header, SPL_GAMECONTROL_HEADER, SPL_HEADER_SIZE) == 0) &&
262  (ctrlmsg.version == SPL_STRUCT_VERSION) ) {
263  process_struct(&ctrlmsg);
264  _rsh->handle_refbox_state();
265  } else {
266  printf("Received illegal package\n");
267  }
268  }
269  }
270 }
char header[SPL_HEADER_SIZE]
header to identify the structure
Definition: spl.h:64
static const uint16_t SPL_PENALTY_ILLEGAL_DEFENDER
SPL_PENALTY_ILLEGAL_DEFENDER constant.
uint8_t first_half
1 = game in first half, 0 otherwise
Definition: spl.h:68
Blue goal.
Definition: enums.h:64
int get_errno()
Get errno.
Definition: exception.cpp:643
spl_teaminfo_t teams[2]
Info about the teams.
Definition: spl.h:74
uint32_t version
version of the data structure
Definition: spl.h:65
Yellow goal.
Definition: enums.h:65
static const uint16_t SPL_PENALTY_NONE
SPL_PENALTY_NONE constant.
void run()
Run.
Definition: spl.cpp:255
Magenta team.
Definition: enums.h:57
Datagram socket.
Definition: datagram.h:31
First half.
Definition: enums.h:71
static const uint16_t SPL_PENALTY_LEAVING_THE_FIELD
SPL_PENALTY_LEAVING_THE_FIELD constant.
Base class for exceptions in Fawkes.
Definition: exception.h:36
static const uint16_t SPL_PENALTY_REQ_FOR_PICKUP
SPL_PENALTY_REQ_FOR_PICKUP constant.
Both teams.
Definition: enums.h:58
SplRefBoxProcessor(fawkes::Logger *logger, unsigned short int broadcast_port, unsigned int team_number, unsigned int player_number)
Constructor.
Definition: spl.cpp:106
uint8_t score
team's score
Definition: spl.h:57
static const uint16_t SPL_PENALTY_MANUAL
SPL_PENALTY_MANUAL constant.
Second half.
Definition: enums.h:72
SPL RefBox protocol game control struct.
Definition: spl.h:63
uint8_t state
state of the game (STATE_READY, STATE_PLAYING, etc.)
Definition: spl.h:67
static const uint16_t SPL_PENALTY_PLAYER_PUSHING
SPL_PENALTY_PLAYER_PUSHING constant.
Corner kick.
Definition: enums.h:49
Cyan team.
Definition: enums.h:56
uint8_t team_number
unique team number
Definition: spl.h:51
uint16_t penalty
penalty state of the player
Definition: spl.h:45
worldinfo_gamestate_team_t
Team.
Definition: enums.h:54
No penalty.
Definition: enums.h:77
~SplRefBoxProcessor()
Destructor.
Definition: spl.cpp:123
Wait for kick-off.
Definition: enums.h:47
uint8_t kick_off_team
the next team to kick off
Definition: spl.h:69
static const uint16_t SPL_PENALTY_BALL_HOLDING
SPL_PENALTY_BALL_HOLDING constant.
Move to kick-off positions.
Definition: enums.h:46
spl_robotinfo_t players[SPL_MAX_NUM_PLAYERS]
the team's players
Definition: spl.h:59
bool check_connection()
Check if the connection is alive and reconnect.
Definition: spl.cpp:245
static const uint16_t SPL_PENALTY_OBSTRUCTION
SPL_PENALTY_OBSTRUCTION constant.
Initial setup phase.
Definition: enums.h:45
void refbox_process()
Process incoming refbox communication.
Definition: spl.cpp:225
uint16_t secs_till_unpenalized
estimate of time till unpenalised
Definition: spl.h:46
uint8_t team_color
colour of the team
Definition: spl.h:52
Interface for logging.
Definition: logger.h:34