Add more debug information to 2022 localizer
Adds data in a similar format to 2020's LocalizerDebug message,
specifically intended for consumption by live debugging webpages
where attempting to send large 2 kHz messages (the normal
LocalizerStatus) may not work well, especially on the real field.
Change-Id: I747b66668567760a42c77653e2d8c05b0ebfa4f3
Signed-off-by: James Kuszmaul <jabukuszmaul+collab@gmail.com>
diff --git a/y2022/localizer/localizer.h b/y2022/localizer/localizer.h
index 978eb15..4b7eff0 100644
--- a/y2022/localizer/localizer.h
+++ b/y2022/localizer/localizer.h
@@ -4,6 +4,7 @@
#include "Eigen/Dense"
#include "Eigen/Geometry"
#include "aos/containers/ring_buffer.h"
+#include "aos/containers/sized_array.h"
#include "aos/events/event_loop.h"
#include "aos/network/message_bridge_server_generated.h"
#include "aos/time/time.h"
@@ -15,6 +16,7 @@
#include "y2022/control_loops/superstructure/superstructure_status_generated.h"
#include "y2022/localizer/localizer_output_generated.h"
#include "y2022/localizer/localizer_status_generated.h"
+#include "y2022/localizer/localizer_visualization_generated.h"
#include "y2022/vision/target_estimate_generated.h"
namespace frc971::controls {
@@ -95,6 +97,8 @@
// ~20 gives ~55-60% CPU.
static constexpr int kBranchPeriod = 100;
+ static constexpr size_t kDebugBufferSize = 10;
+
typedef Eigen::Matrix<double, kNModelStates, 1> ModelState;
typedef Eigen::Matrix<double, kNAccelStates, 1> AccelState;
typedef Eigen::Matrix<double, kNModelInputs, 1> ModelInput;
@@ -108,7 +112,8 @@
void HandleTurret(aos::monotonic_clock::time_point sample_time,
double turret_position, double turret_velocity);
void HandleImageMatch(aos::monotonic_clock::time_point sample_time,
- const y2022::vision::TargetEstimate *target);
+ const y2022::vision::TargetEstimate *target,
+ int camera_index);
void HandleReset(aos::monotonic_clock::time_point,
const Eigen::Vector3d &xytheta);
@@ -129,10 +134,12 @@
void set_longitudinal_offset(double offset) { long_offset_ = offset; }
- void TallyRejection(const RejectionReason reason) {
- statistics_.total_candidates++;
- statistics_.rejection_counts[static_cast<size_t>(reason)]++;
- }
+ void TallyRejection(const RejectionReason reason);
+
+ flatbuffers::Offset<LocalizerVisualization> PopulateVisualization(
+ flatbuffers::FlatBufferBuilder *fbb);
+
+ size_t NumQueuedImageDebugs() const { return image_debugs_.size(); }
private:
struct CombinedState {
@@ -197,9 +204,17 @@
// Returns the robot x/y position implied by the specified camera data and
// estimated state from that time.
+ // H_field_camera is passed in so that it can be used as a debugging output.
const std::optional<Eigen::Vector2d> CameraMeasuredRobotPosition(
const OldPosition &state, const y2022::vision::TargetEstimate *target,
- std::optional<RejectionReason> *rejection_reason) const;
+ std::optional<RejectionReason> *rejection_reason,
+ Eigen::Matrix<double, 4, 4> *H_field_camera_measured) const;
+
+ flatbuffers::Offset<TargetEstimateDebug> PackTargetEstimateDebug(
+ const TargetEstimateDebugT &debug, flatbuffers::FlatBufferBuilder *fbb);
+
+ flatbuffers::Offset<CumulativeStatistics> PopulateStatistics(
+ flatbuffers::FlatBufferBuilder *fbb);
const control_loops::drivetrain::DrivetrainConfig<double> dt_config_;
const StateFeedbackHybridPlantCoefficients<2, 2, 2, double>
@@ -282,11 +297,15 @@
};
Statistics statistics_;
+ aos::SizedArray<TargetEstimateDebugT, kDebugBufferSize> image_debugs_;
+
friend class testing::LocalizerTest;
};
class EventLoopLocalizer {
public:
+ static constexpr std::chrono::milliseconds kMinVisualizationPeriod{100};
+
EventLoopLocalizer(
aos::EventLoop *event_loop,
const control_loops::drivetrain::DrivetrainConfig<double> &dt_config);
@@ -300,11 +319,14 @@
ModelBasedLocalizer model_based_;
aos::Sender<LocalizerStatus> status_sender_;
aos::Sender<LocalizerOutput> output_sender_;
+ aos::Sender<LocalizerVisualization> visualization_sender_;
aos::Fetcher<frc971::control_loops::drivetrain::Output> output_fetcher_;
aos::Fetcher<aos::message_bridge::ServerStatistics> clock_offset_fetcher_;
zeroing::ImuZeroer zeroer_;
aos::monotonic_clock::time_point last_output_send_ =
aos::monotonic_clock::min_time;
+ aos::monotonic_clock::time_point last_visualization_send_ =
+ aos::monotonic_clock::min_time;
std::optional<aos::monotonic_clock::time_point> last_pico_timestamp_;
aos::monotonic_clock::duration pico_offset_error_;
// t = pico_offset_ + pico_timestamp.