2222
2323from components .chassis import ChassisComponent
2424from utilities .caching import HasPerLoopCache , cache_per_loop
25+ from utilities .functions import clamp
2526from utilities .game import APRILTAGS , apriltag_layout
2627from utilities .rev import configure_through_bore_encoder
27- from utilities .scalers import scale_value
2828
2929
3030@wpiutil .wpistruct .make_wpistruct
@@ -56,7 +56,7 @@ class VisualLocalizer(HasPerLoopCache):
5656 TIMEOUT = 1.0 # s
5757
5858 CAMERA_FOV = math .radians (
59- 65
59+ 68
6060 ) # photon vision says 69.8, but we are being conservative
6161 CAMERA_MAX_RANGE = 4.0 # m
6262
@@ -96,7 +96,7 @@ def __init__(
9696 ) -> None :
9797 super ().__init__ ()
9898 self .camera = PhotonCamera (name )
99- self .encoder = wpilib .DutyCycleEncoder (encoder_id , math .tau , 0 )
99+ self .encoder = wpilib .DutyCycleEncoder (encoder_id , math .pi , - math . pi )
100100 configure_through_bore_encoder (self .encoder )
101101 # Offset of encoder in radians when facing forwards (the desired zero)
102102 # To find this value, manually point the camera forwards and record the encoder value
@@ -107,9 +107,8 @@ def __init__(
107107 # Repeat for full range
108108 self .servo_offsets = servo_offsets
109109
110- relative_rotations = [(r - encoder_offset ).radians () for r in rotation_range ]
111- self .min_rotation = min (relative_rotations )
112- self .max_rotation = max (relative_rotations )
110+ relative_rotations = [(r - encoder_offset ) for r in rotation_range ]
111+ self .min_rotation , self .max_rotation = relative_rotations
113112
114113 self .servo = wpilib .Servo (servo_id )
115114 self .pos = turret_pos
@@ -177,7 +176,8 @@ def visible_tags(self) -> list[VisibleTag]:
177176 distance = turret_to_tag .norm ()
178177 relative_facing = tag .pose .toPose2d ().rotation () - turret_to_tag .angle ()
179178 if (
180- self .min_rotation <= relative_bearing .radians () <= self .max_rotation
179+ (relative_bearing - self .min_rotation ).radians () >= - self .CAMERA_FOV
180+ and (self .max_rotation - relative_bearing ).radians () >= - self .CAMERA_FOV
181181 and abs (relative_facing .degrees ()) > 100
182182 and distance < self .CAMERA_MAX_RANGE
183183 ):
@@ -192,6 +192,10 @@ def desired_turret_rotation(self) -> Rotation2d:
192192 # Read encoder angle and account for offset
193193 return self .relative_bearing_to_best_cluster ()
194194
195+ @feedback
196+ def desired_servo_rotation (self ) -> Rotation2d :
197+ return self .turret_to_servo (self .desired_turret_rotation ())
198+
195199 def turret_to_servo (self , turret : Rotation2d ) -> Rotation2d :
196200 return turret - (self .servo_offsets .neutral - self .encoder_offset )
197201
@@ -228,14 +232,13 @@ def full_range_servo_(self) -> None:
228232 self .servo .set (1.0 )
229233
230234 def execute (self ) -> None :
235+ target = self .turret_to_servo (self .desired_turret_rotation ())
236+ neutral = self .servo_offsets .neutral
237+ full = self .servo_offsets .full_range
238+ half_range = full - neutral
239+ delta = target - neutral
231240 self .servo .set (
232- scale_value (
233- self .turret_to_servo (self .desired_turret_rotation ()).radians (),
234- (self .servo_offsets .neutral - self .encoder_offset ).radians (),
235- (self .servo_offsets .full_range - self .encoder_offset ).radians (),
236- 0.5 ,
237- 1.0 ,
238- )
241+ clamp ((delta .radians () / half_range .radians () + 1.0 ) / 2.0 , 0.0 , 1.0 )
239242 )
240243
241244 self .turret_rotation_buffer .addSample (
0 commit comments