Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/camera/camera.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,6 @@ class ICamera {
[[nodiscard]] virtual auto GetCameraConstant() const -> camera_constant_t = 0;
virtual auto IsDone() -> bool { return false; }
virtual ~ICamera() = default;
virtual void Grab() = 0;
};
} // namespace camera
11 changes: 7 additions & 4 deletions src/camera/cv_camera.cc
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,6 @@ CVCamera::CVCamera(const CameraConstant& c, std::optional<std::string> log_path)
auto CVCamera::GetFrame() -> timestamped_frame_t {
timestamped_frame_t timestamped_frame;
cv::Mat raw_image;
if (!cap_.grab()) {
Restart();
LOG(WARNING) << "Restarting camera";
}
timestamped_frame.timestamp = frc::Timer::GetFPGATimestamp().to<double>();
cap_.retrieve(raw_image);

Expand All @@ -96,6 +92,13 @@ auto CVCamera::Restart() -> void {
std::this_thread::sleep_for(std::chrono::seconds(3));
}

auto CVCamera::Grab() -> void {
if (!cap_.grab()) {
Restart();
LOG(WARNING) << "Restarting camera";
cap_timestamp_ = frc::Timer::GetFPGATimestamp().to<double>();
}

auto CVCamera::GetCameraConstant() const -> camera_constant_t {
return camera_constant_;
}
Expand Down
2 changes: 2 additions & 0 deletions src/camera/cv_camera.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ class CVCamera : public ICamera {
std::optional<std::string> log_path = std::nullopt);
auto GetFrame() -> timestamped_frame_t override;
auto Restart() -> void override;
auto Grab() -> void override;
[[nodiscard]] auto GetCameraConstant() const -> camera_constant_t override;

private:
Expand All @@ -21,6 +22,7 @@ class CVCamera : public ICamera {
std::string pipeline_;
std::optional<std::string> log_path_;
cv::Mat backup_image_;
double cap_timestamp_;
};

} // namespace camera
2 changes: 2 additions & 0 deletions src/camera/disk_camera.cc
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ auto DiskCamera::GetFrame() -> timestamped_frame_t {

auto DiskCamera::Restart() -> void {}

auto DiskCamera::Grab() -> void {}

auto DiskCamera::GetCameraConstant() const -> camera_constant_t {
return *camera_constant_;
}
Expand Down
1 change: 1 addition & 0 deletions src/camera/disk_camera.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ class DiskCamera : public ICamera {
std::optional<double> end = std::nullopt);
auto GetFrame() -> timestamped_frame_t override;
auto Restart() -> void override;
auto Grab() -> void override;
auto IsDone() -> bool override { return image_paths_.empty(); }
[[nodiscard]] auto GetCameraConstant() const -> camera_constant_t override;

Expand Down
3 changes: 3 additions & 0 deletions src/test/integration_test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,6 @@ target_link_libraries(pva_test PRIVATE utils localization vpi)

add_executable(bfs-test bfs_tester.cc)
target_link_libraries(bfs-test PRIVATE pathing utils nlohmann_json::nlohmann_json wpiutil)

add_executable(libjpeg-benchmark libjpeg_benchmark.cc)
target_link_libraries(libjpeg-benchmark PRIVATE ${OpenCV_LIBS} utils)
63 changes: 63 additions & 0 deletions src/test/integration_test/libjpeg_benchmark.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#include <chrono>
#include <iterator>
#include <numeric>
#include "absl/flags/flag.h"
#include "absl/flags/internal/flag.h"
#include "absl/flags/parse.h"
Comment thread
nanoticity marked this conversation as resolved.
Comment thread
nanoticity marked this conversation as resolved.
#include "src/utils/log.h"
#include "src/utils/pch.h"
#include <sstream>

ABSL_FLAG(std::string, image_path, "path/to/image.jpg", // NOLINT
"Path to the image file to be loaded and decoded.");

ABSL_FLAG(uint, num_trials, 10000, "Number of decoding trials to perform."); // NOLINT

auto loadImage(const std::string& path) -> std::vector<uchar> {
std::ifstream file(path, std::ios::binary);
if (!file) {
LOG(FATAL) << "Image could not be loaded from path '" << path
<< "'; path invalid or image doesn't exist.";
}
std::vector<uchar> data(std::istreambuf_iterator<char>(file), {});
return data;
}

auto decodeImage(const std::vector<uchar>& raw) -> cv::Mat {
cv::Mat decoded = cv::imdecode(raw, cv::IMREAD_COLOR);
return decoded;
}

auto main(int argc, char** argv) -> int {
absl::ParseCommandLine(argc, argv);
std::string imagePath = absl::GetFlag(FLAGS_image_path);
std::vector<uchar> rawImageData = loadImage(imagePath);
// print which jpeg library we are using so that we know and don't get mixed up
std::istringstream stream(cv::getBuildInformation());
std::string line;
while (std::getline(stream, line)) {
if (line.find("jpeg:") != std::string::npos ||
line.find("JPEG:") != std::string::npos) {
LOG(INFO) << line;
}
}
const uint tests = absl::GetFlag(FLAGS_num_trials);
std::vector<double> trials;
for (uint i = 0; i < tests; ++i) {
auto start = std::chrono::high_resolution_clock::now();
cv::Mat decodedImage = decodeImage(rawImageData);
auto end = std::chrono::high_resolution_clock::now();
if (decodedImage.empty()) {
LOG(INFO) << "image decode failed";
continue;
}
double ms = std::chrono::duration<double, std::milli>(end - start).count();
trials.push_back(ms);
}
Comment thread
nanoticity marked this conversation as resolved.

double total = std::accumulate(trials.begin(), trials.end(), 0.0);
double average = total / trials.size();
LOG(INFO) << "Average decoding time over " << tests << " trials: " << average
<< " ms";
Comment on lines +58 to +61
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The average calculation uses trials.size(), but the log message reports tests as the number of trials. Also, if all decodes fail then trials will be empty and the average will print as NaN. Consider logging the actual successful decode count and handling the empty case explicitly (e.g., LOG(FATAL) or early return).

Suggested change
double total = std::accumulate(trials.begin(), trials.end(), 0.0);
double average = total / trials.size();
LOG(INFO) << "Average decoding time over " << tests << " trials: " << average
<< " ms";
const size_t successful_decodes = trials.size();
if (successful_decodes == 0) {
LOG(FATAL) << "All " << tests << " image decode attempts failed.";
}
double total = std::accumulate(trials.begin(), trials.end(), 0.0);
double average = total / successful_decodes;
LOG(INFO) << "Average decoding time over " << successful_decodes
<< " successful trials: " << average << " ms";

Copilot uses AI. Check for mistakes.
return 0;
}
Loading