Alex Perry | 731b460 | 2019-02-02 22:13:01 -0800 | [diff] [blame] | 1 | #include "frc971/control_loops/drivetrain/splinedrivetrain.h" |
| 2 | |
| 3 | #include "Eigen/Dense" |
| 4 | |
Alex Perry | cb7da4b | 2019-08-28 19:35:56 -0700 | [diff] [blame^] | 5 | #include "aos/realtime.h" |
James Kuszmaul | c73bb22 | 2019-04-07 12:15:35 -0700 | [diff] [blame] | 6 | #include "aos/util/math.h" |
Alex Perry | cb7da4b | 2019-08-28 19:35:56 -0700 | [diff] [blame^] | 7 | #include "frc971/control_loops/control_loops_generated.h" |
Alex Perry | 731b460 | 2019-02-02 22:13:01 -0800 | [diff] [blame] | 8 | #include "frc971/control_loops/drivetrain/drivetrain_config.h" |
Alex Perry | cb7da4b | 2019-08-28 19:35:56 -0700 | [diff] [blame^] | 9 | #include "frc971/control_loops/drivetrain/drivetrain_goal_generated.h" |
| 10 | #include "frc971/control_loops/drivetrain/drivetrain_output_generated.h" |
| 11 | #include "frc971/control_loops/drivetrain/drivetrain_status_generated.h" |
Alex Perry | 731b460 | 2019-02-02 22:13:01 -0800 | [diff] [blame] | 12 | |
Alex Perry | 731b460 | 2019-02-02 22:13:01 -0800 | [diff] [blame] | 13 | namespace frc971 { |
| 14 | namespace control_loops { |
| 15 | namespace drivetrain { |
| 16 | |
| 17 | SplineDrivetrain::SplineDrivetrain(const DrivetrainConfig<double> &dt_config) |
Alex Perry | cc3ee4c | 2019-02-09 21:20:41 -0800 | [diff] [blame] | 18 | : dt_config_(dt_config), new_goal_(&mutex_) { |
| 19 | worker_thread_ = std::thread(&SplineDrivetrain::ComputeTrajectory, this); |
| 20 | } |
Alex Perry | e32eabc | 2019-02-08 19:51:19 -0800 | [diff] [blame] | 21 | |
| 22 | void SplineDrivetrain::ScaleCapU(Eigen::Matrix<double, 2, 1> *U) { |
Alex Perry | cc3ee4c | 2019-02-09 21:20:41 -0800 | [diff] [blame] | 23 | output_was_capped_ = |
| 24 | ::std::abs((*U)(0, 0)) > 12.0 || ::std::abs((*U)(1, 0)) > 12.0; |
Alex Perry | e32eabc | 2019-02-08 19:51:19 -0800 | [diff] [blame] | 25 | |
Alex Perry | cc3ee4c | 2019-02-09 21:20:41 -0800 | [diff] [blame] | 26 | if (output_was_capped_) { |
Alex Perry | e32eabc | 2019-02-08 19:51:19 -0800 | [diff] [blame] | 27 | *U *= 12.0 / U->lpNorm<Eigen::Infinity>(); |
| 28 | } |
| 29 | } |
Alex Perry | 731b460 | 2019-02-02 22:13:01 -0800 | [diff] [blame] | 30 | |
Alex Perry | cc3ee4c | 2019-02-09 21:20:41 -0800 | [diff] [blame] | 31 | void SplineDrivetrain::ComputeTrajectory() { |
Alex Perry | 1ec3452 | 2019-02-17 22:44:10 -0800 | [diff] [blame] | 32 | ::aos::SetCurrentThreadRealtimePriority(1); |
| 33 | |
Alex Perry | cc3ee4c | 2019-02-09 21:20:41 -0800 | [diff] [blame] | 34 | ::aos::MutexLocker locker(&mutex_); |
| 35 | while (run_) { |
Alex Perry | cb7da4b | 2019-08-28 19:35:56 -0700 | [diff] [blame^] | 36 | while (goal_.spline_idx == future_spline_idx_) { |
Austin Schuh | f257f3c | 2019-10-27 21:00:43 -0700 | [diff] [blame] | 37 | AOS_CHECK(!new_goal_.Wait()); |
Alex Perry | cc3ee4c | 2019-02-09 21:20:41 -0800 | [diff] [blame] | 38 | if (!run_) { |
| 39 | return; |
| 40 | } |
| 41 | } |
| 42 | past_distance_spline_.reset(); |
| 43 | past_trajectory_.reset(); |
| 44 | |
Alex Perry | cb7da4b | 2019-08-28 19:35:56 -0700 | [diff] [blame^] | 45 | plan_state_ = PlanningState_BUILDING_TRAJECTORY; |
| 46 | future_spline_idx_ = goal_.spline_idx; |
Austin Schuh | 6bcc230 | 2019-03-23 22:28:06 -0700 | [diff] [blame] | 47 | planning_spline_idx_ = future_spline_idx_; |
Alex Perry | cb7da4b | 2019-08-28 19:35:56 -0700 | [diff] [blame^] | 48 | const MultiSpline &multispline = goal_.spline; |
Alex Perry | 731b460 | 2019-02-02 22:13:01 -0800 | [diff] [blame] | 49 | auto x = multispline.spline_x; |
| 50 | auto y = multispline.spline_y; |
| 51 | ::std::vector<Spline> splines = ::std::vector<Spline>(); |
| 52 | for (int i = 0; i < multispline.spline_count; ++i) { |
| 53 | ::Eigen::Matrix<double, 2, 6> points = |
| 54 | ::Eigen::Matrix<double, 2, 6>::Zero(); |
| 55 | for (int j = 0; j < 6; ++j) { |
| 56 | points(0, j) = x[i * 5 + j]; |
| 57 | points(1, j) = y[i * 5 + j]; |
| 58 | } |
| 59 | splines.emplace_back(Spline(points)); |
| 60 | } |
| 61 | |
Alex Perry | cb7da4b | 2019-08-28 19:35:56 -0700 | [diff] [blame^] | 62 | future_drive_spline_backwards_ = goal_.drive_spline_backwards; |
James Kuszmaul | 29e417d | 2019-04-13 10:03:35 -0700 | [diff] [blame] | 63 | |
Alex Perry | cc3ee4c | 2019-02-09 21:20:41 -0800 | [diff] [blame] | 64 | future_distance_spline_ = ::std::unique_ptr<DistanceSpline>( |
Alex Perry | 731b460 | 2019-02-02 22:13:01 -0800 | [diff] [blame] | 65 | new DistanceSpline(::std::move(splines))); |
| 66 | |
Alex Perry | cc3ee4c | 2019-02-09 21:20:41 -0800 | [diff] [blame] | 67 | future_trajectory_ = ::std::unique_ptr<Trajectory>( |
| 68 | new Trajectory(future_distance_spline_.get(), dt_config_)); |
Alex Perry | 731b460 | 2019-02-02 22:13:01 -0800 | [diff] [blame] | 69 | |
Alex Perry | cc3ee4c | 2019-02-09 21:20:41 -0800 | [diff] [blame] | 70 | for (size_t i = 0; i < multispline.constraints.size(); ++i) { |
Alex Perry | cb7da4b | 2019-08-28 19:35:56 -0700 | [diff] [blame^] | 71 | const ::frc971::ConstraintT &constraint = multispline.constraints[i]; |
Alex Perry | 731b460 | 2019-02-02 22:13:01 -0800 | [diff] [blame] | 72 | switch (constraint.constraint_type) { |
Alex Perry | cb7da4b | 2019-08-28 19:35:56 -0700 | [diff] [blame^] | 73 | case frc971::ConstraintType_CONSTRAINT_TYPE_UNDEFINED: |
Alex Perry | 731b460 | 2019-02-02 22:13:01 -0800 | [diff] [blame] | 74 | break; |
Alex Perry | cb7da4b | 2019-08-28 19:35:56 -0700 | [diff] [blame^] | 75 | case frc971::ConstraintType_LONGITUDINAL_ACCELERATION: |
Alex Perry | cc3ee4c | 2019-02-09 21:20:41 -0800 | [diff] [blame] | 76 | future_trajectory_->set_longitudal_acceleration(constraint.value); |
Alex Perry | 731b460 | 2019-02-02 22:13:01 -0800 | [diff] [blame] | 77 | break; |
Alex Perry | cb7da4b | 2019-08-28 19:35:56 -0700 | [diff] [blame^] | 78 | case frc971::ConstraintType_LATERAL_ACCELERATION: |
Alex Perry | cc3ee4c | 2019-02-09 21:20:41 -0800 | [diff] [blame] | 79 | future_trajectory_->set_lateral_acceleration(constraint.value); |
Alex Perry | 731b460 | 2019-02-02 22:13:01 -0800 | [diff] [blame] | 80 | break; |
Alex Perry | cb7da4b | 2019-08-28 19:35:56 -0700 | [diff] [blame^] | 81 | case frc971::ConstraintType_VOLTAGE: |
Alex Perry | cc3ee4c | 2019-02-09 21:20:41 -0800 | [diff] [blame] | 82 | future_trajectory_->set_voltage_limit(constraint.value); |
Alex Perry | 731b460 | 2019-02-02 22:13:01 -0800 | [diff] [blame] | 83 | break; |
Alex Perry | cb7da4b | 2019-08-28 19:35:56 -0700 | [diff] [blame^] | 84 | case frc971::ConstraintType_VELOCITY: |
Alex Perry | cc3ee4c | 2019-02-09 21:20:41 -0800 | [diff] [blame] | 85 | future_trajectory_->LimitVelocity(constraint.start_distance, |
| 86 | constraint.end_distance, |
| 87 | constraint.value); |
Alex Perry | 731b460 | 2019-02-02 22:13:01 -0800 | [diff] [blame] | 88 | break; |
| 89 | } |
| 90 | } |
Alex Perry | cb7da4b | 2019-08-28 19:35:56 -0700 | [diff] [blame^] | 91 | plan_state_ = PlanningState_PLANNING_TRAJECTORY; |
Alex Perry | 731b460 | 2019-02-02 22:13:01 -0800 | [diff] [blame] | 92 | |
Alex Perry | cc3ee4c | 2019-02-09 21:20:41 -0800 | [diff] [blame] | 93 | future_trajectory_->Plan(); |
Alex Perry | cb7da4b | 2019-08-28 19:35:56 -0700 | [diff] [blame^] | 94 | plan_state_ = PlanningState_PLANNED; |
Alex Perry | cc3ee4c | 2019-02-09 21:20:41 -0800 | [diff] [blame] | 95 | } |
| 96 | } |
| 97 | |
| 98 | void SplineDrivetrain::SetGoal( |
Alex Perry | cb7da4b | 2019-08-28 19:35:56 -0700 | [diff] [blame^] | 99 | const ::frc971::control_loops::drivetrain::Goal *goal) { |
| 100 | current_spline_handle_ = goal->spline_handle(); |
| 101 | |
James Kuszmaul | 29e417d | 2019-04-13 10:03:35 -0700 | [diff] [blame] | 102 | // If told to stop, set the executing spline to an invalid index and clear out |
| 103 | // its plan: |
| 104 | if (current_spline_handle_ == 0 && |
Alex Perry | cb7da4b | 2019-08-28 19:35:56 -0700 | [diff] [blame^] | 105 | (goal->spline() == nullptr || |
| 106 | current_spline_idx_ != CHECK_NOTNULL(goal->spline())->spline_idx())) { |
Alex Perry | cc3ee4c | 2019-02-09 21:20:41 -0800 | [diff] [blame] | 107 | current_spline_idx_ = -1; |
| 108 | } |
| 109 | |
| 110 | ::aos::Mutex::State mutex_state = mutex_.TryLock(); |
| 111 | if (mutex_state == ::aos::Mutex::State::kLocked) { |
Alex Perry | cb7da4b | 2019-08-28 19:35:56 -0700 | [diff] [blame^] | 112 | if (goal->spline() != nullptr && goal->spline()->spline_idx() && |
| 113 | future_spline_idx_ != goal->spline()->spline_idx()) { |
| 114 | CHECK_NOTNULL(goal->spline()); |
| 115 | goal_.spline_idx = goal->spline()->spline_idx(); |
| 116 | goal_.drive_spline_backwards = goal->spline()->drive_spline_backwards(); |
| 117 | |
| 118 | const frc971::MultiSpline *multispline = goal->spline()->spline(); |
| 119 | CHECK_NOTNULL(multispline); |
| 120 | |
| 121 | goal_.spline.spline_count = multispline->spline_count(); |
| 122 | |
| 123 | CHECK_EQ(multispline->spline_x()->size(), |
| 124 | static_cast<size_t>(goal_.spline.spline_count * 5 + 1)); |
| 125 | CHECK_EQ(multispline->spline_y()->size(), |
| 126 | static_cast<size_t>(goal_.spline.spline_count * 5 + 1)); |
| 127 | |
| 128 | std::copy(multispline->spline_x()->begin(), |
| 129 | multispline->spline_x()->end(), goal_.spline.spline_x.begin()); |
| 130 | std::copy(multispline->spline_y()->begin(), |
| 131 | multispline->spline_y()->end(), goal_.spline.spline_y.begin()); |
| 132 | |
| 133 | for (size_t i = 0; i < 6; ++i) { |
| 134 | if (multispline->constraints() != nullptr && |
| 135 | i < multispline->constraints()->size()) { |
| 136 | multispline->constraints()->Get(i)->UnPackTo( |
| 137 | &goal_.spline.constraints[i]); |
| 138 | } else { |
| 139 | goal_.spline.constraints[i].constraint_type = |
| 140 | ConstraintType_CONSTRAINT_TYPE_UNDEFINED; |
| 141 | } |
| 142 | } |
| 143 | |
Alex Perry | cc3ee4c | 2019-02-09 21:20:41 -0800 | [diff] [blame] | 144 | new_goal_.Broadcast(); |
James Kuszmaul | 29e417d | 2019-04-13 10:03:35 -0700 | [diff] [blame] | 145 | if (current_spline_handle_ != current_spline_idx_) { |
| 146 | // If we aren't going to actively execute the current spline, evict it's |
| 147 | // plan. |
| 148 | past_trajectory_ = std::move(current_trajectory_); |
| 149 | past_distance_spline_ = std::move(current_distance_spline_); |
| 150 | } |
Alex Perry | cc3ee4c | 2019-02-09 21:20:41 -0800 | [diff] [blame] | 151 | } |
James Kuszmaul | 29e417d | 2019-04-13 10:03:35 -0700 | [diff] [blame] | 152 | // If you never started executing the previous spline, you're screwed. |
Alex Perry | cc3ee4c | 2019-02-09 21:20:41 -0800 | [diff] [blame] | 153 | if (future_trajectory_ && |
| 154 | (!current_trajectory_ || |
| 155 | current_trajectory_->is_at_end(current_xva_.block<2, 1>(0, 0)) || |
| 156 | current_spline_idx_ == -1)) { |
| 157 | // Move current data to other variables to be cleared by worker. |
| 158 | past_trajectory_ = std::move(current_trajectory_); |
| 159 | past_distance_spline_ = std::move(current_distance_spline_); |
| 160 | |
| 161 | // Move the computed data to be executed. |
| 162 | current_trajectory_ = std::move(future_trajectory_); |
| 163 | current_distance_spline_ = std::move(future_distance_spline_); |
James Kuszmaul | 29e417d | 2019-04-13 10:03:35 -0700 | [diff] [blame] | 164 | current_drive_spline_backwards_ = future_drive_spline_backwards_; |
Alex Perry | cc3ee4c | 2019-02-09 21:20:41 -0800 | [diff] [blame] | 165 | current_spline_idx_ = future_spline_idx_; |
| 166 | |
| 167 | // Reset internal state to a trajectory start position. |
| 168 | current_xva_ = current_trajectory_->FFAcceleration(0); |
| 169 | current_xva_(1) = 0.0; |
Alex Perry | 4b502a9 | 2019-04-06 22:00:38 -0700 | [diff] [blame] | 170 | has_started_execution_ = false; |
Alex Perry | cc3ee4c | 2019-02-09 21:20:41 -0800 | [diff] [blame] | 171 | } |
| 172 | mutex_.Unlock(); |
Alex Perry | a71badb | 2019-02-06 19:40:41 -0800 | [diff] [blame] | 173 | } |
| 174 | } |
| 175 | |
Alex Perry | e32eabc | 2019-02-08 19:51:19 -0800 | [diff] [blame] | 176 | // TODO(alex): Hold position when done following the spline. |
| 177 | // TODO(Austin): Compensate for voltage error. |
Alex Perry | cc3ee4c | 2019-02-09 21:20:41 -0800 | [diff] [blame] | 178 | void SplineDrivetrain::Update(bool enable, const ::Eigen::Matrix<double, 5, 1> &state) { |
| 179 | next_U_ = ::Eigen::Matrix<double, 2, 1>::Zero(); |
Alex Perry | e32eabc | 2019-02-08 19:51:19 -0800 | [diff] [blame] | 180 | enable_ = enable; |
| 181 | if (enable && current_trajectory_) { |
| 182 | ::Eigen::Matrix<double, 2, 1> U_ff = ::Eigen::Matrix<double, 2, 1>::Zero(); |
Alex Perry | cc3ee4c | 2019-02-09 21:20:41 -0800 | [diff] [blame] | 183 | if (!IsAtEnd() && |
| 184 | current_spline_handle_ == current_spline_idx_) { |
Alex Perry | 4b502a9 | 2019-04-06 22:00:38 -0700 | [diff] [blame] | 185 | has_started_execution_ = true; |
Alex Perry | e32eabc | 2019-02-08 19:51:19 -0800 | [diff] [blame] | 186 | // TODO(alex): It takes about a cycle for the outputs to propagate to the |
| 187 | // motors. Consider delaying the output by a cycle. |
| 188 | U_ff = current_trajectory_->FFVoltage(current_xva_(0)); |
| 189 | } |
Alex Perry | cc3ee4c | 2019-02-09 21:20:41 -0800 | [diff] [blame] | 190 | |
Alex Perry | e32eabc | 2019-02-08 19:51:19 -0800 | [diff] [blame] | 191 | ::Eigen::Matrix<double, 2, 5> K = |
| 192 | current_trajectory_->KForState(state, dt_config_.dt, Q, R); |
James Kuszmaul | 1057ce8 | 2019-02-09 17:58:24 -0800 | [diff] [blame] | 193 | ::Eigen::Matrix<double, 5, 1> goal_state = CurrentGoalState(); |
James Kuszmaul | 29e417d | 2019-04-13 10:03:35 -0700 | [diff] [blame] | 194 | if (current_drive_spline_backwards_) { |
James Kuszmaul | c73bb22 | 2019-04-07 12:15:35 -0700 | [diff] [blame] | 195 | ::Eigen::Matrix<double, 2, 1> swapU(U_ff(1, 0), U_ff(0, 0)); |
| 196 | U_ff = -swapU; |
| 197 | goal_state(2, 0) += M_PI; |
| 198 | double left_goal = goal_state(3, 0); |
| 199 | double right_goal = goal_state(4, 0); |
| 200 | goal_state(3, 0) = -right_goal; |
| 201 | goal_state(4, 0) = -left_goal; |
| 202 | } |
Alex Perry | e32eabc | 2019-02-08 19:51:19 -0800 | [diff] [blame] | 203 | ::Eigen::Matrix<double, 5, 1> state_error = goal_state - state; |
James Kuszmaul | c73bb22 | 2019-04-07 12:15:35 -0700 | [diff] [blame] | 204 | state_error(2, 0) = ::aos::math::NormalizeAngle(state_error(2, 0)); |
Alex Perry | e32eabc | 2019-02-08 19:51:19 -0800 | [diff] [blame] | 205 | ::Eigen::Matrix<double, 2, 1> U_fb = K * state_error; |
Alex Perry | cc3ee4c | 2019-02-09 21:20:41 -0800 | [diff] [blame] | 206 | |
| 207 | ::Eigen::Matrix<double, 2, 1> xv_state = current_xva_.block<2,1>(0,0); |
| 208 | next_xva_ = current_trajectory_->GetNextXVA(dt_config_.dt, &xv_state); |
Alex Perry | e32eabc | 2019-02-08 19:51:19 -0800 | [diff] [blame] | 209 | next_U_ = U_ff + U_fb; |
| 210 | uncapped_U_ = next_U_; |
| 211 | ScaleCapU(&next_U_); |
Alex Perry | 731b460 | 2019-02-02 22:13:01 -0800 | [diff] [blame] | 212 | } |
| 213 | } |
| 214 | |
Alex Perry | 731b460 | 2019-02-02 22:13:01 -0800 | [diff] [blame] | 215 | void SplineDrivetrain::SetOutput( |
Alex Perry | cb7da4b | 2019-08-28 19:35:56 -0700 | [diff] [blame^] | 216 | ::frc971::control_loops::drivetrain::OutputT *output) { |
Alex Perry | 731b460 | 2019-02-02 22:13:01 -0800 | [diff] [blame] | 217 | if (!output) { |
| 218 | return; |
| 219 | } |
| 220 | if (current_spline_handle_ == current_spline_idx_) { |
James Kuszmaul | 1057ce8 | 2019-02-09 17:58:24 -0800 | [diff] [blame] | 221 | if (!IsAtEnd()) { |
Alex Perry | e32eabc | 2019-02-08 19:51:19 -0800 | [diff] [blame] | 222 | output->left_voltage = next_U_(0); |
| 223 | output->right_voltage = next_U_(1); |
Alex Perry | a71badb | 2019-02-06 19:40:41 -0800 | [diff] [blame] | 224 | current_xva_ = next_xva_; |
Alex Perry | 731b460 | 2019-02-02 22:13:01 -0800 | [diff] [blame] | 225 | } |
| 226 | } |
Alex Perry | cc3ee4c | 2019-02-09 21:20:41 -0800 | [diff] [blame] | 227 | output->left_voltage = next_U_(0); |
| 228 | output->right_voltage = next_U_(1); |
Alex Perry | 731b460 | 2019-02-02 22:13:01 -0800 | [diff] [blame] | 229 | } |
| 230 | |
Alex Perry | cb7da4b | 2019-08-28 19:35:56 -0700 | [diff] [blame^] | 231 | |
Alex Perry | e32eabc | 2019-02-08 19:51:19 -0800 | [diff] [blame] | 232 | void SplineDrivetrain::PopulateStatus( |
Alex Perry | cb7da4b | 2019-08-28 19:35:56 -0700 | [diff] [blame^] | 233 | drivetrain::Status::Builder *builder) const { |
| 234 | if (builder && enable_) { |
| 235 | builder->add_uncapped_left_voltage(uncapped_U_(0)); |
| 236 | builder->add_uncapped_right_voltage(uncapped_U_(1)); |
| 237 | builder->add_robot_speed(current_xva_(1)); |
| 238 | builder->add_output_was_capped(output_was_capped_); |
Alex Perry | cc3ee4c | 2019-02-09 21:20:41 -0800 | [diff] [blame] | 239 | } |
Alex Perry | cb7da4b | 2019-08-28 19:35:56 -0700 | [diff] [blame^] | 240 | } |
Alex Perry | cc3ee4c | 2019-02-09 21:20:41 -0800 | [diff] [blame] | 241 | |
Alex Perry | cb7da4b | 2019-08-28 19:35:56 -0700 | [diff] [blame^] | 242 | flatbuffers::Offset<TrajectoryLogging> SplineDrivetrain::MakeTrajectoryLogging( |
| 243 | flatbuffers::FlatBufferBuilder *builder) const { |
| 244 | drivetrain::TrajectoryLogging::Builder trajectory_logging_builder(*builder); |
| 245 | if (current_distance_spline_) { |
| 246 | ::Eigen::Matrix<double, 5, 1> goal_state = CurrentGoalState(); |
| 247 | trajectory_logging_builder.add_x(goal_state(0)); |
| 248 | trajectory_logging_builder.add_y(goal_state(1)); |
| 249 | trajectory_logging_builder.add_theta(::aos::math::NormalizeAngle( |
| 250 | goal_state(2) + (current_drive_spline_backwards_ ? M_PI : 0.0))); |
| 251 | trajectory_logging_builder.add_left_velocity(goal_state(3)); |
| 252 | trajectory_logging_builder.add_right_velocity(goal_state(4)); |
Alex Perry | e32eabc | 2019-02-08 19:51:19 -0800 | [diff] [blame] | 253 | } |
Alex Perry | cb7da4b | 2019-08-28 19:35:56 -0700 | [diff] [blame^] | 254 | trajectory_logging_builder.add_planning_state(plan_state_.load()); |
| 255 | trajectory_logging_builder.add_is_executing(!IsAtEnd() && |
| 256 | has_started_execution_); |
| 257 | trajectory_logging_builder.add_is_executed((current_spline_idx_ != -1) && |
| 258 | IsAtEnd()); |
| 259 | trajectory_logging_builder.add_goal_spline_handle(current_spline_handle_); |
| 260 | trajectory_logging_builder.add_current_spline_idx(current_spline_idx_); |
| 261 | trajectory_logging_builder.add_distance_remaining( |
| 262 | current_trajectory_ ? current_trajectory_->length() - current_xva_.x() |
| 263 | : 0.0); |
| 264 | |
| 265 | int32_t planning_spline_idx = planning_spline_idx_; |
| 266 | if (current_spline_idx_ == planning_spline_idx) { |
| 267 | trajectory_logging_builder.add_planning_spline_idx(0); |
| 268 | } else { |
| 269 | trajectory_logging_builder.add_planning_spline_idx(planning_spline_idx_); |
| 270 | } |
| 271 | return trajectory_logging_builder.Finish(); |
| 272 | } |
| 273 | |
| 274 | flatbuffers::Offset<TrajectoryLogging> SplineDrivetrain::MakeTrajectoryLogging( |
| 275 | aos::Sender<drivetrain::Status>::Builder *builder) const { |
| 276 | return MakeTrajectoryLogging(builder->fbb()); |
Alex Perry | e32eabc | 2019-02-08 19:51:19 -0800 | [diff] [blame] | 277 | } |
| 278 | |
Alex Perry | 731b460 | 2019-02-02 22:13:01 -0800 | [diff] [blame] | 279 | } // namespace drivetrain |
| 280 | } // namespace control_loops |
| 281 | } // namespace frc971 |