-
Notifications
You must be signed in to change notification settings - Fork 56
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add scenario for visual referee free kick behavior
Co-authored-by: MaikRe <[email protected]>
- Loading branch information
1 parent
88c7ba0
commit 3822b94
Showing
4 changed files
with
148 additions
and
1 deletion.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains 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
143 changes: 143 additions & 0 deletions
143
crates/bevyhavior_simulator/src/bin/visual_referee_free_kick_behavior.rs
This file contains 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,143 @@ | ||
use bevy::{ecs::system::SystemParam, prelude::*}; | ||
|
||
use approx::AbsDiffEq; | ||
use linear_algebra::point; | ||
use scenario::scenario; | ||
use spl_network_messages::{GameState, PlayerNumber, SubState, Team}; | ||
|
||
use bevyhavior_simulator::{ | ||
ball::BallResource, | ||
game_controller::{GameController, GameControllerCommand}, | ||
robot::Robot, | ||
time::{Ticks, TicksTime}, | ||
}; | ||
use types::{motion_command::HeadMotion, roles::Role}; | ||
|
||
/// Is used to generate the test functions for cargo test | ||
#[scenario] | ||
fn visual_referee_free_kick_behavior(app: &mut App) { | ||
app.add_systems(Startup, startup); | ||
app.add_systems(Update, update); | ||
} | ||
|
||
#[derive(SystemParam)] | ||
struct State<'s> { | ||
detecting_robots_when_home: Local<'s, usize>, | ||
detecting_robots_when_away: Local<'s, usize>, | ||
} | ||
|
||
/// Runs at the start of the behavior simulator and is used to spawn in robots and set GameStates | ||
fn startup( | ||
mut commands: Commands, | ||
mut game_controller_commands: EventWriter<GameControllerCommand>, | ||
) { | ||
for number in [ | ||
PlayerNumber::One, | ||
PlayerNumber::Two, | ||
PlayerNumber::Three, | ||
PlayerNumber::Four, | ||
PlayerNumber::Five, | ||
PlayerNumber::Six, | ||
PlayerNumber::Seven, | ||
] { | ||
commands.spawn(Robot::new(number)); | ||
} | ||
game_controller_commands.send(GameControllerCommand::SetGameState(GameState::Ready)); | ||
} | ||
|
||
fn update( | ||
mut game_controller: ResMut<GameController>, | ||
mut game_controller_commands: EventWriter<GameControllerCommand>, | ||
time: Res<Time<Ticks>>, | ||
mut exit: EventWriter<AppExit>, | ||
robots: Query<&mut Robot>, | ||
mut ball: ResMut<BallResource>, | ||
mut state: State, | ||
) { | ||
if time.ticks() >= 10_000 { | ||
println!("Scenario failed: Time ran out. Behavior for detecting free kick kicking team was not executed correctly."); | ||
exit.send(AppExit::from_code(1)); | ||
} | ||
|
||
if time.ticks() == 3000 { | ||
// Set substate | ||
game_controller_commands.send(GameControllerCommand::SetSubState( | ||
Some(SubState::PushingFreeKick), | ||
Team::Opponent, | ||
)); | ||
} | ||
|
||
if time.ticks() == 3005 { | ||
for relevant_robots in robots.iter().filter(|robot| { | ||
matches!( | ||
robot.database.main_outputs.role, | ||
Role::DefenderRight | Role::MidfielderRight | ||
) | ||
}) { | ||
if let Some(expected_referee_position) = relevant_robots | ||
.database | ||
.main_outputs | ||
.expected_referee_position | ||
{ | ||
let ground_to_field = relevant_robots.ground_to_field(); | ||
let expected_referee_position_in_ground = | ||
ground_to_field.inverse() * expected_referee_position; | ||
if matches!( | ||
relevant_robots.database.main_outputs.motion_command.head_motion(), | ||
Some(HeadMotion::LookAt { target, .. }) if target.abs_diff_eq(&expected_referee_position_in_ground, 1e-4) | ||
) { | ||
*state.detecting_robots_when_home += 1; | ||
} | ||
} | ||
} | ||
} | ||
|
||
if time.ticks() == 3500 { | ||
// Set substate | ||
game_controller_commands.send(GameControllerCommand::SetSubState(None, Team::Opponent)); | ||
} | ||
|
||
if time.ticks() == 4000 { | ||
// Set substate | ||
game_controller_commands.send(GameControllerCommand::SetSubState( | ||
Some(SubState::KickIn), | ||
Team::Opponent, | ||
)); | ||
|
||
game_controller.state.hulks_team_is_home_after_coin_toss = false; | ||
|
||
if let Some(ball) = ball.state.as_mut() { | ||
ball.position = point!(2.0, 4.5); | ||
} | ||
} | ||
if time.ticks() == 4002 { | ||
for relevant_robot in robots.iter().filter(|robot| { | ||
matches!( | ||
robot.database.main_outputs.role, | ||
Role::DefenderLeft | Role::MidfielderLeft | ||
) | ||
}) { | ||
if let Some(expected_referee_position) = relevant_robot | ||
.database | ||
.main_outputs | ||
.expected_referee_position | ||
{ | ||
let ground_to_field = relevant_robot.ground_to_field(); | ||
let expected_referee_position_in_ground = | ||
ground_to_field.inverse() * expected_referee_position; | ||
|
||
if matches!( | ||
relevant_robot.database.main_outputs.motion_command.head_motion(), | ||
Some(HeadMotion::LookAt { target, .. }) if target.abs_diff_eq(&expected_referee_position_in_ground, 1e-4) | ||
) { | ||
*state.detecting_robots_when_away += 1; | ||
} | ||
} | ||
} | ||
} | ||
|
||
if (*state.detecting_robots_when_home == 2) && (*state.detecting_robots_when_away == 2) { | ||
println!("Done! Successfully performed behavior for free kick kicking team detection."); | ||
exit.send(AppExit::Success); | ||
} | ||
} |
This file contains 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