Fawkes API  Fawkes Development Version
transceiver.cpp
1 
2 /***************************************************************************
3  * transceiver.h - World Info Transceiver
4  *
5  * Created: Sun Jan 21 14:15:32 2007
6  * Copyright 2006-2007 Tim Niemueller [www.niemueller.de]
7  *
8  ****************************************************************************/
9 
10 /* This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version. A runtime exception applies to
14  * this software (see LICENSE.GPL_WRE file mentioned below for details).
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_WRE file in the doc directory.
22  */
23 
24 #include <core/exceptions/system.h>
25 #include <core/exceptions/software.h>
26 
27 #include <netcomm/worldinfo/transceiver.h>
28 #include <netcomm/worldinfo/messages.h>
29 #include <netcomm/worldinfo/encrypt.h>
30 #include <netcomm/worldinfo/decrypt.h>
31 
32 #include <netcomm/socket/datagram_broadcast.h>
33 #include <netcomm/socket/datagram_multicast.h>
34 #include <netcomm/utils/resolver.h>
35 
36 #include <arpa/inet.h>
37 #include <netinet/in.h>
38 #include <cstdlib>
39 #include <cstring>
40 
41 namespace fawkes {
42 
43 /** @class WorldInfoException transceiver.h <netcomm/worldinfo/transceiver.h>
44  * Thrown on critical errors in world info handling.
45  * @ingroup NetComm
46  */
47 
48 /** Constructor.
49  * @param msg message
50  */
52  : Exception(msg)
53 {
54 }
55 
56 
57 /** @class WorldInfoTransceiver transceiver.h <netcomm/worldinfo/transceiver.h>
58  * Class to send and receive world information.
59  * An important point in a domain of cooperating soccer robots is transmitting
60  * and receiving a robot's belief of its surrounding. The world info
61  * transceiver does exactly that. It allows for sending information about the
62  * robot's pose and velocity and its perception of the ball and other robots
63  * on the field.
64  *
65  * The unit for distances and positions is meter (m), speed is given in
66  * meter per second (m/s), angles are given in radiant (rad). Angles can be in
67  * the range 0 to 2 * PI or -PI to PI. Since they can be converted easily
68  * between these ranges without further information users of such information
69  * shall be able to process both.
70  *
71  * Coordinates are given in a right-handed coordinate system with the origin in
72  * center of the field, X pointing towards the opponent goal, Y to the right
73  * and Z downwards.
74  *
75  * Information is transmitted with a simple protocol via UDP Multicast or
76  * Broadcast packets.
77  *
78  * A call to send() will reset all information, thus all opponents are removed
79  * from the list to be sent, positions of robot and ball are marked invalid.
80  * You have to call the appropriate set methods before the information is sent.
81  * You can thus call send() at any time but only changed information
82  * (information set since last send() call) is transmitted over the network.
83  *
84  * @ingroup NetComm
85  * @author Tim Niemueller
86  */
87 
88 
89 /** Constructor.
90  * @param socket_type either multicast or broadcast socket
91  * @param addr multicast or broadcast address to send information to and receive from
92  * @param port UDP port to send information to and receive from
93  * @param key encryption key
94  * @param iv encryption initialisation vector
95  * @param resolver An initialized network resolver, is NULL is supplied
96  * an internal resolver will be created without mDNS support.
97  * @exception OutOfMemoryException thrown if internal buffers cannot be created
98  */
100  const char *addr, unsigned short port,
101  const char *key, const char *iv,
102  NetworkNameResolver *resolver) :
103  pose_changed( false ),
104  vel_changed( false ),
105  rel_ball_changed( false ),
106  rel_ball_vel_changed( false ),
107  glob_ball_changed( false ),
108  glob_ball_vel_changed( false ),
109  gamestate_changed( false )
110 {
111  try {
112  switch (socket_type) {
113  case MULTICAST: {
114  MulticastDatagramSocket* ms = new MulticastDatagramSocket(addr, port);
115  ms->bind();
116  s = ms;
117  break;
118  }
119  case BROADCAST: {
120  BroadcastDatagramSocket* bs = new BroadcastDatagramSocket(addr, port);
121  bs->bind();
122  s = bs;
123  break;
124  }
125  }
126  set_loop(false);
127  } catch (SocketException &e) {
128  e.append("WorldInfoTransceiver cannot instantiate socket for %s:%u", addr, port);
129  throw;
130  }
131 
132  in_buffer = malloc(WORLDINFO_MTU);
133  out_buffer = malloc(WORLDINFO_MTU);
134  if (! in_buffer || ! out_buffer) {
135  throw OutOfMemoryException();
136  }
137 
138  fatmsg_enabled = false;
139  fatmsg_bufsize = 0;
140  fatmsg_buf = NULL;
141  fatmsg_header = NULL;
142  fatmsg_msgheader = NULL;
143  fatmsg = NULL;
144 
145  __key = strdup(key);
146  __iv = strdup(iv);
147 
148  encryptor = new WorldInfoMessageEncryptor((const unsigned char *)__key, (const unsigned char *)__iv);
149  decryptor = new WorldInfoMessageDecryptor((const unsigned char *)__key, (const unsigned char *)__iv);
150 
151  // set maximum size buffer to get valid results from encryptor
152  encryptor->set_plain_buffer(out_buffer, WORLDINFO_MTU);
153 
154  crypt_buffer_size = encryptor->recommended_crypt_buffer_size();
155  crypted_out_buffer = malloc(crypt_buffer_size);
156  crypted_in_buffer = malloc(crypt_buffer_size);
157 
158  if (! crypted_in_buffer || ! crypted_out_buffer) {
159  throw OutOfMemoryException();
160  }
161 
162  encryptor->set_crypt_buffer(crypted_out_buffer, crypt_buffer_size);
163 
164  decryptor->set_plain_buffer(in_buffer, WORLDINFO_MTU);
165 
166  if ( resolver == NULL ) {
167  this->resolver = new NetworkNameResolver();
168  resolver_delete = true;
169  } else {
170  this->resolver = resolver;
171  resolver_delete = false;
172  }
173 
174  out_seq = 0;
175 }
176 
177 
178 /** Destructor. */
180 {
181  set_fatmsg_enabled(false);
182  free(out_buffer);
183  free(in_buffer);
184  free(crypted_out_buffer);
185  free(crypted_in_buffer);
186  free(__key);
187  free(__iv);
188  delete s;
189  delete encryptor;
190  delete decryptor;
191  if ( resolver_delete ) {
192  delete resolver;
193  }
194 }
195 
196 
197 /** Set loopback of sent packets.
198  * This sets whether packets should be looped back to local sockets for multicast
199  * communication.
200  * @param loop true to deliver sent packets to local sockets, false prevent delivering
201  * @see MulticastDatagramSocket::set_loop()
202  */
203 void
205 {
206  MulticastDatagramSocket* ms = dynamic_cast<MulticastDatagramSocket*>(s);
207  if (s) {
208  ms->set_loop( loop );
209  }
210  this->loop = loop;
211 }
212 
213 
214 /** Enable or disable sending of fat message.
215  * The fat message is considered to be legacy code and therefore disabled by default.
216  * If you happen to need the fat message you can enable it using this method and then
217  * it will be send for every call to send().
218  * @param fatmsg_enabled true to enable sending of fat message, false otherwise
219  */
220 void
222 {
223  if ( this->fatmsg_enabled && ! fatmsg_enabled ) {
224  // fatmsg turned off
225  free(fatmsg_buf);
226  fatmsg_buf = NULL;
227  fatmsg_msgheader = NULL;
228  fatmsg_header = NULL;
229  fatmsg = NULL;
230  fatmsg_bufsize = 0;
231  } else if (! this->fatmsg_enabled && fatmsg_enabled ) {
232  // fatmsg turned on
233  fatmsg_bufsize = sizeof(worldinfo_header_t) + sizeof(worldinfo_message_header_t)
234  + sizeof(worldinfo_fat_message_t);
235  fatmsg_buf = calloc(1, fatmsg_bufsize);
236  fatmsg_header = (worldinfo_header_t *)fatmsg_buf;
237  fatmsg_msgheader = (worldinfo_message_header_t *)((char *)fatmsg_buf + sizeof(worldinfo_header_t));
238  fatmsg = (worldinfo_fat_message_t *)((char *)fatmsg_buf + sizeof(worldinfo_header_t)
239  + sizeof(worldinfo_message_header_t));
240  } // else unchanged
241 
242  this->fatmsg_enabled = fatmsg_enabled;
243 }
244 
245 
246 /** Add a handler for world information.
247  * World information will be dispatched to all registered handlers as soon it
248  * is received.
249  * @param h handler to register
250  */
251 void
253 {
254  handlers.lock();
255  handlers.push_back(h);
256  handlers.sort();
257  handlers.unique();
258  handlers.unlock();
259 }
260 
261 
262 /** Remove handler for world information.
263  * The handler is removed from the list of handlers that incoming information
264  * is dispatched to. No error is thrown if the handler was never registered
265  * so it is safe to call this for any handler.
266  * @param h handler to remove from subscriber list
267  */
268 void
270 {
271  handlers.remove_locked(h);
272 }
273 
274 
275 /** Flush sequence numbers conditionally.
276  * This will conditionally flush the sequence numbers stored per sender. The
277  * sequence numbers are stored per IP. With this method you can flush the
278  * sequence numbers that have been inactive for a specified time. A recommended
279  * value is 10 seconds. You may NOT call this concurrently to recv()!
280  * @param sec number of seconds since that must have passed without a message
281  * to remove a specific IP from sequence list
282  */
283 void
285 {
286  time_t limit = time(NULL) - sec;
287 
288  std::map<uint32_t, time_t>::iterator lrtit2;
289  lrtit = last_received_time.begin();
290  while (lrtit != last_received_time.end()) {
291  if ( (*lrtit).second < limit ) {
292  sequence_numbers.erase((*lrtit).first);
293  lrtit2 = lrtit;
294  ++lrtit;
295  last_received_time.erase(lrtit2);
296  } else {
297  ++lrtit;
298  }
299  }
300 }
301 
302 
303 /** Set global pose of robot.
304  * Global pose of sensing robot (x, y, theta) with the origin in the
305  * middle of the field, right handed coordinate system (y to opponent goal,
306  * x to the right, z pointing upwards, same as in simulation league).
307  * Theta points in y direction (theta = 0 iff robot front points to opponent
308  * goal).
309  * The confidence about the robot's pose is transmitted as a 3x3 covariance
310  * matrix.
311  * @param x x position of robot
312  * @param y y position of robot
313  * @param theta rotation of robot
314  * @param covariance covariance matrix with 9 entries, ordered as three concatenated
315  * rows (first row, three floats, second row, three floats, third row, three
316  * floats). No length check or whatsoever is done. This will crash if c is not
317  * long enough! c will not be copied but referenced so it has to exist when
318  * send() is called!
319  */
320 void
321 WorldInfoTransceiver::set_pose(float x, float y, float theta, float *covariance)
322 {
323  pose_x = x;
324  pose_y = y;
325  pose_theta = theta;
326  pose_covariance = covariance;
327  pose_changed = true;
328 }
329 
330 
331 /** Set velocity of the robot.
332  * Set the current velocity of the robot.
333  * @param vel_x velocity in x direction
334  * @param vel_y velocity in y direction
335  * @param vel_theta rotational velocity, positive velocity means clockwise
336  * rotation, negative velocity means counter-clockwise.
337  * @param covariance covariance matrix with 9 entries, ordered as three concatenated
338  * rows (first row, three floats, second row, three floats, third row, three
339  * floats). No length check or whatsoever is done. This will crash if c is not
340  * long enough! c will not be copied but referenced so it has to exist when
341  * send() is called!
342  */
343 void
344 WorldInfoTransceiver::set_velocity(float vel_x, float vel_y, float vel_theta, float *covariance)
345 {
346  this->vel_x = vel_x;
347  this->vel_y = vel_y;
348  this->vel_theta = vel_theta;
349  this->vel_covariance = covariance;
350  this->vel_changed = true;
351 }
352 
353 
354 /** Set ball position.
355  * Set the ball perception relative to the current robot position.
356  * Note that the ball position is given in polar coordinates in
357  * 3D space!
358  * The confidence about the ball position is transmitted as a 3x3 covariance
359  * matrix.
360  * @param dist distance to ball in meters
361  * @param bearing bearing angle to ball
362  * @param slope slope angle to ball
363  * @param covariance covariance matrix with 9 entries, ordered as three concatenated
364  * rows (first row, three floats, second row, three floats, third row, three
365  * floats). No length check or whatsoever is done. This will crash if c is not
366  * long enough! c will not be copied but referenced so it has to exist when
367  * send() is called!
368  */
369 void
370 WorldInfoTransceiver::set_rel_ball_pos(float dist, float bearing, float slope, float *covariance)
371 {
372  rel_ball_dist = dist;
373  rel_ball_bearing = bearing;
374  rel_ball_slope = slope;
375  rel_ball_covariance = covariance;
376  rel_ball_changed = true;
377 }
378 
379 
380 /** Set global ball position.
381  * Note that the ball position is given in polar coordinates in
382  * 3D space!
383  * The confidence about the ball position is transmitted as a 3x3 covariance
384  * matrix.
385  * @param x the x-coordinate of the global ball position
386  * @param y the y-coordinate of the global ball position
387  * @param z the z-coordinate of the global ball position
388  * @param covariance covariance matrix with 9 entries, ordered as three concatenated
389  * rows (first row, three floats, second row, three floats, third row, three
390  * floats). No length check or whatsoever is done. This will crash if c is not
391  * long enough! c will not be copied but referenced so it has to exist when
392  * send() is called!
393  */
394 void
395 WorldInfoTransceiver::set_glob_ball_pos(float x, float y, float z, float *covariance)
396 {
397  glob_ball_x = x;
398  glob_ball_y = y;
399  glob_ball_z = z;
400  glob_ball_covariance = covariance;
401  glob_ball_changed = true;
402 }
403 
404 
405 /** Set ball visibility.
406  * This method defines if the ball is currently visible or not. Additionally more detailed
407  * information is provided in the visibility history. The history shall be 0 only if the
408  * vision has just been initialized. It shall be positive if the ball is visible and shall
409  * have the number of vision cycles in which the ball was visible in a row. It shall be
410  * negative if the ball is not visible and shall be the negative value of the number
411  * of frames where the ball was not visible. A value of 30 for example means that the
412  * ball has been continuously visible for 30 frames, it was never lost. A value of
413  * -20 means that the ball was not seen for the last 20 frames.
414  * @param visible true if the ball is visible, false otherwise
415  * @param visibility_history visibility history, see above.
416  */
417 void
418 WorldInfoTransceiver::set_rel_ball_visible(bool visible, int visibility_history)
419 {
420  rel_ball_visible = visible;
421  rel_ball_visibility_history = visibility_history;
422  rel_ball_changed = true;
423 }
424 
425 
426 /** Set ball visibility for the global ball.
427  * Same semantics as set_ball_visible().
428  * @param visible true if the ball is visible, false otherwise
429  * @param visibility_history visibility history, see above.
430  */
431 void
432 WorldInfoTransceiver::set_glob_ball_visible(bool visible, int visibility_history)
433 {
434  glob_ball_visible = visible;
435  glob_ball_visibility_history = visibility_history;
436  glob_ball_changed = true;
437 }
438 
439 
440 /** Set ball velocity.
441  * Set the current velocity of the robot.
442  * @param vel_x velocity in x direction
443  * @param vel_y velocity in y direction
444  * @param vel_z velocity in z direction
445  * @param covariance covariance matrix with 9 entries, ordered as three concatenated
446  * rows (first row, three floats, second row, three floats, third row, three
447  * floats). No length check or whatsoever is done. This will crash if c is not
448  * long enough! c will not be copied but referenced so it has to exist when
449  * send() is called!
450  */
451 void
452 WorldInfoTransceiver::set_rel_ball_velocity(float vel_x, float vel_y, float vel_z,
453  float *covariance)
454 {
455  rel_ball_vel_x = vel_x;
456  rel_ball_vel_y = vel_y;
457  rel_ball_vel_z = vel_z;
458  rel_ball_vel_covariance = covariance;
459  rel_ball_vel_changed = true;
460 }
461 
462 
463 /** Set global ball velocity.
464  * Set the current, global velocity of the robot.
465  * @param vel_x velocity in x direction wrt. to the global frame
466  * @param vel_y velocity in y direction wrt. to the global frame
467  * @param vel_z velocity in z direction wrt. to the global frame
468  * @param covariance covariance matrix with 9 entries, ordered as three concatenated
469  * rows (first row, three floats, second row, three floats, third row, three
470  * floats). No length check or whatsoever is done. This will crash if c is not
471  * long enough! c will not be copied but referenced so it has to exist when
472  * send() is called!
473  */
474 void
475 WorldInfoTransceiver::set_glob_ball_velocity(float vel_x, float vel_y, float vel_z,
476  float *covariance)
477 {
478  glob_ball_vel_x = vel_x;
479  glob_ball_vel_y = vel_y;
480  glob_ball_vel_z = vel_z;
481  glob_ball_vel_covariance = covariance;
482  glob_ball_vel_changed = true;
483 }
484 
485 
486 /** Set current game state.
487  * @param gamestate current game state
488  * @param state_team team referenced by the game state
489  */
490 void
492  worldinfo_gamestate_team_t state_team)
493 {
494  if ((gamestate < 0) || (gamestate >= 16)) {
495  throw OutOfBoundsException("Illegal gamestate", gamestate, 0, 15);
496  }
497  gamestate_msg.game_state = gamestate;
498  gamestate_msg.state_team = state_team;
499  gamestate_changed = true;
500 }
501 
502 
503 /** Set score.
504  * @param score_cyan current score of team cyan
505  * @param score_magenta current score of team magenta
506  */
507 void
508 WorldInfoTransceiver::set_score(unsigned int score_cyan, unsigned int score_magenta)
509 {
510  gamestate_msg.score_cyan = score_cyan;
511  gamestate_msg.score_magenta = score_magenta;
512  gamestate_changed = true;
513 }
514 
515 
516 /** Add penalty message.
517  * @param player player for which the penalty applies
518  * @param penalty penalty code
519  * @param seconds_remaining estimated time in seconds until the penalty is lifted
520  */
521 void
522 WorldInfoTransceiver::add_penalty(unsigned int player, unsigned int penalty,
523  unsigned int seconds_remaining)
524 {
526  pm.reserved = 0;
527  pm.player = player;
528  pm.penalty = penalty;
529  pm.seconds_remaining = seconds_remaining;
530  penalties[player] = pm;
531 }
532 
533 /** Set team and goal info.
534  * @param our_team our team color
535  * @param goal_color our goal color
536  */
537 void
540 {
541  gamestate_msg.our_team = our_team;
542  gamestate_msg.our_goal_color = goal_color;
543  gamestate_changed = true;
544 }
545 
546 
547 /** Set current half of the game time.
548  * @param half current half
549  */
550 void
552 {
553  gamestate_msg.half = half;
554  gamestate_changed = true;
555 }
556 
557 
558 /** Clear opponents list.
559  * Clear the list of opponents that has to be transmitted. This is done
560  * implicitly in send().
561  */
562 void
564 {
565  opponents.clear();
566 }
567 
568 
569 /** Add opponent to transmit list.
570  * Add an opponent to the list of opponents to be transmitted on next send()
571  * call. Opponents are given in a 2D polar coordinate system (assumption is that
572  * robots don't fly in the soccer domain).
573  * @param uid unique ID of this opponent. The caller shall assign the same UID to an
574  * opponent if and only if the object is the same (for example an opponent that was
575  * tracked)
576  * @param distance to opponent
577  * @param bearing to opponent (angle is zero if opponent is in front of robot,
578  * positive if right of robot, negative if left of robot).
579  * @param covariance covariance matrix with 4 entries, ordered as two concatenated
580  * rows (first row, two floats, second row, two floats. No length check or
581  * whatsoever is done. This will crash if c is not
582  * long enough! c will not be copied but referenced so it has to exist when
583  * send() is called!
584  */
585 void
587  float distance, float bearing, float *covariance)
588 {
589  opponent_t o = { uid, distance, bearing, covariance };
590  opponents.push_back(o);
591 }
592 
593 
594 /** Add disappeared opponent.
595  * Add any opponent that you had added in an earlier cycle (before the last send()) with
596  * add_opponent() and that is no longer visible. After it has been marked as disappeared
597  * the unique ID may not be reused. Gibt it another new ID instead.
598  * @param uid Unique ID of opponent that disappeared
599  */
600 void
602 {
603  disappeared_opponents.push_back(uid);
604 }
605 
606 /** Append packet to outbound buffer.
607  * @param msg_type message type
608  * @param msg message buffer
609  * @param msg_size size of message buffer
610  * @exception OutOfMemoryException thrown if message is too big or if the
611  * remaining size in the outbound buffer is not big enough
612  */
613 void
614 WorldInfoTransceiver::append_outbound(uint16_t msg_type,
615  void *msg, uint16_t msg_size)
616 {
618 
619  if ( (outbound_bytes + sizeof(mh) + msg_size ) > WORLDINFO_MTU ) {
620  throw OutOfMemoryException();
621  }
622 
623  // per message header
624  mh.type = htons(msg_type);
625  mh.size = htons(msg_size);
626  memcpy(outbound_buffer, &mh, sizeof(mh));
627 
628  outbound_bytes += sizeof(mh);
629  outbound_buffer += sizeof(mh);
630 
631  // message body
632  memcpy(outbound_buffer, msg, msg_size);
633  outbound_bytes += msg_size;
634  outbound_buffer += msg_size;
635  ++outbound_num_msgs;
636 }
637 
638 
639 /** Reset outbound buffer.
640  */
641 void
642 WorldInfoTransceiver::reset_outbound()
643 {
644  worldinfo_header_t *header = (worldinfo_header_t *)out_buffer;
645  header->beef = htons(0xBEEF);
646  header->version = WORLDINFO_VERSION;
647 
648  if ( fatmsg_enabled ) {
649  memset(fatmsg_buf, 0, fatmsg_bufsize);
650  fatmsg_header->beef = htons(0xBEEF);
651  fatmsg_header->version = WORLDINFO_VERSION;
652  fatmsg_msgheader->type = htons(WORLDINFO_MSGTYPE_FAT_WORLDINFO);
653  fatmsg_msgheader->size = htons(sizeof(worldinfo_fat_message_t));
654  }
655 
656  outbound_buffer = (unsigned char *)out_buffer + sizeof(worldinfo_header_t);
657  outbound_bytes = sizeof(worldinfo_header_t);
658  outbound_num_msgs = 0;
659 }
660 
661 
662 /** Send information.
663  * All information that has been set since last call is sent over the network.
664  * This implicitly resets all information and flushes the opponent list.
665  */
666 void
668 {
669  worldinfo_header_t *header = (worldinfo_header_t *)out_buffer;
670 
671  reset_outbound();
672 
673  if ( pose_changed ) {
675  pm.x = pose_x;
676  pm.y = pose_y;
677  pm.theta = pose_theta;
678  memcpy(&(pm.covariance), pose_covariance, sizeof(pm.covariance));
679  pose_changed = false;
680 
681  append_outbound(WORLDINFO_MSGTYPE_POSE, &pm, sizeof(pm));
682 
683  if ( fatmsg_enabled ) {
684  // fill fat msg
685  memcpy(&(fatmsg->pose), &pm, sizeof(pm));
686  fatmsg->valid_pose = 1;
687  }
688  } else {
689  if ( fatmsg_enabled ) {
690  fatmsg->valid_pose = 0;
691  }
692  }
693 
694  if ( vel_changed ) {
696  vm.vel_x = vel_x;
697  vm.vel_y = vel_y;
698  vm.vel_theta = vel_theta;
699  memcpy(&(vm.covariance), vel_covariance, sizeof(vm.covariance));
700  vel_changed = false;
701 
702  append_outbound(WORLDINFO_MSGTYPE_VELO, &vm, sizeof(vm));
703 
704  if ( fatmsg_enabled ) {
705  // fill fat msg
706  memcpy(&(fatmsg->velo), &vm, sizeof(vm));
707  fatmsg->valid_velo = 1;
708  }
709  } else {
710  if ( fatmsg_enabled ) {
711  fatmsg->valid_velo = 0;
712  }
713  }
714 
715  if ( rel_ball_changed ) {
717  bm.dist = rel_ball_dist;
718  bm.bearing = rel_ball_bearing;
719  bm.slope = rel_ball_slope;
720  bm.history = rel_ball_visibility_history;
721  bm.visible = rel_ball_visible ? -1 : 0;
722  memcpy(&(bm.covariance), rel_ball_covariance, sizeof(bm.covariance));
723 
724  rel_ball_changed = false;
725 
726  append_outbound(WORLDINFO_MSGTYPE_GLOBBALL, &bm, sizeof(bm));
727 
728  if ( fatmsg_enabled ) {
729  // fill fat msg
730  memcpy(&(fatmsg->relball_pos), &bm, sizeof(bm));
731  fatmsg->valid_relball_pos = 1;
732  }
733  } else {
734  if ( fatmsg_enabled ) {
735  fatmsg->valid_relball_pos = 0;
736  }
737  }
738 
739  if ( glob_ball_changed ) {
741  bm.x = glob_ball_x;
742  bm.y = glob_ball_y;
743  bm.z = glob_ball_z;
744  bm.history = glob_ball_visibility_history;
745  bm.visible = glob_ball_visible ? -1 : 0;
746  memcpy(&(bm.covariance), glob_ball_covariance, sizeof(bm.covariance));
747 
748  glob_ball_changed = false;
749 
750  append_outbound(WORLDINFO_MSGTYPE_GLOBBALL, &bm, sizeof(bm));
751  }
752 
753  if ( gamestate_changed ) {
754  append_outbound(WORLDINFO_MSGTYPE_GAMESTATE,
755  &gamestate_msg, sizeof(worldinfo_gamestate_message_t));
756  gamestate_changed = false;
757  }
758 
759  if ( rel_ball_vel_changed ) {
761  rbvm.vel_x = rel_ball_vel_x;
762  rbvm.vel_y = rel_ball_vel_y;
763  rbvm.vel_z = rel_ball_vel_z;
764  memcpy(&(rbvm.covariance), rel_ball_vel_covariance, sizeof(rbvm.covariance));
765  rel_ball_vel_changed = false;
766 
767  append_outbound(WORLDINFO_MSGTYPE_RELBALLVELO, &rbvm, sizeof(rbvm));
768 
769  if ( fatmsg_enabled ) {
770  // fill fat msg
771  memcpy(&(fatmsg->relball_velo), &rbvm, sizeof(rbvm));
772  fatmsg->valid_relball_velo = 1;
773  }
774  } else {
775  if ( fatmsg_enabled ) {
776  fatmsg->valid_relball_velo = 0;
777  }
778  }
779 
780  if ( glob_ball_vel_changed ) {
782  rbvm.vel_x = glob_ball_vel_x;
783  rbvm.vel_y = glob_ball_vel_y;
784  rbvm.vel_z = glob_ball_vel_z;
785  memcpy(&(rbvm.covariance), glob_ball_vel_covariance, sizeof(rbvm.covariance));
786  glob_ball_vel_changed = false;
787 
788  append_outbound(WORLDINFO_MSGTYPE_GLOBBALLVELO, &rbvm, sizeof(rbvm));
789  }
790 
791  // Append penalties
792  for (penit = penalties.begin(); penit != penalties.end(); ++penit) {
793  append_outbound(WORLDINFO_MSGTYPE_PENALTY,
794  &(penit->second), sizeof(worldinfo_penalty_message_t));
795  }
796  penalties.clear();
797 
798  // Append opponents
799  unsigned int num_opponents = 0;
800  for ( oppit = opponents.begin(); oppit != opponents.end(); ++oppit) {
802  opm.uid = (*oppit).uid;
803  opm.dist = (*oppit).distance;
804  opm.bearing = (*oppit).bearing;
805  memcpy(&(opm.covariance), (*oppit).covariance, sizeof(opm.covariance));
806 
807  append_outbound(WORLDINFO_MSGTYPE_OPP_POSE, &opm, sizeof(opm));
808 
809  if ( fatmsg_enabled ) {
810  if ( num_opponents < WORLDINFO_FATMSG_NUMOPPS ) {
811  // fill fat msg
812  memcpy(&(fatmsg->opponents[num_opponents]), &opm, sizeof(opm));
813  ++num_opponents;
814  fatmsg->num_opponents = num_opponents;
815  }
816  }
817  }
818  opponents.clear();
819 
820  for ( doppit = disappeared_opponents.begin(); doppit != disappeared_opponents.end(); ++doppit) {
822  opdm.uid = *doppit;
823 
824  append_outbound(WORLDINFO_MSGTYPE_OPP_DISAPP, &opdm, sizeof(opdm));
825  }
826  disappeared_opponents.clear();
827 
828  if ( outbound_num_msgs > 0 ) {
829  // send slim msgs
830  header->seq = htonl(out_seq++);
831 
832  encryptor->set_plain_buffer(out_buffer, outbound_bytes);
833  crypted_out_bytes = encryptor->encrypt();
834 
835  s->send(crypted_out_buffer, crypted_out_bytes);
836 
837  if ( fatmsg_enabled ) {
838  // send fat msg
839  fatmsg_header->seq = htonl(out_seq++);
840 
841  encryptor->set_plain_buffer(fatmsg_buf, fatmsg_bufsize);
842  crypted_out_bytes = encryptor->encrypt();
843 
844  s->send(crypted_out_buffer, crypted_out_bytes);
845  }
846  }
847 
848 }
849 
850 
851 /** Receive information.
852  * This checks if there is information on the network waiting to be received
853  * and if so receives and processes the information and dispatches it to all
854  * registered handlers. If you order it to block this method will block until
855  * information has been received and dispatched (useful if running in a
856  * thread).
857  *
858  * Received packets will be ignored if
859  * - they do not start with 0xBEEF
860  * - they are of an incompatible version
861  * - the sequence number is smaller or equal to an already received packet
862  * They will only be partially handled if
863  * - a packet has been truncated (truncated message is ignored)
864  * - an unknown message type is encountered (message is ignored)
865  * - a message size does not match the expected size for a given type (message is ignored)
866  *
867  * @param block set to true for blocking operation, in this case recv() will
868  * block until data is available, false for non-blocking operation where recv()
869  * will immediately return if there is no data available
870  * @param max_num_msgs maximum number of messages to process in a single
871  * call to recv(). Set to 0 for an unlimited number of messages per call (this
872  * can block for an infinite time if messages are coming in fast).
873  */
874 void
875 WorldInfoTransceiver::recv(bool block, unsigned int max_num_msgs)
876 {
877  if ( ! block ) {
878  if ( ! s->available() ) {
879  return;
880  }
881  }
882 
883  handlers.lock();
884 
885  unsigned int num_msgs = (max_num_msgs == 0 ? 0 : 1);
886  do {
887  struct sockaddr_in from;
888  socklen_t addr_len = sizeof(from);
889  size_t bytes = crypt_buffer_size;
890 
891  if ( max_num_msgs != 0 ) ++num_msgs;
892 
893  bytes = s->recv(crypted_in_buffer, bytes, (struct sockaddr *)&from, &addr_len);
894 
895  // skip message if it is looped
896  if (!loop) {
897  struct in_addr localhost;
898  ::inet_aton("127.0.0.1", &localhost);
899  if (from.sin_addr.s_addr == localhost.s_addr) {
900  continue;
901  }
902  }
903 
904  // decryptor decrypts to in_buffer, see constructor
905  decryptor->set_crypt_buffer(crypted_in_buffer, bytes);
906  try {
907  inbound_bytes = decryptor->decrypt();
908  } catch (MessageDecryptionException &e) {
909  //LibLogger::log_warn("WorldInfoTransceiver", "Message decryption failed, ignoring");
910  //LibLogger::log_warn("WorldInfoTransceiver", e);
911  continue;
912  }
913 
914  /*
915  cout << "Plain:";
916  for (size_t i = 0; i < inbound_bytes; ++i) {
917  unsigned int u = *((unsigned char *)in_buffer + i);
918  printf("%02x ", u);
919  }
920  cout << endl;
921  */
922 
923  // Process
924  worldinfo_header_t *header = (worldinfo_header_t *)in_buffer;
925  if ( ntohs(header->beef) != 0xBEEF ) {
926  // throw WorldInfoException("Incorrect message received, wrong key?");
927  //LibLogger::log_warn("WorldInfoTransceiver", "Invalid message received (no 0xBEEF), ignoring");
928  continue;
929  }
930 
931  if ( header->version != WORLDINFO_VERSION ) {
932  //LibLogger::log_warn("WorldInfoTransceiver", "Unsupported version of world info data received, ignoring");
933  continue;
934  }
935 
936  // Sequence number handling per client, IPv4 only, for IPv6 in the pre-128-bit era
937  // we would need a custom compare function
938  unsigned int cseq = ntohl(header->seq);
939  if ( sequence_numbers.find(from.sin_addr.s_addr) != sequence_numbers.end() ) {
940  if ( cseq <= sequence_numbers[from.sin_addr.s_addr] ) {
941  // Already received (loop) or replay attack, just ignore
942  //LibLogger::log_warn("WorldInfoTransceiver", "Received packet twice, ignoring");
943  continue;
944  }
945  }
946  sequence_numbers[from.sin_addr.s_addr] = cseq;
947  last_received_time[from.sin_addr.s_addr] = time(NULL);
948 
949  inbound_bytes -= sizeof(worldinfo_header_t);
950  inbound_buffer = (unsigned char *)in_buffer + sizeof(worldinfo_header_t);
951 
952  std::string hostname_s;
953  if ( ! resolver->resolve_address((struct sockaddr *)&from, sizeof(from), hostname_s) ) {
954  hostname_s = "unknown";
955  }
956  const char *hostname = hostname_s.c_str();
957 
958  // Go through messages
959  while ( inbound_bytes > 0 ) {
960  worldinfo_message_header_t *msgh = (worldinfo_message_header_t *)inbound_buffer;
961  inbound_bytes -= sizeof(worldinfo_message_header_t);
962  inbound_buffer += sizeof(worldinfo_message_header_t);
963  uint16_t msg_type = ntohs(msgh->type);
964  uint16_t msg_size = ntohs(msgh->size);
965  //printf("Message type: %u size: %u ntype: %u nsize: %u\n",
966  // msg_type, msg_size, msgh->type, msgh->size);
967  if ( inbound_bytes < msg_size ) {
968  //LibLogger::log_warn("WorldInfoTransceiver", "Truncated packet received or protocol "
969  // "error, ignoring rest of packet (got %zu bytes, but expected "
970  // "%zu bytes)", inbound_bytes, msg_size);
971  break;
972  }
973  switch ( msg_type ) {
975  if ( msg_size == sizeof(worldinfo_pose_message_t) ) {
976  worldinfo_pose_message_t *pose_msg = (worldinfo_pose_message_t *)inbound_buffer;
977  for ( hit = handlers.begin(); hit != handlers.end(); ++hit ) {
978  (*hit)->pose_rcvd(hostname,
979  pose_msg->x, pose_msg->y, pose_msg->theta,
980  pose_msg->covariance);
981  }
982  } else {
983  //LibLogger::log_warn("WorldInfoTransceiver", "Invalid pose message received "
984  // "(got %zu bytes but expected %zu bytes), ignoring",
985  // msg_size, sizeof(worldinfo_pose_message_t));
986  }
987  break;
988 
990  if ( msg_size == sizeof(worldinfo_velocity_message_t) ) {
991  worldinfo_velocity_message_t *velo_msg = (worldinfo_velocity_message_t *)inbound_buffer;
992  for ( hit = handlers.begin(); hit != handlers.end(); ++hit ) {
993  (*hit)->velocity_rcvd(hostname,
994  velo_msg->vel_x, velo_msg->vel_y, velo_msg->vel_theta,
995  velo_msg->covariance);
996  }
997  } else {
998  // LibLogger::log_warn("WorldInfoTransceiver", "Invalid velocity message received "
999  // "(got %zu bytes but expected %zu bytes), ignoring",
1000  // msg_size, sizeof(worldinfo_velocity_message_t));
1001  }
1002  break;
1003 
1005  if ( msg_size == sizeof(worldinfo_relballpos_message_t) ) {
1006  worldinfo_relballpos_message_t *ball_msg = (worldinfo_relballpos_message_t *)inbound_buffer;
1007  for ( hit = handlers.begin(); hit != handlers.end(); ++hit ) {
1008  (*hit)->ball_pos_rcvd(hostname,
1009  (ball_msg->visible == -1), ball_msg->history,
1010  ball_msg->dist, ball_msg->bearing, ball_msg->slope,
1011  ball_msg->covariance);
1012  }
1013  } else {
1014  //LibLogger::log_warn("WorldInfoTransceiver", "Invalid relative ball pos message received "
1015  // "(got %zu bytes but expected %zu bytes), ignoring",
1016  // msg_size, sizeof(worldinfo_relballpos_message_t));
1017  }
1018  break;
1019 
1021  if ( msg_size == sizeof(worldinfo_globballpos_message_t) ) {
1023  for ( hit = handlers.begin(); hit != handlers.end(); ++hit ) {
1024  (*hit)->global_ball_pos_rcvd(hostname,
1025  (ball_msg->visible == -1), ball_msg->history,
1026  ball_msg->x, ball_msg->y, ball_msg->z,
1027  ball_msg->covariance);
1028  }
1029  } else {
1030  //LibLogger::log_warn("WorldInfoTransceiver", "Invalid global ball pos message received "
1031  // "(got %zu bytes but expected %zu bytes), ignoring",
1032  // msg_size, sizeof(worldinfo_globballpos_message_t));
1033  }
1034  break;
1035 
1037  if ( msg_size == sizeof(worldinfo_relballvelo_message_t) ) {
1039  for ( hit = handlers.begin(); hit != handlers.end(); ++hit ) {
1040  (*hit)->ball_velocity_rcvd(hostname,
1041  bvel_msg->vel_x, bvel_msg->vel_y, bvel_msg->vel_z,
1042  bvel_msg->covariance);
1043  }
1044  } else {
1045  //LibLogger::log_warn("WorldInfoTransceiver", "Invalid relative ball velocity message received "
1046  // "(got %zu bytes but expected %zu bytes), ignoring",
1047  // msg_size, sizeof(worldinfo_relballvelo_message_t));
1048  }
1049  break;
1050 
1052  if ( msg_size == sizeof(worldinfo_globballvelo_message_t) ) {
1054  for ( hit = handlers.begin(); hit != handlers.end(); ++hit ) {
1055  (*hit)->global_ball_velocity_rcvd(hostname,
1056  bvel_msg->vel_x, bvel_msg->vel_y, bvel_msg->vel_z,
1057  bvel_msg->covariance);
1058  }
1059  } else {
1060  //LibLogger::log_warn("WorldInfoTransceiver", "Invalid global ball velocity message received "
1061  // "(got %zu bytes but expected %zu bytes), ignoring",
1062  // msg_size, sizeof(worldinfo_globballvelo_message_t));
1063  }
1064  break;
1065 
1067  if ( msg_size == sizeof(worldinfo_opppose_message_t) ) {
1068  worldinfo_opppose_message_t *oppp_msg = (worldinfo_opppose_message_t *)inbound_buffer;
1069  for ( hit = handlers.begin(); hit != handlers.end(); ++hit ) {
1070  (*hit)->opponent_pose_rcvd(hostname,
1071  oppp_msg->uid, oppp_msg->dist, oppp_msg->bearing,
1072  oppp_msg->covariance);
1073  }
1074  } else {
1075  //LibLogger::log_warn("WorldInfoTransceiver", "Invalid opponent pose message received "
1076  // "(got %zu bytes but expected %zu bytes), ignoring",
1077  // msg_size, sizeof(worldinfo_opppose_message_t));
1078  }
1079  break;
1080 
1082  if ( msg_size == sizeof(worldinfo_oppdisappeared_message_t) ) {
1084  for ( hit = handlers.begin(); hit != handlers.end(); ++hit ) {
1085  (*hit)->opponent_disapp_rcvd(hostname, oppd_msg->uid);
1086  }
1087  } else {
1088  //LibLogger::log_warn("WorldInfoTransceiver", "Invalid opponent disappeared message received "
1089  // "(got %zu bytes but expected %zu bytes), ignoring",
1090  // msg_size, sizeof(worldinfo_oppdisappeared_message_t));
1091  }
1092  break;
1093 
1095  if ( msg_size == sizeof(worldinfo_gamestate_message_t) ) {
1097  for ( hit = handlers.begin(); hit != handlers.end(); ++hit ) {
1098  (*hit)->gamestate_rcvd(hostname,
1099  gs_msg->game_state,
1101  gs_msg->score_cyan, gs_msg->score_magenta,
1104  (worldinfo_gamestate_half_t)gs_msg->half);
1105  }
1106  } else {
1107  //LibLogger::log_warn("WorldInfoTransceiver", "Invalid gamestate message received "
1108  // "(got %zu bytes but expected %zu bytes), ignoring",
1109  // msg_size, sizeof(worldinfo_gamestate_message_t));
1110  }
1111  break;
1112 
1114  if ( msg_size == sizeof(worldinfo_penalty_message_t) ) {
1115  worldinfo_penalty_message_t *p_msg = (worldinfo_penalty_message_t *)inbound_buffer;
1116  for ( hit = handlers.begin(); hit != handlers.end(); ++hit ) {
1117  (*hit)->penalty_rcvd(hostname,
1118  p_msg->player, p_msg->penalty, p_msg->seconds_remaining);
1119  }
1120 
1121  } else {
1122  //LibLogger::log_warn("WorldInfoTransceiver", "Invalid penalty message received "
1123  // "(got %zu bytes but expected %zu bytes), ignoring",
1124  // msg_size, sizeof(worldinfo_penalty_message_t));
1125  }
1126  break;
1127 
1129  if ( msg_size == sizeof(worldinfo_fat_message_t) ) {
1130  worldinfo_fat_message_t *fat_msg = (worldinfo_fat_message_t *)inbound_buffer;
1131  for ( hit = handlers.begin(); hit != handlers.end(); ++hit ) {
1132  if ( fat_msg->valid_pose ) {
1133  (*hit)->pose_rcvd(hostname,
1134  fat_msg->pose.x, fat_msg->pose.y, fat_msg->pose.theta,
1135  fat_msg->pose.covariance);
1136  }
1137 
1138  if ( fat_msg->valid_velo ) {
1139  (*hit)->velocity_rcvd(hostname,
1140  fat_msg->velo.vel_x, fat_msg->velo.vel_y,
1141  fat_msg->velo.vel_theta, fat_msg->velo.covariance);
1142  }
1143  if ( fat_msg->valid_relball_pos ) {
1144  (*hit)->ball_pos_rcvd(hostname,
1145  (fat_msg->relball_pos.visible == -1),
1146  fat_msg->relball_pos.history,
1147  fat_msg->relball_pos.dist, fat_msg->relball_pos.bearing,
1148  fat_msg->relball_pos.slope, fat_msg->relball_pos.covariance);
1149  }
1150  if ( fat_msg->valid_relball_velo ) {
1151  (*hit)->ball_velocity_rcvd(hostname,
1152  fat_msg->relball_velo.vel_x,
1153  fat_msg->relball_velo.vel_y,
1154  fat_msg->relball_velo.vel_z,
1155  fat_msg->relball_velo.covariance);
1156  }
1157 
1158  if ( fat_msg->num_opponents > WORLDINFO_FATMSG_NUMOPPS ) {
1159  // We can't handle this
1160  //LibLogger::log_warn("WorldInfoTransceiver", "Too many opponents marked valid in message "
1161  // "(got %zu but expected a maximum of %zu), ignoring",
1162  // fat_msg->num_opponents, WORLDINFO_FATMSG_NUMOPPS);
1163  } else {
1164  for ( unsigned int i = 0; i < fat_msg->num_opponents; ++i ) {
1165  (*hit)->opponent_pose_rcvd(hostname,
1166  fat_msg->opponents[i].uid,
1167  fat_msg->opponents[i].dist,
1168  fat_msg->opponents[i].bearing,
1169  fat_msg->opponents[i].covariance);
1170  }
1171  }
1172  } // end for each handler
1173  } else {
1174  //LibLogger::log_warn("WorldInfoTransceiver", "Invalid fat message received "
1175  // "(got %zu bytes but expected %zu bytes), ignoring",
1176  // msg_size, sizeof(worldinfo_fat_message_t));
1177  }
1178  break;
1179 
1180 
1181  //default:
1182  //LibLogger::log_warn("WorldInfoTransceiver", "Unknown message type %u received "
1183  // ", ignoring", msg_type);
1184  }
1185  // there is more to process
1186  inbound_bytes -= msg_size;
1187  inbound_buffer += msg_size;
1188  }
1189 
1190  } while ( s->available() && (num_msgs <= max_num_msgs) );
1191 
1192  handlers.unlock();
1193 }
1194 
1195 
1196 /** Get last sent plain buffer.
1197  * This method is meant to be used for debugging and testing purposes only.
1198  * @return last plain text message buffer
1199  */
1200 void *
1202 {
1203  return out_buffer;
1204 }
1205 
1206 
1207 /** Get last sent plain buffer size.
1208  * This method is meant to be used for debugging and testing purposes only.
1209  * @return last plain text message buffer size
1210  */
1211 size_t
1213 {
1214  return outbound_bytes;
1215 }
1216 
1217 
1218 /** Get last sent crypted buffer.
1219  * This method is meant to be used for debugging and testing purposes only.
1220  * @return last crytped message buffer
1221  */
1222 void *
1224 {
1225  return crypted_out_buffer;
1226 }
1227 
1228 
1229 /** Get last sent crypted buffer size.
1230  * This method is meant to be used for debugging and testing purposes only.
1231  * @return last crypted message buffer size
1232  */
1233 size_t
1235 {
1236  return crypted_out_bytes;
1237 }
1238 
1239 } // end namespace fawkes
float vel_z
relative velocity of the ball in z direction
Definition: messages.h:161
void set_rel_ball_pos(float dist, float bearing, float slope, float *covariance)
Set ball position.
void set_glob_ball_velocity(float vel_x, float vel_y, float vel_z, float *covariance)
Set global ball velocity.
Global ball position message.
Definition: messages.h:133
worldinfo_velocity_message_t velo
sending robot's velocity
Definition: messages.h:218
uint32_t state_team
Team the game state references.
Definition: messages.h:232
float y
Y coordinate.
Definition: messages.h:82
uint32_t valid_pose
1 if pose is valid, 0 otherwise
Definition: messages.h:211
Relative ball position message.
Definition: messages.h:110
World info handler.
Definition: handler.h:31
void clear_opponents()
Clear opponents list.
void add_disappeared_opponent(unsigned int uid)
Add disappeared opponent.
float covariance[WORLDINFO_COVARIANCE_SIZE_2X2]
opponent position covariance matrix
Definition: messages.h:193
void send()
Send information.
WorldInfoException(const char *msg)
Constructor.
Definition: transceiver.cpp:51
uint32_t our_goal_color
Our own goal color.
Definition: messages.h:236
uint32_t penalty
Penalty code, cf.
Definition: messages.h:247
float distance(float x1, float y1, float x2, float y2)
Get distance between two 2D cartesian coordinates.
Definition: angle.h:62
void set_team_goal(worldinfo_gamestate_team_t our_color, worldinfo_gamestate_goalcolor_t goal_color)
Set team and goal info.
float bearing
bearing to the ball, this is the angle between the robots forward direction and the ball on the groun...
Definition: messages.h:120
void set_half(worldinfo_gamestate_half_t half)
Set current half of the game time.
WorldInfo message decryptor.
Definition: decrypt.h:39
int32_t visible
-1 if ball visible, 0 otherwise.
Definition: messages.h:139
float vel_x
relative velocity of the ball in x direction
Definition: messages.h:159
void set_glob_ball_pos(float x, float y, float z, float *covariance)
Set global ball position.
Fawkes library namespace.
float covariance[WORLDINFO_COVARIANCE_SIZE_3X3]
ball velocity covariance matrix
Definition: messages.h:162
virtual size_t recv(void *buf, size_t buf_len)
Read from socket.
Definition: socket.cpp:628
uint32_t num_opponents
number of opponents with valid data in opponents
Definition: messages.h:215
void set_rel_ball_velocity(float vel_x, float vel_y, float vel_z, float *covariance)
Set ball velocity.
void set_loop(bool loop)
Set loopback of sent packets.
uint32_t valid_velo
1 if velo is valid, 0 otherwise
Definition: messages.h:212
size_t recommended_crypt_buffer_size()
Get recommended crypted buffer size.
Definition: encrypt.cpp:132
void set_plain_buffer(void *buffer, size_t buffer_length)
Set plain buffer.
Definition: encrypt.cpp:112
float slope
slope to the ball, this is the angle between the robots center position on the ground plane and the b...
Definition: messages.h:123
float covariance[WORLDINFO_COVARIANCE_SIZE_3X3]
ball covariance matrix
Definition: messages.h:125
Message decryption failed.
Definition: decrypt.h:32
void set_crypt_buffer(void *buffer, size_t buffer_length)
Set crypted buffer.
Definition: encrypt.cpp:156
Observed relative ball position.
Definition: messages.h:38
uint16_t beef
has to contain 0xBEEF in network byte order
Definition: messages.h:67
void set_plain_buffer(void *buffer, size_t buffer_length)
Set plain buffer.
Definition: decrypt.cpp:95
uint16_t size
message size in network byte order
Definition: messages.h:56
void add_opponent(unsigned int uid, float distance, float bearing, float *covariance)
Add opponent to transmit list.
World info header.
Definition: messages.h:66
virtual void bind()
Bind socket.
uint32_t player
Number of penalized robot.
Definition: messages.h:246
uint32_t score_magenta
Score of team magenta.
Definition: messages.h:234
uint32_t uid
unique ID of the disappeared opponent
Definition: messages.h:203
float vel_x
Velocity in X direction.
Definition: messages.h:95
virtual bool available()
Check if data is available.
Definition: socket.cpp:411
uint32_t valid_relball_velo
1 if relball_velo is valid, 0 otherwise
Definition: messages.h:214
worldinfo_gamestate_half_t
Game time half.
Definition: enums.h:70
uint32_t score_cyan
Score of team cyan.
Definition: messages.h:233
float dist
distance to the opponent.
Definition: messages.h:190
float x
x-coordinate of the global ball positions
Definition: messages.h:143
Global ball position.
Definition: messages.h:45
float vel_z
global velocity of the ball in z direction
Definition: messages.h:172
size_t last_sent_plain_buffer_size()
Get last sent plain buffer size.
uint32_t reserved
Reserved for future use.
Definition: messages.h:248
void add_penalty(unsigned int player, unsigned int penalty, unsigned int seconds_remaining)
Add penalty message.
worldinfo_opppose_message_t opponents[WORLDINFO_FATMSG_NUMOPPS]
best seen opponents
Definition: messages.h:221
Observed opponent pose.
Definition: messages.h:40
Observed opponent disappered.
Definition: messages.h:41
worldinfo_pose_message_t pose
sending robot's pose
Definition: messages.h:217
void set_pose(float x, float y, float theta, float *covariance)
Set global pose of robot.
Base class for exceptions in Fawkes.
Definition: exception.h:36
uint32_t half
Game time half.
Definition: messages.h:237
Use multicast socket for communication.
Definition: transceiver.h:57
void * last_sent_crypted_buffer()
Get last sent crypted buffer.
Fat worldinfo message.
Definition: messages.h:210
Multicast datagram socket.
Broadcast datagram socket.
void set_loop(bool loop)
Set loopback of sent packets.
float vel_theta
Rotational velocity.
Definition: messages.h:97
float vel_y
relative velocity of the ball in y direction
Definition: messages.h:160
void set_rel_ball_visible(bool visible, int visibility_history)
Set ball visibility.
float z
z-coordinate of the global ball positions
Definition: messages.h:145
Sending robot's velocity.
Definition: messages.h:37
void * last_sent_plain_buffer()
Get last sent plain buffer.
void rem_handler(WorldInfoHandler *h)
Remove handler for world information.
void set_score(unsigned int score_cyan, unsigned int score_magenta)
Set score.
virtual void bind()
Bind socket.
worldinfo_relballpos_message_t relball_pos
ball position relative to sending robot
Definition: messages.h:219
void recv(bool block=false, unsigned int max_num_msgs=0)
Receive information.
~WorldInfoTransceiver()
Destructor.
float covariance[WORLDINFO_COVARIANCE_SIZE_3X3]
velocity covariance matrix
Definition: messages.h:98
bool resolve_address(struct sockaddr *addr, socklen_t addr_len, std::string &name)
Resolve address.
Definition: resolver.cpp:250
uint32_t game_state
Current game state, can be freely chosen, worldinfo_gamestate_t provides recommended values for socce...
Definition: messages.h:229
Relative ball velocity message.
Definition: messages.h:158
Per-message header.
Definition: messages.h:54
Sending robot's pose.
Definition: messages.h:36
int32_t history
visibility history, positive means number of positive observations in a row, 0 means vision has just ...
Definition: messages.h:111
int32_t history
visibility history, positive means number of positive observations in a row, 0 means vision has just ...
Definition: messages.h:134
void flush_sequence_numbers(unsigned int sec)
Flush sequence numbers conditionally.
Network name and address resolver.
Definition: resolver.h:48
uint32_t valid_relball_pos
1 if relball_pos is valid, 0 otherwise
Definition: messages.h:213
float theta
orientation
Definition: messages.h:83
uint32_t seq
sequence number in network byte order
Definition: messages.h:70
void set_gamestate(int gamestate, worldinfo_gamestate_team_t state_team)
Set current game state.
worldinfo_gamestate_team_t
Team.
Definition: enums.h:54
uint32_t seconds_remaining
Estimate in seconds when unpenalized.
Definition: messages.h:249
Global ball velocity message.
Definition: messages.h:169
Robot velocity message.
Definition: messages.h:94
Robot pose message.
Definition: messages.h:80
WorldInfo message encryptor.
Definition: encrypt.h:38
Global ball velocity.
Definition: messages.h:46
worldinfo_relballvelo_message_t relball_velo
ball velocity relative to sending robot
Definition: messages.h:220
int32_t visible
-1 if ball visible, 0 otherwise.
Definition: messages.h:116
float covariance[WORLDINFO_COVARIANCE_SIZE_3X3]
position covariance matrix
Definition: messages.h:84
void set_glob_ball_visible(bool visible, int visibility_history)
Set ball visibility for the global ball.
virtual void send(void *buf, size_t buf_len)
Write to the socket.
Definition: socket.cpp:608
Observed relative ball velocity.
Definition: messages.h:39
void add_handler(WorldInfoHandler *h)
Add a handler for world information.
Fat message containing all the information,.
Definition: messages.h:42
float x
X coordinate.
Definition: messages.h:81
float vel_y
Velocity in Y direction.
Definition: messages.h:96
Use broadcase socket for communication.
Definition: transceiver.h:58
uint16_t type
message type in network byte order
Definition: messages.h:55
uint32_t uid
unique ID of this opponent
Definition: messages.h:189
Index out of bounds.
Definition: software.h:88
size_t last_sent_crypted_buffer_size()
Get last sent crypted buffer size.
void set_velocity(float vel_x, float vel_y, float vel_theta, float *covariance)
Set velocity of the robot.
float vel_y
global velocity of the ball in y direction
Definition: messages.h:171
float bearing
bearing to the opponent, this is the angle between the robots forward direction and the opponent on t...
Definition: messages.h:191
WorldInfoTransceiver(SocketType socket_type, const char *addr, unsigned short port, const char *key, const char *iv, NetworkNameResolver *resolver=NULL)
Constructor.
Definition: transceiver.cpp:99
float dist
distance to the robot
Definition: messages.h:122
worldinfo_gamestate_goalcolor_t
Goal color.
Definition: enums.h:63
float covariance[WORLDINFO_COVARIANCE_SIZE_3X3]
ball covariance matrix
Definition: messages.h:146
uint8_t version
version of the following content
Definition: messages.h:68
void set_crypt_buffer(void *buffer, size_t buffer_length)
Set crypted buffer.
Definition: decrypt.cpp:108
uint32_t our_team
Our team color.
Definition: messages.h:235
System ran out of memory and desired operation could not be fulfilled.
Definition: system.h:32
void append(const char *format,...)
Append messages to the message list.
Definition: exception.cpp:341
float covariance[WORLDINFO_COVARIANCE_SIZE_3X3]
ball velocity covariance matrix
Definition: messages.h:173
float y
y-coordinate of the global ball positions
Definition: messages.h:144
Socket exception.
Definition: socket.h:58
void set_fatmsg_enabled(bool fatmsg_enabled)
Enable or disable sending of fat message.
float vel_x
global velocity of the ball in x direction
Definition: messages.h:170