Skip to content

Commit

Permalink
Merge pull request #141 from robocup-junior/update-webots
Browse files Browse the repository at this point in the history
Update webots to R2023b
  • Loading branch information
Adman committed Oct 6, 2023
2 parents da989e6 + 56e096d commit cd03e70
Show file tree
Hide file tree
Showing 18 changed files with 196 additions and 232 deletions.
6 changes: 3 additions & 3 deletions .pre-commit-config.yml
Expand Up @@ -2,19 +2,19 @@ default_language_version:
python: python3.8
repos:
- repo: https://github.com/pycqa/isort
rev: 5.10.1
rev: 5.12.0
hooks:
- id: isort
entry: bash -c 'isort --check-only .'
stages: [commit]
- repo: https://github.com/ambv/black
rev: 21.11b1
rev: 23.9.1
hooks:
- id: black
entry: bash -c 'black --check .'
stages: [commit]
- repo: https://gitlab.com/pycqa/flake8
rev: 4.0.1
rev: 6.1.0
hooks:
- id: flake8
entry: bash -c 'python3 -m flake8 .'
Expand Down
6 changes: 6 additions & 0 deletions CHANGELOG.md
Expand Up @@ -2,6 +2,12 @@

## Unreleased

* Features
* **BREAKING** Change the message format sent between Emitter and Receiver
* Update Webots from R2022a to R2023b
* Other
* Update development requirements

## v2.1

* Features
Expand Down
12 changes: 6 additions & 6 deletions README.md
Expand Up @@ -3,24 +3,24 @@
This is the official repository of the RoboCupJunior Soccer Simulator. The
simulator is based on [Webots](https://github.com/cyberbotics/webots) and this
repository provides both the "automatic referee" (which implements the [Soccer
Simulated Rules](https://github.com/RoboCupJuniorTC/soccer-rules-simulation))
Simulated Rules](https://github.com/robocup-junior/soccer-rules-simulation))
as well as a sample simulated team of robots with some basic strategy.

![Soccer Sim](./docs/docs/images/soccer_sim.png)

*Learn more in the [documentation](https://robocupjuniortc.github.io/rcj-soccersim/).*
*Learn more in the [documentation](https://robocup-junior.github.io/rcj-soccersim/).*

# How do I try this out?

## Installation

1. Install Python 3.7 (or higher) 64 bit from the [official website](https://www.python.org/downloads/) (please make sure it is version 3.7 or higher for Windows, and 3.8 or higher if installing on MacOS or Linux). On Windows, please make sure your Python is referenced in Windows PATH by selecting the option "Add Python 3.x to PATH" during the installation. Check out this great [installation guide](https://realpython.com/installing-python/) if you need some help!

2. Download [Webots](https://www.cyberbotics.com/#download) from their official website. Currently, version R2022a is stable with the Soccer Simulator. You can find detailed installation procedure on the official [Webots Installation guide](https://cyberbotics.com/doc/guide/installation-procedure).
2. Download [Webots](https://www.cyberbotics.com/#download) from their official website. Currently, version R2023b is stable with the Soccer Simulator. You can find detailed installation procedure on the official [Webots Installation guide](https://cyberbotics.com/doc/guide/installation-procedure).

3. Clone the rcj-soccersim repository to your computer by downloading the ZIP file from [here](https://github.com/RoboCupJuniorTC/rcj-soccersim/archive/master.zip) or running
3. Clone the rcj-soccersim repository to your computer by downloading the ZIP file from [here](https://github.com/robocup-junior/rcj-soccersim/archive/master.zip) or running

git clone https://github.com/RoboCupJuniorTC/rcj-soccersim.git
git clone https://github.com/robocup-junior/rcj-soccersim.git

4. Finally, run Webots, go to `Tools > Preferences > Python command` and set it to `python` or `python3` to point Webots to Python 3. Depending on your system, the reference to Python 3 can be via the command `python` or `python3`. More information on how to configure Webots to work with Python can be found [here](https://cyberbotics.com/doc/guide/using-python).

Expand Down Expand Up @@ -48,7 +48,7 @@ avoid any compilation issues.

## Development

We are open to contributions! Have a look at our [issues](https://github.com/RoboCupJuniorTC/rcj-soccersim/issues).
We are open to contributions! Have a look at our [issues](https://github.com/robocup-junior/rcj-soccersim/issues).
Before you make a pull request, make sure the code is formatted
with `black` and `isort`, and `flake8` issues are fixed.

Expand Down
7 changes: 2 additions & 5 deletions controllers/rcj_soccer_ball/rcj_soccer_ball.py
@@ -1,12 +1,9 @@
import struct

from controller import Robot

robot = Robot()
ball_emitter = robot.getDevice("ball emitter")

data = [True] # Packet cannot be empty
packet = struct.pack("?", *data)
data = "x" # Packet cannot be empty

while robot.step(32) != -1:
ball_emitter.send(packet)
ball_emitter.send(data)
Expand Up @@ -30,7 +30,6 @@ def output_path(
match_id: int,
half_id: int,
) -> PosixPath:

now_str = datetime.utcnow().strftime("%Y%m%dT%H%M%S")
team_blue = team_blue_id.replace(" ", "_")
team_yellow = team_yellow_id.replace(" ", "_")
Expand Down
Expand Up @@ -17,7 +17,6 @@ def __init__(
fastforward_rate: int = 1,
resolution: str = "720p",
):

self.supervisor = supervisor
self.output_path = output_path
self.fastforward_rate = fastforward_rate
Expand Down
Expand Up @@ -15,10 +15,10 @@ def reset(self):
self.prev_position = None

def track(self, position: List[float]):
"""Make ProgressChecker react to a new position. Internally, it computes
the Euclidian distance from the previous position and saves it so that
it can be used when computing whether the given object has made
progress.
"""Make ProgressChecker react to a new position. Internally, it
computes the Euclidian distance from the previous position and
saves it so that it can be used when computing whether the given
object has made progress.
Args:
position (list): Current position of the object
Expand Down
23 changes: 10 additions & 13 deletions controllers/rcj_soccer_referee_supervisor/referee/referee.py
@@ -1,5 +1,5 @@
import json
import random
import struct
from typing import List, Optional, Tuple

from controller import Supervisor
Expand Down Expand Up @@ -91,21 +91,18 @@ def __init__(
self.sv.draw_team_names(self.team_name_blue, self.team_name_yellow)
self.sv.draw_scores(self.score_blue, self.score_yellow)

def _pack_packet(self) -> bytes:
"""Pack data into packet.
def _pack_data(self) -> str:
"""Pack data into json string.
Returns:
bytes: the packed packet.
str: json data encoded into string.
"""
# True/False telling whether the goal was scored
struct_fmt = "?"
data = list()
# Add Notification if the goal is scored and we are
# waiting for kickoff. The value is True or False
waiting_for_kickoff = self.ball_reset_timer > 0

# Add Notification if the goal is scored and we are waiting for kickoff
# The value is True or False
data.append(self.ball_reset_timer > 0)

return struct.pack(struct_fmt, *data)
data = {"waiting_for_kickoff": waiting_for_kickoff}
return json.dumps(data)

def _add_initial_position_noise(
self, translation: List[float]
Expand Down Expand Up @@ -396,7 +393,7 @@ def tick(self) -> bool:
)

self.sv.update_positions()
self.sv.emit_data(self._pack_packet())
self.sv.emit_data(self._pack_data())
self.time -= TIME_STEP / 1000.0

# On the very last tick, note that the match has finished
Expand Down
Expand Up @@ -217,13 +217,13 @@ def move_object_to_neutral_spot(self, object_name: str, neutral_spot: str):
object_name, ROBOT_INITIAL_ROTATION[object_name]
)

def emit_data(self, packet: bytes):
def emit_data(self, data: str):
"""Send packet via emitter
Args:
packet (bytes): the packet to be sent
data (str): the data to be sent
"""
self.emitter.send(packet)
self.emitter.send(data)

def draw_team_names(self, team_name_blue: str, team_name_yellow: str):
"""Visualize (draw) the names of the teams.
Expand Down
Expand Up @@ -32,7 +32,7 @@ def referee() -> RCJSoccerReferee:


def test_pack_packet(referee: RCJSoccerReferee):
assert referee._pack_packet() == b"\x00"
assert referee._pack_data() == '{"waiting_for_kickoff": false}'


def test_add_initial_position_noise(referee: RCJSoccerReferee):
Expand Down
54 changes: 25 additions & 29 deletions controllers/rcj_soccer_team_blue/rcj_soccer_robot.py
@@ -1,5 +1,5 @@
import json
import math
import struct

TIME_STEP = 32
ROBOT_NAMES = ["B1", "B2", "B3", "Y1", "Y2", "Y3"]
Expand Down Expand Up @@ -47,33 +47,30 @@ def __init__(self, robot):
self.left_motor.setVelocity(0.0)
self.right_motor.setVelocity(0.0)

def parse_supervisor_msg(self, packet: str) -> dict:
def parse_supervisor_msg(self, data: str) -> dict:
"""Parse message received from supervisor
Args:
data: json data encoded into string
Returns:
dict: Location info about each robot and the ball.
dict: data decoded into dictionary
Example:
{
'waiting_for_kickoff': False,
}
"""
# True/False telling whether the goal was scored
struct_fmt = "?"
unpacked = struct.unpack(struct_fmt, packet)

data = {"waiting_for_kickoff": unpacked[0]}
return data
return json.loads(data)

def get_new_data(self) -> dict:
"""Read new data from supervisor
Returns:
dict: See `parse_supervisor_msg` method
"""
packet = self.receiver.getData()
data = self.receiver.getString()
self.receiver.nextPacket()

return self.parse_supervisor_msg(packet)
return self.parse_supervisor_msg(data)

def is_new_data(self) -> bool:
"""Check if there is new data from supervisor to be received
Expand All @@ -83,28 +80,26 @@ def is_new_data(self) -> bool:
"""
return self.receiver.getQueueLength() > 0

def parse_team_msg(self, packet: str) -> dict:
def parse_team_msg(self, data: str) -> dict:
"""Parse message received from team robot
Args:
dict: json data encoded into string
Returns:
dict: Parsed message stored in dictionary.
dict: data decoded into dictionary
"""
struct_fmt = "i"
unpacked = struct.unpack(struct_fmt, packet)
data = {
"robot_id": unpacked[0],
}
return data
return json.loads(data)

def get_new_team_data(self) -> dict:
"""Read new data from team robot
Returns:
dict: See `parse_team_msg` method
"""
packet = self.team_receiver.getData()
data = self.team_receiver.getString()
self.team_receiver.nextPacket()
return self.parse_team_msg(packet)
return self.parse_team_msg(data)

def is_new_team_data(self) -> bool:
"""Check if there is new data from team robots to be received
Expand All @@ -114,16 +109,14 @@ def is_new_team_data(self) -> bool:
"""
return self.team_receiver.getQueueLength() > 0

def send_data_to_team(self, robot_id) -> None:
def send_data_to_team(self, robot_id: int) -> None:
"""Send data to the team
Args:
robot_id (int): ID of the robot
"""
struct_fmt = "i"
data = [robot_id]
packet = struct.pack(struct_fmt, *data)
self.team_emitter.send(packet)
data = {"robot_id": robot_id}
self.team_emitter.send(json.dumps(data))

def get_new_ball_data(self) -> dict:
"""Read new data from IR sensor
Expand All @@ -138,9 +131,12 @@ def get_new_ball_data(self) -> dict:
'strength': 0.1
}
"""
_ = self.ball_receiver.getData()
_ = self.ball_receiver.getString()
data = {
"direction": self.ball_receiver.getEmitterDirection(),
# TODO: Remove [:3] once
# https://github.com/cyberbotics/webots/pull/6394
# is released and Webots updated
"direction": self.ball_receiver.getEmitterDirection()[:3],
"strength": self.ball_receiver.getSignalStrength(),
}
self.ball_receiver.nextPacket()
Expand Down

0 comments on commit cd03e70

Please sign in to comment.