├── src ├── aux │ ├── __init__.py │ ├── hw_challenge_3.py │ ├── utils.py │ ├── hw_challenge_2.py │ ├── hw_challenge_4.py │ ├── hw_challenge_1.py │ ├── tc_ball_placement.py │ ├── challenge_aux.py │ ├── GCSocket.py │ ├── RobotBall.py │ ├── hw_challenge_fsm.py │ └── position_robot.py ├── json_examples │ ├── challenge_4.json │ ├── tc_bp_scenario_1.json │ ├── challenge_2.json │ ├── challenge_1.json │ └── challenge_3.json ├── ssl_wrapper_pb2.py ├── ssl_vision_wrapper_tracked_pb2.py ├── ssl_gc_geometry_pb2.py ├── ssl_gc_common_pb2.py ├── ProcessUDPData.py ├── ChallengeManager.py ├── ssl_vision_detection_pb2.py ├── DrawSSL.py ├── ssl_vision_detection_tracked_pb2.py ├── referee_pb2.py └── ssl_vision_geometry_pb2.py ├── resources ├── Days.ttf ├── positioning.gif └── view_example.png ├── update_protos.sh ├── protos ├── ssl_wrapper.proto ├── ssl_gc_geometry.proto ├── ssl_gc_common.proto ├── ssl_vision_wrapper_tracked.proto ├── ssl_vision_detection.proto ├── ssl_vision_detection_tracked.proto ├── ssl_vision_geometry.proto └── referee.proto ├── .gitignore └── README.md /src/aux/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /resources/Days.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RoboCup-SSL/ssl-hardware-challenge-tool/main/resources/Days.ttf -------------------------------------------------------------------------------- /resources/positioning.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RoboCup-SSL/ssl-hardware-challenge-tool/main/resources/positioning.gif -------------------------------------------------------------------------------- /resources/view_example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RoboCup-SSL/ssl-hardware-challenge-tool/main/resources/view_example.png -------------------------------------------------------------------------------- /update_protos.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/sh 2 | protoc -I=protos --python_out=src/ protos/*.proto 3 | echo "Proto files for python generated!" 4 | -------------------------------------------------------------------------------- /src/json_examples/challenge_4.json: -------------------------------------------------------------------------------- 1 | { 2 | "ball": { 3 | "pos": [ 4 | 0, 5 | 0, 6 | 0.0 7 | ] 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /protos/ssl_wrapper.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto2"; 2 | import "ssl_vision_detection.proto"; 3 | import "ssl_vision_geometry.proto"; 4 | 5 | message SSL_WrapperPacket { 6 | optional SSL_DetectionFrame detection = 1; 7 | optional SSL_GeometryData geometry = 2; 8 | optional uint64 packet_timestamp_fei=3; 9 | } 10 | -------------------------------------------------------------------------------- /src/json_examples/tc_bp_scenario_1.json: -------------------------------------------------------------------------------- 1 | { 2 | "ball": { 3 | "pos": [ 4 | -200, 5 | -1800, 6 | 0 7 | ] 8 | }, 9 | "ball_placement": { 10 | "pos": [ 11 | -660, 12 | -1140, 13 | 0 14 | ] 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /protos/ssl_gc_geometry.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto2"; 2 | 3 | package edu.tigers.sumatra.referee.proto; 4 | option go_package = "github.com/RoboCup-SSL/ssl-game-controller/internal/app/geom"; 5 | 6 | // A vector with two dimensions 7 | message Vector2 { 8 | required float x = 1; 9 | required float y = 2; 10 | } 11 | 12 | // A vector with three dimensions 13 | message Vector3 { 14 | required float x = 1; 15 | required float y = 2; 16 | required float z = 3; 17 | } 18 | -------------------------------------------------------------------------------- /protos/ssl_gc_common.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto2"; 2 | 3 | package edu.tigers.sumatra.referee.proto; 4 | option go_package = "github.com/RoboCup-SSL/ssl-game-controller/internal/app/state"; 5 | 6 | // Team is either blue or yellow 7 | enum Team { 8 | // team not set 9 | UNKNOWN = 0; 10 | // yellow team 11 | YELLOW = 1; 12 | // blue team 13 | BLUE = 2; 14 | } 15 | 16 | // RobotId is the combination of a team and a robot id 17 | message RobotId { 18 | // the robot number 19 | optional uint32 id = 1; 20 | // the team that the robot belongs to 21 | optional Team team = 2; 22 | } 23 | 24 | // Division denotes the current division, which influences some rules 25 | enum Division { 26 | DIV_UNKNOWN = 0; 27 | DIV_A = 1; 28 | DIV_B = 2; 29 | } 30 | -------------------------------------------------------------------------------- /src/json_examples/challenge_2.json: -------------------------------------------------------------------------------- 1 | { 2 | "ball": { 3 | "pos": [ 4 | -850, 5 | 0, 6 | 0 7 | ] 8 | }, 9 | "bots": [ 10 | { 11 | "obj": { 12 | "pos": [ 13 | -1000, 14 | 0, 15 | 0 16 | ] 17 | }, 18 | "id": { 19 | "number": 0, 20 | "color": "YELLOW" 21 | } 22 | }, 23 | { 24 | "obj": { 25 | "pos": [ 26 | -500, 27 | 0, 28 | 3.14 29 | ] 30 | }, 31 | "id": { 32 | "number": 0, 33 | "color": "BLUE" 34 | } 35 | } 36 | ] 37 | } 38 | -------------------------------------------------------------------------------- /protos/ssl_vision_wrapper_tracked.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto2"; 2 | 3 | option java_package = "edu.tigers.sumatra.wp.proto"; 4 | option go_package = "github.com/RoboCup-SSL/ssl-game-controller/internal/app/tracker"; 5 | 6 | import "ssl_vision_detection_tracked.proto"; 7 | 8 | // A wrapper packet containing meta data of the source 9 | // Also serves for the possibility to extend the protocol later 10 | message TrackerWrapperPacket { 11 | // A random UUID of the source that is kept constant at the source while running 12 | // If multiple sources are broadcasting to the same network, this id can be used to identify individual sources 13 | required string uuid = 1; 14 | // The name of the source software that is producing this messages. 15 | optional string source_name = 2; 16 | // The tracked frame 17 | optional TrackedFrame tracked_frame = 3; 18 | } 19 | -------------------------------------------------------------------------------- /src/aux/hw_challenge_3.py: -------------------------------------------------------------------------------- 1 | from aux.challenge_aux import ChallengeSteps, ChallengeEvents, Action 2 | from aux.GCSocket import GCCommands 3 | 4 | 5 | class Challenge_3(object): 6 | max_steps = 2 7 | id = 3 8 | max_attack_robots = 0 # The robot is in the json file 9 | min_attack_robots = 0 10 | has_extra_data = False 11 | 12 | @staticmethod 13 | def Step(step: ChallengeSteps) -> Action: 14 | if step == ChallengeSteps.STEP_0: 15 | return Action(False) 16 | elif step == ChallengeSteps.STEP_1: 17 | return Challenge_3.Step_1() 18 | elif step == ChallengeSteps.STEP_2: 19 | return Challenge_3.Step_2() 20 | 21 | @staticmethod 22 | def Step_1() -> Action: 23 | return Action(True, command=GCCommands.FORCE_START) 24 | 25 | @staticmethod 26 | def Step_2() -> Action: 27 | return Action(False, timer=120) 28 | -------------------------------------------------------------------------------- /src/aux/utils.py: -------------------------------------------------------------------------------- 1 | RED = "\033[0;31m" 2 | BLUE = "\033[0;34m" 3 | GREEN = "\033[0;92m" 4 | PURPLE = "\033[0;95m" 5 | RESET = "\033[0m" 6 | 7 | 8 | def red_print(*kargs): 9 | print(RED, end="") 10 | end_c = '\n' 11 | if kargs[-1] == '\r': 12 | end_c = '\r' 13 | print(*kargs, end=end_c) 14 | print(RESET, end="") 15 | 16 | 17 | def blue_print(*kargs): 18 | print(BLUE, end="") 19 | end_c = '\n' 20 | if kargs[-1] == '\r': 21 | end_c = '\r' 22 | print(*kargs, end=end_c) 23 | print(RESET, end="") 24 | 25 | 26 | def green_print(*kargs): 27 | print(GREEN, end="") 28 | end_c = '\n' 29 | if kargs[-1] == '\r': 30 | end_c = '\r' 31 | print(*kargs, end=end_c) 32 | print(RESET, end="") 33 | 34 | 35 | def purple_print(*kargs): 36 | print(PURPLE, end="") 37 | end_c = '\n' 38 | if kargs[-1] == '\r': 39 | end_c = '\r' 40 | print(*kargs, end=end_c) 41 | print(RESET, end="") 42 | -------------------------------------------------------------------------------- /src/json_examples/challenge_1.json: -------------------------------------------------------------------------------- 1 | { 2 | "ball": { 3 | "pos": [ 4 | -200, 5 | -1800, 6 | 0 7 | ] 8 | }, 9 | "bots": [ 10 | { 11 | "obj": { 12 | "pos": [ 13 | -2900, 14 | 0, 15 | -0.785398 16 | ] 17 | }, 18 | "id": { 19 | "number": 0, 20 | "color": "YELLOW" 21 | } 22 | }, 23 | { 24 | "obj": { 25 | "pos": [ 26 | -2000, 27 | -750, 28 | 0 29 | ] 30 | }, 31 | "id": { 32 | "number": 1, 33 | "color": "YELLOW" 34 | } 35 | }, 36 | { 37 | "obj": { 38 | "pos": [ 39 | -2000, 40 | -550, 41 | 0 42 | ] 43 | }, 44 | "id": { 45 | "number": 2, 46 | "color": "YELLOW" 47 | } 48 | } 49 | ] 50 | } 51 | -------------------------------------------------------------------------------- /protos/ssl_vision_detection.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto2"; 2 | option go_package = "github.com/RoboCup-SSL/ssl-simulation-protocol/pkg/sim"; 3 | 4 | message SSL_DetectionBall { 5 | required float confidence = 1; 6 | optional uint32 area = 2; 7 | required float x = 3; 8 | required float y = 4; 9 | optional float z = 5; 10 | required float pixel_x = 6; 11 | required float pixel_y = 7; 12 | } 13 | 14 | message SSL_DetectionRobot { 15 | required float confidence = 1; 16 | optional uint32 robot_id = 2; 17 | required float x = 3; 18 | required float y = 4; 19 | optional float orientation = 5; 20 | required float pixel_x = 6; 21 | required float pixel_y = 7; 22 | optional float height = 8; 23 | } 24 | 25 | message SSL_DetectionFrame { 26 | required uint32 frame_number = 1; 27 | required double t_capture = 2; 28 | required double t_sent = 3; 29 | required uint32 camera_id = 4; 30 | repeated SSL_DetectionBall balls = 5; 31 | repeated SSL_DetectionRobot robots_yellow = 6; 32 | repeated SSL_DetectionRobot robots_blue = 7; 33 | } 34 | -------------------------------------------------------------------------------- /src/aux/hw_challenge_2.py: -------------------------------------------------------------------------------- 1 | from aux.challenge_aux import ChallengeSteps, ChallengeEvents, Action 2 | from aux.GCSocket import GCCommands 3 | from aux.RobotBall import Position 4 | 5 | 6 | class Challenge_2(object): 7 | max_steps = 4 8 | id = 2 9 | max_attack_robots = 0 10 | min_attack_robots = 0 11 | has_extra_data = False 12 | 13 | @staticmethod 14 | def Step(step: ChallengeSteps) -> Action: 15 | if step == ChallengeSteps.STEP_0: 16 | return Action(False) 17 | elif step == ChallengeSteps.STEP_1: 18 | return Challenge_2.Step_1() 19 | elif step == ChallengeSteps.STEP_2: 20 | return Challenge_2.Step_2() 21 | elif step == ChallengeSteps.STEP_3: 22 | return Challenge_2.Step_3() 23 | elif step == ChallengeSteps.STEP_4: 24 | return Challenge_2.Step_4() 25 | 26 | @staticmethod 27 | def Step_1() -> Action: 28 | return Action(False, command=GCCommands.STOP) 29 | 30 | @staticmethod 31 | def Step_2() -> Action: 32 | return Action(False, timer=0.5) 33 | 34 | @staticmethod 35 | def Step_3() -> Action: 36 | return Action(True, command=GCCommands.FORCE_START) 37 | 38 | @staticmethod 39 | def Step_4() -> Action: 40 | return Action(False, timer=30) 41 | -------------------------------------------------------------------------------- /src/aux/hw_challenge_4.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from aux.challenge_aux import ChallengeSteps, ChallengeEvents, Action 3 | from aux.GCSocket import GCCommands 4 | from aux.RobotBall import Robot, DISTANCE_THRESHOLD 5 | 6 | 7 | class Challenge_4(object): 8 | max_steps = 2 9 | id = 4 10 | max_attack_robots = 6 11 | min_attack_robots = 3 12 | has_extra_data = True 13 | robots_restriction = 'MiddleLine' 14 | 15 | @staticmethod 16 | def Step(step: ChallengeSteps) -> Action: 17 | if step == ChallengeSteps.STEP_0: 18 | return Action(False) 19 | elif step == ChallengeSteps.STEP_1: 20 | return Challenge_4.Step_1() 21 | elif step == ChallengeSteps.STEP_2: 22 | return Challenge_4.Step_2() 23 | 24 | @staticmethod 25 | def Step_1() -> Action: 26 | return Action(True, command=GCCommands.FORCE_START) 27 | 28 | @staticmethod 29 | def Step_2() -> Action: 30 | return Action(False, timer=300) 31 | 32 | @staticmethod 33 | def check_restriction(robots: [Robot]) -> (bool, int): 34 | away_from_line = [1 for bot in robots 35 | if abs(bot.pos.x) > 3*DISTANCE_THRESHOLD and 36 | bot.in_vision()] 37 | 38 | if np.sum(np.array(away_from_line)) > 0: 39 | return False, 0 40 | return True, 0 41 | -------------------------------------------------------------------------------- /src/aux/hw_challenge_1.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from aux.challenge_aux import ChallengeSteps, ChallengeEvents, Action 3 | from aux.GCSocket import GCCommands 4 | from aux.RobotBall import Robot, DISTANCE_THRESHOLD 5 | 6 | 7 | class Challenge_1(object): 8 | max_steps = 4 9 | id = 1 10 | max_attack_robots = 3 11 | min_attack_robots = 1 12 | has_extra_data = True 13 | robots_restriction = 'MiddleLine' 14 | 15 | @staticmethod 16 | def Step(step: ChallengeSteps) -> Action: 17 | if step == ChallengeSteps.STEP_0: 18 | return Action(False) 19 | elif step == ChallengeSteps.STEP_1: 20 | return Challenge_1.Step_1() 21 | elif step == ChallengeSteps.STEP_2: 22 | return Challenge_1.Step_2() 23 | elif step == ChallengeSteps.STEP_3: 24 | return Challenge_1.Step_3() 25 | elif step == ChallengeSteps.STEP_4: 26 | return Challenge_1.Step_4() 27 | 28 | @staticmethod 29 | def Step_1() -> Action: 30 | return Action(False, command=GCCommands.STOP) 31 | 32 | @staticmethod 33 | def Step_2() -> Action: 34 | return Action(False, timer=5) 35 | 36 | @staticmethod 37 | def Step_3() -> Action: 38 | return Action(True, command=GCCommands.FREE_KICK) 39 | 40 | @staticmethod 41 | def Step_4() -> Action: 42 | return Action(False, timer=20) 43 | 44 | @staticmethod 45 | def check_restriction(robots: [Robot]) -> (bool, int): 46 | away_from_line = [1 for bot in robots 47 | if abs(bot.pos.x) > 100 and 48 | bot.in_vision()] 49 | 50 | if np.sum(np.array(away_from_line)) > 0: 51 | return False, 0 52 | return True, 0 53 | -------------------------------------------------------------------------------- /src/aux/tc_ball_placement.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from aux.challenge_aux import ChallengeSteps, ChallengeEvents, Action 3 | from aux.GCSocket import GCCommands 4 | from aux.RobotBall import Robot, DISTANCE_THRESHOLD 5 | 6 | 7 | class BallPlacement(object): 8 | max_steps = 4 9 | id = 5 10 | max_attack_robots = 6 11 | min_attack_robots = 1 12 | has_extra_data = True 13 | robots_restriction = 'MiddleLine' 14 | 15 | @staticmethod 16 | def Step(step: ChallengeSteps) -> Action: 17 | if step == ChallengeSteps.STEP_0: 18 | return Action(False) 19 | elif step == ChallengeSteps.STEP_1: 20 | return BallPlacement.Step_1() 21 | elif step == ChallengeSteps.STEP_2: 22 | return BallPlacement.Step_2() 23 | elif step == ChallengeSteps.STEP_3: 24 | return BallPlacement.Step_3() 25 | elif step == ChallengeSteps.STEP_4: 26 | return BallPlacement.Step_4() 27 | 28 | @staticmethod 29 | def Step_1() -> Action: 30 | return Action(False, command=GCCommands.STOP) 31 | 32 | @staticmethod 33 | def Step_2() -> Action: 34 | return Action(False, timer=2) 35 | 36 | @staticmethod 37 | def Step_3() -> Action: 38 | return Action(True, command=GCCommands.BALL_PLACEMENT) 39 | 40 | @staticmethod 41 | def Step_4() -> Action: 42 | return Action(False, timer=30) 43 | 44 | @staticmethod 45 | def check_restriction(robots: [Robot]) -> (bool, int): 46 | away_from_line = [1 for bot in robots 47 | if abs(bot.pos.x) > DISTANCE_THRESHOLD and 48 | bot.in_vision()] 49 | 50 | if np.sum(np.array(away_from_line)) > 0: 51 | return False, 0 52 | return True, 0 53 | -------------------------------------------------------------------------------- /src/aux/challenge_aux.py: -------------------------------------------------------------------------------- 1 | from enum import Enum 2 | from aux.GCSocket import GCCommands 3 | 4 | 5 | class ChallengeSteps(Enum): 6 | """ 7 | Each challenge is composed of n steps: 8 | - Challenge 1 9 | - Step 1: Send Stop 10 | - Step 2: Wait for 5s 11 | - Step 3: Send FreeKick 12 | - Step 4: Wait until goal or 20s 13 | 14 | - Challenge 2 15 | - Step 1: Send ForceStart 16 | - Step 2: Wait until goal or 30s 17 | 18 | - Challenge 3 19 | - Step 1: Send ForceStart 20 | - Step 2: Wait until the robot completely stops or 2min 21 | 22 | - Challenge 4 23 | - Step 1: Send ForceStart 24 | - Step 2: Wait until 5min 25 | """ 26 | STEP_0 = 0 27 | STEP_1 = 1 28 | STEP_2 = 2 29 | STEP_3 = 3 30 | STEP_4 = 4 31 | 32 | @staticmethod 33 | def next_step(step): 34 | if step == ChallengeSteps.STEP_0: 35 | return ChallengeSteps.STEP_1 36 | 37 | if step == ChallengeSteps.STEP_1: 38 | return ChallengeSteps.STEP_2 39 | 40 | if step == ChallengeSteps.STEP_2: 41 | return ChallengeSteps.STEP_3 42 | 43 | if step == ChallengeSteps.STEP_3: 44 | return ChallengeSteps.STEP_4 45 | 46 | if step == ChallengeSteps.STEP_4: 47 | return ChallengeSteps.STEP_0 48 | 49 | 50 | class ChallengeEvents(Enum): 51 | GOAL = 0, 52 | ROBOT_STOPPED = 1 53 | STOP = 2 54 | 55 | 56 | class Action(object): 57 | def __init__(self, start_timer=False, command=GCCommands.NONE, timer=0): 58 | self.start_timer = start_timer 59 | self.command = command 60 | self.timer = timer # in seconds 61 | 62 | def set_action(self, start_timer: bool, command=GCCommands.NONE, timer=0): 63 | self.execute = start_timer 64 | self.command = command 65 | self.timer = timer 66 | -------------------------------------------------------------------------------- /src/json_examples/challenge_3.json: -------------------------------------------------------------------------------- 1 | { 2 | "ball": { 3 | "pos": [ 4 | -1500, 5 | -1500, 6 | 0.0 7 | ] 8 | }, 9 | "bots": [ 10 | { 11 | "obj": { 12 | "pos": [ 13 | -1500, 14 | 1500, 15 | 0 16 | ] 17 | }, 18 | "id": { 19 | "number": 0, 20 | "color": "YELLOW" 21 | } 22 | }, 23 | { 24 | "obj": { 25 | "pos": [ 26 | -1500, 27 | 900, 28 | 0 29 | ] 30 | }, 31 | "id": { 32 | "number": 1, 33 | "color": "YELLOW" 34 | } 35 | }, 36 | { 37 | "obj": { 38 | "pos": [ 39 | -1500, 40 | 400, 41 | 0 42 | ] 43 | }, 44 | "id": { 45 | "number": 2, 46 | "color": "YELLOW" 47 | } 48 | }, 49 | { 50 | "obj": { 51 | "pos": [ 52 | -1500, 53 | -200, 54 | 0 55 | ] 56 | }, 57 | "id": { 58 | "number": 3, 59 | "color": "YELLOW" 60 | } 61 | }, 62 | { 63 | "obj": { 64 | "pos": [ 65 | -1500, 66 | -1000, 67 | 0 68 | ] 69 | }, 70 | "id": { 71 | "number": 4, 72 | "color": "YELLOW" 73 | } 74 | }, 75 | { 76 | "obj": { 77 | "pos": [ 78 | -1500, 79 | -1900, 80 | 1.57 81 | ] 82 | }, 83 | "id": { 84 | "number": 0, 85 | "color": "BLUE" 86 | } 87 | } 88 | ] 89 | } 90 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # pipenv 88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 91 | # install all needed dependencies. 92 | #Pipfile.lock 93 | 94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 95 | __pypackages__/ 96 | 97 | # Celery stuff 98 | celerybeat-schedule 99 | celerybeat.pid 100 | 101 | # SageMath parsed files 102 | *.sage.py 103 | 104 | # Environments 105 | .env 106 | .venv 107 | env/ 108 | venv/ 109 | ENV/ 110 | env.bak/ 111 | venv.bak/ 112 | 113 | # Spyder project settings 114 | .spyderproject 115 | .spyproject 116 | 117 | # Rope project settings 118 | .ropeproject 119 | 120 | # mkdocs documentation 121 | /site 122 | 123 | # mypy 124 | .mypy_cache/ 125 | .dmypy.json 126 | dmypy.json 127 | 128 | # Pyre type checker 129 | .pyre/ 130 | 131 | # IntelliJ 132 | .idea 133 | -------------------------------------------------------------------------------- /src/aux/GCSocket.py: -------------------------------------------------------------------------------- 1 | import websocket 2 | import time 3 | from enum import Enum 4 | 5 | from aux.RobotBall import BLUE_TEAM, YELLOW_TEAM 6 | from aux.utils import red_print, blue_print, green_print, purple_print 7 | 8 | WEB_SOCKET_URL = 'ws://localhost:8081/api/control' 9 | 10 | # websocket.enableTrace(True) 11 | 12 | 13 | class GCCommands(Enum): 14 | NONE = 0 15 | HALT = 1 16 | STOP = 2 17 | FORCE_START = 3 18 | FREE_KICK = 4 19 | BALL_PLACEMENT = 5 20 | 21 | 22 | class GCSocket(object): 23 | def __init__(self): 24 | self.w_socket = None 25 | self.RETRY_LIMIT = 20 26 | self.placement_pos = [0.0, 0.0] 27 | 28 | while not self.connect_web_socket() and self.RETRY_LIMIT > 0: 29 | self.RETRY_LIMIT -= 1 30 | time.sleep(1) 31 | 32 | if self.RETRY_LIMIT == 0: 33 | red_print( 34 | '[W Socket] Connect to web socket failed too many times, exiting...') 35 | exit(1) 36 | green_print('[W Socket] Connected to the GC socket!') 37 | 38 | def __del__(self): 39 | if self.w_socket != None: 40 | self.w_socket.close() 41 | 42 | def connect_web_socket(self) -> bool: 43 | try: 44 | self.w_socket = websocket.create_connection(WEB_SOCKET_URL) 45 | return True 46 | except ConnectionRefusedError: 47 | red_print( 48 | '[W Socket] Failed to connect to the Game Controller! Make sure the Port is correct') 49 | except Exception as expt: 50 | red_print('[W Socket]', expt) 51 | blue_print('Trying again...') 52 | return False 53 | 54 | def set_placement_pos(self, pos: [int, int]): 55 | for n, coordinate in enumerate(pos): 56 | self.placement_pos[n] = coordinate/1e3 57 | 58 | def send_command(self, gc_command: GCCommands, team=None) -> bool: 59 | if team == None or (team != BLUE_TEAM and team != YELLOW_TEAM): 60 | team = 'UNKNOWN' 61 | 62 | # Must send STOP before ForceStart ou Direct 63 | if gc_command == GCCommands.FREE_KICK or gc_command == GCCommands.FORCE_START: 64 | self.send_command(GCCommands.STOP) 65 | 66 | if gc_command.name == 'FREE_KICK': 67 | cmd_str = 'DIRECT' 68 | if team == None: 69 | raise ValueError( 70 | 'The command {} must have a team associated, got {}'.format(cmd_str, team)) 71 | else: 72 | cmd_str = gc_command.name 73 | 74 | if gc_command == GCCommands.BALL_PLACEMENT: 75 | if team == None: 76 | raise ValueError( 77 | f'The command {cmd_str} must have a team associated, got {team}') 78 | 79 | purple_print( 80 | f'Set placement position = [{self.placement_pos[0]}, {self.placement_pos[1]}]') 81 | data = '"x":{},"y":{}'.format(self.placement_pos[0], 82 | self.placement_pos[1]) 83 | prepare_placement = '{"change":{"origin":"UI","revertible":true,"setBallPlacementPos":{"pos":{' + data + '}}}}' 84 | self.w_socket.send(prepare_placement) 85 | 86 | try: 87 | cmd_str = '{"change":{"newCommand":{"command":{"type":"' + \ 88 | cmd_str + '","forTeam":"' + team + '"}},"origin":"UI"}}' 89 | self.w_socket.send(cmd_str) 90 | return True 91 | 92 | except Exception as expt: 93 | red_print('[W Socket]', expt, type(expt)) 94 | 95 | return False 96 | -------------------------------------------------------------------------------- /src/ssl_wrapper_pb2.py: -------------------------------------------------------------------------------- 1 | # Generated by the protocol buffer compiler. DO NOT EDIT! 2 | # source: ssl_wrapper.proto 3 | 4 | import sys 5 | _b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) 6 | from google.protobuf import descriptor as _descriptor 7 | from google.protobuf import message as _message 8 | from google.protobuf import reflection as _reflection 9 | from google.protobuf import symbol_database as _symbol_database 10 | # @@protoc_insertion_point(imports) 11 | 12 | _sym_db = _symbol_database.Default() 13 | 14 | 15 | import ssl_vision_detection_pb2 as ssl__vision__detection__pb2 16 | import ssl_vision_geometry_pb2 as ssl__vision__geometry__pb2 17 | 18 | 19 | DESCRIPTOR = _descriptor.FileDescriptor( 20 | name='ssl_wrapper.proto', 21 | package='', 22 | syntax='proto2', 23 | serialized_options=None, 24 | serialized_pb=_b('\n\x11ssl_wrapper.proto\x1a\x1assl_vision_detection.proto\x1a\x19ssl_vision_geometry.proto\"~\n\x11SSL_WrapperPacket\x12&\n\tdetection\x18\x01 \x01(\x0b\x32\x13.SSL_DetectionFrame\x12#\n\x08geometry\x18\x02 \x01(\x0b\x32\x11.SSL_GeometryData\x12\x1c\n\x14packet_timestamp_fei\x18\x03 \x01(\x04') 25 | , 26 | dependencies=[ssl__vision__detection__pb2.DESCRIPTOR,ssl__vision__geometry__pb2.DESCRIPTOR,]) 27 | 28 | 29 | 30 | 31 | _SSL_WRAPPERPACKET = _descriptor.Descriptor( 32 | name='SSL_WrapperPacket', 33 | full_name='SSL_WrapperPacket', 34 | filename=None, 35 | file=DESCRIPTOR, 36 | containing_type=None, 37 | fields=[ 38 | _descriptor.FieldDescriptor( 39 | name='detection', full_name='SSL_WrapperPacket.detection', index=0, 40 | number=1, type=11, cpp_type=10, label=1, 41 | has_default_value=False, default_value=None, 42 | message_type=None, enum_type=None, containing_type=None, 43 | is_extension=False, extension_scope=None, 44 | serialized_options=None, file=DESCRIPTOR), 45 | _descriptor.FieldDescriptor( 46 | name='geometry', full_name='SSL_WrapperPacket.geometry', index=1, 47 | number=2, type=11, cpp_type=10, label=1, 48 | has_default_value=False, default_value=None, 49 | message_type=None, enum_type=None, containing_type=None, 50 | is_extension=False, extension_scope=None, 51 | serialized_options=None, file=DESCRIPTOR), 52 | _descriptor.FieldDescriptor( 53 | name='packet_timestamp_fei', full_name='SSL_WrapperPacket.packet_timestamp_fei', index=2, 54 | number=3, type=4, cpp_type=4, label=1, 55 | has_default_value=False, default_value=0, 56 | message_type=None, enum_type=None, containing_type=None, 57 | is_extension=False, extension_scope=None, 58 | serialized_options=None, file=DESCRIPTOR), 59 | ], 60 | extensions=[ 61 | ], 62 | nested_types=[], 63 | enum_types=[ 64 | ], 65 | serialized_options=None, 66 | is_extendable=False, 67 | syntax='proto2', 68 | extension_ranges=[], 69 | oneofs=[ 70 | ], 71 | serialized_start=76, 72 | serialized_end=202, 73 | ) 74 | 75 | _SSL_WRAPPERPACKET.fields_by_name['detection'].message_type = ssl__vision__detection__pb2._SSL_DETECTIONFRAME 76 | _SSL_WRAPPERPACKET.fields_by_name['geometry'].message_type = ssl__vision__geometry__pb2._SSL_GEOMETRYDATA 77 | DESCRIPTOR.message_types_by_name['SSL_WrapperPacket'] = _SSL_WRAPPERPACKET 78 | _sym_db.RegisterFileDescriptor(DESCRIPTOR) 79 | 80 | SSL_WrapperPacket = _reflection.GeneratedProtocolMessageType('SSL_WrapperPacket', (_message.Message,), dict( 81 | DESCRIPTOR = _SSL_WRAPPERPACKET, 82 | __module__ = 'ssl_wrapper_pb2' 83 | # @@protoc_insertion_point(class_scope:SSL_WrapperPacket) 84 | )) 85 | _sym_db.RegisterMessage(SSL_WrapperPacket) 86 | 87 | 88 | # @@protoc_insertion_point(module_scope) 89 | -------------------------------------------------------------------------------- /src/ssl_vision_wrapper_tracked_pb2.py: -------------------------------------------------------------------------------- 1 | # Generated by the protocol buffer compiler. DO NOT EDIT! 2 | # source: ssl_vision_wrapper_tracked.proto 3 | 4 | import sys 5 | _b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) 6 | from google.protobuf import descriptor as _descriptor 7 | from google.protobuf import message as _message 8 | from google.protobuf import reflection as _reflection 9 | from google.protobuf import symbol_database as _symbol_database 10 | # @@protoc_insertion_point(imports) 11 | 12 | _sym_db = _symbol_database.Default() 13 | 14 | 15 | import ssl_vision_detection_tracked_pb2 as ssl__vision__detection__tracked__pb2 16 | 17 | 18 | DESCRIPTOR = _descriptor.FileDescriptor( 19 | name='ssl_vision_wrapper_tracked.proto', 20 | package='', 21 | syntax='proto2', 22 | serialized_options=_b('\n\033edu.tigers.sumatra.wp.protoZ?github.com/RoboCup-SSL/ssl-game-controller/internal/app/tracker'), 23 | serialized_pb=_b('\n ssl_vision_wrapper_tracked.proto\x1a\"ssl_vision_detection_tracked.proto\"_\n\x14TrackerWrapperPacket\x12\x0c\n\x04uuid\x18\x01 \x02(\t\x12\x13\n\x0bsource_name\x18\x02 \x01(\t\x12$\n\rtracked_frame\x18\x03 \x01(\x0b\x32\r.TrackedFrameB^\n\x1b\x65\x64u.tigers.sumatra.wp.protoZ?github.com/RoboCup-SSL/ssl-game-controller/internal/app/tracker') 24 | , 25 | dependencies=[ssl__vision__detection__tracked__pb2.DESCRIPTOR,]) 26 | 27 | 28 | 29 | 30 | _TRACKERWRAPPERPACKET = _descriptor.Descriptor( 31 | name='TrackerWrapperPacket', 32 | full_name='TrackerWrapperPacket', 33 | filename=None, 34 | file=DESCRIPTOR, 35 | containing_type=None, 36 | fields=[ 37 | _descriptor.FieldDescriptor( 38 | name='uuid', full_name='TrackerWrapperPacket.uuid', index=0, 39 | number=1, type=9, cpp_type=9, label=2, 40 | has_default_value=False, default_value=_b("").decode('utf-8'), 41 | message_type=None, enum_type=None, containing_type=None, 42 | is_extension=False, extension_scope=None, 43 | serialized_options=None, file=DESCRIPTOR), 44 | _descriptor.FieldDescriptor( 45 | name='source_name', full_name='TrackerWrapperPacket.source_name', index=1, 46 | number=2, type=9, cpp_type=9, label=1, 47 | has_default_value=False, default_value=_b("").decode('utf-8'), 48 | message_type=None, enum_type=None, containing_type=None, 49 | is_extension=False, extension_scope=None, 50 | serialized_options=None, file=DESCRIPTOR), 51 | _descriptor.FieldDescriptor( 52 | name='tracked_frame', full_name='TrackerWrapperPacket.tracked_frame', index=2, 53 | number=3, type=11, cpp_type=10, label=1, 54 | has_default_value=False, default_value=None, 55 | message_type=None, enum_type=None, containing_type=None, 56 | is_extension=False, extension_scope=None, 57 | serialized_options=None, file=DESCRIPTOR), 58 | ], 59 | extensions=[ 60 | ], 61 | nested_types=[], 62 | enum_types=[ 63 | ], 64 | serialized_options=None, 65 | is_extendable=False, 66 | syntax='proto2', 67 | extension_ranges=[], 68 | oneofs=[ 69 | ], 70 | serialized_start=72, 71 | serialized_end=167, 72 | ) 73 | 74 | _TRACKERWRAPPERPACKET.fields_by_name['tracked_frame'].message_type = ssl__vision__detection__tracked__pb2._TRACKEDFRAME 75 | DESCRIPTOR.message_types_by_name['TrackerWrapperPacket'] = _TRACKERWRAPPERPACKET 76 | _sym_db.RegisterFileDescriptor(DESCRIPTOR) 77 | 78 | TrackerWrapperPacket = _reflection.GeneratedProtocolMessageType('TrackerWrapperPacket', (_message.Message,), dict( 79 | DESCRIPTOR = _TRACKERWRAPPERPACKET, 80 | __module__ = 'ssl_vision_wrapper_tracked_pb2' 81 | # @@protoc_insertion_point(class_scope:TrackerWrapperPacket) 82 | )) 83 | _sym_db.RegisterMessage(TrackerWrapperPacket) 84 | 85 | 86 | DESCRIPTOR._options = None 87 | # @@protoc_insertion_point(module_scope) 88 | -------------------------------------------------------------------------------- /protos/ssl_vision_detection_tracked.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto2"; 2 | 3 | option java_package = "edu.tigers.sumatra.wp.proto"; 4 | option go_package = "github.com/RoboCup-SSL/ssl-game-controller/internal/app/tracker"; 5 | 6 | import "ssl_gc_common.proto"; 7 | import "ssl_gc_geometry.proto"; 8 | 9 | // Default network address: 224.5.23.2:10010 10 | 11 | // Capabilities that a source implementation can have 12 | enum Capability { 13 | CAPABILITY_UNKNOWN = 0; 14 | CAPABILITY_DETECT_FLYING_BALLS = 1; 15 | CAPABILITY_DETECT_MULTIPLE_BALLS = 2; 16 | CAPABILITY_DETECT_KICKED_BALLS = 3; 17 | } 18 | 19 | // A single tracked ball 20 | message TrackedBall { 21 | // The position (x, y, height) [m] in the ssl-vision coordinate system 22 | required edu.tigers.sumatra.referee.proto.Vector3 pos = 1; 23 | 24 | // The velocity [m/s] in the ssl-vision coordinate system 25 | optional edu.tigers.sumatra.referee.proto.Vector3 vel = 2; 26 | 27 | // The visibility of the ball 28 | // A value between 0 (not visible) and 1 (visible) 29 | // The exact implementation depends on the source software 30 | optional float visibility = 3; 31 | } 32 | 33 | // A ball kicked by a robot, including predictions when the ball will come to a stop 34 | message KickedBall { 35 | // The initial position [m] from which the ball was kicked 36 | required edu.tigers.sumatra.referee.proto.Vector2 pos = 1; 37 | // The initial velocity [m/s] with which the ball was kicked 38 | required edu.tigers.sumatra.referee.proto.Vector3 vel = 2; 39 | // The unix timestamp [s] when the kick was performed 40 | required double start_timestamp = 3; 41 | 42 | // The predicted unix timestamp [s] when the ball comes to a stop 43 | optional double stop_timestamp = 4; 44 | // The predicted position [m] at which the ball will come to a stop 45 | optional edu.tigers.sumatra.referee.proto.Vector2 stop_pos = 5; 46 | 47 | // The robot that kicked the ball 48 | optional edu.tigers.sumatra.referee.proto.RobotId robot_id = 6; 49 | } 50 | 51 | // A single tracked robot 52 | message TrackedRobot { 53 | required edu.tigers.sumatra.referee.proto.RobotId robot_id = 1; 54 | 55 | // The position [m] in the ssl-vision coordinate system 56 | required edu.tigers.sumatra.referee.proto.Vector2 pos = 2; 57 | // The orientation [rad] in the ssl-vision coordinate system 58 | required float orientation = 3; 59 | 60 | // The velocity [m/s] in the ssl-vision coordinate system 61 | optional edu.tigers.sumatra.referee.proto.Vector2 vel = 4; 62 | // The angular velocity [rad/s] in the ssl-vision coordinate system 63 | optional float vel_angular = 5; 64 | 65 | // The visibility of the robot 66 | // A value between 0 (not visible) and 1 (visible) 67 | // The exact implementation depends on the source software 68 | optional float visibility = 6; 69 | } 70 | 71 | // A frame that contains all currently tracked objects on the field on all cameras 72 | message TrackedFrame { 73 | // A monotonous increasing frame counter 74 | required uint32 frame_number = 1; 75 | // The unix timestamp in [s] of the data 76 | // If timestamp is larger than timestamp_captured, the source has applied a prediction already 77 | required double timestamp = 2; 78 | 79 | // The list of detected balls 80 | // The first ball is the primary one 81 | // Sources may add additional balls based on their capabilities 82 | repeated TrackedBall balls = 3; 83 | // The list of detected robots of both teams 84 | repeated TrackedRobot robots = 4; 85 | 86 | // Information about a kicked ball, if the ball was kicked by a robot and is still moving 87 | // Note: This field is optional. Some source implementations might not set this at any time 88 | optional KickedBall kicked_ball = 5; 89 | 90 | // List of capabilities of the source implementation 91 | repeated Capability capabilities = 6; 92 | } 93 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SSL Hardware Challenge Tool 2 | 3 | This tool will check if the robots/ball are correctly placed for the given 4 | challenge. 5 | 6 | It will wait until all robots/ball are placed, wait 2 seconds and ask the user 7 | to confirm the beginning of the challenge. After that, everything will happen 8 | automatically. 9 | 10 | ## Dependencies 11 | 12 | - Python 3.8.5 13 | - [WebSocket](https://pypi.org/project/websocket-client/) 14 | - Pygame 15 | - Numpy 16 | - Protobuf 17 | 18 | **PS**: Only tested in Ubuntu 20.04. 19 | 20 | To install the Python packages run 21 | 22 | ```shell 23 | pip3 install websocket-client pygame tabulate numpy protobuf 24 | ``` 25 | 26 | The project already contains de compiled .proto files for Python, but, in case 27 | you need to re-compile/update them you need to place the new .proto files in 28 | the `proto` folder and then use the included script: 29 | 30 | ```shell 31 | ./update_protos.sh 32 | ``` 33 | 34 | ## Usage 35 | 36 | Before starting any challenge make sure that all the following conditions are 37 | met: 38 | 39 | - Both GameController and AutoRef (Preferably TIGERs) must be used 40 | - The tool must run in the same computer as the GC 41 | - The GC must be set to accept GOAL and POSSIBLE_GOAL proposals, the others can 42 | be turned off 43 | - The AutoRef must be set to *active* 44 | - The game state must be either First Half or Second Half 45 | - Make sure the goal positions for each team are configured correctly in the GC 46 | 47 | At last, run the `ChallengeManager.py` with: 48 | 49 | ```shell 50 | python3 src/ChallengeManager.py -f -c 51 | ``` 52 | 53 | - **challenge_positions.json**: is the .json file that contains the positions 54 | of the challenge. 55 | - **challenge_number**: is the **id** of the challenge, must be between 1 and 5. 56 | 57 | **NOTE**: Challenge N⁰ 5 is the Technical Challenge - Ball Placement. 58 | 59 | **NOTE**: In case there is too much noise in your camera setup, you can enable 60 | TIGERs AutoRef detection by passing the argument **-A 1**. 61 | 62 | Example: 63 | 64 | ```shell 65 | python3 src/ChallengeManager.py -f src/json_examples/challenge_1.json -c 1 66 | ``` 67 | 68 | For more information about the input arguments use: 69 | 70 | ```shell 71 | python3 src/ChallengeManager.py -h 72 | ``` 73 | 74 | ### User Interface 75 | 76 | The graphical user interface shows: 77 | 78 | - The position of each yellow robot: dark yellow circle 79 | - The position of each blue robot: light blue circle 80 | - The position of the ball: orange circle 81 | 82 | The colored circles indicate a threshold distance where the object must be 83 | placed, currently this threshold is **20mm** and **5⁰**. Therefore, the object 84 | must be within a distance of **20mm** from the challenge position, with less 85 | than **5⁰** of orientation error. (subject to change) 86 | 87 | If the object (robot/ball) is correctly placed, it's corresponding circle will 88 | turn light green, as shown in the image below. 89 | 90 | ![SSL Hardware Challenge Tool](./resources/positioning.gif) 91 | 92 | **NOTE**: If the robot drawing is too big, it is probably because the tool hasn't 93 | received a geometry packet yet. 94 | 95 | ### Warnings 96 | 97 | The tool will warn the user if there is any infliction of the rules of the challenge 98 | regarding the initial position, the warnings indicate: 99 | 100 | - If there are more defending robots (yellow) than the number defined in the 101 | json 102 | - If there are more attacking robots (blue) than the number allowed for the 103 | current challenge 104 | - The 'Found' and 'Max' values in this warning mean, how many extra robots 105 | are in the field, and how many extra robots are allowed, respectively. A 106 | robot with its position defined in the json doesn't count 107 | 108 | - If the robots that do not have their position defined in the json are in a 109 | valid position (usually the middle line) 110 | -------------------------------------------------------------------------------- /src/aux/RobotBall.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | from math import sqrt, pow, pi 3 | from aux.utils import red_print 4 | 5 | import numpy as np 6 | 7 | BLUE_TEAM = 'BLUE' 8 | YELLOW_TEAM = 'YELLOW' 9 | BALL = 'ORANGE' 10 | 11 | MAX_FRAMES_UNSEEN = 50 12 | DISTANCE_THRESHOLD = 35 # [mm] 13 | ORIENTATION_THRESHOLD = 10 * pi/180.0 # [rad] 14 | INF = 999999999999 15 | 16 | 17 | class Position(object): 18 | def __init__(self, x=INF, y=INF, orientation=0): 19 | self.x = x 20 | self.y = y 21 | self.orientation = float(orientation) 22 | 23 | def __repr__(self): 24 | return '({}, {}, {:.3f})'.format(self.x, self.y, self.orientation) 25 | 26 | def set_pos(self, pos: Position): 27 | self.x = pos.x 28 | self.y = pos.y 29 | 30 | def to_numpy(self) -> np.array: 31 | return np.array([self.x, self.y]) 32 | 33 | def distance(self, pos) -> int: 34 | return round(sqrt(pow(self.x - pos.x, 2) + pow(self.y - pos.y, 2))) 35 | 36 | def distance_orientation(self, pos) -> float: 37 | return abs(abs(self.orientation) - abs(pos.orientation)) 38 | 39 | # ============================================================================= 40 | 41 | 42 | class VisionObject(object): 43 | def __init__(self): 44 | self.unseen_frames = 0 45 | self.pos = Position() 46 | 47 | def update(self, **kargs): 48 | raise NotImplementedError() 49 | 50 | def in_vision(self) -> bool: 51 | return self.unseen_frames > 0 52 | 53 | # ============================================================================= 54 | 55 | 56 | class Robot(VisionObject): 57 | def __init__(self, **kargs): 58 | super().__init__() 59 | self.id = -1 60 | self.team = BLUE_TEAM 61 | 62 | for key, value in kargs.items(): 63 | if key == 'robot_id': 64 | self.id = value 65 | elif key == 'pos': 66 | self.pos = value 67 | elif key == 'team': 68 | self.team = value 69 | elif key == 'obj': 70 | self.pos = Position(*tuple(value['pos'])) 71 | elif key == 'id': 72 | self.id = value['number'] 73 | self.team = value['color'] 74 | 75 | def __repr__(self): 76 | if self.in_vision(): 77 | return 'Robot {}/{} = {}'.format(self.id, self.team, self.pos) 78 | return '' 79 | 80 | def update(self, **kargs): 81 | is_robot = False 82 | pos = None 83 | 84 | for key, value in kargs.items(): 85 | if key == 'id': 86 | if value['number'] == self.id and value['color'] == self.team: 87 | is_robot = True 88 | 89 | elif key == 'obj': 90 | pos = Position(*tuple(value['pos'])) 91 | 92 | if is_robot and pos != None: 93 | self.pos = pos 94 | self.unseen_frames = MAX_FRAMES_UNSEEN 95 | 96 | elif self.in_vision(): 97 | self.unseen_frames = self.unseen_frames - 1 98 | 99 | def compare(self, data: Robot): 100 | if not self.in_vision(): 101 | return False 102 | 103 | # Do not consider the robot id 104 | if self.pos.distance(data.pos) <= DISTANCE_THRESHOLD and \ 105 | self.pos.distance_orientation(data.pos) <= ORIENTATION_THRESHOLD: 106 | return True 107 | return False 108 | 109 | # ============================================================================= 110 | 111 | 112 | class Ball(VisionObject): 113 | def __init__(self, pos=None): 114 | super().__init__() 115 | 116 | if pos != None: 117 | self.pos = pos 118 | 119 | def __repr__(self): 120 | return 'Ball = {}'.format(self.pos) 121 | 122 | def update(self, **kargs): 123 | pos = None 124 | for key, data in kargs.items(): 125 | if 'pos' == key: 126 | pos = Position(*tuple(data['pos'])) 127 | 128 | if pos == None: 129 | red_print('Ball update | No position given in {}'.format(kargs)) 130 | return 131 | 132 | if self.in_vision(): 133 | if pos.distance(Position()) != 0: 134 | self.unseen_frames = MAX_FRAMES_UNSEEN 135 | self.pos = pos 136 | else: 137 | self.unseen_frames = MAX_FRAMES_UNSEEN 138 | self.pos = pos 139 | 140 | self.unseen_frames = self.unseen_frames - 1 141 | 142 | def compare(self, data: Ball): 143 | if not self.in_vision(): 144 | return False 145 | 146 | return self.pos.distance(data.pos) <= DISTANCE_THRESHOLD 147 | -------------------------------------------------------------------------------- /protos/ssl_vision_geometry.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto2"; 2 | option go_package = "github.com/RoboCup-SSL/ssl-simulation-protocol/pkg/sim"; 3 | 4 | // A 2D float vector. 5 | message Vector2f { 6 | required float x = 1; 7 | required float y = 2; 8 | } 9 | 10 | // Represents a field marking as a line segment represented by a start point p1, 11 | // and end point p2, and a line thickness. The start and end points are along 12 | // the center of the line, so the thickness of the line extends by thickness / 2 13 | // on either side of the line. 14 | message SSL_FieldLineSegment { 15 | // Name of this field marking. 16 | required string name = 1; 17 | // Start point of the line segment. 18 | required Vector2f p1 = 2; 19 | // End point of the line segment. 20 | required Vector2f p2 = 3; 21 | // Thickness of the line segment. 22 | required float thickness = 4; 23 | // The type of this shape 24 | optional SSL_FieldShapeType type = 5; 25 | } 26 | 27 | // Represents a field marking as a circular arc segment represented by center point, a 28 | // start angle, an end angle, and an arc thickness. 29 | message SSL_FieldCircularArc { 30 | // Name of this field marking. 31 | required string name = 1; 32 | // Center point of the circular arc. 33 | required Vector2f center = 2; 34 | // Radius of the arc. 35 | required float radius = 3; 36 | // Start angle in counter-clockwise order. 37 | required float a1 = 4; 38 | // End angle in counter-clockwise order. 39 | required float a2 = 5; 40 | // Thickness of the arc. 41 | required float thickness = 6; 42 | // The type of this shape 43 | optional SSL_FieldShapeType type = 7; 44 | } 45 | 46 | message SSL_GeometryFieldSize { 47 | required int32 field_length = 1; 48 | required int32 field_width = 2; 49 | required int32 goal_width = 3; 50 | required int32 goal_depth = 4; 51 | required int32 boundary_width = 5; 52 | repeated SSL_FieldLineSegment field_lines = 6; 53 | repeated SSL_FieldCircularArc field_arcs = 7; 54 | optional int32 penalty_area_depth = 8; 55 | optional int32 penalty_area_width = 9; 56 | } 57 | 58 | message SSL_GeometryCameraCalibration { 59 | required uint32 camera_id = 1; 60 | required float focal_length = 2; 61 | required float principal_point_x = 3; 62 | required float principal_point_y = 4; 63 | required float distortion = 5; 64 | required float q0 = 6; 65 | required float q1 = 7; 66 | required float q2 = 8; 67 | required float q3 = 9; 68 | required float tx = 10; 69 | required float ty = 11; 70 | required float tz = 12; 71 | optional float derived_camera_world_tx = 13; 72 | optional float derived_camera_world_ty = 14; 73 | optional float derived_camera_world_tz = 15; 74 | optional uint32 pixel_image_width = 16; 75 | optional uint32 pixel_image_height = 17; 76 | } 77 | 78 | // Two-Phase model for straight-kicked balls. 79 | // There are two phases with different accelerations during the ball kicks: 80 | // 1. Sliding 81 | // 2. Rolling 82 | // The full model is described in the TDP of ER-Force from 2016, which can be found here: 83 | // https://ssl.robocup.org/wp-content/uploads/2019/01/2016_ETDP_ER-Force.pdf 84 | message SSL_BallModelStraightTwoPhase { 85 | // Ball sliding acceleration [m/s^2] (should be negative) 86 | required double acc_slide = 1; 87 | // Ball rolling acceleration [m/s^2] (should be negative) 88 | required double acc_roll = 2; 89 | // Fraction of the initial velocity where the ball starts to roll 90 | required double k_switch = 3; 91 | } 92 | 93 | // Fixed-Loss model for chipped balls. 94 | // Uses fixed damping factors for xy and z direction per hop. 95 | message SSL_BallModelChipFixedLoss { 96 | // Chip kick velocity damping factor in XY direction for the first hop 97 | required double damping_xy_first_hop = 1; 98 | // Chip kick velocity damping factor in XY direction for all following hops 99 | required double damping_xy_other_hops = 2; 100 | // Chip kick velocity damping factor in Z direction for all hops 101 | required double damping_z = 3; 102 | } 103 | 104 | message SSL_GeometryModels { 105 | optional SSL_BallModelStraightTwoPhase straight_two_phase = 1; 106 | optional SSL_BallModelChipFixedLoss chip_fixed_loss = 2; 107 | } 108 | 109 | message SSL_GeometryData { 110 | required SSL_GeometryFieldSize field = 1; 111 | repeated SSL_GeometryCameraCalibration calib = 2; 112 | optional SSL_GeometryModels models = 3; 113 | } 114 | 115 | enum SSL_FieldShapeType { 116 | Undefined = 0; 117 | CenterCircle = 1; 118 | TopTouchLine = 2; 119 | BottomTouchLine = 3; 120 | LeftGoalLine = 4; 121 | RightGoalLine = 5; 122 | HalfwayLine = 6; 123 | CenterLine = 7; 124 | LeftPenaltyStretch = 8; 125 | RightPenaltyStretch = 9; 126 | LeftFieldLeftPenaltyStretch = 10; 127 | LeftFieldRightPenaltyStretch = 11; 128 | RightFieldLeftPenaltyStretch = 12; 129 | RightFieldRightPenaltyStretch = 13; 130 | } -------------------------------------------------------------------------------- /src/ssl_gc_geometry_pb2.py: -------------------------------------------------------------------------------- 1 | # Generated by the protocol buffer compiler. DO NOT EDIT! 2 | # source: ssl_gc_geometry.proto 3 | 4 | import sys 5 | _b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) 6 | from google.protobuf import descriptor as _descriptor 7 | from google.protobuf import message as _message 8 | from google.protobuf import reflection as _reflection 9 | from google.protobuf import symbol_database as _symbol_database 10 | # @@protoc_insertion_point(imports) 11 | 12 | _sym_db = _symbol_database.Default() 13 | 14 | 15 | 16 | 17 | DESCRIPTOR = _descriptor.FileDescriptor( 18 | name='ssl_gc_geometry.proto', 19 | package='edu.tigers.sumatra.referee.proto', 20 | syntax='proto2', 21 | serialized_options=_b('ZZ 1: 33 | self.finish_challenge() 34 | 35 | elif event == ChallengeEvents.ROBOT_STOPPED and self.current_challenge.id == 3: 36 | self.finish_challenge() 37 | 38 | elif event == ChallengeEvents.STOP and self.current_challenge.id == 5: 39 | dt = self.dt_cmd[1] - self.dt_cmd[0] 40 | if dt > 1 and self.current_step == ChallengeSteps.STEP_4: 41 | purple_print('\nStop!') 42 | self.finish_challenge() 43 | 44 | def finish_challenge(self): 45 | self.proceed_step() 46 | blue_print('\nFinish Challenge!') 47 | 48 | if self.current_step == ChallengeSteps.STEP_0 and \ 49 | self.challenge_end_callback != None: 50 | self.dt_chl[1] = time.time_ns() / 1e9 51 | 52 | blue_print('Stop challenge timer!') 53 | 54 | self.challenge_end_callback() 55 | 56 | def set_challenge(self, challenge: int): 57 | self.current_step = ChallengeSteps.STEP_1 58 | self.dt_chl = [0, 0] 59 | 60 | if not isinstance(challenge, int) or \ 61 | (challenge < 1 or challenge > MAX_CHALLENGES): 62 | raise ValueError( 63 | f'Challenge ID must be between 1 and {MAX_CHALLENGES}!') 64 | 65 | if challenge == 1: 66 | self.current_challenge = Challenge_1 67 | elif challenge == 2: 68 | self.current_challenge = Challenge_2 69 | elif challenge == 3: 70 | self.current_challenge = Challenge_3 71 | elif challenge == 4: 72 | self.current_challenge = Challenge_4 73 | elif challenge == 5: 74 | self.current_challenge = BallPlacement 75 | 76 | green_print('[CHALLENGE FSM] Challenge {} set!'.format(challenge)) 77 | 78 | def set_end_callback(self, callback_fn=None): 79 | if callback_fn != None: 80 | self.challenge_end_callback = callback_fn 81 | green_print('[CHALLENGE FSM] Callback set!') 82 | 83 | def proceed_step(self): 84 | next_step = ChallengeSteps.next_step(self.current_step) 85 | 86 | if next_step.value <= self.current_challenge.max_steps: 87 | self.current_step = next_step 88 | else: 89 | self.current_step = ChallengeSteps.STEP_0 90 | 91 | def get_challenge_time(self): 92 | ch_time = self.dt_chl[1] - self.dt_chl[0] 93 | if self.current_challenge.id == 3: 94 | ch_time = ch_time - ROBOT_STOP_TRESHOLD 95 | return ch_time 96 | 97 | def get_current_command(self) -> GCCommands: 98 | action = self.current_challenge.Step(self.current_step) 99 | timer_ended = False 100 | 101 | if action.timer != 0 and self.dt_cmd == [0, 0]: 102 | self.dt_cmd[0] = time.time_ns() / 1e9 103 | self.dt_cmd[1] = time.time_ns() / 1e9 104 | 105 | elif action.timer != 0 and self.dt_cmd[0] > 0: 106 | self.dt_cmd[1] = time.time_ns() / 1e9 107 | 108 | dt = self.dt_cmd[1] - self.dt_cmd[0] 109 | print('Challenge time = {:.2f}/{} s'.format(dt, action.timer), 110 | end='\r') 111 | 112 | if dt >= action.timer: 113 | timer_ended = True 114 | self.dt_cmd = [0, 0] 115 | 116 | if action.command != GCCommands.NONE or timer_ended: 117 | if action.start_timer and self.dt_chl[0] == 0: 118 | self.dt_chl[0] = time.time_ns() / 1e9 119 | blue_print('Starting challenge timer...') 120 | 121 | self.proceed_step() 122 | 123 | if self.current_step == ChallengeSteps.STEP_0 and \ 124 | self.challenge_end_callback != None: 125 | self.dt_chl[1] = time.time_ns() / 1e9 126 | 127 | if timer_ended: 128 | blue_print('\nStop challenge timer - Timeout =(!') 129 | else: 130 | blue_print('\nStop challenge timer - Completed =)!') 131 | 132 | self.challenge_end_callback() 133 | 134 | return action.command 135 | -------------------------------------------------------------------------------- /protos/referee.proto: -------------------------------------------------------------------------------- 1 | syntax="proto2"; 2 | // Each UDP packet contains one of these messages. 3 | message SSL_Referee { 4 | // The UNIX timestamp when the packet was sent, in microseconds. 5 | // Divide by 1,000,000 to get a time_t. 6 | required uint64 packet_timestamp = 1; 7 | 8 | // These are the "coarse" stages of the game. 9 | enum Stage { 10 | // The first half is about to start. 11 | // A kickoff is called within this stage. 12 | // This stage ends with the NORMAL_START. 13 | NORMAL_FIRST_HALF_PRE = 0; 14 | // The first half of the normal game, before half time. 15 | NORMAL_FIRST_HALF = 1; 16 | // Half time between first and second halves. 17 | NORMAL_HALF_TIME = 2; 18 | // The second half is about to start. 19 | // A kickoff is called within this stage. 20 | // This stage ends with the NORMAL_START. 21 | NORMAL_SECOND_HALF_PRE = 3; 22 | // The second half of the normal game, after half time. 23 | NORMAL_SECOND_HALF = 4; 24 | // The break before extra time. 25 | EXTRA_TIME_BREAK = 5; 26 | // The first half of extra time is about to start. 27 | // A kickoff is called within this stage. 28 | // This stage ends with the NORMAL_START. 29 | EXTRA_FIRST_HALF_PRE = 6; 30 | // The first half of extra time. 31 | EXTRA_FIRST_HALF = 7; 32 | // Half time between first and second extra halves. 33 | EXTRA_HALF_TIME = 8; 34 | // The second half of extra time is about to start. 35 | // A kickoff is called within this stage. 36 | // This stage ends with the NORMAL_START. 37 | EXTRA_SECOND_HALF_PRE = 9; 38 | // The second half of extra time. 39 | EXTRA_SECOND_HALF = 10; 40 | // The break before penalty shootout. 41 | PENALTY_SHOOTOUT_BREAK = 11; 42 | // The penalty shootout. 43 | PENALTY_SHOOTOUT = 12; 44 | // The game is over. 45 | POST_GAME = 13; 46 | } 47 | required Stage stage = 2; 48 | 49 | // The number of microseconds left in the stage. 50 | // The following stages have this value; the rest do not: 51 | // NORMAL_FIRST_HALF 52 | // NORMAL_HALF_TIME 53 | // NORMAL_SECOND_HALF 54 | // EXTRA_TIME_BREAK 55 | // EXTRA_FIRST_HALF 56 | // EXTRA_HALF_TIME 57 | // EXTRA_SECOND_HALF 58 | // PENALTY_SHOOTOUT_BREAK 59 | // 60 | // If the stage runs over its specified time, this value 61 | // becomes negative. 62 | optional sint32 stage_time_left = 3; 63 | 64 | // These are the "fine" states of play on the field. 65 | enum Command { 66 | // All robots should completely stop moving. 67 | HALT = 0; 68 | // Robots must keep 50 cm from the ball. 69 | STOP = 1; 70 | // A prepared kickoff or penalty may now be taken. 71 | NORMAL_START = 2; 72 | // The ball is dropped and free for either team. 73 | FORCE_START = 3; 74 | // The yellow team may move into kickoff position. 75 | PREPARE_KICKOFF_YELLOW = 4; 76 | // The blue team may move into kickoff position. 77 | PREPARE_KICKOFF_BLUE = 5; 78 | // The yellow team may move into penalty position. 79 | PREPARE_PENALTY_YELLOW = 6; 80 | // The blue team may move into penalty position. 81 | PREPARE_PENALTY_BLUE = 7; 82 | // The yellow team may take a direct free kick. 83 | DIRECT_FREE_YELLOW = 8; 84 | // The blue team may take a direct free kick. 85 | DIRECT_FREE_BLUE = 9; 86 | // The yellow team may take an indirect free kick. 87 | INDIRECT_FREE_YELLOW = 10; 88 | // The blue team may take an indirect free kick. 89 | INDIRECT_FREE_BLUE = 11; 90 | // The yellow team is currently in a timeout. 91 | TIMEOUT_YELLOW = 12; 92 | // The blue team is currently in a timeout. 93 | TIMEOUT_BLUE = 13; 94 | // The yellow team just scored a goal. 95 | // For information only. 96 | // For rules compliance, teams must treat as STOP. 97 | GOAL_YELLOW = 14; 98 | // The blue team just scored a goal. 99 | GOAL_BLUE = 15; 100 | // Equivalent to STOP, but the yellow team must pick up the ball and 101 | // drop it in the Designated Position. 102 | BALL_PLACEMENT_YELLOW = 16; 103 | // Equivalent to STOP, but the blue team must pick up the ball and drop 104 | // it in the Designated Position. 105 | BALL_PLACEMENT_BLUE = 17; 106 | } 107 | required Command command = 4; 108 | 109 | // The number of commands issued since startup (mod 2^32). 110 | required uint32 command_counter = 5; 111 | 112 | // The UNIX timestamp when the command was issued, in microseconds. 113 | // This value changes only when a new command is issued, not on each packet. 114 | required uint64 command_timestamp = 6; 115 | 116 | // Information about a single team. 117 | message TeamInfo { 118 | // The team's name (empty string if operator has not typed anything). 119 | required string name = 1; 120 | // The number of goals scored by the team during normal play and overtime. 121 | required uint32 score = 2; 122 | // The number of red cards issued to the team since the beginning of the game. 123 | required uint32 red_cards = 3; 124 | // The amount of time (in microseconds) left on each yellow card issued to the team. 125 | // If no yellow cards are issued, this array has no elements. 126 | // Otherwise, times are ordered from smallest to largest. 127 | repeated uint32 yellow_card_times = 4 [packed=true]; 128 | // The total number of yellow cards ever issued to the team. 129 | required uint32 yellow_cards = 5; 130 | // The number of timeouts this team can still call. 131 | // If in a timeout right now, that timeout is excluded. 132 | required uint32 timeouts = 6; 133 | // The number of microseconds of timeout this team can use. 134 | required uint32 timeout_time = 7; 135 | // The pattern number of this team's goalie. 136 | required uint32 goalie = 8; 137 | } 138 | 139 | // Information about the two teams. 140 | required TeamInfo yellow = 7; 141 | required TeamInfo blue = 8; 142 | 143 | // The coordinates of the Designated Position. These are measured in 144 | // millimetres and correspond to SSL-Vision coordinates. These fields are 145 | // always either both present (in the case of a ball placement command) or 146 | // both absent (in the case of any other command). 147 | message Point { 148 | required float x = 1; 149 | required float y = 2; 150 | } 151 | optional Point designated_position = 9; 152 | optional uint64 packet_timestamp_fei=10; 153 | } 154 | -------------------------------------------------------------------------------- /src/ProcessUDPData.py: -------------------------------------------------------------------------------- 1 | import socket 2 | import struct 3 | import pickle 4 | import time 5 | import numpy as np 6 | from google.protobuf.message import DecodeError 7 | 8 | from socket import timeout as TimeoutException 9 | 10 | import ssl_vision_detection_pb2 as detection 11 | import ssl_vision_detection_tracked_pb2 as tigers_detection 12 | 13 | import ssl_vision_geometry_pb2 as geometry 14 | import ssl_gc_geometry_pb2 as tigers_geometry 15 | 16 | import ssl_wrapper_pb2 as wrapper 17 | import ssl_vision_wrapper_tracked_pb2 as tigers_wrapper 18 | 19 | import referee_pb2 as referee 20 | from ssl_vision_geometry_pb2 import SSL_GeometryData, SSL_GeometryFieldSize, SSL_FieldCircularArc 21 | 22 | from aux.utils import red_print, blue_print, green_print, purple_print 23 | from aux.RobotBall import BLUE_TEAM, YELLOW_TEAM 24 | 25 | DEBUG = False 26 | DEFAULT_VISION_PORT = 10006 27 | DEFAULT_VISION_IP = '224.5.23.2' 28 | 29 | DEFAULT_REFEREE_PORT = 10003 30 | DEFAULT_REFEREE_IP = '224.5.23.1' 31 | 32 | AUTOREF_TRACKED_PORT = 10010 33 | 34 | 35 | class UDPCommunication(object): 36 | def __init__(self, v_port: int, v_group: str, r_port: int, r_group: str, use_autoref: bool): 37 | self.UDP_TIMEOUT = 0.0001 # in seconds 38 | self.packets_since_autoref = 0 39 | self.last_vision_packet = None 40 | green_print(f'Use AutoRef Data = {use_autoref}') 41 | 42 | self.v_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 43 | socket.IPPROTO_UDP) 44 | self.init_socket(self.v_socket, v_group, v_port) 45 | 46 | if use_autoref: 47 | self.autoref_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 48 | socket.IPPROTO_UDP) 49 | self.init_socket(self.autoref_socket, v_group, 50 | AUTOREF_TRACKED_PORT) 51 | else: 52 | self.autoref_socket = None 53 | 54 | self.r_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 55 | socket.IPPROTO_UDP) 56 | self.init_socket(self.r_socket, r_group, r_port) 57 | 58 | # ============================================================================= 59 | 60 | def init_socket(self, socket_obj: socket, group, port): 61 | socket_obj.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 62 | socket_obj.bind((group, port)) 63 | green_print(f'Connecting to {group}:{port}...') 64 | 65 | mreq = struct.pack('4sl', socket.inet_aton(group), socket.INADDR_ANY) 66 | socket_obj.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, 67 | mreq) 68 | socket_obj.settimeout(self.UDP_TIMEOUT) 69 | 70 | # ============================================================================= 71 | 72 | def __del__(self): 73 | try: 74 | self.v_socket.close() 75 | blue_print('Closing UDP socket') 76 | except Exception: 77 | pass 78 | 79 | # ============================================================================= 80 | 81 | def process_vision_packet(self, packet) -> (bool, detection.SSL_DetectionFrame, 82 | geometry.SSL_GeometryData): 83 | if packet == None: 84 | return (False, None, None) 85 | 86 | data_ok = False 87 | wrapper_frame = wrapper.SSL_WrapperPacket() 88 | tigers_detection_frame = tigers_detection.TrackedFrame() 89 | tigers_wrapper_frame = tigers_wrapper.TrackerWrapperPacket() 90 | geometry_data = geometry.SSL_GeometryData() 91 | 92 | if len(packet) > 0: 93 | try: 94 | wrapper_frame.ParseFromString(packet) 95 | pkt_fields = wrapper_frame.ListFields() 96 | 97 | for field in pkt_fields: 98 | if field[0].name == 'geometry': 99 | geometry_data = wrapper_frame.geometry 100 | 101 | data_ok = True 102 | return (data_ok, wrapper_frame.detection, geometry_data) 103 | 104 | except DecodeError as except_type: 105 | tigers_wrapper_frame.ParseFromString(packet) 106 | tigers_detection_frame = tigers_wrapper_frame.tracked_frame 107 | 108 | data_ok = True 109 | return (data_ok, tigers_detection_frame, None) 110 | 111 | except Exception as except_type: 112 | red_print(except_type, type(except_type)) 113 | 114 | return (data_ok, detection.SSL_DetectionFrame(), geometry.SSL_GeometryData()) 115 | 116 | # ============================================================================= 117 | 118 | def process_referee_packet(self, packet) -> (bool, referee.SSL_Referee): 119 | data_ok = False 120 | referee_frame = referee.SSL_Referee() 121 | 122 | if len(packet) > 0: 123 | try: 124 | referee_frame.ParseFromString(packet) 125 | data_ok = True 126 | return (data_ok, referee_frame) 127 | 128 | except Exception as except_type: 129 | red_print(except_type) 130 | 131 | return (data_ok, referee.SSL_Referee()) 132 | 133 | # ============================================================================= 134 | 135 | def detection_frame_to_dict(self, detection_frame: detection.SSL_DetectionFrame) -> dict: 136 | frame_dict = dict() 137 | 138 | if not isinstance(detection_frame, detection.SSL_DetectionFrame) and \ 139 | not isinstance(detection_frame, tigers_detection.TrackedFrame): 140 | return frame_dict 141 | 142 | if isinstance(detection_frame, detection.SSL_DetectionFrame): 143 | ball_pos = [[round(ball.x), round(ball.y), 0] 144 | for ball in detection_frame.balls] 145 | 146 | # Use the mean in case there is more than one ball 147 | if len(ball_pos) > 0: 148 | if len(ball_pos) > 1 and DEBUG: 149 | red_print('WARNING! More than one ball detected') 150 | mean_pos = np.mean(np.array(ball_pos), axis=0) 151 | ball_pos = mean_pos.tolist() 152 | 153 | ball = {'pos': ball_pos} 154 | 155 | blue_robots = [{'obj': {'pos': [round(robot.x), round(robot.y), robot.orientation]}, 156 | 'id': {'number': robot.robot_id, 'color': BLUE_TEAM}} 157 | for robot in detection_frame.robots_blue] 158 | 159 | yellow_robots = [{'obj': {'pos': [round(robot.x), round(robot.y), robot.orientation]}, 160 | 'id': {'number': robot.robot_id, 'color': YELLOW_TEAM}} 161 | for robot in detection_frame.robots_yellow] 162 | elif isinstance(detection_frame, tigers_detection.TrackedFrame): 163 | ball_pos = [[round(ball.pos.x*1000), round(ball.pos.y*1000), 0] 164 | for ball in detection_frame.balls] 165 | 166 | # Use the mean in case there is more than one ball 167 | if len(ball_pos) > 0: 168 | if len(ball_pos) > 1 and DEBUG: 169 | red_print('WARNING! More than one ball detected') 170 | mean_pos = np.mean(np.array(ball_pos), axis=0) 171 | ball_pos = mean_pos.tolist() 172 | 173 | ball = {'pos': ball_pos} 174 | 175 | def conv_team(t_id): return BLUE_TEAM if t_id == 2 else YELLOW_TEAM 176 | 177 | blue_robots = [{'obj': {'pos': [round(robot.pos.x*1000), round(robot.pos.y*1000), robot.orientation]}, 178 | 'id': {'number': robot.robot_id.id, 'color': conv_team(robot.robot_id.team)}} 179 | for robot in detection_frame.robots] 180 | yellow_robots = [] 181 | 182 | frame_dict['ball'] = ball 183 | frame_dict['bots'] = blue_robots 184 | frame_dict['bots'].extend(yellow_robots) 185 | 186 | return frame_dict 187 | 188 | def geometry_frame_to_dict(self, geometry_frame: geometry.SSL_GeometryData) -> dict(): 189 | frame_dict = dict() 190 | 191 | if not isinstance(geometry_frame, geometry.SSL_GeometryData): 192 | return frame_dict 193 | 194 | if geometry_frame.field.field_length != 0: 195 | frame_dict['field_size'] = [geometry_frame.field.field_length, 196 | geometry_frame.field.field_width] 197 | for arc in geometry_frame.field.field_arcs: 198 | if arc.name == 'CenterCircle': 199 | frame_dict['center_circle'] = arc.radius 200 | return frame_dict 201 | return None 202 | 203 | # ============================================================================= 204 | 205 | def get_vision_socket_data(self) -> (dict, dict): 206 | vision_packet = self.get_vision_packet() 207 | if self.autoref_socket != None: 208 | autoref_packet = self.get_autoref_vision_packet() 209 | else: 210 | autoref_packet = None 211 | 212 | vis_ok, det_data, geo_data = self.process_vision_packet(vision_packet) 213 | ar_ok, ar_det_data, _ = self.process_vision_packet(autoref_packet) 214 | 215 | if ar_ok: 216 | self.packets_since_autoref = 0 217 | det_data = ar_det_data 218 | self.last_vision_packet = det_data 219 | elif self.packets_since_autoref < 1000: 220 | det_data = self.last_vision_packet 221 | else: 222 | self.last_vision_packet = det_data 223 | 224 | if vis_ok or ar_ok: 225 | return (self.detection_frame_to_dict(det_data), 226 | self.geometry_frame_to_dict(geo_data)) 227 | # else: 228 | # red_print('[UDP] Failed to process vision packet!', '\r') 229 | return (None, None) 230 | 231 | def get_vision_packet(self): 232 | try: 233 | packet = self.v_socket.recv(4096) 234 | return packet 235 | except TimeoutException: 236 | self.packets_since_autoref += 1 237 | return None 238 | except Exception as except_type: 239 | red_print('[UDP]', except_type) 240 | return None 241 | 242 | def get_autoref_vision_packet(self): 243 | try: 244 | packet = self.autoref_socket.recv(4096) 245 | return packet 246 | except TimeoutException: 247 | return None 248 | except Exception as except_type: 249 | red_print('[UDP]', except_type) 250 | return None 251 | 252 | # ============================================================================= 253 | 254 | def get_referee_socket_data(self) -> dict: 255 | packet = b'' 256 | ok = False 257 | ret_val = None 258 | try: 259 | packet = self.r_socket.recv(4096) 260 | ok = True 261 | except TimeoutException: 262 | return None 263 | 264 | except Exception as except_type: 265 | red_print('[UDP]', except_type) 266 | 267 | if ok: 268 | ok, ref_data = self.process_referee_packet(packet) 269 | if ok: 270 | ret_val = {'Command': ref_data.Command.Name(ref_data.command)} 271 | 272 | else: 273 | red_print('[UDP] Failed to process referee packet!', '\r') 274 | ret_val = None 275 | else: 276 | red_print('[UDP] Failed to receive referee packet!', '\r') 277 | ret_val = None 278 | return ret_val 279 | 280 | # ============================================================================= 281 | -------------------------------------------------------------------------------- /src/ChallengeManager.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3.8 2 | import json 3 | import argparse 4 | import time 5 | import numpy as np 6 | from os.path import isfile 7 | 8 | from ProcessUDPData import UDPCommunication, DEFAULT_VISION_PORT, DEFAULT_VISION_IP, \ 9 | DEFAULT_REFEREE_PORT, DEFAULT_REFEREE_IP 10 | from DrawSSL import DrawSSL 11 | 12 | from aux.GCSocket import GCCommands, GCSocket 13 | from aux.position_robot import PositionFSM 14 | 15 | from aux.RobotBall import Robot, Ball, Position, BLUE_TEAM, YELLOW_TEAM, \ 16 | DISTANCE_THRESHOLD, INF 17 | from aux.utils import red_print, blue_print, green_print, purple_print 18 | 19 | from aux.hw_challenge_fsm import ChallengeFSM, ROBOT_STOP_TRESHOLD 20 | from aux.challenge_aux import ChallengeEvents 21 | 22 | DEBUG = False 23 | MAX_ROBOTS = 16 24 | 25 | 26 | class SpecialBotPosition(Position): 27 | def __init__(self): 28 | super().__init__() 29 | self.t = 0 30 | 31 | 32 | class HWChallengeManager(object): 33 | def __init__(self): 34 | args = self.parse_args() 35 | self.running = False 36 | 37 | self.udp_communication = UDPCommunication(v_port=int(args['vision_port']), 38 | v_group=args['vision_ip'], 39 | r_port=int( 40 | args['referee_port']), 41 | r_group=args['referee_ip'], 42 | use_autoref=bool(int(args['use_autoref_data']))) 43 | self.gc_socket = GCSocket() 44 | self.gc_socket.send_command(GCCommands.HALT) 45 | 46 | self.challenge_running = False 47 | self.challenge_number = int(args['challenge_number']) 48 | 49 | self.position_fsm = PositionFSM(args['challenge_file']) 50 | self.position_fsm.set_end_callback(self.objects_positioned) 51 | self.position_fsm.set_challenge(self.challenge_number) 52 | 53 | self.gc_socket.set_placement_pos(self.position_fsm.get_placement()) 54 | 55 | self.manager_fsm = ChallengeFSM() 56 | self.manager_fsm.set_challenge(self.challenge_number) 57 | self.manager_fsm.set_end_callback(self.challenge_end) 58 | 59 | # Init data 60 | self.challenge_3_bot_pos = [SpecialBotPosition(), SpecialBotPosition()] 61 | self.ball = Ball() 62 | self.blue_robots = [Robot(team=BLUE_TEAM, robot_id=i) 63 | for i in range(MAX_ROBOTS)] 64 | self.yellow_robots = [Robot(team=YELLOW_TEAM, robot_id=i) 65 | for i in range(MAX_ROBOTS)] 66 | self.init_drawings() 67 | 68 | # ============================================================================= 69 | 70 | def parse_args(self): 71 | arg_parser = argparse.ArgumentParser() 72 | if DEBUG: 73 | arg_parser.add_argument('-f', '--challenge-file', required=False, 74 | help='JSON file that contains the challenge positioning', 75 | default='./json_examples/challenge_2.json') 76 | arg_parser.add_argument('-c', '--challenge-number', required=False, 77 | help='ID of the hardware challenge, must be between 1 and 4', 78 | default=2) 79 | else: 80 | arg_parser.add_argument('-f', '--challenge-file', required=True, 81 | help='JSON file that contains the challenge positioning') 82 | arg_parser.add_argument('-c', '--challenge-number', required=True, 83 | help='ID of the hardware challenge, must be between 1 and 4') 84 | 85 | arg_parser.add_argument('-p', '--vision-port', required=False, 86 | help='UDP Vision Port, default value is {}'.format( 87 | DEFAULT_VISION_PORT), 88 | default=DEFAULT_VISION_PORT) 89 | arg_parser.add_argument('-i', '--vision-ip', required=False, 90 | help='UDP Vision IP, default value is {}'.format( 91 | DEFAULT_VISION_IP), 92 | default=DEFAULT_VISION_IP) 93 | arg_parser.add_argument('-P', '--referee-port', required=False, 94 | help='UDP Referee Port, default value is {}'.format( 95 | DEFAULT_REFEREE_PORT), 96 | default=DEFAULT_REFEREE_PORT) 97 | arg_parser.add_argument('-I', '--referee-ip', required=False, 98 | help='UDP Referee IP, default value is {}'.format( 99 | DEFAULT_REFEREE_IP), 100 | default=DEFAULT_REFEREE_IP) 101 | 102 | arg_parser.add_argument('-A', '--use-autoref-data', required=False, 103 | help='Indicates wheter to use the autoref tracked data (1/0), default is 0', 104 | default=0) 105 | 106 | return vars(arg_parser.parse_args()) 107 | 108 | # ============================================================================= 109 | 110 | def init_drawings(self): 111 | self.draw = DrawSSL() 112 | self.draw.start() 113 | self.running = True 114 | 115 | # ============================================================================= 116 | 117 | def update_vision_data(self): 118 | vision_data, geometry_data = self.udp_communication.get_vision_socket_data() 119 | 120 | if geometry_data != None and 'field_size' in geometry_data.keys() and \ 121 | 'center_circle' in geometry_data.keys(): 122 | self.draw.set_field_size(geometry_data['field_size']) 123 | self.draw.set_center_circle_radius(geometry_data['center_circle']) 124 | 125 | if vision_data != None: 126 | data_keys = list(vision_data.keys()) 127 | if 'ball' in data_keys: 128 | self.ball.update(pos=vision_data['ball']) 129 | self.draw.update_ball(self.ball.pos) 130 | 131 | blue_bots = [] 132 | yellow_bots = [] 133 | if 'bots' in data_keys: 134 | for robot in vision_data['bots']: 135 | for r_id in range(MAX_ROBOTS): 136 | self.blue_robots[r_id].update(obj=robot['obj'], 137 | id=robot['id']) 138 | 139 | if r_id == self.position_fsm.json_blue_id: 140 | self.update_challenge_3_bot_position( 141 | self.blue_robots[r_id].pos, 142 | self.position_fsm.get_pos(r_id, BLUE_TEAM)) 143 | 144 | self.yellow_robots[r_id].update(obj=robot['obj'], 145 | id=robot['id']) 146 | # In case there are no robots in the field, make sure they get 147 | # their 'in_vision' state updated 148 | if len(vision_data['bots']) == 0: 149 | for r_id in range(MAX_ROBOTS): 150 | self.blue_robots[r_id].update( 151 | id={'number': r_id, 'color': BLUE_TEAM}) 152 | self.yellow_robots[r_id].update( 153 | id={'number': r_id, 'color': YELLOW_TEAM}) 154 | 155 | blue_bots.extend([bot for bot in self.blue_robots 156 | if bot.in_vision()]) 157 | yellow_bots.extend([bot for bot in self.yellow_robots 158 | if bot.in_vision()]) 159 | 160 | self.draw.update_robots(blue_bots, BLUE_TEAM) 161 | self.draw.update_robots(yellow_bots, YELLOW_TEAM) 162 | 163 | self.check_challenge_positions() 164 | self.draw.update_challenge_data( 165 | self.position_fsm.get_challenge_positions()) 166 | 167 | # ============================================================================= 168 | 169 | def update_referee_data(self): 170 | referee_data = self.udp_communication.get_referee_socket_data() 171 | ref_cmd = 'NONE' 172 | 173 | if referee_data != None: 174 | ref_cmd = referee_data['Command'] 175 | 176 | if self.challenge_running: 177 | if ref_cmd == 'HALT': 178 | purple_print(f'\nReferee Command = {ref_cmd}') 179 | self.manager_fsm.challenge_external_event(ChallengeEvents.GOAL) 180 | elif ref_cmd == 'STOP': 181 | purple_print(f'\nReferee Command = {ref_cmd}') 182 | self.manager_fsm.challenge_external_event(ChallengeEvents.STOP) 183 | 184 | # ============================================================================= 185 | 186 | def check_challenge_positions(self): 187 | self.position_fsm.update_positions(self.blue_robots, 188 | self.yellow_robots, self.ball) 189 | 190 | def objects_positioned(self): 191 | green_print('Start') 192 | self.challenge_running = True 193 | 194 | def run_challenge(self): 195 | gc_command = self.manager_fsm.get_current_command() 196 | 197 | if gc_command != GCCommands.NONE: 198 | self.gc_socket.send_command(gc_command, BLUE_TEAM) 199 | purple_print('Sent', gc_command.name) 200 | 201 | def challenge_end(self): 202 | blue_print('Challenge Ended!') 203 | self.gc_socket.send_command(GCCommands.HALT) 204 | challenge_time = self.manager_fsm.get_challenge_time() 205 | 206 | green_print('Challenge took {:.2f} seconds'.format(challenge_time)) 207 | 208 | self.challenge_running = False 209 | self.running = False 210 | 211 | # ============================================================================= 212 | 213 | def update_challenge_3_bot_position(self, pos: Position, start_pos: Position): 214 | if pos.x >= INF: 215 | return 216 | 217 | if self.challenge_number == 3 and self.challenge_running: 218 | if self.challenge_3_bot_pos[0].t <= 0: 219 | if DEBUG: 220 | purple_print('Start counting') 221 | self.challenge_3_bot_pos[0].t = time.time_ns()/1e9 222 | self.challenge_3_bot_pos[1].t = time.time_ns()/1e9 223 | self.challenge_3_bot_pos[0].set_pos(pos) 224 | self.challenge_3_bot_pos[1].set_pos(pos) 225 | else: 226 | self.challenge_3_bot_pos[1].t = time.time_ns()/1e9 227 | self.challenge_3_bot_pos[1].set_pos(pos) 228 | 229 | dist = self.challenge_3_bot_pos[1].distance( 230 | self.challenge_3_bot_pos[0]) 231 | 232 | dist_start = self.challenge_3_bot_pos[0].distance(start_pos) 233 | dt = self.challenge_3_bot_pos[1].t - self.challenge_3_bot_pos[0].t 234 | 235 | if dist >= DISTANCE_THRESHOLD: 236 | self.challenge_3_bot_pos[0].t = 0 237 | self.challenge_3_bot_pos[1].t = 0 238 | 239 | elif dt >= ROBOT_STOP_TRESHOLD: 240 | if DEBUG: 241 | purple_print('Stop counting') 242 | if dist <= DISTANCE_THRESHOLD and dist_start > 2400: 243 | self.manager_fsm.challenge_external_event( 244 | ChallengeEvents.ROBOT_STOPPED) 245 | 246 | 247 | # ============================================================================= 248 | 249 | def end_program(self): 250 | self.running = False 251 | 252 | # ============================================================================= 253 | 254 | 255 | if __name__ == "__main__": 256 | manager = HWChallengeManager() 257 | 258 | while manager.running: 259 | manager.update_vision_data() 260 | manager.update_referee_data() 261 | 262 | if manager.challenge_running: 263 | manager.run_challenge() 264 | 265 | ui_msg = manager.draw.get_ui_event() 266 | if ui_msg == 'QUIT': 267 | break 268 | 269 | manager.draw.stop() 270 | red_print('\nQuit') 271 | -------------------------------------------------------------------------------- /src/aux/position_robot.py: -------------------------------------------------------------------------------- 1 | import json 2 | import time 3 | import numpy as np 4 | 5 | from enum import Enum 6 | from tabulate import tabulate 7 | from os.path import isfile 8 | from aux.RobotBall import Position, Ball, Robot, BLUE_TEAM, YELLOW_TEAM, BALL,\ 9 | DISTANCE_THRESHOLD 10 | from aux.utils import red_print, blue_print, green_print, purple_print 11 | 12 | from aux.hw_challenge_1 import Challenge_1 13 | from aux.hw_challenge_2 import Challenge_2 14 | from aux.hw_challenge_3 import Challenge_3 15 | from aux.hw_challenge_4 import Challenge_4 16 | from aux.tc_ball_placement import BallPlacement 17 | from aux.hw_challenge_fsm import MAX_CHALLENGES 18 | 19 | CONFIRMATION_DT = 2 # in seconds 20 | 21 | 22 | class PositionStates(Enum): 23 | POSITIONING = 0, 24 | POSITIONED = 1 25 | 26 | 27 | class Challenge_Data(Robot): 28 | def __init__(self): 29 | super().__init__() 30 | self.ok = False 31 | self.type = BLUE_TEAM 32 | 33 | def __repr__(self) -> str: 34 | return '{}/{}/{} = {}'.format(self.type, self.id, self.ok, self.pos) 35 | 36 | def to_table_format(self) -> []: 37 | obj = 'Robot {}'.format(self.type) 38 | if self.type == BALL: 39 | obj = 'Ball' 40 | return [self.ok, obj, self.id, 41 | self.pos.x, self.pos.y, self.pos.orientation] 42 | 43 | def from_Robot(self, robot: Robot): 44 | self.pos = robot.pos 45 | self.type = robot.team 46 | self.id = robot.id 47 | self.unseen_frames = robot.unseen_frames 48 | 49 | def from_Ball(self, ball: Ball): 50 | self.pos = ball.pos 51 | self.type = BALL 52 | 53 | 54 | class PositionFSM(object): 55 | """ 56 | Finite State Machine that checks wheter the robots/ball are correctly 57 | positioned before the hardware challenge starts 58 | """ 59 | 60 | def __init__(self, challenge_filename: str): 61 | self.use_ball = False 62 | self.has_ball_placement_data = False 63 | self.json_blue_id = -1 64 | self.read_challenge_file(challenge_filename) 65 | 66 | self.state = PositionStates.POSITIONING 67 | self.object_positioned_callback = None 68 | 69 | self.current_challenge = None 70 | self.objects_in_place = False 71 | self.objects_t1 = 0 72 | self.objects_t2 = 0 73 | 74 | # ============================================================================= 75 | 76 | def challenge_positions_print(self): 77 | header = ['Positioned', 'Object', 'ID', 78 | 'X [mm]', 'Y [mm]', 'Angle [rad]'] 79 | data = [line.to_table_format() for line in self.challenge_pos] 80 | blue_print(tabulate(data, header), '\n') 81 | 82 | # ============================================================================= 83 | 84 | def set_end_callback(self, callback_fn=None): 85 | if callback_fn != None: 86 | self.object_positioned_callback = callback_fn 87 | green_print('[POSITION FSM] Callback Set!') 88 | 89 | # ============================================================================= 90 | 91 | def set_challenge(self, challenge: int): 92 | if not isinstance(challenge, int) or (challenge < 1 or challenge > MAX_CHALLENGES): 93 | raise ValueError( 94 | f'Challenge ID must be between 1 and {MAX_CHALLENGES}!') 95 | 96 | if challenge == 1: 97 | self.current_challenge = Challenge_1 98 | elif challenge == 2: 99 | self.current_challenge = Challenge_2 100 | elif challenge == 3: 101 | self.current_challenge = Challenge_3 102 | elif challenge == 4: 103 | self.current_challenge = Challenge_4 104 | elif challenge == 5: 105 | self.current_challenge = BallPlacement 106 | 107 | # ============================================================================= 108 | 109 | def read_challenge_file(self, filename): 110 | if not isfile(filename): 111 | red_print("The file {} doesn't exist!".format(filename)) 112 | exit(1) 113 | 114 | with open(filename) as challenge_file: 115 | json_data = json.load(challenge_file) 116 | 117 | data_keys = list(json_data.keys()) 118 | 119 | n_bots = 0 120 | if 'bots' in data_keys: 121 | n_bots = len(json_data['bots']) 122 | 123 | self.challenge_pos = [Challenge_Data() for i in range(n_bots + 1)] 124 | self.ball_placement_pos = Challenge_Data() 125 | 126 | if 'ball' in data_keys: 127 | self.use_ball = True 128 | self.challenge_pos[0].from_Ball( 129 | Ball(Position(*tuple(json_data['ball']['pos'])))) 130 | 131 | if 'ball_placement' in data_keys: 132 | self.has_ball_placement_data = True 133 | self.ball_placement_pos.from_Ball( 134 | Ball(Position(*tuple(json_data['ball_placement']['pos'])))) 135 | 136 | if n_bots > 0: 137 | [self.challenge_pos[n+int(self.use_ball)].from_Robot(Robot(obj=bot_data['obj'], id=bot_data['id'])) 138 | for n, bot_data in enumerate(json_data['bots'])] 139 | 140 | for bot in self.challenge_pos: 141 | if bot.type == BLUE_TEAM: 142 | self.json_blue_id = bot.id 143 | 144 | self.challenge_positions_print() 145 | 146 | # ============================================================================= 147 | 148 | def update_positions(self, blue_robots: [Robot], yellow_robots: [Robot], 149 | ball: Ball): 150 | n_pos_ok = self.n_positions_ok() 151 | for pos_data in self.challenge_pos: 152 | pos_data.ok = False 153 | if pos_data.type == BLUE_TEAM: 154 | for blue_robot in blue_robots: 155 | if blue_robot.compare(pos_data): 156 | pos_data.ok = True 157 | 158 | elif pos_data.type == YELLOW_TEAM: 159 | for yellow_robot in yellow_robots: 160 | if yellow_robot.compare(pos_data): 161 | pos_data.ok = True 162 | 163 | elif pos_data.type == BALL: 164 | if ball.compare(pos_data): 165 | pos_data.ok = True 166 | 167 | if self.state == PositionStates.POSITIONING: 168 | yellow_not_in_json = self.robot_ids_not_in_json(yellow_robots) 169 | blue_not_in_json = self.robot_ids_not_in_json(blue_robots) 170 | extra_robots_ok = True 171 | 172 | if yellow_not_in_json > 0: 173 | extra_robots_ok = False 174 | # red_print( 175 | # f'[POSITION FSM] There are {yellow_not_in_json} extra yellow robots in the field, please remove them!') 176 | 177 | if blue_not_in_json > 0: 178 | extra_robots_ok = extra_robots_ok & self.check_extra_robots(blue_robots, 179 | blue_not_in_json, 180 | ball) 181 | 182 | self.check_positions_ok(extra_robots_ok) 183 | 184 | if self.n_positions_ok() > n_pos_ok: 185 | self.challenge_positions_print() 186 | 187 | # ============================================================================= 188 | 189 | def n_positions_ok(self) -> int: 190 | return np.sum(np.array([data.ok for data in self.challenge_pos])) 191 | 192 | # ============================================================================= 193 | 194 | def check_extra_robots(self, robots: [Robot], robot_ids: int, ball: Ball) -> bool: 195 | ok = True 196 | type_of_restriction = '' 197 | if self.current_challenge != None: 198 | if self.current_challenge.has_extra_data: 199 | type_of_restriction = self.current_challenge.robots_restriction 200 | else: 201 | red_print( 202 | '[POSITION FSM] Current challenge undefined, should not happen!') 203 | return False 204 | 205 | if robot_ids > self.max_attackers(): 206 | ok = False 207 | # red_print("""[POSITION FSM] There are extra blue robots in the field 208 | # \t Found = {}, Max = {}""".format(robot_ids, 209 | # self.max_attackers())) 210 | elif robot_ids < self.min_attackers(): 211 | ok = False 212 | # red_print("""[POSITION FSM] Not enough blue robots in the field 213 | # \t Found = {}, Min = {}""".format(robot_ids, 214 | # self.min_attackers())) 215 | 216 | # If the number of robots is ok, check their positions 217 | if ok: 218 | msg = '' 219 | if type_of_restriction == 'MiddleLine': 220 | ok, _ = self.current_challenge.check_restriction(robots) 221 | 222 | if not ok: 223 | msg = '[POSITION FSM] The robots must stay in the middle line (x = 0)' 224 | 225 | if len(msg) > 0 and not ok: 226 | red_print(msg) 227 | 228 | return ok 229 | 230 | # ============================================================================= 231 | 232 | def check_positions_ok(self, extra_robots_ok: bool): 233 | # All objects are in the correct place 234 | if not any(np.invert([data.ok for data in self.challenge_pos])) and extra_robots_ok: 235 | if self.objects_in_place == False: 236 | self.objects_in_place = True 237 | self.objects_t1 = time.time_ns() 238 | self.objects_t2 = CONFIRMATION_DT 239 | 240 | green_print('All robots and ball are placed correctly!') 241 | 242 | elif self.objects_t2 > 0: 243 | self.objects_t2 -= 1e-9*(time.time_ns() - self.objects_t1) 244 | self.objects_t1 = time.time_ns() 245 | 246 | print('Wait {:.2f} seconds'.format(self.objects_t2), end='\r') 247 | 248 | elif self.objects_in_place and self.objects_t2 <= 0: 249 | self.state = PositionStates.POSITIONED 250 | 251 | green_print( 252 | 'Starting the challenge, press Enter to continue...') 253 | input() 254 | 255 | if self.object_positioned_callback != None: 256 | self.object_positioned_callback() 257 | 258 | elif self.objects_in_place == True: 259 | self.objects_in_place = False 260 | self.objects_t1 = 0 261 | self.objects_t1 = 0 262 | 263 | # ============================================================================= 264 | 265 | def get_challenge_positions(self) -> [Challenge_Data]: 266 | return self.challenge_pos 267 | 268 | # ============================================================================= 269 | 270 | def robot_ids_not_in_json(self, robots: [Robot]) -> int: 271 | challenge_ids = len([data.id for data in self.challenge_pos 272 | if data.type == robots[0].team]) 273 | 274 | ids_not_json = len([robot.id for robot in robots if robot.in_vision()]) 275 | 276 | return ids_not_json - challenge_ids 277 | 278 | # ============================================================================= 279 | 280 | def max_attackers(self) -> int: 281 | if self.current_challenge != None: 282 | return self.current_challenge.max_attack_robots 283 | # There are no limits 284 | raise ValueError( 285 | '[POSITION FSM] Current challenge undefined, should not happen!') 286 | 287 | def min_attackers(self) -> int: 288 | if self.current_challenge != None: 289 | return self.current_challenge.min_attack_robots 290 | # There are no limits 291 | raise ValueError( 292 | '[POSITION FSM] Current challenge undefined, should not happen!') 293 | 294 | # ============================================================================= 295 | 296 | def get_pos(self, id: int, type: str) -> Position: 297 | for pos in self.challenge_pos: 298 | if pos.id == id and pos.type == type: 299 | return pos.pos 300 | return Position() 301 | 302 | def get_placement(self) -> [int, int]: 303 | if self.has_ball_placement_data: 304 | return [self.ball_placement_pos.pos.x, 305 | self.ball_placement_pos.pos.y] 306 | return [0, 0] 307 | -------------------------------------------------------------------------------- /src/ssl_vision_detection_pb2.py: -------------------------------------------------------------------------------- 1 | # Generated by the protocol buffer compiler. DO NOT EDIT! 2 | # source: ssl_vision_detection.proto 3 | 4 | import sys 5 | _b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) 6 | from google.protobuf import descriptor as _descriptor 7 | from google.protobuf import message as _message 8 | from google.protobuf import reflection as _reflection 9 | from google.protobuf import symbol_database as _symbol_database 10 | # @@protoc_insertion_point(imports) 11 | 12 | _sym_db = _symbol_database.Default() 13 | 14 | 15 | 16 | 17 | DESCRIPTOR = _descriptor.FileDescriptor( 18 | name='ssl_vision_detection.proto', 19 | package='', 20 | syntax='proto2', 21 | serialized_options=_b('Z6github.com/RoboCup-SSL/ssl-simulation-protocol/pkg/sim'), 22 | serialized_pb=_b('\n\x1assl_vision_detection.proto\"x\n\x11SSL_DetectionBall\x12\x12\n\nconfidence\x18\x01 \x02(\x02\x12\x0c\n\x04\x61rea\x18\x02 \x01(\r\x12\t\n\x01x\x18\x03 \x02(\x02\x12\t\n\x01y\x18\x04 \x02(\x02\x12\t\n\x01z\x18\x05 \x01(\x02\x12\x0f\n\x07pixel_x\x18\x06 \x02(\x02\x12\x0f\n\x07pixel_y\x18\x07 \x02(\x02\"\x97\x01\n\x12SSL_DetectionRobot\x12\x12\n\nconfidence\x18\x01 \x02(\x02\x12\x10\n\x08robot_id\x18\x02 \x01(\r\x12\t\n\x01x\x18\x03 \x02(\x02\x12\t\n\x01y\x18\x04 \x02(\x02\x12\x13\n\x0borientation\x18\x05 \x01(\x02\x12\x0f\n\x07pixel_x\x18\x06 \x02(\x02\x12\x0f\n\x07pixel_y\x18\x07 \x02(\x02\x12\x0e\n\x06height\x18\x08 \x01(\x02\"\xd9\x01\n\x12SSL_DetectionFrame\x12\x14\n\x0c\x66rame_number\x18\x01 \x02(\r\x12\x11\n\tt_capture\x18\x02 \x02(\x01\x12\x0e\n\x06t_sent\x18\x03 \x02(\x01\x12\x11\n\tcamera_id\x18\x04 \x02(\r\x12!\n\x05\x62\x61lls\x18\x05 \x03(\x0b\x32\x12.SSL_DetectionBall\x12*\n\rrobots_yellow\x18\x06 \x03(\x0b\x32\x13.SSL_DetectionRobot\x12(\n\x0brobots_blue\x18\x07 \x03(\x0b\x32\x13.SSL_DetectionRobotB8Z6github.com/RoboCup-SSL/ssl-simulation-protocol/pkg/sim') 23 | ) 24 | 25 | 26 | 27 | 28 | _SSL_DETECTIONBALL = _descriptor.Descriptor( 29 | name='SSL_DetectionBall', 30 | full_name='SSL_DetectionBall', 31 | filename=None, 32 | file=DESCRIPTOR, 33 | containing_type=None, 34 | fields=[ 35 | _descriptor.FieldDescriptor( 36 | name='confidence', full_name='SSL_DetectionBall.confidence', index=0, 37 | number=1, type=2, cpp_type=6, label=2, 38 | has_default_value=False, default_value=float(0), 39 | message_type=None, enum_type=None, containing_type=None, 40 | is_extension=False, extension_scope=None, 41 | serialized_options=None, file=DESCRIPTOR), 42 | _descriptor.FieldDescriptor( 43 | name='area', full_name='SSL_DetectionBall.area', index=1, 44 | number=2, type=13, cpp_type=3, label=1, 45 | has_default_value=False, default_value=0, 46 | message_type=None, enum_type=None, containing_type=None, 47 | is_extension=False, extension_scope=None, 48 | serialized_options=None, file=DESCRIPTOR), 49 | _descriptor.FieldDescriptor( 50 | name='x', full_name='SSL_DetectionBall.x', index=2, 51 | number=3, type=2, cpp_type=6, label=2, 52 | has_default_value=False, default_value=float(0), 53 | message_type=None, enum_type=None, containing_type=None, 54 | is_extension=False, extension_scope=None, 55 | serialized_options=None, file=DESCRIPTOR), 56 | _descriptor.FieldDescriptor( 57 | name='y', full_name='SSL_DetectionBall.y', index=3, 58 | number=4, type=2, cpp_type=6, label=2, 59 | has_default_value=False, default_value=float(0), 60 | message_type=None, enum_type=None, containing_type=None, 61 | is_extension=False, extension_scope=None, 62 | serialized_options=None, file=DESCRIPTOR), 63 | _descriptor.FieldDescriptor( 64 | name='z', full_name='SSL_DetectionBall.z', index=4, 65 | number=5, type=2, cpp_type=6, label=1, 66 | has_default_value=False, default_value=float(0), 67 | message_type=None, enum_type=None, containing_type=None, 68 | is_extension=False, extension_scope=None, 69 | serialized_options=None, file=DESCRIPTOR), 70 | _descriptor.FieldDescriptor( 71 | name='pixel_x', full_name='SSL_DetectionBall.pixel_x', index=5, 72 | number=6, type=2, cpp_type=6, label=2, 73 | has_default_value=False, default_value=float(0), 74 | message_type=None, enum_type=None, containing_type=None, 75 | is_extension=False, extension_scope=None, 76 | serialized_options=None, file=DESCRIPTOR), 77 | _descriptor.FieldDescriptor( 78 | name='pixel_y', full_name='SSL_DetectionBall.pixel_y', index=6, 79 | number=7, type=2, cpp_type=6, label=2, 80 | has_default_value=False, default_value=float(0), 81 | message_type=None, enum_type=None, containing_type=None, 82 | is_extension=False, extension_scope=None, 83 | serialized_options=None, file=DESCRIPTOR), 84 | ], 85 | extensions=[ 86 | ], 87 | nested_types=[], 88 | enum_types=[ 89 | ], 90 | serialized_options=None, 91 | is_extendable=False, 92 | syntax='proto2', 93 | extension_ranges=[], 94 | oneofs=[ 95 | ], 96 | serialized_start=30, 97 | serialized_end=150, 98 | ) 99 | 100 | 101 | _SSL_DETECTIONROBOT = _descriptor.Descriptor( 102 | name='SSL_DetectionRobot', 103 | full_name='SSL_DetectionRobot', 104 | filename=None, 105 | file=DESCRIPTOR, 106 | containing_type=None, 107 | fields=[ 108 | _descriptor.FieldDescriptor( 109 | name='confidence', full_name='SSL_DetectionRobot.confidence', index=0, 110 | number=1, type=2, cpp_type=6, label=2, 111 | has_default_value=False, default_value=float(0), 112 | message_type=None, enum_type=None, containing_type=None, 113 | is_extension=False, extension_scope=None, 114 | serialized_options=None, file=DESCRIPTOR), 115 | _descriptor.FieldDescriptor( 116 | name='robot_id', full_name='SSL_DetectionRobot.robot_id', index=1, 117 | number=2, type=13, cpp_type=3, label=1, 118 | has_default_value=False, default_value=0, 119 | message_type=None, enum_type=None, containing_type=None, 120 | is_extension=False, extension_scope=None, 121 | serialized_options=None, file=DESCRIPTOR), 122 | _descriptor.FieldDescriptor( 123 | name='x', full_name='SSL_DetectionRobot.x', index=2, 124 | number=3, type=2, cpp_type=6, label=2, 125 | has_default_value=False, default_value=float(0), 126 | message_type=None, enum_type=None, containing_type=None, 127 | is_extension=False, extension_scope=None, 128 | serialized_options=None, file=DESCRIPTOR), 129 | _descriptor.FieldDescriptor( 130 | name='y', full_name='SSL_DetectionRobot.y', index=3, 131 | number=4, type=2, cpp_type=6, label=2, 132 | has_default_value=False, default_value=float(0), 133 | message_type=None, enum_type=None, containing_type=None, 134 | is_extension=False, extension_scope=None, 135 | serialized_options=None, file=DESCRIPTOR), 136 | _descriptor.FieldDescriptor( 137 | name='orientation', full_name='SSL_DetectionRobot.orientation', index=4, 138 | number=5, type=2, cpp_type=6, label=1, 139 | has_default_value=False, default_value=float(0), 140 | message_type=None, enum_type=None, containing_type=None, 141 | is_extension=False, extension_scope=None, 142 | serialized_options=None, file=DESCRIPTOR), 143 | _descriptor.FieldDescriptor( 144 | name='pixel_x', full_name='SSL_DetectionRobot.pixel_x', index=5, 145 | number=6, type=2, cpp_type=6, label=2, 146 | has_default_value=False, default_value=float(0), 147 | message_type=None, enum_type=None, containing_type=None, 148 | is_extension=False, extension_scope=None, 149 | serialized_options=None, file=DESCRIPTOR), 150 | _descriptor.FieldDescriptor( 151 | name='pixel_y', full_name='SSL_DetectionRobot.pixel_y', index=6, 152 | number=7, type=2, cpp_type=6, label=2, 153 | has_default_value=False, default_value=float(0), 154 | message_type=None, enum_type=None, containing_type=None, 155 | is_extension=False, extension_scope=None, 156 | serialized_options=None, file=DESCRIPTOR), 157 | _descriptor.FieldDescriptor( 158 | name='height', full_name='SSL_DetectionRobot.height', index=7, 159 | number=8, type=2, cpp_type=6, label=1, 160 | has_default_value=False, default_value=float(0), 161 | message_type=None, enum_type=None, containing_type=None, 162 | is_extension=False, extension_scope=None, 163 | serialized_options=None, file=DESCRIPTOR), 164 | ], 165 | extensions=[ 166 | ], 167 | nested_types=[], 168 | enum_types=[ 169 | ], 170 | serialized_options=None, 171 | is_extendable=False, 172 | syntax='proto2', 173 | extension_ranges=[], 174 | oneofs=[ 175 | ], 176 | serialized_start=153, 177 | serialized_end=304, 178 | ) 179 | 180 | 181 | _SSL_DETECTIONFRAME = _descriptor.Descriptor( 182 | name='SSL_DetectionFrame', 183 | full_name='SSL_DetectionFrame', 184 | filename=None, 185 | file=DESCRIPTOR, 186 | containing_type=None, 187 | fields=[ 188 | _descriptor.FieldDescriptor( 189 | name='frame_number', full_name='SSL_DetectionFrame.frame_number', index=0, 190 | number=1, type=13, cpp_type=3, label=2, 191 | has_default_value=False, default_value=0, 192 | message_type=None, enum_type=None, containing_type=None, 193 | is_extension=False, extension_scope=None, 194 | serialized_options=None, file=DESCRIPTOR), 195 | _descriptor.FieldDescriptor( 196 | name='t_capture', full_name='SSL_DetectionFrame.t_capture', index=1, 197 | number=2, type=1, cpp_type=5, label=2, 198 | has_default_value=False, default_value=float(0), 199 | message_type=None, enum_type=None, containing_type=None, 200 | is_extension=False, extension_scope=None, 201 | serialized_options=None, file=DESCRIPTOR), 202 | _descriptor.FieldDescriptor( 203 | name='t_sent', full_name='SSL_DetectionFrame.t_sent', index=2, 204 | number=3, type=1, cpp_type=5, label=2, 205 | has_default_value=False, default_value=float(0), 206 | message_type=None, enum_type=None, containing_type=None, 207 | is_extension=False, extension_scope=None, 208 | serialized_options=None, file=DESCRIPTOR), 209 | _descriptor.FieldDescriptor( 210 | name='camera_id', full_name='SSL_DetectionFrame.camera_id', index=3, 211 | number=4, type=13, cpp_type=3, label=2, 212 | has_default_value=False, default_value=0, 213 | message_type=None, enum_type=None, containing_type=None, 214 | is_extension=False, extension_scope=None, 215 | serialized_options=None, file=DESCRIPTOR), 216 | _descriptor.FieldDescriptor( 217 | name='balls', full_name='SSL_DetectionFrame.balls', index=4, 218 | number=5, type=11, cpp_type=10, label=3, 219 | has_default_value=False, default_value=[], 220 | message_type=None, enum_type=None, containing_type=None, 221 | is_extension=False, extension_scope=None, 222 | serialized_options=None, file=DESCRIPTOR), 223 | _descriptor.FieldDescriptor( 224 | name='robots_yellow', full_name='SSL_DetectionFrame.robots_yellow', index=5, 225 | number=6, type=11, cpp_type=10, label=3, 226 | has_default_value=False, default_value=[], 227 | message_type=None, enum_type=None, containing_type=None, 228 | is_extension=False, extension_scope=None, 229 | serialized_options=None, file=DESCRIPTOR), 230 | _descriptor.FieldDescriptor( 231 | name='robots_blue', full_name='SSL_DetectionFrame.robots_blue', index=6, 232 | number=7, type=11, cpp_type=10, label=3, 233 | has_default_value=False, default_value=[], 234 | message_type=None, enum_type=None, containing_type=None, 235 | is_extension=False, extension_scope=None, 236 | serialized_options=None, file=DESCRIPTOR), 237 | ], 238 | extensions=[ 239 | ], 240 | nested_types=[], 241 | enum_types=[ 242 | ], 243 | serialized_options=None, 244 | is_extendable=False, 245 | syntax='proto2', 246 | extension_ranges=[], 247 | oneofs=[ 248 | ], 249 | serialized_start=307, 250 | serialized_end=524, 251 | ) 252 | 253 | _SSL_DETECTIONFRAME.fields_by_name['balls'].message_type = _SSL_DETECTIONBALL 254 | _SSL_DETECTIONFRAME.fields_by_name['robots_yellow'].message_type = _SSL_DETECTIONROBOT 255 | _SSL_DETECTIONFRAME.fields_by_name['robots_blue'].message_type = _SSL_DETECTIONROBOT 256 | DESCRIPTOR.message_types_by_name['SSL_DetectionBall'] = _SSL_DETECTIONBALL 257 | DESCRIPTOR.message_types_by_name['SSL_DetectionRobot'] = _SSL_DETECTIONROBOT 258 | DESCRIPTOR.message_types_by_name['SSL_DetectionFrame'] = _SSL_DETECTIONFRAME 259 | _sym_db.RegisterFileDescriptor(DESCRIPTOR) 260 | 261 | SSL_DetectionBall = _reflection.GeneratedProtocolMessageType('SSL_DetectionBall', (_message.Message,), dict( 262 | DESCRIPTOR = _SSL_DETECTIONBALL, 263 | __module__ = 'ssl_vision_detection_pb2' 264 | # @@protoc_insertion_point(class_scope:SSL_DetectionBall) 265 | )) 266 | _sym_db.RegisterMessage(SSL_DetectionBall) 267 | 268 | SSL_DetectionRobot = _reflection.GeneratedProtocolMessageType('SSL_DetectionRobot', (_message.Message,), dict( 269 | DESCRIPTOR = _SSL_DETECTIONROBOT, 270 | __module__ = 'ssl_vision_detection_pb2' 271 | # @@protoc_insertion_point(class_scope:SSL_DetectionRobot) 272 | )) 273 | _sym_db.RegisterMessage(SSL_DetectionRobot) 274 | 275 | SSL_DetectionFrame = _reflection.GeneratedProtocolMessageType('SSL_DetectionFrame', (_message.Message,), dict( 276 | DESCRIPTOR = _SSL_DETECTIONFRAME, 277 | __module__ = 'ssl_vision_detection_pb2' 278 | # @@protoc_insertion_point(class_scope:SSL_DetectionFrame) 279 | )) 280 | _sym_db.RegisterMessage(SSL_DetectionFrame) 281 | 282 | 283 | DESCRIPTOR._options = None 284 | # @@protoc_insertion_point(module_scope) 285 | -------------------------------------------------------------------------------- /src/DrawSSL.py: -------------------------------------------------------------------------------- 1 | import pygame 2 | import pygame.freetype 3 | import time 4 | import numpy as np 5 | 6 | from multiprocessing import Process, Queue 7 | from math import sqrt, acos, pi, trunc, cos, sin 8 | 9 | from aux.RobotBall import Robot, Position, BLUE_TEAM, YELLOW_TEAM, BALL, INF,\ 10 | DISTANCE_THRESHOLD, ORIENTATION_THRESHOLD 11 | from aux.utils import red_print, blue_print, green_print, purple_print 12 | from aux.position_robot import Challenge_Data 13 | 14 | FIELD_LINE_PEN_SZ = 6 15 | SCREEN_SIZE = [800, 600] 16 | FIELD_BORDER = 500 17 | 18 | BALL_RADIUS = 42 # a bit bigger just to be more visible 19 | BOT_RADIUS = 90 20 | 21 | BLUE_C = 'blue' 22 | C_BLUE_C = (102, 204, 255) # = #66ccff 23 | 24 | YELLOW_C = (179, 179, 0) # = #b3b300 25 | D_YELLOW_C = (153, 102, 0) # = #996600 26 | 27 | GREEN_C = (153, 255, 153) # = #99ff99 28 | D_GREEN_C = (0, 102, 0) # = #006600 29 | BLACK_C = 'black' 30 | 31 | ORANGE_C = (255, 153, 0) # = #ff9900 32 | 33 | 34 | class DrawSSL(object): 35 | def __init__(self): 36 | self.ui_init = False 37 | 38 | self.field_size = np.array([800, 600]) 39 | self.center_circle_radius = 100 40 | self.ball = np.array([INF, INF]) 41 | self.blue_robots = [] 42 | self.yellow_robots = [] 43 | self.challenge_positions = [] 44 | 45 | # ============================================================================= 46 | 47 | def draw(self): 48 | while True: 49 | if not self.process_queue.empty(): 50 | if self.parse_process_msg(): 51 | break 52 | 53 | if not self.ui_init: 54 | self.ui_init = True 55 | self.init_ui() 56 | else: 57 | self.update_drawings() 58 | self.event_loop() 59 | 60 | pygame.display.update() 61 | self.clock.tick(60) 62 | 63 | # ============================================================================= 64 | 65 | def event_loop(self): 66 | for event in pygame.event.get(): 67 | if event.type == pygame.QUIT: 68 | self.ui_queue.put_nowait('QUIT') 69 | 70 | elif event.type == pygame.KEYUP: 71 | if event.key == pygame.K_q: 72 | self.ui_queue.put_nowait('QUIT') 73 | elif event.type == pygame.WINDOWRESIZED: 74 | win_sz = self.window.get_size() 75 | global SCREEN_SIZE 76 | SCREEN_SIZE = [win_sz[0], win_sz[1]] 77 | 78 | # ============================================================================= 79 | 80 | def parse_process_msg(self) -> str: 81 | end_ui = False 82 | while not self.process_queue.empty(): 83 | msg = self.process_queue.get_nowait() 84 | if 'END' in msg.keys() and msg['END']: 85 | end_ui = True 86 | elif 'FieldSZ' in msg.keys(): 87 | self.field_size = msg['FieldSZ'] 88 | end_ui = False 89 | elif 'CircleSZ' in msg.keys(): 90 | self.center_circle_radius = msg['CircleSZ'] 91 | end_ui = False 92 | elif 'BallP' in msg.keys(): 93 | self.ball = msg['BallP'] 94 | end_ui = False 95 | elif 'BotYP' in msg.keys(): 96 | self.yellow_robots = msg['BotYP'] 97 | end_ui = False 98 | elif 'BotBP' in msg.keys(): 99 | self.blue_robots = msg['BotBP'] 100 | end_ui = False 101 | elif 'ChallengeP' in msg.keys(): 102 | self.challenge_positions = msg['ChallengeP'] 103 | end_ui = False 104 | return end_ui 105 | 106 | # ============================================================================= 107 | 108 | def update_drawings(self): 109 | self.window.fill(D_GREEN_C) 110 | 111 | scaled_field = self.scale(self.field_size) 112 | self.draw_field(scaled_field) 113 | self.draw_ball(scaled_field) 114 | self.draw_robots(scaled_field) 115 | self.draw_challenges_positions(scaled_field) 116 | 117 | # ============================================================================= 118 | 119 | def init_ui(self): 120 | pygame.init() 121 | self.font = pygame.freetype.Font(r'resources/Days.ttf', 14) 122 | self.font.antialiased = True 123 | 124 | self.clock = pygame.time.Clock() 125 | 126 | self.canvas = pygame.Surface(SCREEN_SIZE) 127 | flags = pygame.RESIZABLE 128 | self.window = pygame.display.set_mode(SCREEN_SIZE, flags) 129 | pygame.display.set_caption('Field View') 130 | 131 | # ============================================================================= 132 | 133 | def start(self): 134 | green_print('[UI] Started!\n\t Press Q/q or close the window to exit!') 135 | self.ui_queue = Queue() 136 | # 16 = MAX_ROBOTS 137 | self.process_queue = Queue(16*3 + 5) 138 | self.process = Process(target=self.draw) 139 | 140 | self.process.start() 141 | 142 | # ============================================================================= 143 | 144 | def stop(self): 145 | self.process_queue.put({'END': True}) 146 | self.process.join() 147 | pygame.quit() 148 | 149 | # ============================================================================= 150 | 151 | def set_field_size(self, new_size: [int, int]): 152 | if self.process.is_alive() and not self.process_queue.full(): 153 | self.field_size = np.array(new_size) 154 | self.process_queue.put_nowait({'FieldSZ': self.field_size}) 155 | 156 | # ============================================================================= 157 | 158 | def set_center_circle_radius(self, radius: int): 159 | if self.process.is_alive() and not self.process_queue.full(): 160 | self.center_circle_radius = radius 161 | self.process_queue.put_nowait({'CircleSZ': radius}) 162 | 163 | # ============================================================================= 164 | 165 | def draw_field(self, scaled_field: np.array): 166 | adj_border = self.scale_val(FIELD_BORDER) 167 | 168 | pygame.draw.rect(self.window, 'white', width=FIELD_LINE_PEN_SZ, 169 | rect=(adj_border[0], adj_border[1], 170 | scaled_field[0], scaled_field[1])) 171 | 172 | for line in self.field_lines(scaled_field, adj_border): 173 | pygame.draw.line(self.window, 'white', 174 | width=round(FIELD_LINE_PEN_SZ/2), 175 | start_pos=line[0], end_pos=line[1]) 176 | 177 | pygame.draw.circle(self.window, 'white', 178 | width=round(FIELD_LINE_PEN_SZ/2), 179 | center=self.adjust_axis(np.array([0, 0]), 180 | scaled_field), 181 | radius=self.scale_rad(self.center_circle_radius)) 182 | 183 | 184 | # ============================================================================= 185 | 186 | def draw_ball(self, scaled_field: np.array): 187 | ball_p = self.scale(self.ball, scaled_field) 188 | 189 | if isinstance(scaled_field, np.ndarray) or isinstance(ball_p, np.ndarray) or \ 190 | len(ball_p) + len(scaled_field) == 4: 191 | pygame.draw.circle(self.window, ORANGE_C, ball_p, 192 | self.scale_rad(BALL_RADIUS)) 193 | 194 | # ============================================================================= 195 | 196 | def draw_robots(self, scaled_field: np.array): 197 | for bot in self.blue_robots: 198 | if bot.pos.x < INF: 199 | b_pos = np.array([bot.pos.x, bot.pos.y]) 200 | self.draw_bot(b_pos, bot.pos.orientation, BLUE_C, scaled_field, 201 | bot.id) 202 | 203 | for bot in self.yellow_robots: 204 | if bot.pos.x < INF: 205 | b_pos = np.array([bot.pos.x, bot.pos.y]) 206 | self.draw_bot(b_pos, bot.pos.orientation, YELLOW_C, scaled_field, 207 | bot.id) 208 | 209 | def draw_bot(self, pos: np.array, orientation: float, color, 210 | scaled_field: np.array, id: int): 211 | # Both arguments must be a numpy array and have a length of 2 each 212 | if not isinstance(scaled_field, np.ndarray) or \ 213 | not isinstance(pos, np.ndarray) or \ 214 | len(pos) + len(scaled_field) != 4: 215 | red_print('Invalid data received ', pos, scaled_field, type(pos), 216 | type(scaled_field)) 217 | return 218 | 219 | b_pos = self.scale(pos, scaled_field) 220 | id_pos = self.scale(pos - np.array([0.6*BOT_RADIUS, -0.5*BOT_RADIUS]), 221 | scaled_field) 222 | 223 | bot_rad = self.scale_rad(BOT_RADIUS) 224 | bot_teta = self.convert_orientation(orientation) 225 | angle_vec = np.array([cos(bot_teta)*bot_rad, -sin(bot_teta)*bot_rad]) 226 | 227 | pygame.draw.circle(self.window, color, b_pos, bot_rad) 228 | try: 229 | self.font.render_to(self.window, id_pos, f'{id}', (0, 0, 0)) 230 | except TypeError: 231 | pass 232 | except Exception as except_msg: 233 | blue_print(id_pos, type(id_pos), except_msg) 234 | 235 | b_pos = b_pos + angle_vec 236 | angle_pos = b_pos + angle_vec 237 | pygame.draw.line(self.window, 'red', b_pos, angle_pos, 3) 238 | 239 | def convert_orientation(self, orientation) -> float: 240 | if abs(orientation) > 2*pi: 241 | factor = orientation/(2*pi) - trunc(orientation/(2*pi)) 242 | orientation = factor * 2*pi 243 | 244 | if orientation < 0: 245 | orientation += 2*pi 246 | 247 | if orientation > 2*pi: 248 | orientation = orientation - 2*pi 249 | 250 | return orientation 251 | 252 | # ============================================================================= 253 | 254 | def draw_challenges_positions(self, scaled_field: np.array): 255 | color = BLUE_C 256 | for position in self.challenge_positions: 257 | draw_orientation = True 258 | text_c = BLACK_C 259 | 260 | if position.type == BLUE_TEAM: 261 | color = C_BLUE_C 262 | elif position.type == YELLOW_TEAM: 263 | color = D_YELLOW_C 264 | elif position.type == BALL: 265 | color = ORANGE_C 266 | draw_orientation = False 267 | 268 | if position.ok: 269 | color = GREEN_C 270 | text_c = GREEN_C 271 | 272 | id_pos = position.pos.to_numpy() 273 | id_pos = self.scale(id_pos + np.array([BOT_RADIUS, 2*BOT_RADIUS]), 274 | scaled_field) 275 | 276 | c_pos = self.scale(position.pos.to_numpy(), scaled_field) 277 | c_rad = self.scale_rad(BOT_RADIUS) 278 | pygame.draw.circle(self.window, color, c_pos, c_rad, width=4) 279 | 280 | if not draw_orientation: 281 | continue 282 | 283 | c_teta = self.convert_orientation(position.pos.orientation) 284 | 285 | min_thr = c_teta - ORIENTATION_THRESHOLD 286 | max_thr = c_teta + ORIENTATION_THRESHOLD 287 | 288 | angle_vec_min = 2 * c_rad * np.array([cos(min_thr), -sin(min_thr)]) 289 | angle_vec_max = 2 * c_rad * np.array([cos(max_thr), -sin(max_thr)]) 290 | 291 | p_min = c_pos + angle_vec_min 292 | p_max = c_pos + angle_vec_max 293 | pos_ang = [p_max, p_min, c_pos] 294 | 295 | pygame.draw.aalines(self.window, text_c, True, pos_ang) 296 | 297 | 298 | # ============================================================================= 299 | 300 | def update_robots(self, robots: [Robot], team: str): 301 | if self.process.is_alive() and not self.process_queue.full(): 302 | if team == YELLOW_TEAM: 303 | self.yellow_robots = robots 304 | self.process_queue.put_nowait({'BotYP': self.yellow_robots}) 305 | elif team == BLUE_TEAM: 306 | self.blue_robots = robots 307 | self.process_queue.put_nowait({'BotBP': self.blue_robots}) 308 | 309 | # ============================================================================= 310 | 311 | def update_ball(self, pos: Position): 312 | if self.process.is_alive() and not self.process_queue.full(): 313 | self.ball = np.array([pos.x, pos.y]) 314 | self.process_queue.put_nowait({'BallP': self.ball}) 315 | 316 | # ============================================================================= 317 | 318 | def update_challenge_data(self, chl_data: [Challenge_Data]): 319 | if self.process.is_alive() and not self.process_queue.full(): 320 | self.challenge_positions = chl_data 321 | self.process_queue.put_nowait({'ChallengeP': chl_data}) 322 | 323 | # ============================================================================= 324 | 325 | def scale(self, pos: np.array, field_sz=None) -> np.array: 326 | field_sz_border = self.field_size + \ 327 | np.array([2*FIELD_BORDER, 2*FIELD_BORDER]) 328 | scale_val = np.divide(np.array(SCREEN_SIZE), field_sz_border) 329 | 330 | if not isinstance(field_sz, np.ndarray): 331 | return np.multiply(pos, scale_val) 332 | 333 | return self.adjust_axis(np.multiply(pos, scale_val), field_sz) 334 | 335 | def scale_val(self, val) -> [float, float]: 336 | field_sz_border = self.field_size + \ 337 | np.array([2*FIELD_BORDER, 2*FIELD_BORDER]) 338 | scale_val = np.divide(np.array(SCREEN_SIZE), field_sz_border) 339 | 340 | return val * scale_val 341 | 342 | def scale_rad(self, val) -> float: 343 | field_sz_border = self.field_size + \ 344 | np.array([2*FIELD_BORDER, 2*FIELD_BORDER]) 345 | scale_val = np.divide(np.array(SCREEN_SIZE), field_sz_border) 346 | 347 | return val * sqrt(scale_val[0]**2 + scale_val[1]**2) 348 | 349 | def adjust_axis(self, pos: np.array, field_sz: np.array) -> np.array: 350 | border = self.scale_val(FIELD_BORDER) 351 | adj_p = np.add(pos, field_sz/2) 352 | adj_p[1] = field_sz[1] - adj_p[1] 353 | adj_p = np.add(adj_p, border) 354 | 355 | return adj_p 356 | 357 | # ============================================================================= 358 | 359 | def field_lines(self, field_sz: np.array, field_border: np.array): 360 | l1 = np.array([[field_sz[0]/2 + field_border[0], field_border[1]], 361 | [field_sz[0]/2 + field_border[0], field_sz[1] + field_border[1]]]) 362 | l2 = np.array([[field_border[0], field_sz[1]/2 + field_border[1]], 363 | [field_sz[0] + field_border[0], field_sz[1]/2 + field_border[1]]]) 364 | 365 | return [l1.tolist(), l2.tolist()] 366 | 367 | # ============================================================================= 368 | 369 | def get_ui_event(self) -> str: 370 | if self.init_ui and not self.ui_queue.empty(): 371 | return self.ui_queue.get_nowait() 372 | -------------------------------------------------------------------------------- /src/ssl_vision_detection_tracked_pb2.py: -------------------------------------------------------------------------------- 1 | # Generated by the protocol buffer compiler. DO NOT EDIT! 2 | # source: ssl_vision_detection_tracked.proto 3 | 4 | import sys 5 | _b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) 6 | from google.protobuf.internal import enum_type_wrapper 7 | from google.protobuf import descriptor as _descriptor 8 | from google.protobuf import message as _message 9 | from google.protobuf import reflection as _reflection 10 | from google.protobuf import symbol_database as _symbol_database 11 | # @@protoc_insertion_point(imports) 12 | 13 | _sym_db = _symbol_database.Default() 14 | 15 | 16 | import ssl_gc_common_pb2 as ssl__gc__common__pb2 17 | import ssl_gc_geometry_pb2 as ssl__gc__geometry__pb2 18 | 19 | 20 | DESCRIPTOR = _descriptor.FileDescriptor( 21 | name='ssl_vision_detection_tracked.proto', 22 | package='', 23 | syntax='proto2', 24 | serialized_options=_b('\n\033edu.tigers.sumatra.wp.protoZ?github.com/RoboCup-SSL/ssl-game-controller/internal/app/tracker'), 25 | serialized_pb=_b('\n\"ssl_vision_detection_tracked.proto\x1a\x13ssl_gc_common.proto\x1a\x15ssl_gc_geometry.proto\"\x91\x01\n\x0bTrackedBall\x12\x36\n\x03pos\x18\x01 \x02(\x0b\x32).edu.tigers.sumatra.referee.proto.Vector3\x12\x36\n\x03vel\x18\x02 \x01(\x0b\x32).edu.tigers.sumatra.referee.proto.Vector3\x12\x12\n\nvisibility\x18\x03 \x01(\x02\"\xa7\x02\n\nKickedBall\x12\x36\n\x03pos\x18\x01 \x02(\x0b\x32).edu.tigers.sumatra.referee.proto.Vector2\x12\x36\n\x03vel\x18\x02 \x02(\x0b\x32).edu.tigers.sumatra.referee.proto.Vector3\x12\x17\n\x0fstart_timestamp\x18\x03 \x02(\x01\x12\x16\n\x0estop_timestamp\x18\x04 \x01(\x01\x12;\n\x08stop_pos\x18\x05 \x01(\x0b\x32).edu.tigers.sumatra.referee.proto.Vector2\x12;\n\x08robot_id\x18\x06 \x01(\x0b\x32).edu.tigers.sumatra.referee.proto.RobotId\"\xf9\x01\n\x0cTrackedRobot\x12;\n\x08robot_id\x18\x01 \x02(\x0b\x32).edu.tigers.sumatra.referee.proto.RobotId\x12\x36\n\x03pos\x18\x02 \x02(\x0b\x32).edu.tigers.sumatra.referee.proto.Vector2\x12\x13\n\x0borientation\x18\x03 \x02(\x02\x12\x36\n\x03vel\x18\x04 \x01(\x0b\x32).edu.tigers.sumatra.referee.proto.Vector2\x12\x13\n\x0bvel_angular\x18\x05 \x01(\x02\x12\x12\n\nvisibility\x18\x06 \x01(\x02\"\xb8\x01\n\x0cTrackedFrame\x12\x14\n\x0c\x66rame_number\x18\x01 \x02(\r\x12\x11\n\ttimestamp\x18\x02 \x02(\x01\x12\x1b\n\x05\x62\x61lls\x18\x03 \x03(\x0b\x32\x0c.TrackedBall\x12\x1d\n\x06robots\x18\x04 \x03(\x0b\x32\r.TrackedRobot\x12 \n\x0bkicked_ball\x18\x05 \x01(\x0b\x32\x0b.KickedBall\x12!\n\x0c\x63\x61pabilities\x18\x06 \x03(\x0e\x32\x0b.Capability*\x92\x01\n\nCapability\x12\x16\n\x12\x43\x41PABILITY_UNKNOWN\x10\x00\x12\"\n\x1e\x43\x41PABILITY_DETECT_FLYING_BALLS\x10\x01\x12$\n CAPABILITY_DETECT_MULTIPLE_BALLS\x10\x02\x12\"\n\x1e\x43\x41PABILITY_DETECT_KICKED_BALLS\x10\x03\x42^\n\x1b\x65\x64u.tigers.sumatra.wp.protoZ?github.com/RoboCup-SSL/ssl-game-controller/internal/app/tracker') 26 | , 27 | dependencies=[ssl__gc__common__pb2.DESCRIPTOR,ssl__gc__geometry__pb2.DESCRIPTOR,]) 28 | 29 | _CAPABILITY = _descriptor.EnumDescriptor( 30 | name='Capability', 31 | full_name='Capability', 32 | filename=None, 33 | file=DESCRIPTOR, 34 | values=[ 35 | _descriptor.EnumValueDescriptor( 36 | name='CAPABILITY_UNKNOWN', index=0, number=0, 37 | serialized_options=None, 38 | type=None), 39 | _descriptor.EnumValueDescriptor( 40 | name='CAPABILITY_DETECT_FLYING_BALLS', index=1, number=1, 41 | serialized_options=None, 42 | type=None), 43 | _descriptor.EnumValueDescriptor( 44 | name='CAPABILITY_DETECT_MULTIPLE_BALLS', index=2, number=2, 45 | serialized_options=None, 46 | type=None), 47 | _descriptor.EnumValueDescriptor( 48 | name='CAPABILITY_DETECT_KICKED_BALLS', index=3, number=3, 49 | serialized_options=None, 50 | type=None), 51 | ], 52 | containing_type=None, 53 | serialized_options=None, 54 | serialized_start=968, 55 | serialized_end=1114, 56 | ) 57 | _sym_db.RegisterEnumDescriptor(_CAPABILITY) 58 | 59 | Capability = enum_type_wrapper.EnumTypeWrapper(_CAPABILITY) 60 | CAPABILITY_UNKNOWN = 0 61 | CAPABILITY_DETECT_FLYING_BALLS = 1 62 | CAPABILITY_DETECT_MULTIPLE_BALLS = 2 63 | CAPABILITY_DETECT_KICKED_BALLS = 3 64 | 65 | 66 | 67 | _TRACKEDBALL = _descriptor.Descriptor( 68 | name='TrackedBall', 69 | full_name='TrackedBall', 70 | filename=None, 71 | file=DESCRIPTOR, 72 | containing_type=None, 73 | fields=[ 74 | _descriptor.FieldDescriptor( 75 | name='pos', full_name='TrackedBall.pos', index=0, 76 | number=1, type=11, cpp_type=10, label=2, 77 | has_default_value=False, default_value=None, 78 | message_type=None, enum_type=None, containing_type=None, 79 | is_extension=False, extension_scope=None, 80 | serialized_options=None, file=DESCRIPTOR), 81 | _descriptor.FieldDescriptor( 82 | name='vel', full_name='TrackedBall.vel', index=1, 83 | number=2, type=11, cpp_type=10, label=1, 84 | has_default_value=False, default_value=None, 85 | message_type=None, enum_type=None, containing_type=None, 86 | is_extension=False, extension_scope=None, 87 | serialized_options=None, file=DESCRIPTOR), 88 | _descriptor.FieldDescriptor( 89 | name='visibility', full_name='TrackedBall.visibility', index=2, 90 | number=3, type=2, cpp_type=6, label=1, 91 | has_default_value=False, default_value=float(0), 92 | message_type=None, enum_type=None, containing_type=None, 93 | is_extension=False, extension_scope=None, 94 | serialized_options=None, file=DESCRIPTOR), 95 | ], 96 | extensions=[ 97 | ], 98 | nested_types=[], 99 | enum_types=[ 100 | ], 101 | serialized_options=None, 102 | is_extendable=False, 103 | syntax='proto2', 104 | extension_ranges=[], 105 | oneofs=[ 106 | ], 107 | serialized_start=83, 108 | serialized_end=228, 109 | ) 110 | 111 | 112 | _KICKEDBALL = _descriptor.Descriptor( 113 | name='KickedBall', 114 | full_name='KickedBall', 115 | filename=None, 116 | file=DESCRIPTOR, 117 | containing_type=None, 118 | fields=[ 119 | _descriptor.FieldDescriptor( 120 | name='pos', full_name='KickedBall.pos', index=0, 121 | number=1, type=11, cpp_type=10, label=2, 122 | has_default_value=False, default_value=None, 123 | message_type=None, enum_type=None, containing_type=None, 124 | is_extension=False, extension_scope=None, 125 | serialized_options=None, file=DESCRIPTOR), 126 | _descriptor.FieldDescriptor( 127 | name='vel', full_name='KickedBall.vel', index=1, 128 | number=2, type=11, cpp_type=10, label=2, 129 | has_default_value=False, default_value=None, 130 | message_type=None, enum_type=None, containing_type=None, 131 | is_extension=False, extension_scope=None, 132 | serialized_options=None, file=DESCRIPTOR), 133 | _descriptor.FieldDescriptor( 134 | name='start_timestamp', full_name='KickedBall.start_timestamp', index=2, 135 | number=3, type=1, cpp_type=5, label=2, 136 | has_default_value=False, default_value=float(0), 137 | message_type=None, enum_type=None, containing_type=None, 138 | is_extension=False, extension_scope=None, 139 | serialized_options=None, file=DESCRIPTOR), 140 | _descriptor.FieldDescriptor( 141 | name='stop_timestamp', full_name='KickedBall.stop_timestamp', index=3, 142 | number=4, type=1, cpp_type=5, label=1, 143 | has_default_value=False, default_value=float(0), 144 | message_type=None, enum_type=None, containing_type=None, 145 | is_extension=False, extension_scope=None, 146 | serialized_options=None, file=DESCRIPTOR), 147 | _descriptor.FieldDescriptor( 148 | name='stop_pos', full_name='KickedBall.stop_pos', index=4, 149 | number=5, type=11, cpp_type=10, label=1, 150 | has_default_value=False, default_value=None, 151 | message_type=None, enum_type=None, containing_type=None, 152 | is_extension=False, extension_scope=None, 153 | serialized_options=None, file=DESCRIPTOR), 154 | _descriptor.FieldDescriptor( 155 | name='robot_id', full_name='KickedBall.robot_id', index=5, 156 | number=6, type=11, cpp_type=10, label=1, 157 | has_default_value=False, default_value=None, 158 | message_type=None, enum_type=None, containing_type=None, 159 | is_extension=False, extension_scope=None, 160 | serialized_options=None, file=DESCRIPTOR), 161 | ], 162 | extensions=[ 163 | ], 164 | nested_types=[], 165 | enum_types=[ 166 | ], 167 | serialized_options=None, 168 | is_extendable=False, 169 | syntax='proto2', 170 | extension_ranges=[], 171 | oneofs=[ 172 | ], 173 | serialized_start=231, 174 | serialized_end=526, 175 | ) 176 | 177 | 178 | _TRACKEDROBOT = _descriptor.Descriptor( 179 | name='TrackedRobot', 180 | full_name='TrackedRobot', 181 | filename=None, 182 | file=DESCRIPTOR, 183 | containing_type=None, 184 | fields=[ 185 | _descriptor.FieldDescriptor( 186 | name='robot_id', full_name='TrackedRobot.robot_id', index=0, 187 | number=1, type=11, cpp_type=10, label=2, 188 | has_default_value=False, default_value=None, 189 | message_type=None, enum_type=None, containing_type=None, 190 | is_extension=False, extension_scope=None, 191 | serialized_options=None, file=DESCRIPTOR), 192 | _descriptor.FieldDescriptor( 193 | name='pos', full_name='TrackedRobot.pos', index=1, 194 | number=2, type=11, cpp_type=10, label=2, 195 | has_default_value=False, default_value=None, 196 | message_type=None, enum_type=None, containing_type=None, 197 | is_extension=False, extension_scope=None, 198 | serialized_options=None, file=DESCRIPTOR), 199 | _descriptor.FieldDescriptor( 200 | name='orientation', full_name='TrackedRobot.orientation', index=2, 201 | number=3, type=2, cpp_type=6, label=2, 202 | has_default_value=False, default_value=float(0), 203 | message_type=None, enum_type=None, containing_type=None, 204 | is_extension=False, extension_scope=None, 205 | serialized_options=None, file=DESCRIPTOR), 206 | _descriptor.FieldDescriptor( 207 | name='vel', full_name='TrackedRobot.vel', index=3, 208 | number=4, type=11, cpp_type=10, label=1, 209 | has_default_value=False, default_value=None, 210 | message_type=None, enum_type=None, containing_type=None, 211 | is_extension=False, extension_scope=None, 212 | serialized_options=None, file=DESCRIPTOR), 213 | _descriptor.FieldDescriptor( 214 | name='vel_angular', full_name='TrackedRobot.vel_angular', index=4, 215 | number=5, type=2, cpp_type=6, label=1, 216 | has_default_value=False, default_value=float(0), 217 | message_type=None, enum_type=None, containing_type=None, 218 | is_extension=False, extension_scope=None, 219 | serialized_options=None, file=DESCRIPTOR), 220 | _descriptor.FieldDescriptor( 221 | name='visibility', full_name='TrackedRobot.visibility', index=5, 222 | number=6, type=2, cpp_type=6, label=1, 223 | has_default_value=False, default_value=float(0), 224 | message_type=None, enum_type=None, containing_type=None, 225 | is_extension=False, extension_scope=None, 226 | serialized_options=None, file=DESCRIPTOR), 227 | ], 228 | extensions=[ 229 | ], 230 | nested_types=[], 231 | enum_types=[ 232 | ], 233 | serialized_options=None, 234 | is_extendable=False, 235 | syntax='proto2', 236 | extension_ranges=[], 237 | oneofs=[ 238 | ], 239 | serialized_start=529, 240 | serialized_end=778, 241 | ) 242 | 243 | 244 | _TRACKEDFRAME = _descriptor.Descriptor( 245 | name='TrackedFrame', 246 | full_name='TrackedFrame', 247 | filename=None, 248 | file=DESCRIPTOR, 249 | containing_type=None, 250 | fields=[ 251 | _descriptor.FieldDescriptor( 252 | name='frame_number', full_name='TrackedFrame.frame_number', index=0, 253 | number=1, type=13, cpp_type=3, label=2, 254 | has_default_value=False, default_value=0, 255 | message_type=None, enum_type=None, containing_type=None, 256 | is_extension=False, extension_scope=None, 257 | serialized_options=None, file=DESCRIPTOR), 258 | _descriptor.FieldDescriptor( 259 | name='timestamp', full_name='TrackedFrame.timestamp', index=1, 260 | number=2, type=1, cpp_type=5, label=2, 261 | has_default_value=False, default_value=float(0), 262 | message_type=None, enum_type=None, containing_type=None, 263 | is_extension=False, extension_scope=None, 264 | serialized_options=None, file=DESCRIPTOR), 265 | _descriptor.FieldDescriptor( 266 | name='balls', full_name='TrackedFrame.balls', index=2, 267 | number=3, type=11, cpp_type=10, label=3, 268 | has_default_value=False, default_value=[], 269 | message_type=None, enum_type=None, containing_type=None, 270 | is_extension=False, extension_scope=None, 271 | serialized_options=None, file=DESCRIPTOR), 272 | _descriptor.FieldDescriptor( 273 | name='robots', full_name='TrackedFrame.robots', index=3, 274 | number=4, type=11, cpp_type=10, label=3, 275 | has_default_value=False, default_value=[], 276 | message_type=None, enum_type=None, containing_type=None, 277 | is_extension=False, extension_scope=None, 278 | serialized_options=None, file=DESCRIPTOR), 279 | _descriptor.FieldDescriptor( 280 | name='kicked_ball', full_name='TrackedFrame.kicked_ball', index=4, 281 | number=5, type=11, cpp_type=10, label=1, 282 | has_default_value=False, default_value=None, 283 | message_type=None, enum_type=None, containing_type=None, 284 | is_extension=False, extension_scope=None, 285 | serialized_options=None, file=DESCRIPTOR), 286 | _descriptor.FieldDescriptor( 287 | name='capabilities', full_name='TrackedFrame.capabilities', index=5, 288 | number=6, type=14, cpp_type=8, label=3, 289 | has_default_value=False, default_value=[], 290 | message_type=None, enum_type=None, containing_type=None, 291 | is_extension=False, extension_scope=None, 292 | serialized_options=None, file=DESCRIPTOR), 293 | ], 294 | extensions=[ 295 | ], 296 | nested_types=[], 297 | enum_types=[ 298 | ], 299 | serialized_options=None, 300 | is_extendable=False, 301 | syntax='proto2', 302 | extension_ranges=[], 303 | oneofs=[ 304 | ], 305 | serialized_start=781, 306 | serialized_end=965, 307 | ) 308 | 309 | _TRACKEDBALL.fields_by_name['pos'].message_type = ssl__gc__geometry__pb2._VECTOR3 310 | _TRACKEDBALL.fields_by_name['vel'].message_type = ssl__gc__geometry__pb2._VECTOR3 311 | _KICKEDBALL.fields_by_name['pos'].message_type = ssl__gc__geometry__pb2._VECTOR2 312 | _KICKEDBALL.fields_by_name['vel'].message_type = ssl__gc__geometry__pb2._VECTOR3 313 | _KICKEDBALL.fields_by_name['stop_pos'].message_type = ssl__gc__geometry__pb2._VECTOR2 314 | _KICKEDBALL.fields_by_name['robot_id'].message_type = ssl__gc__common__pb2._ROBOTID 315 | _TRACKEDROBOT.fields_by_name['robot_id'].message_type = ssl__gc__common__pb2._ROBOTID 316 | _TRACKEDROBOT.fields_by_name['pos'].message_type = ssl__gc__geometry__pb2._VECTOR2 317 | _TRACKEDROBOT.fields_by_name['vel'].message_type = ssl__gc__geometry__pb2._VECTOR2 318 | _TRACKEDFRAME.fields_by_name['balls'].message_type = _TRACKEDBALL 319 | _TRACKEDFRAME.fields_by_name['robots'].message_type = _TRACKEDROBOT 320 | _TRACKEDFRAME.fields_by_name['kicked_ball'].message_type = _KICKEDBALL 321 | _TRACKEDFRAME.fields_by_name['capabilities'].enum_type = _CAPABILITY 322 | DESCRIPTOR.message_types_by_name['TrackedBall'] = _TRACKEDBALL 323 | DESCRIPTOR.message_types_by_name['KickedBall'] = _KICKEDBALL 324 | DESCRIPTOR.message_types_by_name['TrackedRobot'] = _TRACKEDROBOT 325 | DESCRIPTOR.message_types_by_name['TrackedFrame'] = _TRACKEDFRAME 326 | DESCRIPTOR.enum_types_by_name['Capability'] = _CAPABILITY 327 | _sym_db.RegisterFileDescriptor(DESCRIPTOR) 328 | 329 | TrackedBall = _reflection.GeneratedProtocolMessageType('TrackedBall', (_message.Message,), dict( 330 | DESCRIPTOR = _TRACKEDBALL, 331 | __module__ = 'ssl_vision_detection_tracked_pb2' 332 | # @@protoc_insertion_point(class_scope:TrackedBall) 333 | )) 334 | _sym_db.RegisterMessage(TrackedBall) 335 | 336 | KickedBall = _reflection.GeneratedProtocolMessageType('KickedBall', (_message.Message,), dict( 337 | DESCRIPTOR = _KICKEDBALL, 338 | __module__ = 'ssl_vision_detection_tracked_pb2' 339 | # @@protoc_insertion_point(class_scope:KickedBall) 340 | )) 341 | _sym_db.RegisterMessage(KickedBall) 342 | 343 | TrackedRobot = _reflection.GeneratedProtocolMessageType('TrackedRobot', (_message.Message,), dict( 344 | DESCRIPTOR = _TRACKEDROBOT, 345 | __module__ = 'ssl_vision_detection_tracked_pb2' 346 | # @@protoc_insertion_point(class_scope:TrackedRobot) 347 | )) 348 | _sym_db.RegisterMessage(TrackedRobot) 349 | 350 | TrackedFrame = _reflection.GeneratedProtocolMessageType('TrackedFrame', (_message.Message,), dict( 351 | DESCRIPTOR = _TRACKEDFRAME, 352 | __module__ = 'ssl_vision_detection_tracked_pb2' 353 | # @@protoc_insertion_point(class_scope:TrackedFrame) 354 | )) 355 | _sym_db.RegisterMessage(TrackedFrame) 356 | 357 | 358 | DESCRIPTOR._options = None 359 | # @@protoc_insertion_point(module_scope) 360 | -------------------------------------------------------------------------------- /src/referee_pb2.py: -------------------------------------------------------------------------------- 1 | # Generated by the protocol buffer compiler. DO NOT EDIT! 2 | # source: referee.proto 3 | 4 | import sys 5 | _b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) 6 | from google.protobuf import descriptor as _descriptor 7 | from google.protobuf import message as _message 8 | from google.protobuf import reflection as _reflection 9 | from google.protobuf import symbol_database as _symbol_database 10 | # @@protoc_insertion_point(imports) 11 | 12 | _sym_db = _symbol_database.Default() 13 | 14 | 15 | 16 | 17 | DESCRIPTOR = _descriptor.FileDescriptor( 18 | name='referee.proto', 19 | package='', 20 | syntax='proto2', 21 | serialized_options=None, 22 | serialized_pb=_b('\n\rreferee.proto\"\xff\t\n\x0bSSL_Referee\x12\x18\n\x10packet_timestamp\x18\x01 \x02(\x04\x12!\n\x05stage\x18\x02 \x02(\x0e\x32\x12.SSL_Referee.Stage\x12\x17\n\x0fstage_time_left\x18\x03 \x01(\x11\x12%\n\x07\x63ommand\x18\x04 \x02(\x0e\x32\x14.SSL_Referee.Command\x12\x17\n\x0f\x63ommand_counter\x18\x05 \x02(\r\x12\x19\n\x11\x63ommand_timestamp\x18\x06 \x02(\x04\x12%\n\x06yellow\x18\x07 \x02(\x0b\x32\x15.SSL_Referee.TeamInfo\x12#\n\x04\x62lue\x18\x08 \x02(\x0b\x32\x15.SSL_Referee.TeamInfo\x12/\n\x13\x64\x65signated_position\x18\t \x01(\x0b\x32\x12.SSL_Referee.Point\x12\x1c\n\x14packet_timestamp_fei\x18\n \x01(\x04\x1a\xa7\x01\n\x08TeamInfo\x12\x0c\n\x04name\x18\x01 \x02(\t\x12\r\n\x05score\x18\x02 \x02(\r\x12\x11\n\tred_cards\x18\x03 \x02(\r\x12\x1d\n\x11yellow_card_times\x18\x04 \x03(\rB\x02\x10\x01\x12\x14\n\x0cyellow_cards\x18\x05 \x02(\r\x12\x10\n\x08timeouts\x18\x06 \x02(\r\x12\x14\n\x0ctimeout_time\x18\x07 \x02(\r\x12\x0e\n\x06goalie\x18\x08 \x02(\r\x1a\x1d\n\x05Point\x12\t\n\x01x\x18\x01 \x02(\x02\x12\t\n\x01y\x18\x02 \x02(\x02\"\xd1\x02\n\x05Stage\x12\x19\n\x15NORMAL_FIRST_HALF_PRE\x10\x00\x12\x15\n\x11NORMAL_FIRST_HALF\x10\x01\x12\x14\n\x10NORMAL_HALF_TIME\x10\x02\x12\x1a\n\x16NORMAL_SECOND_HALF_PRE\x10\x03\x12\x16\n\x12NORMAL_SECOND_HALF\x10\x04\x12\x14\n\x10\x45XTRA_TIME_BREAK\x10\x05\x12\x18\n\x14\x45XTRA_FIRST_HALF_PRE\x10\x06\x12\x14\n\x10\x45XTRA_FIRST_HALF\x10\x07\x12\x13\n\x0f\x45XTRA_HALF_TIME\x10\x08\x12\x19\n\x15\x45XTRA_SECOND_HALF_PRE\x10\t\x12\x15\n\x11\x45XTRA_SECOND_HALF\x10\n\x12\x1a\n\x16PENALTY_SHOOTOUT_BREAK\x10\x0b\x12\x14\n\x10PENALTY_SHOOTOUT\x10\x0c\x12\r\n\tPOST_GAME\x10\r\"\x86\x03\n\x07\x43ommand\x12\x08\n\x04HALT\x10\x00\x12\x08\n\x04STOP\x10\x01\x12\x10\n\x0cNORMAL_START\x10\x02\x12\x0f\n\x0b\x46ORCE_START\x10\x03\x12\x1a\n\x16PREPARE_KICKOFF_YELLOW\x10\x04\x12\x18\n\x14PREPARE_KICKOFF_BLUE\x10\x05\x12\x1a\n\x16PREPARE_PENALTY_YELLOW\x10\x06\x12\x18\n\x14PREPARE_PENALTY_BLUE\x10\x07\x12\x16\n\x12\x44IRECT_FREE_YELLOW\x10\x08\x12\x14\n\x10\x44IRECT_FREE_BLUE\x10\t\x12\x18\n\x14INDIRECT_FREE_YELLOW\x10\n\x12\x16\n\x12INDIRECT_FREE_BLUE\x10\x0b\x12\x12\n\x0eTIMEOUT_YELLOW\x10\x0c\x12\x10\n\x0cTIMEOUT_BLUE\x10\r\x12\x0f\n\x0bGOAL_YELLOW\x10\x0e\x12\r\n\tGOAL_BLUE\x10\x0f\x12\x19\n\x15\x42\x41LL_PLACEMENT_YELLOW\x10\x10\x12\x17\n\x13\x42\x41LL_PLACEMENT_BLUE\x10\x11') 23 | ) 24 | 25 | 26 | 27 | _SSL_REFEREE_STAGE = _descriptor.EnumDescriptor( 28 | name='Stage', 29 | full_name='SSL_Referee.Stage', 30 | filename=None, 31 | file=DESCRIPTOR, 32 | values=[ 33 | _descriptor.EnumValueDescriptor( 34 | name='NORMAL_FIRST_HALF_PRE', index=0, number=0, 35 | serialized_options=None, 36 | type=None), 37 | _descriptor.EnumValueDescriptor( 38 | name='NORMAL_FIRST_HALF', index=1, number=1, 39 | serialized_options=None, 40 | type=None), 41 | _descriptor.EnumValueDescriptor( 42 | name='NORMAL_HALF_TIME', index=2, number=2, 43 | serialized_options=None, 44 | type=None), 45 | _descriptor.EnumValueDescriptor( 46 | name='NORMAL_SECOND_HALF_PRE', index=3, number=3, 47 | serialized_options=None, 48 | type=None), 49 | _descriptor.EnumValueDescriptor( 50 | name='NORMAL_SECOND_HALF', index=4, number=4, 51 | serialized_options=None, 52 | type=None), 53 | _descriptor.EnumValueDescriptor( 54 | name='EXTRA_TIME_BREAK', index=5, number=5, 55 | serialized_options=None, 56 | type=None), 57 | _descriptor.EnumValueDescriptor( 58 | name='EXTRA_FIRST_HALF_PRE', index=6, number=6, 59 | serialized_options=None, 60 | type=None), 61 | _descriptor.EnumValueDescriptor( 62 | name='EXTRA_FIRST_HALF', index=7, number=7, 63 | serialized_options=None, 64 | type=None), 65 | _descriptor.EnumValueDescriptor( 66 | name='EXTRA_HALF_TIME', index=8, number=8, 67 | serialized_options=None, 68 | type=None), 69 | _descriptor.EnumValueDescriptor( 70 | name='EXTRA_SECOND_HALF_PRE', index=9, number=9, 71 | serialized_options=None, 72 | type=None), 73 | _descriptor.EnumValueDescriptor( 74 | name='EXTRA_SECOND_HALF', index=10, number=10, 75 | serialized_options=None, 76 | type=None), 77 | _descriptor.EnumValueDescriptor( 78 | name='PENALTY_SHOOTOUT_BREAK', index=11, number=11, 79 | serialized_options=None, 80 | type=None), 81 | _descriptor.EnumValueDescriptor( 82 | name='PENALTY_SHOOTOUT', index=12, number=12, 83 | serialized_options=None, 84 | type=None), 85 | _descriptor.EnumValueDescriptor( 86 | name='POST_GAME', index=13, number=13, 87 | serialized_options=None, 88 | type=None), 89 | ], 90 | containing_type=None, 91 | serialized_options=None, 92 | serialized_start=567, 93 | serialized_end=904, 94 | ) 95 | _sym_db.RegisterEnumDescriptor(_SSL_REFEREE_STAGE) 96 | 97 | _SSL_REFEREE_COMMAND = _descriptor.EnumDescriptor( 98 | name='Command', 99 | full_name='SSL_Referee.Command', 100 | filename=None, 101 | file=DESCRIPTOR, 102 | values=[ 103 | _descriptor.EnumValueDescriptor( 104 | name='HALT', index=0, number=0, 105 | serialized_options=None, 106 | type=None), 107 | _descriptor.EnumValueDescriptor( 108 | name='STOP', index=1, number=1, 109 | serialized_options=None, 110 | type=None), 111 | _descriptor.EnumValueDescriptor( 112 | name='NORMAL_START', index=2, number=2, 113 | serialized_options=None, 114 | type=None), 115 | _descriptor.EnumValueDescriptor( 116 | name='FORCE_START', index=3, number=3, 117 | serialized_options=None, 118 | type=None), 119 | _descriptor.EnumValueDescriptor( 120 | name='PREPARE_KICKOFF_YELLOW', index=4, number=4, 121 | serialized_options=None, 122 | type=None), 123 | _descriptor.EnumValueDescriptor( 124 | name='PREPARE_KICKOFF_BLUE', index=5, number=5, 125 | serialized_options=None, 126 | type=None), 127 | _descriptor.EnumValueDescriptor( 128 | name='PREPARE_PENALTY_YELLOW', index=6, number=6, 129 | serialized_options=None, 130 | type=None), 131 | _descriptor.EnumValueDescriptor( 132 | name='PREPARE_PENALTY_BLUE', index=7, number=7, 133 | serialized_options=None, 134 | type=None), 135 | _descriptor.EnumValueDescriptor( 136 | name='DIRECT_FREE_YELLOW', index=8, number=8, 137 | serialized_options=None, 138 | type=None), 139 | _descriptor.EnumValueDescriptor( 140 | name='DIRECT_FREE_BLUE', index=9, number=9, 141 | serialized_options=None, 142 | type=None), 143 | _descriptor.EnumValueDescriptor( 144 | name='INDIRECT_FREE_YELLOW', index=10, number=10, 145 | serialized_options=None, 146 | type=None), 147 | _descriptor.EnumValueDescriptor( 148 | name='INDIRECT_FREE_BLUE', index=11, number=11, 149 | serialized_options=None, 150 | type=None), 151 | _descriptor.EnumValueDescriptor( 152 | name='TIMEOUT_YELLOW', index=12, number=12, 153 | serialized_options=None, 154 | type=None), 155 | _descriptor.EnumValueDescriptor( 156 | name='TIMEOUT_BLUE', index=13, number=13, 157 | serialized_options=None, 158 | type=None), 159 | _descriptor.EnumValueDescriptor( 160 | name='GOAL_YELLOW', index=14, number=14, 161 | serialized_options=None, 162 | type=None), 163 | _descriptor.EnumValueDescriptor( 164 | name='GOAL_BLUE', index=15, number=15, 165 | serialized_options=None, 166 | type=None), 167 | _descriptor.EnumValueDescriptor( 168 | name='BALL_PLACEMENT_YELLOW', index=16, number=16, 169 | serialized_options=None, 170 | type=None), 171 | _descriptor.EnumValueDescriptor( 172 | name='BALL_PLACEMENT_BLUE', index=17, number=17, 173 | serialized_options=None, 174 | type=None), 175 | ], 176 | containing_type=None, 177 | serialized_options=None, 178 | serialized_start=907, 179 | serialized_end=1297, 180 | ) 181 | _sym_db.RegisterEnumDescriptor(_SSL_REFEREE_COMMAND) 182 | 183 | 184 | _SSL_REFEREE_TEAMINFO = _descriptor.Descriptor( 185 | name='TeamInfo', 186 | full_name='SSL_Referee.TeamInfo', 187 | filename=None, 188 | file=DESCRIPTOR, 189 | containing_type=None, 190 | fields=[ 191 | _descriptor.FieldDescriptor( 192 | name='name', full_name='SSL_Referee.TeamInfo.name', index=0, 193 | number=1, type=9, cpp_type=9, label=2, 194 | has_default_value=False, default_value=_b("").decode('utf-8'), 195 | message_type=None, enum_type=None, containing_type=None, 196 | is_extension=False, extension_scope=None, 197 | serialized_options=None, file=DESCRIPTOR), 198 | _descriptor.FieldDescriptor( 199 | name='score', full_name='SSL_Referee.TeamInfo.score', index=1, 200 | number=2, type=13, cpp_type=3, label=2, 201 | has_default_value=False, default_value=0, 202 | message_type=None, enum_type=None, containing_type=None, 203 | is_extension=False, extension_scope=None, 204 | serialized_options=None, file=DESCRIPTOR), 205 | _descriptor.FieldDescriptor( 206 | name='red_cards', full_name='SSL_Referee.TeamInfo.red_cards', index=2, 207 | number=3, type=13, cpp_type=3, label=2, 208 | has_default_value=False, default_value=0, 209 | message_type=None, enum_type=None, containing_type=None, 210 | is_extension=False, extension_scope=None, 211 | serialized_options=None, file=DESCRIPTOR), 212 | _descriptor.FieldDescriptor( 213 | name='yellow_card_times', full_name='SSL_Referee.TeamInfo.yellow_card_times', index=3, 214 | number=4, type=13, cpp_type=3, label=3, 215 | has_default_value=False, default_value=[], 216 | message_type=None, enum_type=None, containing_type=None, 217 | is_extension=False, extension_scope=None, 218 | serialized_options=_b('\020\001'), file=DESCRIPTOR), 219 | _descriptor.FieldDescriptor( 220 | name='yellow_cards', full_name='SSL_Referee.TeamInfo.yellow_cards', index=4, 221 | number=5, type=13, cpp_type=3, label=2, 222 | has_default_value=False, default_value=0, 223 | message_type=None, enum_type=None, containing_type=None, 224 | is_extension=False, extension_scope=None, 225 | serialized_options=None, file=DESCRIPTOR), 226 | _descriptor.FieldDescriptor( 227 | name='timeouts', full_name='SSL_Referee.TeamInfo.timeouts', index=5, 228 | number=6, type=13, cpp_type=3, label=2, 229 | has_default_value=False, default_value=0, 230 | message_type=None, enum_type=None, containing_type=None, 231 | is_extension=False, extension_scope=None, 232 | serialized_options=None, file=DESCRIPTOR), 233 | _descriptor.FieldDescriptor( 234 | name='timeout_time', full_name='SSL_Referee.TeamInfo.timeout_time', index=6, 235 | number=7, type=13, cpp_type=3, label=2, 236 | has_default_value=False, default_value=0, 237 | message_type=None, enum_type=None, containing_type=None, 238 | is_extension=False, extension_scope=None, 239 | serialized_options=None, file=DESCRIPTOR), 240 | _descriptor.FieldDescriptor( 241 | name='goalie', full_name='SSL_Referee.TeamInfo.goalie', index=7, 242 | number=8, type=13, cpp_type=3, label=2, 243 | has_default_value=False, default_value=0, 244 | message_type=None, enum_type=None, containing_type=None, 245 | is_extension=False, extension_scope=None, 246 | serialized_options=None, file=DESCRIPTOR), 247 | ], 248 | extensions=[ 249 | ], 250 | nested_types=[], 251 | enum_types=[ 252 | ], 253 | serialized_options=None, 254 | is_extendable=False, 255 | syntax='proto2', 256 | extension_ranges=[], 257 | oneofs=[ 258 | ], 259 | serialized_start=366, 260 | serialized_end=533, 261 | ) 262 | 263 | _SSL_REFEREE_POINT = _descriptor.Descriptor( 264 | name='Point', 265 | full_name='SSL_Referee.Point', 266 | filename=None, 267 | file=DESCRIPTOR, 268 | containing_type=None, 269 | fields=[ 270 | _descriptor.FieldDescriptor( 271 | name='x', full_name='SSL_Referee.Point.x', index=0, 272 | number=1, type=2, cpp_type=6, label=2, 273 | has_default_value=False, default_value=float(0), 274 | message_type=None, enum_type=None, containing_type=None, 275 | is_extension=False, extension_scope=None, 276 | serialized_options=None, file=DESCRIPTOR), 277 | _descriptor.FieldDescriptor( 278 | name='y', full_name='SSL_Referee.Point.y', index=1, 279 | number=2, type=2, cpp_type=6, label=2, 280 | has_default_value=False, default_value=float(0), 281 | message_type=None, enum_type=None, containing_type=None, 282 | is_extension=False, extension_scope=None, 283 | serialized_options=None, file=DESCRIPTOR), 284 | ], 285 | extensions=[ 286 | ], 287 | nested_types=[], 288 | enum_types=[ 289 | ], 290 | serialized_options=None, 291 | is_extendable=False, 292 | syntax='proto2', 293 | extension_ranges=[], 294 | oneofs=[ 295 | ], 296 | serialized_start=535, 297 | serialized_end=564, 298 | ) 299 | 300 | _SSL_REFEREE = _descriptor.Descriptor( 301 | name='SSL_Referee', 302 | full_name='SSL_Referee', 303 | filename=None, 304 | file=DESCRIPTOR, 305 | containing_type=None, 306 | fields=[ 307 | _descriptor.FieldDescriptor( 308 | name='packet_timestamp', full_name='SSL_Referee.packet_timestamp', index=0, 309 | number=1, type=4, cpp_type=4, label=2, 310 | has_default_value=False, default_value=0, 311 | message_type=None, enum_type=None, containing_type=None, 312 | is_extension=False, extension_scope=None, 313 | serialized_options=None, file=DESCRIPTOR), 314 | _descriptor.FieldDescriptor( 315 | name='stage', full_name='SSL_Referee.stage', index=1, 316 | number=2, type=14, cpp_type=8, label=2, 317 | has_default_value=False, default_value=0, 318 | message_type=None, enum_type=None, containing_type=None, 319 | is_extension=False, extension_scope=None, 320 | serialized_options=None, file=DESCRIPTOR), 321 | _descriptor.FieldDescriptor( 322 | name='stage_time_left', full_name='SSL_Referee.stage_time_left', index=2, 323 | number=3, type=17, cpp_type=1, label=1, 324 | has_default_value=False, default_value=0, 325 | message_type=None, enum_type=None, containing_type=None, 326 | is_extension=False, extension_scope=None, 327 | serialized_options=None, file=DESCRIPTOR), 328 | _descriptor.FieldDescriptor( 329 | name='command', full_name='SSL_Referee.command', index=3, 330 | number=4, type=14, cpp_type=8, label=2, 331 | has_default_value=False, default_value=0, 332 | message_type=None, enum_type=None, containing_type=None, 333 | is_extension=False, extension_scope=None, 334 | serialized_options=None, file=DESCRIPTOR), 335 | _descriptor.FieldDescriptor( 336 | name='command_counter', full_name='SSL_Referee.command_counter', index=4, 337 | number=5, type=13, cpp_type=3, label=2, 338 | has_default_value=False, default_value=0, 339 | message_type=None, enum_type=None, containing_type=None, 340 | is_extension=False, extension_scope=None, 341 | serialized_options=None, file=DESCRIPTOR), 342 | _descriptor.FieldDescriptor( 343 | name='command_timestamp', full_name='SSL_Referee.command_timestamp', index=5, 344 | number=6, type=4, cpp_type=4, label=2, 345 | has_default_value=False, default_value=0, 346 | message_type=None, enum_type=None, containing_type=None, 347 | is_extension=False, extension_scope=None, 348 | serialized_options=None, file=DESCRIPTOR), 349 | _descriptor.FieldDescriptor( 350 | name='yellow', full_name='SSL_Referee.yellow', index=6, 351 | number=7, type=11, cpp_type=10, label=2, 352 | has_default_value=False, default_value=None, 353 | message_type=None, enum_type=None, containing_type=None, 354 | is_extension=False, extension_scope=None, 355 | serialized_options=None, file=DESCRIPTOR), 356 | _descriptor.FieldDescriptor( 357 | name='blue', full_name='SSL_Referee.blue', index=7, 358 | number=8, type=11, cpp_type=10, label=2, 359 | has_default_value=False, default_value=None, 360 | message_type=None, enum_type=None, containing_type=None, 361 | is_extension=False, extension_scope=None, 362 | serialized_options=None, file=DESCRIPTOR), 363 | _descriptor.FieldDescriptor( 364 | name='designated_position', full_name='SSL_Referee.designated_position', index=8, 365 | number=9, type=11, cpp_type=10, label=1, 366 | has_default_value=False, default_value=None, 367 | message_type=None, enum_type=None, containing_type=None, 368 | is_extension=False, extension_scope=None, 369 | serialized_options=None, file=DESCRIPTOR), 370 | _descriptor.FieldDescriptor( 371 | name='packet_timestamp_fei', full_name='SSL_Referee.packet_timestamp_fei', index=9, 372 | number=10, type=4, cpp_type=4, label=1, 373 | has_default_value=False, default_value=0, 374 | message_type=None, enum_type=None, containing_type=None, 375 | is_extension=False, extension_scope=None, 376 | serialized_options=None, file=DESCRIPTOR), 377 | ], 378 | extensions=[ 379 | ], 380 | nested_types=[_SSL_REFEREE_TEAMINFO, _SSL_REFEREE_POINT, ], 381 | enum_types=[ 382 | _SSL_REFEREE_STAGE, 383 | _SSL_REFEREE_COMMAND, 384 | ], 385 | serialized_options=None, 386 | is_extendable=False, 387 | syntax='proto2', 388 | extension_ranges=[], 389 | oneofs=[ 390 | ], 391 | serialized_start=18, 392 | serialized_end=1297, 393 | ) 394 | 395 | _SSL_REFEREE_TEAMINFO.containing_type = _SSL_REFEREE 396 | _SSL_REFEREE_POINT.containing_type = _SSL_REFEREE 397 | _SSL_REFEREE.fields_by_name['stage'].enum_type = _SSL_REFEREE_STAGE 398 | _SSL_REFEREE.fields_by_name['command'].enum_type = _SSL_REFEREE_COMMAND 399 | _SSL_REFEREE.fields_by_name['yellow'].message_type = _SSL_REFEREE_TEAMINFO 400 | _SSL_REFEREE.fields_by_name['blue'].message_type = _SSL_REFEREE_TEAMINFO 401 | _SSL_REFEREE.fields_by_name['designated_position'].message_type = _SSL_REFEREE_POINT 402 | _SSL_REFEREE_STAGE.containing_type = _SSL_REFEREE 403 | _SSL_REFEREE_COMMAND.containing_type = _SSL_REFEREE 404 | DESCRIPTOR.message_types_by_name['SSL_Referee'] = _SSL_REFEREE 405 | _sym_db.RegisterFileDescriptor(DESCRIPTOR) 406 | 407 | SSL_Referee = _reflection.GeneratedProtocolMessageType('SSL_Referee', (_message.Message,), dict( 408 | 409 | TeamInfo = _reflection.GeneratedProtocolMessageType('TeamInfo', (_message.Message,), dict( 410 | DESCRIPTOR = _SSL_REFEREE_TEAMINFO, 411 | __module__ = 'referee_pb2' 412 | # @@protoc_insertion_point(class_scope:SSL_Referee.TeamInfo) 413 | )) 414 | , 415 | 416 | Point = _reflection.GeneratedProtocolMessageType('Point', (_message.Message,), dict( 417 | DESCRIPTOR = _SSL_REFEREE_POINT, 418 | __module__ = 'referee_pb2' 419 | # @@protoc_insertion_point(class_scope:SSL_Referee.Point) 420 | )) 421 | , 422 | DESCRIPTOR = _SSL_REFEREE, 423 | __module__ = 'referee_pb2' 424 | # @@protoc_insertion_point(class_scope:SSL_Referee) 425 | )) 426 | _sym_db.RegisterMessage(SSL_Referee) 427 | _sym_db.RegisterMessage(SSL_Referee.TeamInfo) 428 | _sym_db.RegisterMessage(SSL_Referee.Point) 429 | 430 | 431 | _SSL_REFEREE_TEAMINFO.fields_by_name['yellow_card_times']._options = None 432 | # @@protoc_insertion_point(module_scope) 433 | -------------------------------------------------------------------------------- /src/ssl_vision_geometry_pb2.py: -------------------------------------------------------------------------------- 1 | # Generated by the protocol buffer compiler. DO NOT EDIT! 2 | # source: ssl_vision_geometry.proto 3 | 4 | import sys 5 | _b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) 6 | from google.protobuf.internal import enum_type_wrapper 7 | from google.protobuf import descriptor as _descriptor 8 | from google.protobuf import message as _message 9 | from google.protobuf import reflection as _reflection 10 | from google.protobuf import symbol_database as _symbol_database 11 | # @@protoc_insertion_point(imports) 12 | 13 | _sym_db = _symbol_database.Default() 14 | 15 | 16 | 17 | 18 | DESCRIPTOR = _descriptor.FileDescriptor( 19 | name='ssl_vision_geometry.proto', 20 | package='', 21 | syntax='proto2', 22 | serialized_options=_b('Z6github.com/RoboCup-SSL/ssl-simulation-protocol/pkg/sim'), 23 | serialized_pb=_b('\n\x19ssl_vision_geometry.proto\" \n\x08Vector2f\x12\t\n\x01x\x18\x01 \x02(\x02\x12\t\n\x01y\x18\x02 \x02(\x02\"\x88\x01\n\x14SSL_FieldLineSegment\x12\x0c\n\x04name\x18\x01 \x02(\t\x12\x15\n\x02p1\x18\x02 \x02(\x0b\x32\t.Vector2f\x12\x15\n\x02p2\x18\x03 \x02(\x0b\x32\t.Vector2f\x12\x11\n\tthickness\x18\x04 \x02(\x02\x12!\n\x04type\x18\x05 \x01(\x0e\x32\x13.SSL_FieldShapeType\"\x9d\x01\n\x14SSL_FieldCircularArc\x12\x0c\n\x04name\x18\x01 \x02(\t\x12\x19\n\x06\x63\x65nter\x18\x02 \x02(\x0b\x32\t.Vector2f\x12\x0e\n\x06radius\x18\x03 \x02(\x02\x12\n\n\x02\x61\x31\x18\x04 \x02(\x02\x12\n\n\x02\x61\x32\x18\x05 \x02(\x02\x12\x11\n\tthickness\x18\x06 \x02(\x02\x12!\n\x04type\x18\x07 \x01(\x0e\x32\x13.SSL_FieldShapeType\"\x91\x02\n\x15SSL_GeometryFieldSize\x12\x14\n\x0c\x66ield_length\x18\x01 \x02(\x05\x12\x13\n\x0b\x66ield_width\x18\x02 \x02(\x05\x12\x12\n\ngoal_width\x18\x03 \x02(\x05\x12\x12\n\ngoal_depth\x18\x04 \x02(\x05\x12\x16\n\x0e\x62oundary_width\x18\x05 \x02(\x05\x12*\n\x0b\x66ield_lines\x18\x06 \x03(\x0b\x32\x15.SSL_FieldLineSegment\x12)\n\nfield_arcs\x18\x07 \x03(\x0b\x32\x15.SSL_FieldCircularArc\x12\x1a\n\x12penalty_area_depth\x18\x08 \x01(\x05\x12\x1a\n\x12penalty_area_width\x18\t \x01(\x05\"\x80\x03\n\x1dSSL_GeometryCameraCalibration\x12\x11\n\tcamera_id\x18\x01 \x02(\r\x12\x14\n\x0c\x66ocal_length\x18\x02 \x02(\x02\x12\x19\n\x11principal_point_x\x18\x03 \x02(\x02\x12\x19\n\x11principal_point_y\x18\x04 \x02(\x02\x12\x12\n\ndistortion\x18\x05 \x02(\x02\x12\n\n\x02q0\x18\x06 \x02(\x02\x12\n\n\x02q1\x18\x07 \x02(\x02\x12\n\n\x02q2\x18\x08 \x02(\x02\x12\n\n\x02q3\x18\t \x02(\x02\x12\n\n\x02tx\x18\n \x02(\x02\x12\n\n\x02ty\x18\x0b \x02(\x02\x12\n\n\x02tz\x18\x0c \x02(\x02\x12\x1f\n\x17\x64\x65rived_camera_world_tx\x18\r \x01(\x02\x12\x1f\n\x17\x64\x65rived_camera_world_ty\x18\x0e \x01(\x02\x12\x1f\n\x17\x64\x65rived_camera_world_tz\x18\x0f \x01(\x02\x12\x19\n\x11pixel_image_width\x18\x10 \x01(\r\x12\x1a\n\x12pixel_image_height\x18\x11 \x01(\r\"V\n\x1dSSL_BallModelStraightTwoPhase\x12\x11\n\tacc_slide\x18\x01 \x02(\x01\x12\x10\n\x08\x61\x63\x63_roll\x18\x02 \x02(\x01\x12\x10\n\x08k_switch\x18\x03 \x02(\x01\"l\n\x1aSSL_BallModelChipFixedLoss\x12\x1c\n\x14\x64\x61mping_xy_first_hop\x18\x01 \x02(\x01\x12\x1d\n\x15\x64\x61mping_xy_other_hops\x18\x02 \x02(\x01\x12\x11\n\tdamping_z\x18\x03 \x02(\x01\"\x86\x01\n\x12SSL_GeometryModels\x12:\n\x12straight_two_phase\x18\x01 \x01(\x0b\x32\x1e.SSL_BallModelStraightTwoPhase\x12\x34\n\x0f\x63hip_fixed_loss\x18\x02 \x01(\x0b\x32\x1b.SSL_BallModelChipFixedLoss\"\x8d\x01\n\x10SSL_GeometryData\x12%\n\x05\x66ield\x18\x01 \x02(\x0b\x32\x16.SSL_GeometryFieldSize\x12-\n\x05\x63\x61lib\x18\x02 \x03(\x0b\x32\x1e.SSL_GeometryCameraCalibration\x12#\n\x06models\x18\x03 \x01(\x0b\x32\x13.SSL_GeometryModels*\xdb\x02\n\x12SSL_FieldShapeType\x12\r\n\tUndefined\x10\x00\x12\x10\n\x0c\x43\x65nterCircle\x10\x01\x12\x10\n\x0cTopTouchLine\x10\x02\x12\x13\n\x0f\x42ottomTouchLine\x10\x03\x12\x10\n\x0cLeftGoalLine\x10\x04\x12\x11\n\rRightGoalLine\x10\x05\x12\x0f\n\x0bHalfwayLine\x10\x06\x12\x0e\n\nCenterLine\x10\x07\x12\x16\n\x12LeftPenaltyStretch\x10\x08\x12\x17\n\x13RightPenaltyStretch\x10\t\x12\x1f\n\x1bLeftFieldLeftPenaltyStretch\x10\n\x12 \n\x1cLeftFieldRightPenaltyStretch\x10\x0b\x12 \n\x1cRightFieldLeftPenaltyStretch\x10\x0c\x12!\n\x1dRightFieldRightPenaltyStretch\x10\rB8Z6github.com/RoboCup-SSL/ssl-simulation-protocol/pkg/sim') 24 | ) 25 | 26 | _SSL_FIELDSHAPETYPE = _descriptor.EnumDescriptor( 27 | name='SSL_FieldShapeType', 28 | full_name='SSL_FieldShapeType', 29 | filename=None, 30 | file=DESCRIPTOR, 31 | values=[ 32 | _descriptor.EnumValueDescriptor( 33 | name='Undefined', index=0, number=0, 34 | serialized_options=None, 35 | type=None), 36 | _descriptor.EnumValueDescriptor( 37 | name='CenterCircle', index=1, number=1, 38 | serialized_options=None, 39 | type=None), 40 | _descriptor.EnumValueDescriptor( 41 | name='TopTouchLine', index=2, number=2, 42 | serialized_options=None, 43 | type=None), 44 | _descriptor.EnumValueDescriptor( 45 | name='BottomTouchLine', index=3, number=3, 46 | serialized_options=None, 47 | type=None), 48 | _descriptor.EnumValueDescriptor( 49 | name='LeftGoalLine', index=4, number=4, 50 | serialized_options=None, 51 | type=None), 52 | _descriptor.EnumValueDescriptor( 53 | name='RightGoalLine', index=5, number=5, 54 | serialized_options=None, 55 | type=None), 56 | _descriptor.EnumValueDescriptor( 57 | name='HalfwayLine', index=6, number=6, 58 | serialized_options=None, 59 | type=None), 60 | _descriptor.EnumValueDescriptor( 61 | name='CenterLine', index=7, number=7, 62 | serialized_options=None, 63 | type=None), 64 | _descriptor.EnumValueDescriptor( 65 | name='LeftPenaltyStretch', index=8, number=8, 66 | serialized_options=None, 67 | type=None), 68 | _descriptor.EnumValueDescriptor( 69 | name='RightPenaltyStretch', index=9, number=9, 70 | serialized_options=None, 71 | type=None), 72 | _descriptor.EnumValueDescriptor( 73 | name='LeftFieldLeftPenaltyStretch', index=10, number=10, 74 | serialized_options=None, 75 | type=None), 76 | _descriptor.EnumValueDescriptor( 77 | name='LeftFieldRightPenaltyStretch', index=11, number=11, 78 | serialized_options=None, 79 | type=None), 80 | _descriptor.EnumValueDescriptor( 81 | name='RightFieldLeftPenaltyStretch', index=12, number=12, 82 | serialized_options=None, 83 | type=None), 84 | _descriptor.EnumValueDescriptor( 85 | name='RightFieldRightPenaltyStretch', index=13, number=13, 86 | serialized_options=None, 87 | type=None), 88 | ], 89 | containing_type=None, 90 | serialized_options=None, 91 | serialized_start=1505, 92 | serialized_end=1852, 93 | ) 94 | _sym_db.RegisterEnumDescriptor(_SSL_FIELDSHAPETYPE) 95 | 96 | SSL_FieldShapeType = enum_type_wrapper.EnumTypeWrapper(_SSL_FIELDSHAPETYPE) 97 | Undefined = 0 98 | CenterCircle = 1 99 | TopTouchLine = 2 100 | BottomTouchLine = 3 101 | LeftGoalLine = 4 102 | RightGoalLine = 5 103 | HalfwayLine = 6 104 | CenterLine = 7 105 | LeftPenaltyStretch = 8 106 | RightPenaltyStretch = 9 107 | LeftFieldLeftPenaltyStretch = 10 108 | LeftFieldRightPenaltyStretch = 11 109 | RightFieldLeftPenaltyStretch = 12 110 | RightFieldRightPenaltyStretch = 13 111 | 112 | 113 | 114 | _VECTOR2F = _descriptor.Descriptor( 115 | name='Vector2f', 116 | full_name='Vector2f', 117 | filename=None, 118 | file=DESCRIPTOR, 119 | containing_type=None, 120 | fields=[ 121 | _descriptor.FieldDescriptor( 122 | name='x', full_name='Vector2f.x', index=0, 123 | number=1, type=2, cpp_type=6, label=2, 124 | has_default_value=False, default_value=float(0), 125 | message_type=None, enum_type=None, containing_type=None, 126 | is_extension=False, extension_scope=None, 127 | serialized_options=None, file=DESCRIPTOR), 128 | _descriptor.FieldDescriptor( 129 | name='y', full_name='Vector2f.y', index=1, 130 | number=2, type=2, cpp_type=6, label=2, 131 | has_default_value=False, default_value=float(0), 132 | message_type=None, enum_type=None, containing_type=None, 133 | is_extension=False, extension_scope=None, 134 | serialized_options=None, file=DESCRIPTOR), 135 | ], 136 | extensions=[ 137 | ], 138 | nested_types=[], 139 | enum_types=[ 140 | ], 141 | serialized_options=None, 142 | is_extendable=False, 143 | syntax='proto2', 144 | extension_ranges=[], 145 | oneofs=[ 146 | ], 147 | serialized_start=29, 148 | serialized_end=61, 149 | ) 150 | 151 | 152 | _SSL_FIELDLINESEGMENT = _descriptor.Descriptor( 153 | name='SSL_FieldLineSegment', 154 | full_name='SSL_FieldLineSegment', 155 | filename=None, 156 | file=DESCRIPTOR, 157 | containing_type=None, 158 | fields=[ 159 | _descriptor.FieldDescriptor( 160 | name='name', full_name='SSL_FieldLineSegment.name', index=0, 161 | number=1, type=9, cpp_type=9, label=2, 162 | has_default_value=False, default_value=_b("").decode('utf-8'), 163 | message_type=None, enum_type=None, containing_type=None, 164 | is_extension=False, extension_scope=None, 165 | serialized_options=None, file=DESCRIPTOR), 166 | _descriptor.FieldDescriptor( 167 | name='p1', full_name='SSL_FieldLineSegment.p1', index=1, 168 | number=2, type=11, cpp_type=10, label=2, 169 | has_default_value=False, default_value=None, 170 | message_type=None, enum_type=None, containing_type=None, 171 | is_extension=False, extension_scope=None, 172 | serialized_options=None, file=DESCRIPTOR), 173 | _descriptor.FieldDescriptor( 174 | name='p2', full_name='SSL_FieldLineSegment.p2', index=2, 175 | number=3, type=11, cpp_type=10, label=2, 176 | has_default_value=False, default_value=None, 177 | message_type=None, enum_type=None, containing_type=None, 178 | is_extension=False, extension_scope=None, 179 | serialized_options=None, file=DESCRIPTOR), 180 | _descriptor.FieldDescriptor( 181 | name='thickness', full_name='SSL_FieldLineSegment.thickness', index=3, 182 | number=4, type=2, cpp_type=6, label=2, 183 | has_default_value=False, default_value=float(0), 184 | message_type=None, enum_type=None, containing_type=None, 185 | is_extension=False, extension_scope=None, 186 | serialized_options=None, file=DESCRIPTOR), 187 | _descriptor.FieldDescriptor( 188 | name='type', full_name='SSL_FieldLineSegment.type', index=4, 189 | number=5, type=14, cpp_type=8, label=1, 190 | has_default_value=False, default_value=0, 191 | message_type=None, enum_type=None, containing_type=None, 192 | is_extension=False, extension_scope=None, 193 | serialized_options=None, file=DESCRIPTOR), 194 | ], 195 | extensions=[ 196 | ], 197 | nested_types=[], 198 | enum_types=[ 199 | ], 200 | serialized_options=None, 201 | is_extendable=False, 202 | syntax='proto2', 203 | extension_ranges=[], 204 | oneofs=[ 205 | ], 206 | serialized_start=64, 207 | serialized_end=200, 208 | ) 209 | 210 | 211 | _SSL_FIELDCIRCULARARC = _descriptor.Descriptor( 212 | name='SSL_FieldCircularArc', 213 | full_name='SSL_FieldCircularArc', 214 | filename=None, 215 | file=DESCRIPTOR, 216 | containing_type=None, 217 | fields=[ 218 | _descriptor.FieldDescriptor( 219 | name='name', full_name='SSL_FieldCircularArc.name', index=0, 220 | number=1, type=9, cpp_type=9, label=2, 221 | has_default_value=False, default_value=_b("").decode('utf-8'), 222 | message_type=None, enum_type=None, containing_type=None, 223 | is_extension=False, extension_scope=None, 224 | serialized_options=None, file=DESCRIPTOR), 225 | _descriptor.FieldDescriptor( 226 | name='center', full_name='SSL_FieldCircularArc.center', index=1, 227 | number=2, type=11, cpp_type=10, label=2, 228 | has_default_value=False, default_value=None, 229 | message_type=None, enum_type=None, containing_type=None, 230 | is_extension=False, extension_scope=None, 231 | serialized_options=None, file=DESCRIPTOR), 232 | _descriptor.FieldDescriptor( 233 | name='radius', full_name='SSL_FieldCircularArc.radius', index=2, 234 | number=3, type=2, cpp_type=6, label=2, 235 | has_default_value=False, default_value=float(0), 236 | message_type=None, enum_type=None, containing_type=None, 237 | is_extension=False, extension_scope=None, 238 | serialized_options=None, file=DESCRIPTOR), 239 | _descriptor.FieldDescriptor( 240 | name='a1', full_name='SSL_FieldCircularArc.a1', index=3, 241 | number=4, type=2, cpp_type=6, label=2, 242 | has_default_value=False, default_value=float(0), 243 | message_type=None, enum_type=None, containing_type=None, 244 | is_extension=False, extension_scope=None, 245 | serialized_options=None, file=DESCRIPTOR), 246 | _descriptor.FieldDescriptor( 247 | name='a2', full_name='SSL_FieldCircularArc.a2', index=4, 248 | number=5, type=2, cpp_type=6, label=2, 249 | has_default_value=False, default_value=float(0), 250 | message_type=None, enum_type=None, containing_type=None, 251 | is_extension=False, extension_scope=None, 252 | serialized_options=None, file=DESCRIPTOR), 253 | _descriptor.FieldDescriptor( 254 | name='thickness', full_name='SSL_FieldCircularArc.thickness', index=5, 255 | number=6, type=2, cpp_type=6, label=2, 256 | has_default_value=False, default_value=float(0), 257 | message_type=None, enum_type=None, containing_type=None, 258 | is_extension=False, extension_scope=None, 259 | serialized_options=None, file=DESCRIPTOR), 260 | _descriptor.FieldDescriptor( 261 | name='type', full_name='SSL_FieldCircularArc.type', index=6, 262 | number=7, type=14, cpp_type=8, label=1, 263 | has_default_value=False, default_value=0, 264 | message_type=None, enum_type=None, containing_type=None, 265 | is_extension=False, extension_scope=None, 266 | serialized_options=None, file=DESCRIPTOR), 267 | ], 268 | extensions=[ 269 | ], 270 | nested_types=[], 271 | enum_types=[ 272 | ], 273 | serialized_options=None, 274 | is_extendable=False, 275 | syntax='proto2', 276 | extension_ranges=[], 277 | oneofs=[ 278 | ], 279 | serialized_start=203, 280 | serialized_end=360, 281 | ) 282 | 283 | 284 | _SSL_GEOMETRYFIELDSIZE = _descriptor.Descriptor( 285 | name='SSL_GeometryFieldSize', 286 | full_name='SSL_GeometryFieldSize', 287 | filename=None, 288 | file=DESCRIPTOR, 289 | containing_type=None, 290 | fields=[ 291 | _descriptor.FieldDescriptor( 292 | name='field_length', full_name='SSL_GeometryFieldSize.field_length', index=0, 293 | number=1, type=5, cpp_type=1, label=2, 294 | has_default_value=False, default_value=0, 295 | message_type=None, enum_type=None, containing_type=None, 296 | is_extension=False, extension_scope=None, 297 | serialized_options=None, file=DESCRIPTOR), 298 | _descriptor.FieldDescriptor( 299 | name='field_width', full_name='SSL_GeometryFieldSize.field_width', index=1, 300 | number=2, type=5, cpp_type=1, label=2, 301 | has_default_value=False, default_value=0, 302 | message_type=None, enum_type=None, containing_type=None, 303 | is_extension=False, extension_scope=None, 304 | serialized_options=None, file=DESCRIPTOR), 305 | _descriptor.FieldDescriptor( 306 | name='goal_width', full_name='SSL_GeometryFieldSize.goal_width', index=2, 307 | number=3, type=5, cpp_type=1, label=2, 308 | has_default_value=False, default_value=0, 309 | message_type=None, enum_type=None, containing_type=None, 310 | is_extension=False, extension_scope=None, 311 | serialized_options=None, file=DESCRIPTOR), 312 | _descriptor.FieldDescriptor( 313 | name='goal_depth', full_name='SSL_GeometryFieldSize.goal_depth', index=3, 314 | number=4, type=5, cpp_type=1, label=2, 315 | has_default_value=False, default_value=0, 316 | message_type=None, enum_type=None, containing_type=None, 317 | is_extension=False, extension_scope=None, 318 | serialized_options=None, file=DESCRIPTOR), 319 | _descriptor.FieldDescriptor( 320 | name='boundary_width', full_name='SSL_GeometryFieldSize.boundary_width', index=4, 321 | number=5, type=5, cpp_type=1, label=2, 322 | has_default_value=False, default_value=0, 323 | message_type=None, enum_type=None, containing_type=None, 324 | is_extension=False, extension_scope=None, 325 | serialized_options=None, file=DESCRIPTOR), 326 | _descriptor.FieldDescriptor( 327 | name='field_lines', full_name='SSL_GeometryFieldSize.field_lines', index=5, 328 | number=6, type=11, cpp_type=10, label=3, 329 | has_default_value=False, default_value=[], 330 | message_type=None, enum_type=None, containing_type=None, 331 | is_extension=False, extension_scope=None, 332 | serialized_options=None, file=DESCRIPTOR), 333 | _descriptor.FieldDescriptor( 334 | name='field_arcs', full_name='SSL_GeometryFieldSize.field_arcs', index=6, 335 | number=7, type=11, cpp_type=10, label=3, 336 | has_default_value=False, default_value=[], 337 | message_type=None, enum_type=None, containing_type=None, 338 | is_extension=False, extension_scope=None, 339 | serialized_options=None, file=DESCRIPTOR), 340 | _descriptor.FieldDescriptor( 341 | name='penalty_area_depth', full_name='SSL_GeometryFieldSize.penalty_area_depth', index=7, 342 | number=8, type=5, cpp_type=1, label=1, 343 | has_default_value=False, default_value=0, 344 | message_type=None, enum_type=None, containing_type=None, 345 | is_extension=False, extension_scope=None, 346 | serialized_options=None, file=DESCRIPTOR), 347 | _descriptor.FieldDescriptor( 348 | name='penalty_area_width', full_name='SSL_GeometryFieldSize.penalty_area_width', index=8, 349 | number=9, type=5, cpp_type=1, label=1, 350 | has_default_value=False, default_value=0, 351 | message_type=None, enum_type=None, containing_type=None, 352 | is_extension=False, extension_scope=None, 353 | serialized_options=None, file=DESCRIPTOR), 354 | ], 355 | extensions=[ 356 | ], 357 | nested_types=[], 358 | enum_types=[ 359 | ], 360 | serialized_options=None, 361 | is_extendable=False, 362 | syntax='proto2', 363 | extension_ranges=[], 364 | oneofs=[ 365 | ], 366 | serialized_start=363, 367 | serialized_end=636, 368 | ) 369 | 370 | 371 | _SSL_GEOMETRYCAMERACALIBRATION = _descriptor.Descriptor( 372 | name='SSL_GeometryCameraCalibration', 373 | full_name='SSL_GeometryCameraCalibration', 374 | filename=None, 375 | file=DESCRIPTOR, 376 | containing_type=None, 377 | fields=[ 378 | _descriptor.FieldDescriptor( 379 | name='camera_id', full_name='SSL_GeometryCameraCalibration.camera_id', index=0, 380 | number=1, type=13, cpp_type=3, label=2, 381 | has_default_value=False, default_value=0, 382 | message_type=None, enum_type=None, containing_type=None, 383 | is_extension=False, extension_scope=None, 384 | serialized_options=None, file=DESCRIPTOR), 385 | _descriptor.FieldDescriptor( 386 | name='focal_length', full_name='SSL_GeometryCameraCalibration.focal_length', index=1, 387 | number=2, type=2, cpp_type=6, label=2, 388 | has_default_value=False, default_value=float(0), 389 | message_type=None, enum_type=None, containing_type=None, 390 | is_extension=False, extension_scope=None, 391 | serialized_options=None, file=DESCRIPTOR), 392 | _descriptor.FieldDescriptor( 393 | name='principal_point_x', full_name='SSL_GeometryCameraCalibration.principal_point_x', index=2, 394 | number=3, type=2, cpp_type=6, label=2, 395 | has_default_value=False, default_value=float(0), 396 | message_type=None, enum_type=None, containing_type=None, 397 | is_extension=False, extension_scope=None, 398 | serialized_options=None, file=DESCRIPTOR), 399 | _descriptor.FieldDescriptor( 400 | name='principal_point_y', full_name='SSL_GeometryCameraCalibration.principal_point_y', index=3, 401 | number=4, type=2, cpp_type=6, label=2, 402 | has_default_value=False, default_value=float(0), 403 | message_type=None, enum_type=None, containing_type=None, 404 | is_extension=False, extension_scope=None, 405 | serialized_options=None, file=DESCRIPTOR), 406 | _descriptor.FieldDescriptor( 407 | name='distortion', full_name='SSL_GeometryCameraCalibration.distortion', index=4, 408 | number=5, type=2, cpp_type=6, label=2, 409 | has_default_value=False, default_value=float(0), 410 | message_type=None, enum_type=None, containing_type=None, 411 | is_extension=False, extension_scope=None, 412 | serialized_options=None, file=DESCRIPTOR), 413 | _descriptor.FieldDescriptor( 414 | name='q0', full_name='SSL_GeometryCameraCalibration.q0', index=5, 415 | number=6, type=2, cpp_type=6, label=2, 416 | has_default_value=False, default_value=float(0), 417 | message_type=None, enum_type=None, containing_type=None, 418 | is_extension=False, extension_scope=None, 419 | serialized_options=None, file=DESCRIPTOR), 420 | _descriptor.FieldDescriptor( 421 | name='q1', full_name='SSL_GeometryCameraCalibration.q1', index=6, 422 | number=7, type=2, cpp_type=6, label=2, 423 | has_default_value=False, default_value=float(0), 424 | message_type=None, enum_type=None, containing_type=None, 425 | is_extension=False, extension_scope=None, 426 | serialized_options=None, file=DESCRIPTOR), 427 | _descriptor.FieldDescriptor( 428 | name='q2', full_name='SSL_GeometryCameraCalibration.q2', index=7, 429 | number=8, type=2, cpp_type=6, label=2, 430 | has_default_value=False, default_value=float(0), 431 | message_type=None, enum_type=None, containing_type=None, 432 | is_extension=False, extension_scope=None, 433 | serialized_options=None, file=DESCRIPTOR), 434 | _descriptor.FieldDescriptor( 435 | name='q3', full_name='SSL_GeometryCameraCalibration.q3', index=8, 436 | number=9, type=2, cpp_type=6, label=2, 437 | has_default_value=False, default_value=float(0), 438 | message_type=None, enum_type=None, containing_type=None, 439 | is_extension=False, extension_scope=None, 440 | serialized_options=None, file=DESCRIPTOR), 441 | _descriptor.FieldDescriptor( 442 | name='tx', full_name='SSL_GeometryCameraCalibration.tx', index=9, 443 | number=10, type=2, cpp_type=6, label=2, 444 | has_default_value=False, default_value=float(0), 445 | message_type=None, enum_type=None, containing_type=None, 446 | is_extension=False, extension_scope=None, 447 | serialized_options=None, file=DESCRIPTOR), 448 | _descriptor.FieldDescriptor( 449 | name='ty', full_name='SSL_GeometryCameraCalibration.ty', index=10, 450 | number=11, type=2, cpp_type=6, label=2, 451 | has_default_value=False, default_value=float(0), 452 | message_type=None, enum_type=None, containing_type=None, 453 | is_extension=False, extension_scope=None, 454 | serialized_options=None, file=DESCRIPTOR), 455 | _descriptor.FieldDescriptor( 456 | name='tz', full_name='SSL_GeometryCameraCalibration.tz', index=11, 457 | number=12, type=2, cpp_type=6, label=2, 458 | has_default_value=False, default_value=float(0), 459 | message_type=None, enum_type=None, containing_type=None, 460 | is_extension=False, extension_scope=None, 461 | serialized_options=None, file=DESCRIPTOR), 462 | _descriptor.FieldDescriptor( 463 | name='derived_camera_world_tx', full_name='SSL_GeometryCameraCalibration.derived_camera_world_tx', index=12, 464 | number=13, type=2, cpp_type=6, label=1, 465 | has_default_value=False, default_value=float(0), 466 | message_type=None, enum_type=None, containing_type=None, 467 | is_extension=False, extension_scope=None, 468 | serialized_options=None, file=DESCRIPTOR), 469 | _descriptor.FieldDescriptor( 470 | name='derived_camera_world_ty', full_name='SSL_GeometryCameraCalibration.derived_camera_world_ty', index=13, 471 | number=14, type=2, cpp_type=6, label=1, 472 | has_default_value=False, default_value=float(0), 473 | message_type=None, enum_type=None, containing_type=None, 474 | is_extension=False, extension_scope=None, 475 | serialized_options=None, file=DESCRIPTOR), 476 | _descriptor.FieldDescriptor( 477 | name='derived_camera_world_tz', full_name='SSL_GeometryCameraCalibration.derived_camera_world_tz', index=14, 478 | number=15, type=2, cpp_type=6, label=1, 479 | has_default_value=False, default_value=float(0), 480 | message_type=None, enum_type=None, containing_type=None, 481 | is_extension=False, extension_scope=None, 482 | serialized_options=None, file=DESCRIPTOR), 483 | _descriptor.FieldDescriptor( 484 | name='pixel_image_width', full_name='SSL_GeometryCameraCalibration.pixel_image_width', index=15, 485 | number=16, type=13, cpp_type=3, label=1, 486 | has_default_value=False, default_value=0, 487 | message_type=None, enum_type=None, containing_type=None, 488 | is_extension=False, extension_scope=None, 489 | serialized_options=None, file=DESCRIPTOR), 490 | _descriptor.FieldDescriptor( 491 | name='pixel_image_height', full_name='SSL_GeometryCameraCalibration.pixel_image_height', index=16, 492 | number=17, type=13, cpp_type=3, label=1, 493 | has_default_value=False, default_value=0, 494 | message_type=None, enum_type=None, containing_type=None, 495 | is_extension=False, extension_scope=None, 496 | serialized_options=None, file=DESCRIPTOR), 497 | ], 498 | extensions=[ 499 | ], 500 | nested_types=[], 501 | enum_types=[ 502 | ], 503 | serialized_options=None, 504 | is_extendable=False, 505 | syntax='proto2', 506 | extension_ranges=[], 507 | oneofs=[ 508 | ], 509 | serialized_start=639, 510 | serialized_end=1023, 511 | ) 512 | 513 | 514 | _SSL_BALLMODELSTRAIGHTTWOPHASE = _descriptor.Descriptor( 515 | name='SSL_BallModelStraightTwoPhase', 516 | full_name='SSL_BallModelStraightTwoPhase', 517 | filename=None, 518 | file=DESCRIPTOR, 519 | containing_type=None, 520 | fields=[ 521 | _descriptor.FieldDescriptor( 522 | name='acc_slide', full_name='SSL_BallModelStraightTwoPhase.acc_slide', index=0, 523 | number=1, type=1, cpp_type=5, label=2, 524 | has_default_value=False, default_value=float(0), 525 | message_type=None, enum_type=None, containing_type=None, 526 | is_extension=False, extension_scope=None, 527 | serialized_options=None, file=DESCRIPTOR), 528 | _descriptor.FieldDescriptor( 529 | name='acc_roll', full_name='SSL_BallModelStraightTwoPhase.acc_roll', index=1, 530 | number=2, type=1, cpp_type=5, label=2, 531 | has_default_value=False, default_value=float(0), 532 | message_type=None, enum_type=None, containing_type=None, 533 | is_extension=False, extension_scope=None, 534 | serialized_options=None, file=DESCRIPTOR), 535 | _descriptor.FieldDescriptor( 536 | name='k_switch', full_name='SSL_BallModelStraightTwoPhase.k_switch', index=2, 537 | number=3, type=1, cpp_type=5, label=2, 538 | has_default_value=False, default_value=float(0), 539 | message_type=None, enum_type=None, containing_type=None, 540 | is_extension=False, extension_scope=None, 541 | serialized_options=None, file=DESCRIPTOR), 542 | ], 543 | extensions=[ 544 | ], 545 | nested_types=[], 546 | enum_types=[ 547 | ], 548 | serialized_options=None, 549 | is_extendable=False, 550 | syntax='proto2', 551 | extension_ranges=[], 552 | oneofs=[ 553 | ], 554 | serialized_start=1025, 555 | serialized_end=1111, 556 | ) 557 | 558 | 559 | _SSL_BALLMODELCHIPFIXEDLOSS = _descriptor.Descriptor( 560 | name='SSL_BallModelChipFixedLoss', 561 | full_name='SSL_BallModelChipFixedLoss', 562 | filename=None, 563 | file=DESCRIPTOR, 564 | containing_type=None, 565 | fields=[ 566 | _descriptor.FieldDescriptor( 567 | name='damping_xy_first_hop', full_name='SSL_BallModelChipFixedLoss.damping_xy_first_hop', index=0, 568 | number=1, type=1, cpp_type=5, label=2, 569 | has_default_value=False, default_value=float(0), 570 | message_type=None, enum_type=None, containing_type=None, 571 | is_extension=False, extension_scope=None, 572 | serialized_options=None, file=DESCRIPTOR), 573 | _descriptor.FieldDescriptor( 574 | name='damping_xy_other_hops', full_name='SSL_BallModelChipFixedLoss.damping_xy_other_hops', index=1, 575 | number=2, type=1, cpp_type=5, label=2, 576 | has_default_value=False, default_value=float(0), 577 | message_type=None, enum_type=None, containing_type=None, 578 | is_extension=False, extension_scope=None, 579 | serialized_options=None, file=DESCRIPTOR), 580 | _descriptor.FieldDescriptor( 581 | name='damping_z', full_name='SSL_BallModelChipFixedLoss.damping_z', index=2, 582 | number=3, type=1, cpp_type=5, label=2, 583 | has_default_value=False, default_value=float(0), 584 | message_type=None, enum_type=None, containing_type=None, 585 | is_extension=False, extension_scope=None, 586 | serialized_options=None, file=DESCRIPTOR), 587 | ], 588 | extensions=[ 589 | ], 590 | nested_types=[], 591 | enum_types=[ 592 | ], 593 | serialized_options=None, 594 | is_extendable=False, 595 | syntax='proto2', 596 | extension_ranges=[], 597 | oneofs=[ 598 | ], 599 | serialized_start=1113, 600 | serialized_end=1221, 601 | ) 602 | 603 | 604 | _SSL_GEOMETRYMODELS = _descriptor.Descriptor( 605 | name='SSL_GeometryModels', 606 | full_name='SSL_GeometryModels', 607 | filename=None, 608 | file=DESCRIPTOR, 609 | containing_type=None, 610 | fields=[ 611 | _descriptor.FieldDescriptor( 612 | name='straight_two_phase', full_name='SSL_GeometryModels.straight_two_phase', index=0, 613 | number=1, type=11, cpp_type=10, label=1, 614 | has_default_value=False, default_value=None, 615 | message_type=None, enum_type=None, containing_type=None, 616 | is_extension=False, extension_scope=None, 617 | serialized_options=None, file=DESCRIPTOR), 618 | _descriptor.FieldDescriptor( 619 | name='chip_fixed_loss', full_name='SSL_GeometryModels.chip_fixed_loss', index=1, 620 | number=2, type=11, cpp_type=10, label=1, 621 | has_default_value=False, default_value=None, 622 | message_type=None, enum_type=None, containing_type=None, 623 | is_extension=False, extension_scope=None, 624 | serialized_options=None, file=DESCRIPTOR), 625 | ], 626 | extensions=[ 627 | ], 628 | nested_types=[], 629 | enum_types=[ 630 | ], 631 | serialized_options=None, 632 | is_extendable=False, 633 | syntax='proto2', 634 | extension_ranges=[], 635 | oneofs=[ 636 | ], 637 | serialized_start=1224, 638 | serialized_end=1358, 639 | ) 640 | 641 | 642 | _SSL_GEOMETRYDATA = _descriptor.Descriptor( 643 | name='SSL_GeometryData', 644 | full_name='SSL_GeometryData', 645 | filename=None, 646 | file=DESCRIPTOR, 647 | containing_type=None, 648 | fields=[ 649 | _descriptor.FieldDescriptor( 650 | name='field', full_name='SSL_GeometryData.field', index=0, 651 | number=1, type=11, cpp_type=10, label=2, 652 | has_default_value=False, default_value=None, 653 | message_type=None, enum_type=None, containing_type=None, 654 | is_extension=False, extension_scope=None, 655 | serialized_options=None, file=DESCRIPTOR), 656 | _descriptor.FieldDescriptor( 657 | name='calib', full_name='SSL_GeometryData.calib', index=1, 658 | number=2, type=11, cpp_type=10, label=3, 659 | has_default_value=False, default_value=[], 660 | message_type=None, enum_type=None, containing_type=None, 661 | is_extension=False, extension_scope=None, 662 | serialized_options=None, file=DESCRIPTOR), 663 | _descriptor.FieldDescriptor( 664 | name='models', full_name='SSL_GeometryData.models', index=2, 665 | number=3, type=11, cpp_type=10, label=1, 666 | has_default_value=False, default_value=None, 667 | message_type=None, enum_type=None, containing_type=None, 668 | is_extension=False, extension_scope=None, 669 | serialized_options=None, file=DESCRIPTOR), 670 | ], 671 | extensions=[ 672 | ], 673 | nested_types=[], 674 | enum_types=[ 675 | ], 676 | serialized_options=None, 677 | is_extendable=False, 678 | syntax='proto2', 679 | extension_ranges=[], 680 | oneofs=[ 681 | ], 682 | serialized_start=1361, 683 | serialized_end=1502, 684 | ) 685 | 686 | _SSL_FIELDLINESEGMENT.fields_by_name['p1'].message_type = _VECTOR2F 687 | _SSL_FIELDLINESEGMENT.fields_by_name['p2'].message_type = _VECTOR2F 688 | _SSL_FIELDLINESEGMENT.fields_by_name['type'].enum_type = _SSL_FIELDSHAPETYPE 689 | _SSL_FIELDCIRCULARARC.fields_by_name['center'].message_type = _VECTOR2F 690 | _SSL_FIELDCIRCULARARC.fields_by_name['type'].enum_type = _SSL_FIELDSHAPETYPE 691 | _SSL_GEOMETRYFIELDSIZE.fields_by_name['field_lines'].message_type = _SSL_FIELDLINESEGMENT 692 | _SSL_GEOMETRYFIELDSIZE.fields_by_name['field_arcs'].message_type = _SSL_FIELDCIRCULARARC 693 | _SSL_GEOMETRYMODELS.fields_by_name['straight_two_phase'].message_type = _SSL_BALLMODELSTRAIGHTTWOPHASE 694 | _SSL_GEOMETRYMODELS.fields_by_name['chip_fixed_loss'].message_type = _SSL_BALLMODELCHIPFIXEDLOSS 695 | _SSL_GEOMETRYDATA.fields_by_name['field'].message_type = _SSL_GEOMETRYFIELDSIZE 696 | _SSL_GEOMETRYDATA.fields_by_name['calib'].message_type = _SSL_GEOMETRYCAMERACALIBRATION 697 | _SSL_GEOMETRYDATA.fields_by_name['models'].message_type = _SSL_GEOMETRYMODELS 698 | DESCRIPTOR.message_types_by_name['Vector2f'] = _VECTOR2F 699 | DESCRIPTOR.message_types_by_name['SSL_FieldLineSegment'] = _SSL_FIELDLINESEGMENT 700 | DESCRIPTOR.message_types_by_name['SSL_FieldCircularArc'] = _SSL_FIELDCIRCULARARC 701 | DESCRIPTOR.message_types_by_name['SSL_GeometryFieldSize'] = _SSL_GEOMETRYFIELDSIZE 702 | DESCRIPTOR.message_types_by_name['SSL_GeometryCameraCalibration'] = _SSL_GEOMETRYCAMERACALIBRATION 703 | DESCRIPTOR.message_types_by_name['SSL_BallModelStraightTwoPhase'] = _SSL_BALLMODELSTRAIGHTTWOPHASE 704 | DESCRIPTOR.message_types_by_name['SSL_BallModelChipFixedLoss'] = _SSL_BALLMODELCHIPFIXEDLOSS 705 | DESCRIPTOR.message_types_by_name['SSL_GeometryModels'] = _SSL_GEOMETRYMODELS 706 | DESCRIPTOR.message_types_by_name['SSL_GeometryData'] = _SSL_GEOMETRYDATA 707 | DESCRIPTOR.enum_types_by_name['SSL_FieldShapeType'] = _SSL_FIELDSHAPETYPE 708 | _sym_db.RegisterFileDescriptor(DESCRIPTOR) 709 | 710 | Vector2f = _reflection.GeneratedProtocolMessageType('Vector2f', (_message.Message,), dict( 711 | DESCRIPTOR = _VECTOR2F, 712 | __module__ = 'ssl_vision_geometry_pb2' 713 | # @@protoc_insertion_point(class_scope:Vector2f) 714 | )) 715 | _sym_db.RegisterMessage(Vector2f) 716 | 717 | SSL_FieldLineSegment = _reflection.GeneratedProtocolMessageType('SSL_FieldLineSegment', (_message.Message,), dict( 718 | DESCRIPTOR = _SSL_FIELDLINESEGMENT, 719 | __module__ = 'ssl_vision_geometry_pb2' 720 | # @@protoc_insertion_point(class_scope:SSL_FieldLineSegment) 721 | )) 722 | _sym_db.RegisterMessage(SSL_FieldLineSegment) 723 | 724 | SSL_FieldCircularArc = _reflection.GeneratedProtocolMessageType('SSL_FieldCircularArc', (_message.Message,), dict( 725 | DESCRIPTOR = _SSL_FIELDCIRCULARARC, 726 | __module__ = 'ssl_vision_geometry_pb2' 727 | # @@protoc_insertion_point(class_scope:SSL_FieldCircularArc) 728 | )) 729 | _sym_db.RegisterMessage(SSL_FieldCircularArc) 730 | 731 | SSL_GeometryFieldSize = _reflection.GeneratedProtocolMessageType('SSL_GeometryFieldSize', (_message.Message,), dict( 732 | DESCRIPTOR = _SSL_GEOMETRYFIELDSIZE, 733 | __module__ = 'ssl_vision_geometry_pb2' 734 | # @@protoc_insertion_point(class_scope:SSL_GeometryFieldSize) 735 | )) 736 | _sym_db.RegisterMessage(SSL_GeometryFieldSize) 737 | 738 | SSL_GeometryCameraCalibration = _reflection.GeneratedProtocolMessageType('SSL_GeometryCameraCalibration', (_message.Message,), dict( 739 | DESCRIPTOR = _SSL_GEOMETRYCAMERACALIBRATION, 740 | __module__ = 'ssl_vision_geometry_pb2' 741 | # @@protoc_insertion_point(class_scope:SSL_GeometryCameraCalibration) 742 | )) 743 | _sym_db.RegisterMessage(SSL_GeometryCameraCalibration) 744 | 745 | SSL_BallModelStraightTwoPhase = _reflection.GeneratedProtocolMessageType('SSL_BallModelStraightTwoPhase', (_message.Message,), dict( 746 | DESCRIPTOR = _SSL_BALLMODELSTRAIGHTTWOPHASE, 747 | __module__ = 'ssl_vision_geometry_pb2' 748 | # @@protoc_insertion_point(class_scope:SSL_BallModelStraightTwoPhase) 749 | )) 750 | _sym_db.RegisterMessage(SSL_BallModelStraightTwoPhase) 751 | 752 | SSL_BallModelChipFixedLoss = _reflection.GeneratedProtocolMessageType('SSL_BallModelChipFixedLoss', (_message.Message,), dict( 753 | DESCRIPTOR = _SSL_BALLMODELCHIPFIXEDLOSS, 754 | __module__ = 'ssl_vision_geometry_pb2' 755 | # @@protoc_insertion_point(class_scope:SSL_BallModelChipFixedLoss) 756 | )) 757 | _sym_db.RegisterMessage(SSL_BallModelChipFixedLoss) 758 | 759 | SSL_GeometryModels = _reflection.GeneratedProtocolMessageType('SSL_GeometryModels', (_message.Message,), dict( 760 | DESCRIPTOR = _SSL_GEOMETRYMODELS, 761 | __module__ = 'ssl_vision_geometry_pb2' 762 | # @@protoc_insertion_point(class_scope:SSL_GeometryModels) 763 | )) 764 | _sym_db.RegisterMessage(SSL_GeometryModels) 765 | 766 | SSL_GeometryData = _reflection.GeneratedProtocolMessageType('SSL_GeometryData', (_message.Message,), dict( 767 | DESCRIPTOR = _SSL_GEOMETRYDATA, 768 | __module__ = 'ssl_vision_geometry_pb2' 769 | # @@protoc_insertion_point(class_scope:SSL_GeometryData) 770 | )) 771 | _sym_db.RegisterMessage(SSL_GeometryData) 772 | 773 | 774 | DESCRIPTOR._options = None 775 | # @@protoc_insertion_point(module_scope) 776 | --------------------------------------------------------------------------------