Fawkes API  Fawkes Development Version
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 
26 #include "state_handler.h"
27 
28 #include <core/exception.h>
29 #include <logging/logger.h>
30 #include <netcomm/socket/datagram.h>
31 
32 #ifdef USE_SPL_GC6
33 # include <interfaces/SoccerPenaltyInterface.h>
34 #endif
35 
36 #include <cerrno>
37 #include <cstdio>
38 #include <cstring>
39 #include <unistd.h>
40 // it it was defined, Exception::errno() could not be called...
41 #ifdef errno
42 # undef errno
43 #endif
44 using namespace fawkes;
45 
46 #ifdef USE_SPL_GC6
47 static const uint32_t SPL_STRUCT_VERSION = 6;
48 #else
49 static const uint32_t SPL_STRUCT_VERSION = 7;
50 #endif
51 
52 static const uint8_t SPL_STATE_INITIAL = 0;
53 static const uint8_t SPL_STATE_READY = 1;
54 static const uint8_t SPL_STATE_SET = 2;
55 static const uint8_t SPL_STATE_PLAYING = 3;
56 static const uint8_t SPL_STATE_FINISHED = 4;
57 
58 /*
59 static const uint8_t SPL_STATE2_NORMAL = 0;
60 static const uint8_t SPL_STATE2_PENALTYSHOOT = 1;
61 */
62 
63 static const uint8_t SPL_PENALTY_NONE = 0;
64 #ifdef USE_SPL_GC6
65 static const uint8_t SPL_PENALTY_BALL_HOLDING = 1;
66 static const uint8_t SPL_PENALTY_GOALIE_PUSHING = 2;
67 static const uint8_t SPL_PENALTY_PLAYER_PUSHING = 3;
68 static const uint8_t SPL_PENALTY_ILLEGAL_DEFENDER = 4;
69 static const uint8_t SPL_PENALTY_ILLEGAL_DEFENSE = 5;
70 static const uint8_t SPL_PENALTY_OBSTRUCTION = 6;
71 static const uint8_t SPL_PENALTY_REQ_FOR_PICKUP = 7;
72 static const uint8_t SPL_PENALTY_LEAVING = 8;
73 static const uint8_t SPL_PENALTY_DAMAGE = 9;
74 static const uint8_t SPL_PENALTY_MANUAL = 10;
75 #else
76 /*
77 static const uint8_t SPL_PENALTY_BALL_HOLDING = 1;
78 static const uint8_t SPL_PENALTY_PLAYER_PUSHING = 2;
79 static const uint8_t SPL_PENALTY_OBSTRUCTION = 3;
80 static const uint8_t SPL_PENALTY_INACTIVE_PLAYER = 4;
81 static const uint8_t SPL_PENALTY_ILLEGAL_DEFENDER = 5;
82 static const uint8_t SPL_PENALTY_LEAVING_THE_FIELD = 6;
83 static const uint8_t SPL_PENALTY_PLAYING_WITH_HANDS = 7;
84 static const uint8_t SPL_PENALTY_REQ_FOR_PICKUP = 8;
85 static const uint8_t SPL_PENALTY_MANUAL = 15;
86 */
87 #endif
88 
89 // team numbers
90 static const uint8_t SPL_TEAM_BLUE = 0;
91 static const uint8_t SPL_TEAM_RED = 1;
92 
93 /*
94 static const uint8_t SPL_GOAL_BLUE = 0;
95 static const uint8_t SPL_GOAL_YELLOW = 1;
96 */
97 
98 static const char SPL_GAMECONTROL_HEADER[SPL_HEADER_SIZE] = {'R', 'G', 'm', 'e'};
99 
100 /** @class SplRefBoxProcessor "processor/spl.h"
101  * SPL league refbox repeater.
102  * This class will listen to SPL refbox commands and derive matching
103  * game states from the communication stream and send this via the world info.
104  * @author Tim Niemueller
105  */
106 
107 /** Constructor.
108  * @param logger Logger
109  * @param broadcast_port Broadcast port
110  * @param team_number our team number
111  * @param player_number individual player number
112  */
114  unsigned short int broadcast_port,
115  unsigned int team_number,
116  unsigned int player_number)
117 {
118  player_number_ = player_number;
119  team_number_ = team_number;
120  logger_ = logger;
121  quit_ = false;
122  s_.reset(new DatagramSocket(Socket::IPv4, 0.0000000001));
123  s_->bind(broadcast_port);
124 
125  penalty_ = SPL_PENALTY_NONE;
126 }
127 
128 /** Destructor. */
130 {
131  s_->close();
132  s_.reset();
133 }
134 
135 /** Process received struct. */
136 void
137 SplRefBoxProcessor::process_struct(spl_gamecontrol_t *msg)
138 {
140  //fawkes::worldinfo_gamestate_goalcolor_t our_goal;
141 
142  int team_index;
143  if (msg->teams[0].team_number == team_number_)
144  team_index = 0;
145  else if (msg->teams[1].team_number == team_number_)
146  team_index = 1;
147  else
148  return; //Message doesn't concern us
149 
150  switch (msg->teams[team_index].team_color) {
151  case SPL_TEAM_BLUE: our_team = TEAM_CYAN; break;
152  case SPL_TEAM_RED: our_team = TEAM_MAGENTA; break;
153  default: printf("Ignoring faulty packet\n"); return;
154  }
155 
156  _rsh->set_score(msg->teams[team_index].score, msg->teams[(team_index == 1 ? 0 : 1)].score);
157  _rsh->set_team_goal(our_team,
158  (our_team == TEAM_CYAN ? GOAL_BLUE
159  : GOAL_YELLOW)); //blue team defends blue goal
160 
161  for (unsigned int pl_num = 0; pl_num < SPL_MAX_NUM_PLAYERS; ++pl_num) {
162  if ((pl_num + 1) == player_number_) {
163  if ((msg->teams[team_index].players[pl_num].penalty != penalty_)
164  || (msg->teams[team_index].players[pl_num].penalty != PENALTY_NONE)) {
165  penalty_ = msg->teams[team_index].players[pl_num].penalty;
166 
167 #ifdef USE_SPL_GC6
168  // convert GC6 codes to new GC7 codes, "closest match"
169  switch (penalty_) {
170  case SPL_PENALTY_BALL_HOLDING:
172  break;
173  case SPL_PENALTY_GOALIE_PUSHING:
174  case SPL_PENALTY_PLAYER_PUSHING:
176  break;
177  case SPL_PENALTY_ILLEGAL_DEFENDER:
178  case SPL_PENALTY_ILLEGAL_DEFENSE:
180  break;
181  case SPL_PENALTY_OBSTRUCTION:
183  break;
184  case SPL_PENALTY_REQ_FOR_PICKUP:
186  break;
187  case SPL_PENALTY_LEAVING:
189  break;
190  case SPL_PENALTY_DAMAGE:
191  case SPL_PENALTY_MANUAL: penalty_ = SoccerPenaltyInterface::SPL_PENALTY_MANUAL; break;
192  default: penalty_ = SoccerPenaltyInterface::SPL_PENALTY_NONE; break;
193  }
194 #endif
195 
196  _rsh->add_penalty(penalty_, msg->teams[team_index].players[pl_num].secs_till_unpenalized);
197  }
198  break;
199  }
200  }
201 
202  switch (msg->state) {
203  case SPL_STATE_INITIAL: _rsh->set_gamestate(GS_SPL_INITIAL, TEAM_BOTH); break;
204  case SPL_STATE_READY: _rsh->set_gamestate(GS_SPL_READY, TEAM_BOTH); break;
205  case SPL_STATE_SET: _rsh->set_gamestate(GS_SPL_SET, TEAM_BOTH); break;
206  case SPL_STATE_PLAYING: _rsh->set_gamestate(GS_SPL_PLAY, TEAM_BOTH); break;
207  case SPL_STATE_FINISHED: _rsh->set_gamestate(GS_SPL_FINISHED, TEAM_BOTH); break;
208  default: _rsh->set_gamestate(GS_SPL_FINISHED, TEAM_BOTH); break;
209  }
210 
211  _rsh->set_half((msg->first_half == 1) ? HALF_FIRST : HALF_SECOND,
212  msg->kick_off_team == team_index);
213 }
214 
215 void
217 {
218  try {
219  spl_gamecontrol_t ctrlmsg;
220  size_t bytes_read = s_->recv((void *)&ctrlmsg, sizeof(ctrlmsg));
221  if (bytes_read == sizeof(ctrlmsg)) {
222  if ((strncmp(ctrlmsg.header, SPL_GAMECONTROL_HEADER, SPL_HEADER_SIZE) == 0)
223  && (ctrlmsg.version == SPL_STRUCT_VERSION)) {
224  process_struct(&ctrlmsg);
225  }
226  }
227  } catch (fawkes::Exception &e) {
228  if (e.get_errno() != EAGAIN) {
229  logger_->log_warn("SplRefBoxProcessor", "Receiving failed, exception follows");
230  logger_->log_warn("SplRefBoxProcessor", e);
231  } // else just no data available this time
232  }
233 }
234 
235 bool
237 {
238  return true;
239 }
240 
241 /** Run.
242  * Reads messages from the network, processes them and calls the refbox state sender.
243  */
244 void
246 {
247  spl_gamecontrol_t ctrlmsg;
248  while (!quit_) {
249  size_t bytes_read = s_->recv((void *)&ctrlmsg, sizeof(ctrlmsg));
250  if (bytes_read == sizeof(ctrlmsg)) {
251  if ((strncmp(ctrlmsg.header, SPL_GAMECONTROL_HEADER, SPL_HEADER_SIZE) == 0)
252  && (ctrlmsg.version == SPL_STRUCT_VERSION)) {
253  process_struct(&ctrlmsg);
254  _rsh->handle_refbox_state();
255  } else {
256  printf("Received illegal package\n");
257  }
258  }
259  }
260 }
fawkes::TEAM_MAGENTA
@ TEAM_MAGENTA
Magenta team.
Definition: enums.h:62
fawkes::SoccerPenaltyInterface::SPL_PENALTY_OBSTRUCTION
static const uint16_t SPL_PENALTY_OBSTRUCTION
SPL_PENALTY_OBSTRUCTION constant.
Definition: SoccerPenaltyInterface.h:55
fawkes::Socket::IPv4
@ IPv4
IPv4.
Definition: socket.h:83
fawkes::SoccerPenaltyInterface::SPL_PENALTY_ILLEGAL_DEFENDER
static const uint16_t SPL_PENALTY_ILLEGAL_DEFENDER
SPL_PENALTY_ILLEGAL_DEFENDER constant.
Definition: SoccerPenaltyInterface.h:57
SplRefBoxProcessor::refbox_process
void refbox_process()
Definition: spl.cpp:216
SplRefBoxProcessor::SplRefBoxProcessor
SplRefBoxProcessor(fawkes::Logger *logger, unsigned short int broadcast_port, unsigned int team_number, unsigned int player_number)
Constructor.
Definition: spl.cpp:113
fawkes::GS_SPL_SET
@ GS_SPL_SET
Wait for kick-off.
Definition: enums.h:53
fawkes::TEAM_BOTH
@ TEAM_BOTH
Both teams.
Definition: enums.h:63
fawkes::SoccerPenaltyInterface::SPL_PENALTY_NONE
static const uint16_t SPL_PENALTY_NONE
SPL_PENALTY_NONE constant.
Definition: SoccerPenaltyInterface.h:52
spl_teaminfo_t::score
uint8_t score
team's score
Definition: spl.h:60
fawkes::GOAL_YELLOW
@ GOAL_YELLOW
Yellow goal.
Definition: enums.h:69
SplRefBoxProcessor::check_connection
bool check_connection()
Definition: spl.cpp:236
fawkes::HALF_FIRST
@ HALF_FIRST
First half.
Definition: enums.h:74
spl_teaminfo_t::players
spl_robotinfo_t players[SPL_MAX_NUM_PLAYERS]
the team's players
Definition: spl.h:62
fawkes::Exception::get_errno
int get_errno()
Get errno.
Definition: exception.cpp:622
fawkes::Logger
Definition: logger.h:41
fawkes::HALF_SECOND
@ HALF_SECOND
Second half.
Definition: enums.h:75
fawkes
fawkes::TEAM_CYAN
@ TEAM_CYAN
Cyan team.
Definition: enums.h:61
fawkes::SoccerPenaltyInterface::SPL_PENALTY_BALL_HOLDING
static const uint16_t SPL_PENALTY_BALL_HOLDING
SPL_PENALTY_BALL_HOLDING constant.
Definition: SoccerPenaltyInterface.h:53
fawkes::GS_SPL_FINISHED
@ GS_SPL_FINISHED
Corner kick.
Definition: enums.h:55
spl_gamecontrol_t::state
uint8_t state
state of the game (STATE_READY, STATE_PLAYING, etc.)
Definition: spl.h:71
fawkes::worldinfo_gamestate_team_t
worldinfo_gamestate_team_t
Team.
Definition: enums.h:59
SplRefBoxProcessor::~SplRefBoxProcessor
~SplRefBoxProcessor()
Destructor.
Definition: spl.cpp:129
spl_gamecontrol_t::teams
spl_teaminfo_t teams[2]
Info about the teams.
Definition: spl.h:80
spl_gamecontrol_t::first_half
uint8_t first_half
1 = game in first half, 0 otherwise
Definition: spl.h:72
fawkes::SoccerPenaltyInterface::SPL_PENALTY_REQ_FOR_PICKUP
static const uint16_t SPL_PENALTY_REQ_FOR_PICKUP
SPL_PENALTY_REQ_FOR_PICKUP constant.
Definition: SoccerPenaltyInterface.h:60
spl_gamecontrol_t
SPL RefBox protocol game control struct.
Definition: spl.h:66
spl_teaminfo_t::team_number
uint8_t team_number
unique team number
Definition: spl.h:54
fawkes::SoccerPenaltyInterface::SPL_PENALTY_LEAVING_THE_FIELD
static const uint16_t SPL_PENALTY_LEAVING_THE_FIELD
SPL_PENALTY_LEAVING_THE_FIELD constant.
Definition: SoccerPenaltyInterface.h:58
fawkes::GOAL_BLUE
@ GOAL_BLUE
Blue goal.
Definition: enums.h:68
fawkes::PENALTY_NONE
@ PENALTY_NONE
No penalty.
Definition: enums.h:80
SplRefBoxProcessor::run
void run()
Run.
Definition: spl.cpp:245
fawkes::SoccerPenaltyInterface::SPL_PENALTY_MANUAL
static const uint16_t SPL_PENALTY_MANUAL
SPL_PENALTY_MANUAL constant.
Definition: SoccerPenaltyInterface.h:61
spl_robotinfo_t::secs_till_unpenalized
uint16_t secs_till_unpenalized
estimate of time till unpenalised
Definition: spl.h:48
spl_robotinfo_t::penalty
uint16_t penalty
penalty state of the player
Definition: spl.h:47
fawkes::GS_SPL_READY
@ GS_SPL_READY
Move to kick-off positions.
Definition: enums.h:52
fawkes::SoccerPenaltyInterface::SPL_PENALTY_PLAYER_PUSHING
static const uint16_t SPL_PENALTY_PLAYER_PUSHING
SPL_PENALTY_PLAYER_PUSHING constant.
Definition: SoccerPenaltyInterface.h:54
fawkes::DatagramSocket
Definition: datagram.h:37
fawkes::GS_SPL_PLAY
@ GS_SPL_PLAY
Play!
Definition: enums.h:54
fawkes::GS_SPL_INITIAL
@ GS_SPL_INITIAL
Initial setup phase.
Definition: enums.h:51
spl_gamecontrol_t::kick_off_team
uint8_t kick_off_team
the next team to kick off
Definition: spl.h:73
spl_teaminfo_t::team_color
uint8_t team_color
colour of the team
Definition: spl.h:55
fawkes::Exception
Definition: exception.h:41