blob: bf2a223be100585f032a0d88c151e40a43ab6f88 [file] [log] [blame]
Tyler Chatowbf0609c2021-07-31 16:13:27 -07001#include <cinttypes>
2#include <cstddef>
brians343bc112013-02-10 01:53:46 +00003
John Park33858a32018-09-28 23:05:48 -07004#include "aos/logging/logging.h"
Austin Schuh3d6e3df2014-02-17 01:51:03 -08005
Stephan Pleinesd99b1ee2024-02-02 20:56:44 -08006namespace frc971::controls {
brians343bc112013-02-10 01:53:46 +00007
8// TODO(aschuh): Tests.
9
Alex Perrycb7da4b2019-08-28 19:35:56 -070010template <class GoalType, class PositionType, class StatusType,
11 class OutputType>
12constexpr ::std::chrono::milliseconds ControlLoop<
13 GoalType, PositionType, StatusType, OutputType>::kStaleLogInterval;
14template <class GoalType, class PositionType, class StatusType,
15 class OutputType>
16constexpr ::std::chrono::milliseconds ControlLoop<
17 GoalType, PositionType, StatusType, OutputType>::kPwmDisableTime;
Brian Silverman50a9d032014-02-16 17:20:57 -080018
Alex Perrycb7da4b2019-08-28 19:35:56 -070019template <class GoalType, class PositionType, class StatusType,
20 class OutputType>
Tyler Chatowbf0609c2021-07-31 16:13:27 -070021void ControlLoop<GoalType, PositionType, StatusType,
22 OutputType>::ZeroOutputs() {
Nikolai Sohmers2df6f302024-05-30 13:12:29 -070023 auto builder = BuilderType<OutputType>::MakeBuilder(&output_sender_);
24 BuilderType<OutputType>::SendZeroFlatbuffer(this, &builder);
brians343bc112013-02-10 01:53:46 +000025}
26
Alex Perrycb7da4b2019-08-28 19:35:56 -070027template <class GoalType, class PositionType, class StatusType,
28 class OutputType>
29void ControlLoop<GoalType, PositionType, StatusType,
30 OutputType>::IteratePosition(const PositionType &position) {
Brian Silverman699f0cb2015-02-05 19:45:01 -050031 no_goal_.Print();
Brian Silverman699f0cb2015-02-05 19:45:01 -050032 no_sensor_state_.Print();
Brian Silverman699f0cb2015-02-05 19:45:01 -050033 motors_off_log_.Print();
Brian Silverman6a1cd212014-02-20 21:04:34 -080034
Brian Silvermand8f403a2014-12-13 19:12:04 -050035 // Fetch the latest control loop goal. If there is no new
brians343bc112013-02-10 01:53:46 +000036 // goal, we will just reuse the old one.
Austin Schuha1654ed2019-01-27 17:24:54 -080037 goal_fetcher_.Fetch();
38 const GoalType *goal = goal_fetcher_.get();
Austin Schuh3d6e3df2014-02-17 01:51:03 -080039
Austin Schuheeec74a2019-01-27 20:58:59 -080040 const bool new_robot_state = robot_state_fetcher_.Fetch();
41 if (!robot_state_fetcher_.get()) {
Austin Schuhf257f3c2019-10-27 21:00:43 -070042 AOS_LOG_INTERVAL(no_sensor_state_);
Austin Schuh3d6e3df2014-02-17 01:51:03 -080043 return;
44 }
Alex Perrycb7da4b2019-08-28 19:35:56 -070045 if (sensor_reader_pid_ != robot_state_fetcher_->reader_pid()) {
Austin Schuhf257f3c2019-10-27 21:00:43 -070046 AOS_LOG(INFO, "new sensor reader PID %" PRId32 ", old was %" PRId32 "\n",
Alex Perrycb7da4b2019-08-28 19:35:56 -070047 robot_state_fetcher_->reader_pid(), sensor_reader_pid_);
Austin Schuh3d6e3df2014-02-17 01:51:03 -080048 reset_ = true;
Alex Perrycb7da4b2019-08-28 19:35:56 -070049 sensor_reader_pid_ = robot_state_fetcher_->reader_pid();
Brian Silverman71fbee02014-03-13 17:24:54 -070050 }
brians343bc112013-02-10 01:53:46 +000051
Alex Perrycb7da4b2019-08-28 19:35:56 -070052 bool outputs_enabled = robot_state_fetcher_->outputs_enabled();
brians343bc112013-02-10 01:53:46 +000053
54 // Check to see if we got a driver station packet recently.
Austin Schuh61bdc602016-12-04 19:10:10 -080055 if (new_robot_state) {
Alex Perrycb7da4b2019-08-28 19:35:56 -070056 if (robot_state_fetcher_->outputs_enabled()) {
Brian Silverman295f74b2015-02-14 23:00:47 -050057 // If the driver's station reports being disabled, we're probably not
58 // actually going to send motor values regardless of what the FPGA
59 // reports.
Austin Schuhad154822019-12-27 15:45:13 -080060 last_pwm_sent_ = robot_state_fetcher_.context().monotonic_event_time;
brians343bc112013-02-10 01:53:46 +000061 }
62 }
63
Austin Schuh19845272019-07-07 20:45:22 -070064 const ::aos::monotonic_clock::time_point monotonic_now =
65 event_loop_->monotonic_now();
66 const bool motors_off = monotonic_now >= kPwmDisableTime + last_pwm_sent_;
Austin Schuheeec74a2019-01-27 20:58:59 -080067 joystick_state_fetcher_.Fetch();
Brian Silverman2704ecf2014-04-09 20:24:03 -070068 if (motors_off) {
Alex Perrycb7da4b2019-08-28 19:35:56 -070069 if (joystick_state_fetcher_.get() && joystick_state_fetcher_->enabled()) {
Austin Schuhf257f3c2019-10-27 21:00:43 -070070 AOS_LOG_INTERVAL(motors_off_log_);
Brian Silverman2704ecf2014-04-09 20:24:03 -070071 }
72 outputs_enabled = false;
73 }
74
Nikolai Sohmers2df6f302024-05-30 13:12:29 -070075 StatusBuilder status = BuilderType<StatusType>::MakeBuilder(&status_sender_);
brians343bc112013-02-10 01:53:46 +000076 if (outputs_enabled) {
Nikolai Sohmers2df6f302024-05-30 13:12:29 -070077 OutputBuilder output =
78 BuilderType<OutputType>::MakeBuilder(&output_sender_);
Alex Perrycb7da4b2019-08-28 19:35:56 -070079 RunIteration(goal, &position, &output, &status);
brians343bc112013-02-10 01:53:46 +000080
Nikolai Sohmers2df6f302024-05-30 13:12:29 -070081 BuilderType<OutputType>::CheckSent(&output);
brians343bc112013-02-10 01:53:46 +000082 } else {
Brian Silverman699f0cb2015-02-05 19:45:01 -050083 // The outputs are disabled, so pass nullptr in for the output.
Alex Perrycb7da4b2019-08-28 19:35:56 -070084 RunIteration(goal, &position, nullptr, &status);
brians343bc112013-02-10 01:53:46 +000085 ZeroOutputs();
86 }
87
Nikolai Sohmers2df6f302024-05-30 13:12:29 -070088 BuilderType<StatusType>::CheckSent(&status);
brians343bc112013-02-10 01:53:46 +000089}
90
Stephan Pleinesd99b1ee2024-02-02 20:56:44 -080091} // namespace frc971::controls