33import choreo
44import wpilib
55from choreo .trajectory import SwerveSample , SwerveTrajectory
6- from magicbot import AutonomousStateMachine , state , timed_state
6+ from magicbot import AutonomousStateMachine , state , timed_state , tunable
77from wpilib import RobotBase
88from wpimath .controller import PIDController
99from wpimath .geometry import Pose2d
1010from wpimath .kinematics import ChassisSpeeds
1111
1212from components .chassis import ChassisComponent
13- from components .coral_depositor import CoralDepositorComponent
1413from components .injector import InjectorComponent
1514from components .shooter import ShooterComponent
1615from controllers .algae_shooter import AlgaeShooter
@@ -28,19 +27,25 @@ class AutoBase(AutonomousStateMachine):
2827 algae_shooter : AlgaeShooter
2928 reef_intake : ReefIntake
3029
31- coral_depositor_component : CoralDepositorComponent
3230 shooter_component : ShooterComponent
3331 injector_component : InjectorComponent
3432 chassis : ChassisComponent
3533
3634 field : wpilib .Field2d
3735
3836 DISTANCE_TOLERANCE = 0.1 # metres
37+ SHOOT_DISTANCE_TOLERANCE = 0.4 # metres
38+ SHOOT_ANGLE_TOLERANCE = math .radians (10 )
3939 ANGLE_TOLERANCE = math .radians (3 )
4040 CORAL_DISTANCE_TOLERANCE = 0.2 # metres
4141 TRANSLATIONAL_SPEED_TOLERANCE = 0.2
4242 ROTATIONAL_SPEED_TOLERANCE = 0.1
4343
44+ is_shooting_leg = tunable (False )
45+ is_in_distance_tolerance = tunable (False )
46+ is_in_angle_tolerance = tunable (False )
47+ is_in_second_half_of_leg = tunable (False )
48+
4449 def __init__ (self , trajectory_names : list [str ]) -> None :
4550 # We want to parameterise these by paths and potentially a sequence of events
4651 super ().__init__ ()
@@ -59,6 +64,7 @@ def __init__(self, trajectory_names: list[str]) -> None:
5964
6065 def setup (self ) -> None :
6166 # setup path tracking controllers
67+ self .auto_sample_field_obj = self .field .getObject ("auto_sample" )
6268
6369 # init any other defaults
6470 pass
@@ -106,49 +112,71 @@ def tracking_trajectory(self, initial_call, state_tm) -> None:
106112 if initial_call :
107113 self .current_leg += 1
108114
109- if self .current_leg == len (self .trajectories ):
110- self .done ()
111- return
115+ if self .current_leg == len (self .trajectories ):
116+ self .done ()
117+ return
118+
119+ trajectory = (
120+ self .trajectories [self .current_leg ].flipped ()
121+ if game .is_red ()
122+ else self .trajectories [self .current_leg ]
123+ )
124+
125+ trajectory_poses = trajectory .get_poses ()
126+ self .field .getObject ("trajectory" ).setPoses (trajectory_poses )
112127
113- # get next leg on entry
114- current_pose = self .chassis .get_pose ()
115128 final_pose = self .trajectories [self .current_leg ].get_final_pose (game .is_red ())
116129 if final_pose is None :
117130 self .done ()
118131 return
119132
133+ # get next leg on entry
134+ current_pose = self .chassis .get_pose ()
135+
120136 distance = current_pose .translation ().distance (final_pose .translation ())
121137 angle_error = (final_pose .rotation () - current_pose .rotation ()).radians ()
122- velocity = self .chassis .get_velocity ()
123- speed = math .sqrt (math .pow (velocity .vx , 2.0 ) + math .pow (velocity .vy , 2.0 ))
124138
125- if self .current_leg % 2 != 0 :
139+ self .is_shooting_leg = self .current_leg % 2 != 0
140+
141+ if self .is_shooting_leg :
126142 self .algae_shooter .shoot ()
127143 else :
128144 self .reef_intake .intake ()
129145 # Check if we are close enough to deposit coral
130146 if distance < self .CORAL_DISTANCE_TOLERANCE :
131147 self .reef_intake .holding_coral = False
132148
149+ self .is_in_distance_tolerance = (
150+ distance < self .SHOOT_DISTANCE_TOLERANCE
151+ if self .is_shooting_leg
152+ else distance < self .DISTANCE_TOLERANCE
153+ )
154+
155+ self .is_in_angle_tolerance = (
156+ math .isclose (angle_error , 0.0 , abs_tol = self .SHOOT_ANGLE_TOLERANCE )
157+ if self .is_shooting_leg
158+ else math .isclose (angle_error , 0.0 , abs_tol = self .ANGLE_TOLERANCE )
159+ )
160+ self .is_in_second_half_of_leg = (
161+ state_tm > self .trajectories [self .current_leg ].get_total_time () / 2.0
162+ )
163+
133164 if (
134- distance < self .DISTANCE_TOLERANCE
135- and math .isclose (angle_error , 0.0 , abs_tol = self .ANGLE_TOLERANCE )
136- and math .isclose (speed , 0.0 , abs_tol = self .TRANSLATIONAL_SPEED_TOLERANCE )
137- and math .isclose (
138- velocity .omega , 0.0 , abs_tol = self .ROTATIONAL_SPEED_TOLERANCE
139- )
140- and state_tm > self .trajectories [self .current_leg ].get_total_time () / 2.0
165+ self .is_in_distance_tolerance
166+ and self .is_in_angle_tolerance
167+ and self .chassis .is_stationary ()
168+ and self .is_in_second_half_of_leg
141169 ):
142170 # run cycles of pick up -> shoot
143- if self .injector_component . has_algae () :
171+ if self .is_shooting_leg :
144172 self .next_state ("shooting_algae" )
145173 else :
146174 self .next_state ("intaking_algae" )
147- return
148175
149176 sample = self .trajectories [self .current_leg ].sample_at (state_tm , game .is_red ())
150177 if sample is not None :
151178 self .follow_trajectory (sample )
179+ self .auto_sample_field_obj .setPose (sample .get_pose ())
152180
153181 def follow_trajectory (self , sample : SwerveSample ):
154182 # track path
@@ -170,15 +198,15 @@ def follow_trajectory(self, sample: SwerveSample):
170198
171199 @timed_state (duration = 1.0 , next_state = "tracking_trajectory" )
172200 def intaking_algae (self ) -> None :
173- if self .current_leg == 0 :
174- self .coral_depositor_component .deposit ()
175201 if self .injector_component .has_algae ():
176- self .coral_depositor_component .tuck ()
177202 self .next_state ("tracking_trajectory" )
178203
179204 @timed_state (duration = 1.0 , next_state = "tracking_trajectory" )
180205 def shooting_algae (self ) -> None :
181206 self .algae_shooter .shoot ()
182207
183- if not self .algae_shooter .is_executing :
208+ if (
209+ not self .injector_component .has_algae ()
210+ and not self .algae_shooter .is_executing
211+ ):
184212 self .next_state ("tracking_trajectory" )
0 commit comments