TinyRobotics
Loading...
Searching...
No Matches
CameraEdgeFollower.h
1
2#pragma once
3#include <stddef.h>
4#include <stdint.h>
5
6#include "TinyRobotics/communication/Message.h"
7#include "TinyRobotics/communication/MessageSource.h"
8
9namespace tinyrobotics {
10
11/**
12 * @class CameraEdgeFollower
13 * @ingroup sensors
14 * @brief Simple edge-following algorithm for grayscale camera images.
15 *
16 * This class scans a horizontal row of a grayscale image (e.g., from a line or
17 * edge sensor) to detect the strongest edge (sharpest intensity change) using a
18 * threshold. It is useful for basic line-following or edge-detection robots.
19 *
20 * Features:
21 * - Scans a row near the bottom of the image for the most prominent edge
22 * - Returns the x position of the detected edge and error from image center
23 * - Configurable edge threshold for noise rejection
24 * - Lightweight, suitable for embedded/Arduino use
25 *
26 * @note Expected format:
27 * - The input image should be a grayscale buffer (uint8_t*)
28 * - The pixel intensity is expected to be in the range 0 (black) to 255
29 * (white).
30 * - The layout of the image buffer should be row-major (i.e., pixel at (x,y) is
31 * at index y*width + x).
32 * - on ESP32 e.g. PIXFORMAT_GRAYSCALE, FRAMESIZE_QVGA (320 x 240)
33 *
34 * Usage Example:
35 * @code
36 * CameraEdgeFollower follower(30); // threshold = 30
37 * auto result = follower.process(image, width, height);
38 * if (result.found) {
39 * // Use result.position or result.error for steering
40 * }
41 * @endcode
42 */
43
44class CameraEdgeFollower : public MessageSource {
45 public:
46 struct Result {
47 bool found;
48 int position; // x position of edge
49 int error; // deviation from center
50 };
51
52 CameraEdgeFollower(uint8_t threshold = 20) : _threshold(threshold) {}
53
54 Result process(const uint8_t* image, size_t width, size_t height) {
55 if (!image || width < 2 || height == 0) {
56 return {false, 0, 0};
57 }
58
59 // Scan one row near bottom (where obstacles are closer)
60 size_t y = (height * 3) / 4;
61
62 int best_x = -1;
63 int max_edge = 0;
64
65 for (size_t x = 0; x < width - 1; x++) {
66 uint8_t p1 = image[y * width + x];
67 uint8_t p2 = image[y * width + x + 1];
68
69 int diff = abs((int)p1 - (int)p2);
70
71 if (diff > _threshold && diff > max_edge) {
72 max_edge = diff;
73 best_x = x;
74 }
75 }
76
77 if (best_x < 0) {
78 return {false, 0, 0};
79 }
80
81 int center = width / 2;
82 int error = best_x - center;
83
84 // publish angle to direction of movement
85 Message<float> msgError(MessageContent::Error, error, Unit::Pixel);
86 msgError.origin = MessageOrigin::Camera;
87 sendMessage(msgError);
88
89 return {true, best_x, error};
90 }
91
92 protected:
93 uint8_t _threshold;
94};
95
96} // namespace tinyrobotics
Simple edge-following algorithm for grayscale camera images.
Definition: CameraEdgeFollower.h:44
Base class for message sources in the TinyRobotics communication framework.
Definition: MessageSource.h:35
Definition: CameraEdgeFollower.h:46
Generic message structure for communication, parameterized by value type.
Definition: Message.h:72