Skip to content

Commit 995a2fc

Browse files
paudarknoellle
authored andcommitted
Searcher Standing Delay (HULKs#1735)
* add timeout for defender to become searcher move functionality of delayed movement of defender that became earcher in searcher make the standing time after role change dynamic depending on last known ball posiiton add senario and fmt rename variable undo change of if condition add new edge detection change ball position in passive_defender_positioning * only affect searchers that where defender * add check for y-position of searcher * fmt file * stand only when in own half * make previous role the real previous role * forever keeper * more edge-cases in standing seracher bevi_test * change bevihavior scenario * add aditional assertion at standing_searcher bevytest * add assertions to bevihavior standing_searcher * change parameter for later search motion
1 parent 7fb86d1 commit 995a2fc

8 files changed

Lines changed: 189 additions & 14 deletions

File tree

crates/bevyhavior_simulator/src/bin/passive_defender_positioning.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use spl_network_messages::{GameState, PlayerNumber};
66

77
use bevyhavior_simulator::{
88
ball::BallResource,
9-
game_controller::GameControllerCommand,
9+
game_controller::{GameController, GameControllerCommand},
1010
robot::Robot,
1111
time::{Ticks, TicksTime},
1212
};
@@ -38,14 +38,15 @@ fn startup(
3838

3939
fn update(
4040
time: Res<Time<Ticks>>,
41+
game_controller: Res<GameController>,
4142
mut exit: EventWriter<AppExit>,
4243
mut ball: ResMut<BallResource>,
4344
mut robots: Query<&mut Robot>,
4445
) {
4546
if time.ticks() == 4500 {
4647
ball.state = Some(SimulatorBallState {
47-
position: point!(2.25, 0.0),
48-
velocity: vector![-3.0, -1.0],
48+
position: point!(1.25, 2.0),
49+
velocity: vector![1.0, -3.0],
4950
});
5051
}
5152
if time.ticks() > 4500 && time.ticks() <= 4700 {
@@ -56,7 +57,7 @@ fn update(
5657
match motion_command {
5758
MotionCommand::Stand { .. } => {}
5859
_ => {
59-
println!("Defenders moved unnecessarily");
60+
println!("Defenders moved unnecessarily because of the following command at tick {}: \n{:?}", time.ticks(), motion_command);
6061
exit.send(AppExit::from_code(1));
6162
}
6263
}
@@ -65,8 +66,12 @@ fn update(
6566
}
6667
}
6768
}
69+
if game_controller.state.hulks_team.score > 0 {
70+
println!("Done. Goal was scored.");
71+
exit.send(AppExit::Success);
72+
}
6873
if time.ticks() >= 8_000 {
69-
println!("Done");
74+
println!("Done. But no goal was scored");
7075
exit.send(AppExit::Success);
7176
}
7277
}
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
use std::time::Duration;
2+
3+
use bevy::prelude::*;
4+
5+
use linear_algebra::{point, vector};
6+
use scenario::scenario;
7+
use spl_network_messages::{GameState, Penalty, PlayerNumber, Team};
8+
9+
use bevyhavior_simulator::{
10+
ball::BallResource,
11+
game_controller::GameControllerCommand,
12+
robot::Robot,
13+
time::{Ticks, TicksTime},
14+
};
15+
use types::{ball_position::SimulatorBallState, motion_command::MotionCommand};
16+
17+
#[scenario]
18+
fn standing_searcher(app: &mut App) {
19+
app.add_systems(Startup, startup);
20+
app.add_systems(Update, update);
21+
}
22+
23+
fn startup(
24+
mut commands: Commands,
25+
mut game_controller_commands: EventWriter<GameControllerCommand>,
26+
) {
27+
for number in [
28+
PlayerNumber::One,
29+
PlayerNumber::Two,
30+
PlayerNumber::Three,
31+
PlayerNumber::Four,
32+
PlayerNumber::Five,
33+
PlayerNumber::Seven,
34+
] {
35+
commands.spawn(Robot::new(number));
36+
}
37+
game_controller_commands.send(GameControllerCommand::SetGameState(GameState::Ready));
38+
}
39+
40+
fn update(
41+
time: Res<Time<Ticks>>,
42+
mut ball: ResMut<BallResource>,
43+
mut exit: EventWriter<AppExit>,
44+
mut robots: Query<&mut Robot>,
45+
mut game_controller_commands: EventWriter<GameControllerCommand>,
46+
) {
47+
if time.ticks() == 4150 {
48+
game_controller_commands.send(GameControllerCommand::Penalize(
49+
PlayerNumber::Two,
50+
Penalty::Manual {
51+
remaining: Duration::from_secs(1),
52+
},
53+
Team::Hulks,
54+
));
55+
}
56+
57+
if time.ticks() == 4155 {
58+
game_controller_commands.send(GameControllerCommand::Unpenalize(
59+
PlayerNumber::Two,
60+
Team::Hulks,
61+
));
62+
}
63+
64+
if time.ticks() == 4200 {
65+
ball.state = None;
66+
}
67+
68+
if time.ticks() == 4660 {
69+
if let MotionCommand::Stand { .. } = robots
70+
.iter_mut()
71+
.find(|robot| robot.parameters.player_number == PlayerNumber::Two)
72+
.unwrap()
73+
.database
74+
.main_outputs
75+
.motion_command
76+
{
77+
println!("Standing searcher at penalty walk-in");
78+
exit.send(AppExit::from_code(1));
79+
}
80+
if let MotionCommand::Walk { .. } = robots
81+
.iter_mut()
82+
.find(|robot| robot.parameters.player_number == PlayerNumber::Three)
83+
.unwrap()
84+
.database
85+
.main_outputs
86+
.motion_command
87+
{
88+
println!("Moving searcher after ball loss");
89+
exit.send(AppExit::from_code(1));
90+
}
91+
}
92+
93+
if time.ticks() == 5500 {
94+
ball.state = Some(SimulatorBallState {
95+
position: point![-2.7, -0.2],
96+
velocity: vector![0.0, 0.0],
97+
});
98+
}
99+
if time.ticks() == 6000 {
100+
ball.state = None;
101+
}
102+
if time.ticks() == 6750 {
103+
ball.state = Some(SimulatorBallState {
104+
position: point![4.0, -0.2],
105+
velocity: vector![0.0, 0.0],
106+
});
107+
}
108+
if time.ticks() == 7200 {
109+
ball.state = None;
110+
}
111+
if time.ticks() >= 10_000 {
112+
println!("Done");
113+
exit.send(AppExit::Success);
114+
}
115+
}

crates/control/src/behavior/node.rs

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::time::SystemTime;
1+
use std::time::{SystemTime, UNIX_EPOCH};
22

33
use color_eyre::Result;
44
use serde::{Deserialize, Serialize};
@@ -45,7 +45,9 @@ pub struct Behavior {
4545
last_known_ball_position: Point2<Field>,
4646
active_since: Option<SystemTime>,
4747
previous_role: Role,
48+
previous_cycle_role: Role,
4849
last_defender_mode: DefendMode,
50+
last_time_role_changed: SystemTime,
4951
}
5052

5153
#[context]
@@ -99,6 +101,8 @@ impl Behavior {
99101
last_known_ball_position: point![0.0, 0.0],
100102
active_since: None,
101103
previous_role: Role::Searcher,
104+
previous_cycle_role: Role::Searcher,
105+
last_time_role_changed: UNIX_EPOCH,
102106
last_defender_mode: DefendMode::Passive,
103107
})
104108
}
@@ -125,12 +129,17 @@ impl Behavior {
125129
(Some(_), _) => self.active_since = None,
126130
}
127131

128-
if self.previous_role != context.world_state.robot.role
129-
&& context.world_state.robot.role != Role::Searcher
130-
&& context.world_state.robot.role != Role::Loser
131-
&& self.previous_role != Role::Keeper
132-
{
133-
self.previous_role = context.world_state.robot.role;
132+
if self.previous_cycle_role != context.world_state.robot.role {
133+
match self.previous_cycle_role {
134+
Role::DefenderLeft | Role::DefenderRight => {
135+
self.last_time_role_changed = now;
136+
}
137+
_ => {}
138+
}
139+
if self.previous_role != Role::Keeper {
140+
self.previous_role = self.previous_cycle_role;
141+
}
142+
self.previous_cycle_role = context.world_state.robot.role;
134143
}
135144

136145
let mut actions = vec![
@@ -397,6 +406,8 @@ impl Behavior {
397406
&context.parameters.search,
398407
&mut context.path_obstacles_output,
399408
self.previous_role,
409+
self.last_time_role_changed,
410+
self.last_known_ball_position,
400411
*context.search_walk_speed,
401412
context
402413
.parameters

crates/control/src/behavior/search.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ pub fn execute(
7575
parameters: &SearchParameters,
7676
path_obstacles_output: &mut AdditionalOutput<Vec<PathObstacle>>,
7777
previous_role: Role,
78+
last_time_role_changed: SystemTime,
79+
last_known_ball_position: Point2<Field>,
7880
walk_speed: WalkSpeed,
7981
distance_to_be_aligned: f32,
8082
cycle_start_time: SystemTime,
@@ -103,6 +105,22 @@ pub fn execute(
103105
},
104106
None => HeadMotion::SearchForLostBall,
105107
};
108+
let distance_to_ball = (ground_to_field.inverse() * last_known_ball_position)
109+
.coords()
110+
.norm();
111+
let estimated_ball_arrival_time = distance_to_ball / parameters.estimated_ball_speed;
112+
let near_own_penalty_box = ground_to_field.as_pose().position().y().abs()
113+
< field_dimensions.penalty_area_width / 2.0
114+
&& ground_to_field.as_pose().position().x() < 0.0;
115+
if world_state
116+
.now
117+
.duration_since(last_time_role_changed)
118+
.expect("time went backwards")
119+
< Duration::from_secs_f32(estimated_ball_arrival_time)
120+
&& near_own_penalty_box
121+
{
122+
return Some(MotionCommand::Stand { head });
123+
};
106124
if let Some(SearchRole::Goal) = search_role {
107125
let goal_pose = Pose2::from(search_position);
108126
walk_and_stand.execute(

crates/control/src/world_state_composer.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use spl_network_messages::PlayerNumber;
99
use types::{
1010
ball_position::HypotheticalBallPosition,
1111
calibration::CalibrationCommand,
12+
cycle_time::CycleTime,
1213
fall_state::FallState,
1314
filtered_game_controller_state::FilteredGameControllerState,
1415
kick_decision::KickDecision,
@@ -51,6 +52,7 @@ pub struct CycleContext {
5152
position_of_interest: Input<Point2<Ground>, "position_of_interest">,
5253
calibration_command: Input<Option<CalibrationCommand>, "calibration_command?">,
5354
stand_up_count: CyclerState<u32, "stand_up_count">,
55+
cycle_time: Input<CycleTime, "cycle_time">,
5456
}
5557

5658
#[context]
@@ -89,6 +91,7 @@ impl WorldStateComposer {
8991
filtered_game_controller_state: context.filtered_game_controller_state.cloned(),
9092
hypothetical_ball_positions: context.hypothetical_ball_position.clone(),
9193
calibration_command: context.calibration_command.copied(),
94+
now: context.cycle_time.start_time,
9295
};
9396

9497
Ok(MainOutputs {

crates/types/src/parameters.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ pub struct SearchParameters {
107107
pub rotation_per_step: f32,
108108
pub stand_secs: f32,
109109
pub turn_secs: f32,
110+
pub estimated_ball_speed: f32,
110111
}
111112

112113
#[derive(

crates/types/src/world_state.rs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use crate::{
1515
roles::Role, rule_obstacles::RuleObstacle,
1616
};
1717

18-
#[derive(Clone, Debug, Default, Serialize, Deserialize, PathSerialize, PathIntrospect)]
18+
#[derive(Clone, Debug, Serialize, Deserialize, PathSerialize, PathIntrospect)]
1919
pub struct WorldState {
2020
pub ball: Option<BallState>,
2121
pub rule_ball: Option<BallState>,
@@ -29,6 +29,27 @@ pub struct WorldState {
2929
pub instant_kick_decisions: Option<Vec<KickDecision>>,
3030
pub robot: RobotState,
3131
pub calibration_command: Option<CalibrationCommand>,
32+
pub now: SystemTime,
33+
}
34+
35+
impl Default for WorldState {
36+
fn default() -> Self {
37+
Self {
38+
ball: Default::default(),
39+
rule_ball: Default::default(),
40+
hypothetical_ball_positions: Default::default(),
41+
filtered_game_controller_state: Default::default(),
42+
obstacles: Default::default(),
43+
rule_obstacles: Default::default(),
44+
position_of_interest: Point2::origin(),
45+
suggested_search_position: Default::default(),
46+
kick_decisions: Default::default(),
47+
instant_kick_decisions: Default::default(),
48+
robot: Default::default(),
49+
calibration_command: Default::default(),
50+
now: UNIX_EPOCH,
51+
}
52+
}
3253
}
3354

3455
#[derive(

etc/parameters/default.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1287,7 +1287,8 @@
12871287
"position_reached_distance": 0.4,
12881288
"rotation_per_step": 0.4,
12891289
"turn_secs": 3.0,
1290-
"stand_secs": 1.0
1290+
"stand_secs": 1.0,
1291+
"estimated_ball_speed": 0.75
12911292
},
12921293
"look_action": {
12931294
"angle_threshold": 0.95,

0 commit comments

Comments
 (0)