11use bevy:: prelude:: * ;
2+ use bifrost:: communication:: { GameControllerMessage , SetPlay } ;
23use nalgebra:: { Point2 , Point3 } ;
34use nidhogg:: types:: { FillExt , RightEye , color} ;
45
56use crate :: {
67 behavior:: {
7- behaviors:: { RlStrikerSearchBehavior , Walk , WalkToBall } ,
8- engine:: { CommandsBehaviorExt , RoleState , Roles , in_role} ,
8+ behaviors:: { RlStrikerSearchBehavior , StandLookAt , Walk , WalkTo , WalkToBall } ,
9+ engine:: { BehaviorState , CommandsBehaviorExt , RoleState , Roles , in_role} ,
10+ primary_state:: PrimaryState ,
11+ } ,
12+ core:: config:: {
13+ layout:: { FieldConfig , LayoutConfig } ,
14+ showtime:: PlayerConfig ,
915 } ,
10- core:: config:: layout:: { FieldConfig , LayoutConfig } ,
1116 localization:: RobotPose ,
12- motion:: walking_engine:: step:: Step ,
17+ motion:: { step_planner :: Target , walking_engine:: step:: Step } ,
1318 nao:: { NaoManager , Priority } ,
1419 vision:: ball_detection:: ball_tracker:: BallTracker ,
1520} ;
@@ -22,9 +27,35 @@ pub struct StrikerRolePlugin;
2227
2328impl Plugin for StrikerRolePlugin {
2429 fn build ( & self , app : & mut App ) {
25- app. add_systems ( Update , striker_role. run_if ( in_role :: < Striker > ) )
26- . add_systems ( OnExit ( RoleState :: Striker ) , reset_striker_role) ;
30+ app. add_systems (
31+ Update ,
32+ (
33+ striker_role. run_if ( in_role :: < Striker > . and ( not ( in_set_play) ) ) ,
34+ set_play. run_if ( in_set_play) ,
35+ ) ,
36+ )
37+ . add_systems ( OnExit ( RoleState :: Striker ) , reset_striker_role) ;
38+ }
39+ }
40+
41+ fn in_set_play (
42+ gamecontroller_message : Option < Res < GameControllerMessage > > ,
43+ primary_state : Res < PrimaryState > ,
44+ player_config : Res < PlayerConfig > ,
45+ ) -> bool {
46+ if let Some ( message) = gamecontroller_message {
47+ return match * primary_state {
48+ // return true if there is a set play OR we are in Playing state with a secondary time (Kick-Off)
49+ PrimaryState :: Playing { .. } => {
50+ message. set_play != SetPlay :: None
51+ || ( message. secondary_time != 0
52+ && message. kicking_team != player_config. team_number )
53+ }
54+ _ => false ,
55+ } ;
2756 }
57+
58+ false
2859}
2960
3061/// The `Striker` role has five substates, each indicated by the right eye LED color:
@@ -125,6 +156,52 @@ pub fn striker_role(
125156 }
126157}
127158
159+ //TODO: Make this a separate stand-alone behavior
160+ fn set_play (
161+ mut commands : Commands ,
162+ ball_tracker : Res < BallTracker > ,
163+ pose : Res < RobotPose > ,
164+ behavior_state : Res < State < BehaviorState > > ,
165+ walk : Option < Res < Walk > > ,
166+ ) {
167+ let Some ( relative_ball) = ball_tracker. stationary_ball ( ) else {
168+ return ;
169+ } ;
170+ let absolute_ball = pose. robot_to_world ( & relative_ball) ;
171+ let ball_distance = relative_ball. coords . norm ( ) ;
172+ let ball_target = Point3 :: new ( absolute_ball. x , absolute_ball. y , 0.2 ) ;
173+
174+ if ball_distance > 1.2 {
175+ commands. set_behavior ( WalkTo {
176+ target : Target {
177+ position : absolute_ball,
178+ rotation : None ,
179+ } ,
180+ } ) ;
181+ return ;
182+ }
183+
184+ if behavior_state. get ( ) == & BehaviorState :: Walk {
185+ if let Some ( walk) = walk {
186+ if matches ! ( walk. step, Step :: BACK ) && ball_distance < 0.875 {
187+ return ;
188+ }
189+ }
190+ }
191+
192+ if ball_distance < 0.75 {
193+ commands. set_behavior ( Walk {
194+ step : Step :: BACK ,
195+ look_target : Some ( ball_target) ,
196+ } ) ;
197+ return ;
198+ }
199+
200+ commands. set_behavior ( StandLookAt {
201+ target : absolute_ball,
202+ } ) ;
203+ }
204+
128205pub fn goal_aligned ( pose : & RobotPose , field_config : & FieldConfig ) -> bool {
129206 if pose. inner . translation . x > 0.0 {
130207 // If on enemy side
0 commit comments