blob: 2a600d81a361b1a6c5f117eda751fd3dc8e7ad1e [file] [log] [blame]
James Kuszmaul84083f42022-02-27 17:24:38 -08001#include "y2022/control_loops/superstructure/turret/aiming.h"
2
3#include "y2022/constants.h"
4#include "y2022/control_loops/drivetrain/drivetrain_base.h"
5
6namespace y2022 {
7namespace control_loops {
8namespace superstructure {
9namespace turret {
10
11using frc971::control_loops::Pose;
12using frc971::control_loops::aiming::ShotConfig;
13using frc971::control_loops::aiming::RobotState;
14
15namespace {
16// Average speed-over-ground of the ball on its way to the target. Our current
17// model assumes constant ball velocity regardless of shot distance.
18constexpr double kBallSpeedOverGround = 12.0; // m/s
19
20// If the turret is at zero, then it will be at this angle at which the shot
21// will leave the robot. I.e., if the turret is at zero, then the shot will go
22// straight out the back of the robot.
23constexpr double kTurretZeroOffset = M_PI;
24
James Kuszmaule3fc87f2022-03-12 21:00:50 -080025constexpr double kMaxProfiledVelocity = 10.0;
26constexpr double kMaxProfiledAccel = 20.0;
27
James Kuszmaul84083f42022-02-27 17:24:38 -080028flatbuffers::DetachedBuffer MakePrefilledGoal() {
29 flatbuffers::FlatBufferBuilder fbb;
30 fbb.ForceDefaults(true);
James Kuszmaule3fc87f2022-03-12 21:00:50 -080031 frc971::ProfileParameters::Builder profile_builder(fbb);
32 profile_builder.add_max_velocity(kMaxProfiledVelocity);
33 profile_builder.add_max_acceleration(kMaxProfiledAccel);
34 const flatbuffers::Offset<frc971::ProfileParameters> profile_offset =
35 profile_builder.Finish();
James Kuszmaul84083f42022-02-27 17:24:38 -080036 Aimer::Goal::Builder builder(fbb);
37 builder.add_unsafe_goal(0);
38 builder.add_goal_velocity(0);
James Kuszmaule3fc87f2022-03-12 21:00:50 -080039 builder.add_ignore_profile(false);
40 builder.add_profile_params(profile_offset);
James Kuszmaul84083f42022-02-27 17:24:38 -080041 fbb.Finish(builder.Finish());
42 return fbb.Release();
43}
44} // namespace
45
46Aimer::Aimer() : goal_(MakePrefilledGoal()) {}
47
48void Aimer::Update(const Status *status, ShotMode shot_mode) {
49 const Pose robot_pose({status->x(), status->y(), 0}, status->theta());
50 const Pose goal({0.0, 0.0, 0.0}, 0.0);
51
52 const Eigen::Vector2d linear_angular =
53 drivetrain::GetDrivetrainConfig().Tlr_to_la() *
54 Eigen::Vector2d(status->estimated_left_velocity(),
55 status->estimated_right_velocity());
56 const double xdot = linear_angular(0) * std::cos(status->theta());
57 const double ydot = linear_angular(0) * std::sin(status->theta());
58
59 current_goal_ =
60 frc971::control_loops::aiming::AimerGoal(
61 ShotConfig{goal, shot_mode, constants::Values::kTurretRange(),
62 kBallSpeedOverGround,
63 /*wrap_mode=*/0.0, kTurretZeroOffset},
64 RobotState{robot_pose,
65 {xdot, ydot},
66 linear_angular(1),
67 goal_.message().unsafe_goal()});
68
69 goal_.mutable_message()->mutate_unsafe_goal(current_goal_.position);
70 goal_.mutable_message()->mutate_goal_velocity(
71 std::clamp(current_goal_.velocity, -2.0, 2.0));
72}
73
74flatbuffers::Offset<AimerStatus> Aimer::PopulateStatus(
75 flatbuffers::FlatBufferBuilder *fbb) const {
76 AimerStatus::Builder builder(*fbb);
77 builder.add_turret_position(current_goal_.position);
78 builder.add_turret_velocity(current_goal_.velocity);
79 builder.add_target_distance(current_goal_.target_distance);
80 builder.add_shot_distance(DistanceToGoal());
81 return builder.Finish();
82}
83
84} // namespace turret
85} // namespace superstructure
86} // namespace control_loops
87} // namespace y2022