blob: 4c0309cfcbf12c47c46ae59fc74c0cfce36d3998 [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
25flatbuffers::DetachedBuffer MakePrefilledGoal() {
26 flatbuffers::FlatBufferBuilder fbb;
27 fbb.ForceDefaults(true);
28 Aimer::Goal::Builder builder(fbb);
29 builder.add_unsafe_goal(0);
30 builder.add_goal_velocity(0);
31 builder.add_ignore_profile(true);
32 fbb.Finish(builder.Finish());
33 return fbb.Release();
34}
35} // namespace
36
37Aimer::Aimer() : goal_(MakePrefilledGoal()) {}
38
39void Aimer::Update(const Status *status, ShotMode shot_mode) {
40 const Pose robot_pose({status->x(), status->y(), 0}, status->theta());
41 const Pose goal({0.0, 0.0, 0.0}, 0.0);
42
43 const Eigen::Vector2d linear_angular =
44 drivetrain::GetDrivetrainConfig().Tlr_to_la() *
45 Eigen::Vector2d(status->estimated_left_velocity(),
46 status->estimated_right_velocity());
47 const double xdot = linear_angular(0) * std::cos(status->theta());
48 const double ydot = linear_angular(0) * std::sin(status->theta());
49
50 current_goal_ =
51 frc971::control_loops::aiming::AimerGoal(
52 ShotConfig{goal, shot_mode, constants::Values::kTurretRange(),
53 kBallSpeedOverGround,
54 /*wrap_mode=*/0.0, kTurretZeroOffset},
55 RobotState{robot_pose,
56 {xdot, ydot},
57 linear_angular(1),
58 goal_.message().unsafe_goal()});
59
60 goal_.mutable_message()->mutate_unsafe_goal(current_goal_.position);
61 goal_.mutable_message()->mutate_goal_velocity(
62 std::clamp(current_goal_.velocity, -2.0, 2.0));
63}
64
65flatbuffers::Offset<AimerStatus> Aimer::PopulateStatus(
66 flatbuffers::FlatBufferBuilder *fbb) const {
67 AimerStatus::Builder builder(*fbb);
68 builder.add_turret_position(current_goal_.position);
69 builder.add_turret_velocity(current_goal_.velocity);
70 builder.add_target_distance(current_goal_.target_distance);
71 builder.add_shot_distance(DistanceToGoal());
72 return builder.Finish();
73}
74
75} // namespace turret
76} // namespace superstructure
77} // namespace control_loops
78} // namespace y2022