-
Notifications
You must be signed in to change notification settings - Fork 0
feat: ball placement entry point (conflict-free) #126
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
isaac0804
wants to merge
128
commits into
main
Choose a base branch
from
ball_placement_clean
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 15 commits
Commits
Show all changes
128 commits
Select commit
Hold shift + click to select a range
9720dc1
feat: referee support in rsim
isaac0804 4cff935
hotfix: self.name bug
isaac0804 ac7ffb0
Merge branch 'main' into referee_integration
isaac0804 3f6b0d9
feat: receive complete referee data and use it in strategy runner
isaac0804 27850b1
feat: referee command nodes and test
isaac0804 ec2558b
fix: make RefereeData.__eq__ actually override tuple equality; fix te…
isaac0804 08af954
merge: resolve conflicts from main into referee_integration
isaac0804 769a8a6
Add custom referee integration and profile rename
isaac0804 5c0b05a
Fix referee runner startup and keep-out behavior
isaac0804 626ef22
Scale referee actions with field geometry
isaac0804 d4adaeb
Fix referee restart progression and clearance
isaac0804 a0b120d
Fix custom referee demo wiring and status messages
isaac0804 2250a92
Show referee source details in live status
isaac0804 5d757c1
Add referee behaviour integration tests and unit test coverage
isaac0804 b683f39
Use public Field class properties instead of private constants
isaac0804 f6f1297
Default headless=True, skip ball teleport when placement pending, doc…
isaac0804 aa4974a
Document end-to-end ball placement test as future work
isaac0804 15aa391
Remove advanced controls (penalty & ball placement) from referee GUI
isaac0804 c148b34
Add three future work items to referee integration docs
isaac0804 cb6b176
Fix three bugs identified in Copilot review
isaac0804 5282cc2
Update utama_core/custom_referee/state_machine.py
isaac0804 cc1b187
Address second round of Copilot review comments
isaac0804 9d6b8ea
fix: stage_time_left now updates every frame in RefereeRefiner
isaac0804 6c265ab
fix: increase BALL_KEEP_OUT_DISTANCE to 0.8 m to prevent restart viol…
isaac0804 3125309
Merge origin/main into referee_integration
isaac0804 2040685
fix: adapt referee code to FieldDimensions API and arbitrary field sizes
isaac0804 3d170b8
fix: use own-half fallback direction when robot is coincident with ball
isaac0804 04288e5
feat: make StrategyRunner the single source of truth for referee geom…
isaac0804 fe1c490
refactor: remove RefereeGeometry.from_standard_div_b()
isaac0804 82051b9
refactor: rename half_defense_length → half_defense_depth in RefereeG…
isaac0804 4869ca9
fix: remove dead CLEARANCE_FALLBACK_DIRECTION and fix _clear_to_legal…
isaac0804 d6f4f11
fix: exclude PREPARE_KICKOFF/PENALTY from keep-out rule to prevent se…
isaac0804 b3a02bd
Revert "fix: exclude PREPARE_KICKOFF/PENALTY from keep-out rule to pr…
isaac0804 3bb31bc
fix: clear encroaching robots from current position, not formation ta…
isaac0804 ea33066
fix: use BALL_KEEP_OUT_DISTANCE in _ensure_outside_center_circle
isaac0804 386dd94
fix: address Copilot review issues in referee code and docs
isaac0804 ea8514b
fix: address Copilot review issues in referee actions and tests
isaac0804 530cd0b
fix: keep RefereeRefiner properties current when deduplication skips …
isaac0804 7707973
docs: rename half_defense_length → half_defense_depth in all docs
isaac0804 e5f381b
docs: remove non-existent exhibition.yaml from file structure
isaac0804 aceeb8e
Merge branch 'main' into referee_integration
energy-in-joles 0c65a12
bug fix for pytest and add referee example in main
energy-in-joles 82e80a2
fix: use game.ts as referee timebase instead of wall clock
isaac0804 69b96e0
fix(#107): suppress Kalman ghost tracking during robot substitution
isaac0804 3cc2ee8
Revert "fix(#107): suppress Kalman ghost tracking during robot substi…
isaac0804 d89a3af
fix: address Copilot review issues in main.py and referee tree dispat…
isaac0804 2e65361
fix: make DefenseAreaRule color-aware for symmetric enforcement
isaac0804 6db9d49
fix: cache last RefereeData so GameFrame.referee stays populated betw…
isaac0804 0a1e912
fix: address Copilot review issues in referee tree dispatchers and pe…
isaac0804 60b7c52
fix: prevent keep-out violations and defense-area infinite loop
isaac0804 b317811
fix: seed _prepare_entered_time in set_command() for direct PREPARE_*…
isaac0804 56b20a9
refactor: replace referee_system+custom_referee args with typed Refer…
isaac0804 4104b95
feat: add center_circle_radius to FieldDimensions
isaac0804 58fd7e1
refactor: replace hardcoded geometry fallbacks with STANDARD_FIELD_DI…
isaac0804 bdbe130
refactor: remove dead initial_command and initial_time params from Ga…
isaac0804 7502472
refactor: remove GameTracer from referee_integration branch
isaac0804 7b95ae8
fix: address Copilot review issues — timebase mismatch and center_cir…
isaac0804 d689b5d
fix: snapshot TeamInfo per packet to prevent retroactive history muta…
isaac0804 180d00a
update center circle render for rsim
energy-in-joles d0fb462
fix crash when rsim not included for rendering fpp
energy-in-joles 9193f38
refactor: make StrategyRunner.full_field_dims the single source of fi…
isaac0804 eac4eb8
feat: add Exhibition Road festival demo (2v2, compact field, human-op…
isaac0804 3799bae
refactor: use WanderingStrategy instead of external Strategy_2v2 import
isaac0804 b8a259d
feat: scale WanderingStrategy waypoints to field_dims; pass exhibitio…
isaac0804 7b19c92
fix: propagate geometry mismatch error from vision thread to main thread
isaac0804 a4107af
fix: initialise _stop_event before _setup_vision_and_referee in __init__
isaac0804 2a9237b
fix: guard draw_line calls when env is None (grsim/real mode)
isaac0804 f5f30f0
fix: re-raise parked thread exception after stop_event exits the run …
isaac0804 a0f2bc6
feat: redesign GUI to 2x2 quadrant layout with field filling top-left
isaac0804 a35829c
feat: muted colour palette and grouped ghost-style buttons in GUI
isaac0804 788c637
Revert "feat: muted colour palette and grouped ghost-style buttons in…
isaac0804 0395d80
Revert "feat: redesign GUI to 2x2 quadrant layout with field filling …
isaac0804 7d16076
feat: restore 2x2 quadrant layout with original colour scheme
isaac0804 d380365
fix: pass waypoints directly to WanderingStep instead of via blackboard
isaac0804 a427963
fix: set _waypoints before super().__init__() in WanderingStrategy
isaac0804 3c5a653
config: disable defense area and keep-out rules for exhibition road
isaac0804 7d2c565
feat: add goal_depth to FieldDimensions and propagate to RefereeGeome…
isaac0804 a885932
docs: fix stale referee_gui.py references and outdated StrategyRunner…
isaac0804 b73ba24
fix: add _vision_receiver=None to mock_runner fixture to match Strate…
isaac0804 98e41ee
referee should be using FieldDimensions only
energy-in-joles 7aae73d
tighten docs
energy-in-joles b64e4db
Potential fix for pull request finding
energy-in-joles 25d660d
Potential fix for pull request finding
energy-in-joles f7b9204
update docs
energy-in-joles e2ce95f
implement mapping
energy-in-joles e446948
Merge branch 'main' into real_mapping
energy-in-joles 2c5551b
remove automatic id increment
energy-in-joles 7d2bebf
Potential fix for pull request finding
energy-in-joles f07f01f
check for duplication of cmd ids
energy-in-joles 278c940
prevent double saving duplicaterobot responses
energy-in-joles e206914
fix mapping logic
energy-in-joles dbb13c9
Potential fix for pull request finding
energy-in-joles b267ce2
fix robot response pulling
energy-in-joles 4c39664
Merge branch 'real_mapping' of https://github.com/First-Order-RoboCup…
energy-in-joles 2ed3a53
Potential fix for pull request finding
energy-in-joles 7be21ba
fix unbound reference
energy-in-joles c804a28
move self.opp
energy-in-joles ebf7d4e
migrate mapping logic to strat runner for get_robot_responses
energy-in-joles 8374db1
change erro to warning
5e8ca10
fix: address 6 open Copilot inline review comments in real mapping
isaac0804 fedda8a
fix: follow-up review fixes in real mapping
isaac0804 900581b
Potential fix for pull request finding
energy-in-joles ccf061f
add test cases for new checks
energy-in-joles a57f386
Potential fix for pull request finding
energy-in-joles bcd1c10
Potential fix for pull request finding
energy-in-joles fe2ddc0
feat: per-robot IR sensor trust list with vision-proximity fallback
isaac0804 bdae22b
feat: leaky-bucket dribbler thermal limiter in RealRobotController
isaac0804 a0a54b6
feat: muted colour palette and grouped ghost-style buttons in GUI
isaac0804 87e3d1e
Revert "feat: muted colour palette and grouped ghost-style buttons in…
isaac0804 3e44721
Revert "feat: redesign GUI to 2x2 quadrant layout with field filling …
isaac0804 0f7fd3f
feat: restore 2x2 quadrant layout with original colour scheme
isaac0804 32f716e
feat: add goal_depth to FieldDimensions and propagate to RefereeGeome…
isaac0804 eb4e11d
feat: add ball placement entry point, strategy skeleton, and tests
isaac0804 063aff9
fix: finish the ball_placement
NingchuanIC d0ab7d0
init demp
NingchuanIC 85075ad
take the free kick
NingchuanIC 90aebe7
success sow the demo
NingchuanIC f31ec91
finish the ball placement
NingchuanIC d3de984
test: tighten ball placement rsim tests and add placer selection cove…
isaac0804 6095e2a
feat: add god mode to referee GUI for manual ball placement testing
isaac0804 1566717
fix: update direct free kick tests broken by ball-placement-first rou…
isaac0804 f3324bf
feat: pivot around ball using turn_on_spot during ball placement carry
isaac0804 f81c274
refactor: switch dribbler thermal limiter from steps to wall-clock se…
isaac0804 f7c19d5
fix: warning spam, hysteresis, and heat telemetry for dribbler limiter
isaac0804 9d3fa22
fix: address 4 P2 review comments from fred
isaac0804 c48aa0c
Merge branch 'real_mapping' into ball_placement_clean
isaac0804 a0c4a81
fix: test_placer_moves_toward_designated_position robot start position
isaac0804 914f38c
fix: address 2 new P2 review comments from fred
isaac0804 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,146 @@ | ||
| """demo_ball_placement.py — Entry point for the ball placement feature. | ||
|
|
||
| Run: | ||
| pixi run python demo_ball_placement.py | ||
| # RSim window opens; open http://localhost:8080 in a browser | ||
|
|
||
| What this sets up | ||
| ----------------- | ||
| - Exhibition Road field (4 m × 3 m, ``GREAT_EXHIBITION_FIELD_DIMS``) | ||
| - 2v2 format: two yellow robots (your team) vs two blue robots that | ||
| deliberately push the ball out once per side, then attack the yellow goal | ||
| - CustomReferee pre-configured with: | ||
| - Goal detection enabled (issues PREPARE_KICKOFF → NORMAL_START cycle) | ||
| - Out-of-bounds enabled (issues STOP → BALL_PLACEMENT_YELLOW → DIRECT_FREE) | ||
| - Defense area and keep-out rules OFF (less noise during development) | ||
| - Auto-advance fully enabled so state transitions fire automatically — | ||
| you can watch the full placement → free-kick → restart cycle without | ||
| touching the GUI | ||
| - Browser GUI at http://localhost:8080 — use "Manual Commands" to fire | ||
| BALL_PLACEMENT_YELLOW at any time and set the target position | ||
|
|
||
| Workflow | ||
| -------- | ||
| 1. Run this script and open http://localhost:8080. | ||
| 2. Let the blue robots push the ball out of bounds, or use the GUI "Manual | ||
| Commands" panel to issue BALL_PLACEMENT_YELLOW. | ||
| 3. Watch one of your robots (yellow) drive to the ball, capture it with the | ||
| dribbler, and carry it to the target circle shown in the GUI. | ||
| 4. After the referee advances to NORMAL_START, yellow kicks once toward the | ||
| configured blue robot target. | ||
| """ | ||
|
|
||
| from utama_core.config.field_params import GREAT_EXHIBITION_FIELD_DIMS | ||
| from utama_core.custom_referee import CustomReferee | ||
| from utama_core.custom_referee.profiles.profile_loader import ( | ||
| AutoAdvanceConfig, | ||
| DefenseAreaConfig, | ||
| GameConfig, | ||
| GoalDetectionConfig, | ||
| KeepOutConfig, | ||
| OutOfBoundsConfig, | ||
| RefereeProfile, | ||
| RulesConfig, | ||
| ) | ||
| from utama_core.run import StrategyRunner | ||
| from utama_core.strategy.examples.ball_placement_and_kick_strategy import ( | ||
| BallPlacementAndKickStrategy, | ||
| ) | ||
| from utama_core.strategy.examples.deliberate_out_of_bounds_strategy import ( | ||
| DeliberateOutOfBoundsStrategy, | ||
| ) | ||
|
|
||
| # --------------------------------------------------------------------------- | ||
| # Configuration | ||
| # --------------------------------------------------------------------------- | ||
|
|
||
| GUI_PORT = 8080 | ||
| N_ROBOTS = 2 | ||
| MY_TEAM_IS_YELLOW = True | ||
| MY_TEAM_IS_RIGHT = True | ||
|
|
||
|
|
||
| # --------------------------------------------------------------------------- | ||
| # Referee profile | ||
| # | ||
| # Out-of-bounds is the primary trigger for ball placement in a real game. | ||
| # Defense area and keep-out rules are disabled to reduce noise while you're | ||
| # developing the placement skill itself. | ||
| # --------------------------------------------------------------------------- | ||
|
|
||
| _BALL_PLACEMENT_PROFILE = RefereeProfile( | ||
| profile_name="ball_placement_dev", | ||
| rules=RulesConfig( | ||
| goal_detection=GoalDetectionConfig( | ||
| enabled=True, | ||
| cooldown_seconds=1.0, | ||
| ), | ||
| out_of_bounds=OutOfBoundsConfig( | ||
| enabled=True, | ||
| free_kick_assigner="last_touch", | ||
| ), | ||
| defense_area=DefenseAreaConfig( | ||
| enabled=False, | ||
| max_defenders=1, | ||
| attacker_infringement=False, | ||
| ), | ||
| keep_out=KeepOutConfig( | ||
| enabled=False, | ||
| radius_meters=0.3, | ||
| violation_persistence_frames=30, | ||
| ), | ||
| ), | ||
| game=GameConfig( | ||
| half_duration_seconds=300.0, | ||
| kickoff_team="yellow", | ||
| force_start_after_goal=False, | ||
| stop_duration_seconds=2.0, | ||
| prepare_duration_seconds=3.0, | ||
| kickoff_timeout_seconds=10.0, | ||
| auto_advance=AutoAdvanceConfig( | ||
| # All auto-advance enabled: state machine drives itself so you can | ||
| # observe the full placement → free-kick → normal-start cycle. | ||
| stop_to_next_command=True, | ||
| prepare_kickoff_to_normal=True, | ||
| prepare_penalty_to_normal=True, | ||
| direct_free_to_normal=True, | ||
| ball_placement_to_next=True, | ||
| normal_start_to_force=True, | ||
| ), | ||
| ), | ||
| ) | ||
|
|
||
| # --------------------------------------------------------------------------- | ||
| # Entry point | ||
| # --------------------------------------------------------------------------- | ||
|
|
||
|
|
||
| def main() -> None: | ||
| referee = CustomReferee( | ||
| _BALL_PLACEMENT_PROFILE, | ||
| n_robots_yellow=N_ROBOTS, | ||
| n_robots_blue=N_ROBOTS, | ||
| enable_gui=True, | ||
| gui_port=GUI_PORT, | ||
| ) | ||
|
|
||
| runner = StrategyRunner( | ||
| strategy=BallPlacementAndKickStrategy(), | ||
| # Opponents create one out-of-bounds event per side, then attack yellow's goal. | ||
| opp_strategy=DeliberateOutOfBoundsStrategy(field_dims=GREAT_EXHIBITION_FIELD_DIMS), | ||
| my_team_is_yellow=MY_TEAM_IS_YELLOW, | ||
| my_team_is_right=MY_TEAM_IS_RIGHT, | ||
| mode="rsim", | ||
| control_scheme="pid", | ||
| exp_friendly=N_ROBOTS, | ||
| exp_enemy=N_ROBOTS, | ||
| full_field_dims=GREAT_EXHIBITION_FIELD_DIMS, | ||
| referee=referee, | ||
| show_live_status=True, | ||
| ) | ||
|
|
||
| runner.run() | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| main() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,133 @@ | ||
| """demo_ball_placement_real.py — Test ball placement with a single real robot. | ||
|
|
||
| Run: | ||
| pixi run python demo_ball_placement_real.py | ||
| # Then open http://localhost:8080 in a browser | ||
|
|
||
| What this sets up | ||
| ----------------- | ||
| - Exhibition Road field (4 m x 3 m) | ||
| - 1 yellow robot, no opponents | ||
| - CustomReferee starts in HALT — the robot will not move until you issue a | ||
| command from the GUI | ||
| - All automatic rule detection (out-of-bounds, goal, keep-out) is disabled so | ||
| the only commands come from the operator via the GUI | ||
|
|
||
| Workflow | ||
| -------- | ||
| 1. Run this script and open http://localhost:8080. | ||
| 2. Place the ball somewhere on the field by hand. | ||
| 3. In the GUI "Manual Commands" panel, set a target position and issue | ||
| BALL_PLACEMENT_YELLOW. | ||
| 4. The robot drives to the ball with its dribbler on and attempts to carry it | ||
| to the target. | ||
| 5. Issue HALT from the GUI at any time to stop the robot immediately. | ||
|
|
||
| Safety notes | ||
| ------------ | ||
| - The robot starts in HALT and will not move until you issue a command. | ||
| - Keep the target position within the physical field bounds. | ||
| - Issue HALT from the GUI before approaching the field. | ||
| """ | ||
|
|
||
| from utama_core.config.field_params import GREAT_EXHIBITION_FIELD_DIMS | ||
| from utama_core.custom_referee import CustomReferee | ||
| from utama_core.custom_referee.profiles.profile_loader import ( | ||
| AutoAdvanceConfig, | ||
| DefenseAreaConfig, | ||
| GameConfig, | ||
| GoalDetectionConfig, | ||
| KeepOutConfig, | ||
| OutOfBoundsConfig, | ||
| RefereeProfile, | ||
| RulesConfig, | ||
| ) | ||
| from utama_core.run import StrategyRunner | ||
| from utama_core.strategy.examples.ball_placement_strategy import BallPlacementStrategy | ||
|
|
||
| # --------------------------------------------------------------------------- | ||
| # Configuration -- edit these to match your setup | ||
| # --------------------------------------------------------------------------- | ||
|
|
||
| GUI_PORT = 8080 | ||
| MY_TEAM_IS_YELLOW = True | ||
| MY_TEAM_IS_RIGHT = True | ||
|
|
||
| # --------------------------------------------------------------------------- | ||
| # Referee profile | ||
| # | ||
| # All automatic rules are OFF. Commands come from the operator only. | ||
| # auto_advance is also OFF so the state never transitions without you. | ||
| # --------------------------------------------------------------------------- | ||
|
|
||
| _REAL_TEST_PROFILE = RefereeProfile( | ||
| profile_name="ball_placement_real_test", | ||
| rules=RulesConfig( | ||
| goal_detection=GoalDetectionConfig( | ||
| enabled=False, | ||
| cooldown_seconds=1.0, | ||
| ), | ||
| out_of_bounds=OutOfBoundsConfig( | ||
| enabled=False, | ||
| free_kick_assigner="last_touch", | ||
| ), | ||
| defense_area=DefenseAreaConfig( | ||
| enabled=False, | ||
| max_defenders=1, | ||
| attacker_infringement=False, | ||
| ), | ||
| keep_out=KeepOutConfig( | ||
| enabled=False, | ||
| radius_meters=0.3, | ||
| violation_persistence_frames=30, | ||
| ), | ||
| ), | ||
| game=GameConfig( | ||
| half_duration_seconds=300.0, | ||
| kickoff_team="yellow", | ||
| force_start_after_goal=False, | ||
| stop_duration_seconds=2.0, | ||
| prepare_duration_seconds=3.0, | ||
| kickoff_timeout_seconds=10.0, | ||
| auto_advance=AutoAdvanceConfig( | ||
| stop_to_next_command=False, | ||
| prepare_kickoff_to_normal=False, | ||
| prepare_penalty_to_normal=False, | ||
| direct_free_to_normal=False, | ||
| ball_placement_to_next=False, | ||
| normal_start_to_force=False, | ||
| ), | ||
| ), | ||
| ) | ||
|
|
||
| # --------------------------------------------------------------------------- | ||
| # Entry point | ||
| # --------------------------------------------------------------------------- | ||
|
|
||
|
|
||
| def main() -> None: | ||
| referee = CustomReferee( | ||
| _REAL_TEST_PROFILE, | ||
| n_robots_yellow=1, | ||
| n_robots_blue=0, | ||
| enable_gui=True, | ||
| gui_port=GUI_PORT, | ||
| ) | ||
|
|
||
| runner = StrategyRunner( | ||
| strategy=BallPlacementStrategy(), | ||
| my_team_is_yellow=MY_TEAM_IS_YELLOW, | ||
| my_team_is_right=MY_TEAM_IS_RIGHT, | ||
| mode="rsim", | ||
| exp_friendly=1, | ||
| exp_enemy=0, | ||
| full_field_dims=GREAT_EXHIBITION_FIELD_DIMS, | ||
| referee=referee, | ||
| show_live_status=True, | ||
| ) | ||
|
|
||
| runner.run() | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| main() | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.