blob: 9bf395e12522736feb454bc01ff599fd5be6b4c1 [file] [log] [blame]
brians343bc112013-02-10 01:53:46 +00001#include <stddef.h>
Brian Silverman699f0cb2015-02-05 19:45:01 -05002#include <inttypes.h>
brians343bc112013-02-10 01:53:46 +00003
4#include "aos/common/logging/logging.h"
Brian Silverman2ac0fbc2014-03-20 19:45:13 -07005#include "aos/common/messages/robot_state.q.h"
Brian Silvermand6974f42014-02-14 13:39:21 -08006#include "aos/common/logging/queue_logging.h"
Brian3afd6fc2014-04-02 20:41:49 -07007#include "aos/common/util/phased_loop.h"
Austin Schuh3d6e3df2014-02-17 01:51:03 -08008
brians343bc112013-02-10 01:53:46 +00009namespace aos {
Brian Silverman38111502014-04-10 12:36:26 -070010namespace controls {
brians343bc112013-02-10 01:53:46 +000011
12// TODO(aschuh): Tests.
13
Brian Silverman089f5812015-02-15 01:58:19 -050014template <class T>
15constexpr ::aos::time::Time ControlLoop<T>::kStaleLogInterval;
16template <class T>
17constexpr ::aos::time::Time ControlLoop<T>::kPwmDisableTime;
Brian Silverman50a9d032014-02-16 17:20:57 -080018
Brian Silverman089f5812015-02-15 01:58:19 -050019template <class T>
20void ControlLoop<T>::ZeroOutputs() {
brians343bc112013-02-10 01:53:46 +000021 aos::ScopedMessagePtr<OutputType> output =
22 control_loop_->output.MakeMessage();
23 Zero(output.get());
24 output.Send();
25}
26
Brian Silverman089f5812015-02-15 01:58:19 -050027template <class T>
28void ControlLoop<T>::Iterate() {
Brian Silverman699f0cb2015-02-05 19:45:01 -050029 no_goal_.Print();
Brian Silverman9c9ab422014-02-25 13:42:53 -080030 driver_station_old_.Print();
Brian Silverman699f0cb2015-02-05 19:45:01 -050031 no_sensor_state_.Print();
Brian Silverman9c9ab422014-02-25 13:42:53 -080032 no_driver_station_.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 control_loop_->position.FetchAnother();
36 const PositionType *const position = control_loop_->position.get();
37 LOG_STRUCT(DEBUG, "position", *position);
38
39 // Fetch the latest control loop goal. If there is no new
brians343bc112013-02-10 01:53:46 +000040 // goal, we will just reuse the old one.
brians343bc112013-02-10 01:53:46 +000041 control_loop_->goal.FetchLatest();
brians343bc112013-02-10 01:53:46 +000042 const GoalType *goal = control_loop_->goal.get();
Brian Silverman699f0cb2015-02-05 19:45:01 -050043 if (goal) {
44 LOG_STRUCT(DEBUG, "goal", *goal);
45 } else {
46 LOG_INTERVAL(no_goal_);
brians343bc112013-02-10 01:53:46 +000047 }
Austin Schuh3d6e3df2014-02-17 01:51:03 -080048
Brian Silverman699f0cb2015-02-05 19:45:01 -050049 ::aos::robot_state.FetchLatest();
50 if (!::aos::robot_state.get()) {
51 LOG_INTERVAL(no_sensor_state_);
Austin Schuh3d6e3df2014-02-17 01:51:03 -080052 return;
53 }
Brian Silverman699f0cb2015-02-05 19:45:01 -050054 if (sensor_reader_pid_ != ::aos::robot_state->reader_pid) {
55 LOG(INFO, "new sensor reader PID %" PRId32 ", old was %" PRId32 "\n",
56 ::aos::robot_state->reader_pid, sensor_reader_pid_);
Austin Schuh3d6e3df2014-02-17 01:51:03 -080057 reset_ = true;
Brian Silverman699f0cb2015-02-05 19:45:01 -050058 sensor_reader_pid_ = ::aos::robot_state->reader_pid;
Brian Silverman71fbee02014-03-13 17:24:54 -070059 }
brians343bc112013-02-10 01:53:46 +000060
brians343bc112013-02-10 01:53:46 +000061 bool outputs_enabled = false;
62
63 // Check to see if we got a driver station packet recently.
Brian Silverman699f0cb2015-02-05 19:45:01 -050064 if (::aos::joystick_state.FetchLatest()) {
Brian Silverman295f74b2015-02-14 23:00:47 -050065 if (::aos::joystick_state->enabled) outputs_enabled = true;
Brian Silverman699f0cb2015-02-05 19:45:01 -050066 if (::aos::robot_state->outputs_enabled) {
Brian Silverman295f74b2015-02-14 23:00:47 -050067 // If the driver's station reports being disabled, we're probably not
68 // actually going to send motor values regardless of what the FPGA
69 // reports.
70 if (::aos::joystick_state->enabled) {
71 last_pwm_sent_ = ::aos::robot_state->sent_time;
72 } else {
73 LOG(WARNING, "outputs enabled while disabled\n");
74 }
75 } else if (::aos::joystick_state->enabled) {
76 LOG(WARNING, "outputs disabled while enabled\n");
Brian Silverman699f0cb2015-02-05 19:45:01 -050077 }
Brian Silverman488005d2015-03-15 14:05:42 -070078 } else if (::aos::joystick_state.IsNewerThanMS(kDSPacketTimeoutMs)) {
79 if (::aos::joystick_state->enabled) {
80 outputs_enabled = true;
81 }
brians343bc112013-02-10 01:53:46 +000082 } else {
Brian Silverman699f0cb2015-02-05 19:45:01 -050083 if (::aos::joystick_state.get()) {
Brian Silverman9c9ab422014-02-25 13:42:53 -080084 LOG_INTERVAL(driver_station_old_);
brians343bc112013-02-10 01:53:46 +000085 } else {
Brian Silverman9c9ab422014-02-25 13:42:53 -080086 LOG_INTERVAL(no_driver_station_);
brians343bc112013-02-10 01:53:46 +000087 }
88 }
89
Brian Silverman38111502014-04-10 12:36:26 -070090 const bool motors_off =
Brian Silverman699f0cb2015-02-05 19:45:01 -050091 (::aos::time::Time::Now() - last_pwm_sent_) >= kPwmDisableTime;
Brian Silverman2704ecf2014-04-09 20:24:03 -070092 if (motors_off) {
Brian Silverman699f0cb2015-02-05 19:45:01 -050093 if (::aos::joystick_state.get() && ::aos::joystick_state->enabled) {
Brian Silverman2704ecf2014-04-09 20:24:03 -070094 LOG_INTERVAL(motors_off_log_);
95 }
96 outputs_enabled = false;
97 }
98
brians343bc112013-02-10 01:53:46 +000099 aos::ScopedMessagePtr<StatusType> status =
100 control_loop_->status.MakeMessage();
Brian Silverman699f0cb2015-02-05 19:45:01 -0500101 if (status.get() == nullptr) {
brians343bc112013-02-10 01:53:46 +0000102 return;
103 }
104
105 if (outputs_enabled) {
106 aos::ScopedMessagePtr<OutputType> output =
107 control_loop_->output.MakeMessage();
108 RunIteration(goal, position, output.get(), status.get());
109
Brian Silvermand6974f42014-02-14 13:39:21 -0800110 LOG_STRUCT(DEBUG, "output", *output);
brians343bc112013-02-10 01:53:46 +0000111 output.Send();
112 } else {
Brian Silverman699f0cb2015-02-05 19:45:01 -0500113 // The outputs are disabled, so pass nullptr in for the output.
Ben Fredrickson4283bb42014-02-22 08:31:50 +0000114 RunIteration(goal, position, nullptr, status.get());
brians343bc112013-02-10 01:53:46 +0000115 ZeroOutputs();
116 }
117
Brian Silvermand6974f42014-02-14 13:39:21 -0800118 LOG_STRUCT(DEBUG, "status", *status);
brians343bc112013-02-10 01:53:46 +0000119 status.Send();
120}
121
Brian Silverman089f5812015-02-15 01:58:19 -0500122template <class T>
123void ControlLoop<T>::Run() {
brians343bc112013-02-10 01:53:46 +0000124 while (true) {
brians343bc112013-02-10 01:53:46 +0000125 Iterate();
126 }
127}
128
Brian Silverman38111502014-04-10 12:36:26 -0700129} // namespace controls
brians343bc112013-02-10 01:53:46 +0000130} // namespace aos