blob: 18ebafac0f2b26474d67d4946a81a85a22f5ec27 [file] [log] [blame]
#include "y2022/control_loops/superstructure/turret/aiming.h"
#include "y2022/control_loops/drivetrain/drivetrain_base.h"
namespace y2022::control_loops::superstructure::turret {
using frc971::control_loops::Pose;
using frc971::control_loops::aiming::RobotState;
using frc971::control_loops::aiming::ShotConfig;
namespace {
// If the turret is at zero, then it will be at this angle at which the shot
// will leave the robot. I.e., if the turret is at zero, then the shot will go
// straight out the back of the robot.
constexpr double kTurretZeroOffset = M_PI;
constexpr double kMaxProfiledVelocity = 10.0;
constexpr double kMaxProfiledAccel = 25.0;
flatbuffers::DetachedBuffer MakePrefilledGoal() {
flatbuffers::FlatBufferBuilder fbb;
fbb.ForceDefaults(true);
frc971::ProfileParameters::Builder profile_builder(fbb);
profile_builder.add_max_velocity(kMaxProfiledVelocity);
profile_builder.add_max_acceleration(kMaxProfiledAccel);
const flatbuffers::Offset<frc971::ProfileParameters> profile_offset =
profile_builder.Finish();
Aimer::Goal::Builder builder(fbb);
builder.add_unsafe_goal(0);
builder.add_goal_velocity(0);
builder.add_ignore_profile(false);
builder.add_profile_params(profile_offset);
fbb.Finish(builder.Finish());
return fbb.Release();
}
} // namespace
Aimer::Aimer(std::shared_ptr<const constants::Values> constants)
: constants_(constants), goal_(MakePrefilledGoal()) {}
void Aimer::Update(const Status *status, ShotMode shot_mode) {
const Pose robot_pose({status->x(), status->y(), 0}, status->theta());
const Pose goal({0.0, 0.0, 0.0}, 0.0);
const Eigen::Vector2d linear_angular =
drivetrain::GetDrivetrainConfig().Tlr_to_la() *
Eigen::Vector2d(status->estimated_left_velocity(),
status->estimated_right_velocity());
const double xdot = linear_angular(0) * std::cos(status->theta());
const double ydot = linear_angular(0) * std::sin(status->theta());
// Use the previous shot distance to estimate the speed-over-ground of the
// ball.
current_goal_ = frc971::control_loops::aiming::AimerGoal(
ShotConfig{goal, shot_mode, constants_->turret_range,
constants_->shot_velocity_interpolation_table
.Get(current_goal_.target_distance)
.shot_speed_over_ground,
/*wrap_mode=*/0.0, kTurretZeroOffset},
RobotState{robot_pose,
{xdot, ydot},
linear_angular(1),
goal_.message().unsafe_goal()});
goal_.mutable_message()->mutate_unsafe_goal(current_goal_.position);
goal_.mutable_message()->mutate_goal_velocity(
std::clamp(current_goal_.velocity, 0.0, 0.0));
}
flatbuffers::Offset<AimerStatus> Aimer::PopulateStatus(
flatbuffers::FlatBufferBuilder *fbb) const {
AimerStatus::Builder builder(*fbb);
builder.add_turret_position(current_goal_.position);
builder.add_turret_velocity(current_goal_.velocity);
builder.add_target_distance(current_goal_.target_distance);
builder.add_shot_distance(DistanceToGoal());
return builder.Finish();
}
} // namespace y2022::control_loops::superstructure::turret