From 91535f73a0c2125b9c5dcb7769a318e64f9b7a3d Mon Sep 17 00:00:00 2001 From: MaticTonin Date: Tue, 13 Jan 2026 15:12:30 +0100 Subject: [PATCH 1/2] Unify that DepthUnits.hpp is used in every node --- src/device/CalibrationHandler.cpp | 3 +- src/pipeline/node/host/RGBD.cpp | 24 ++------------- tests/CMakeLists.txt | 4 +++ tests/src/onhost_tests/depth_unit_test.cpp | 35 ++++++++++++++++++++++ 4 files changed, 44 insertions(+), 22 deletions(-) create mode 100644 tests/src/onhost_tests/depth_unit_test.cpp diff --git a/src/device/CalibrationHandler.cpp b/src/device/CalibrationHandler.cpp index c5779e80b1..f19e4ba647 100644 --- a/src/device/CalibrationHandler.cpp +++ b/src/device/CalibrationHandler.cpp @@ -11,6 +11,7 @@ #include #include "depthai/common/CameraInfo.hpp" +#include "depthai/common/DepthUnit.hpp" #include "depthai/common/Extrinsics.hpp" #include "depthai/common/HousingCoordinateSystem.hpp" #include "depthai/common/Point3f.hpp" @@ -539,7 +540,7 @@ std::vector> CalibrationHandler::getHousingToHousingOrigin(co bool useSpecTranslation, CameraBoardSocket& originSocket) const { // Define scale parameter for mm to cm conversion - constexpr float MM_TO_CM_SCALE = 10.0f; + constexpr float MM_TO_CM_SCALE = getDepthUnitMultiplier(DepthUnit::MILLIMETER) / getDepthUnitMultiplier(DepthUnit::CENTIMETER); const Extrinsics& housingExtrinsics = eepromData.housingExtrinsics; diff --git a/src/pipeline/node/host/RGBD.cpp b/src/pipeline/node/host/RGBD.cpp index 8e5961dc77..e30ed270c1 100644 --- a/src/pipeline/node/host/RGBD.cpp +++ b/src/pipeline/node/host/RGBD.cpp @@ -7,6 +7,7 @@ #include "common/CameraFeatures.hpp" #include "common/CameraSensorType.hpp" #include "common/Point3fRGBA.hpp" +#include "depthai/common/DepthUnit.hpp" #include "depthai/common/Point3fRGBA.hpp" #include "depthai/pipeline/Pipeline.hpp" #include "depthai/pipeline/datatype/ImgFrame.hpp" @@ -48,27 +49,8 @@ class RGBD::Impl { } } void setDepthUnit(StereoDepthConfig::AlgorithmControl::DepthUnit depthUnit) { - // Default is millimeter - switch(depthUnit) { - case StereoDepthConfig::AlgorithmControl::DepthUnit::MILLIMETER: - scaleFactor = 1.0f; - break; - case StereoDepthConfig::AlgorithmControl::DepthUnit::METER: - scaleFactor = 0.001f; - break; - case StereoDepthConfig::AlgorithmControl::DepthUnit::CENTIMETER: - scaleFactor = 0.01f; - break; - case StereoDepthConfig::AlgorithmControl::DepthUnit::FOOT: - scaleFactor = 0.3048f; - break; - case StereoDepthConfig::AlgorithmControl::DepthUnit::INCH: - scaleFactor = 0.0254f; - break; - case StereoDepthConfig::AlgorithmControl::DepthUnit::CUSTOM: - scaleFactor = 1.0f; - break; - } + const float unitPerMeter = getDepthUnitMultiplier(depthUnit); + scaleFactor = unitPerMeter > 0.0f ? (1.0f / unitPerMeter) : 1.0f; } void printDevices() { #ifdef DEPTHAI_ENABLE_KOMPUTE diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index c7b18f0628..e67af2211e 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -387,6 +387,10 @@ dai_set_test_labels(image_transformations_test onhost ci) dai_add_test(normalization_test src/onhost_tests/normalization_test.cpp) dai_set_test_labels(normalization_test onhost ci) +# Depth unit tests +dai_add_test(depth_unit_test src/onhost_tests/depth_unit_test.cpp) +dai_set_test_labels(depth_unit_test onhost ci) + # MessageQueue tests dai_add_test(message_queue_test src/onhost_tests/message_queue_test.cpp) dai_set_test_labels(message_queue_test onhost ci) diff --git a/tests/src/onhost_tests/depth_unit_test.cpp b/tests/src/onhost_tests/depth_unit_test.cpp new file mode 100644 index 0000000000..10b9e3d6d4 --- /dev/null +++ b/tests/src/onhost_tests/depth_unit_test.cpp @@ -0,0 +1,35 @@ +#define CATCH_CONFIG_MAIN +#include +#include + +namespace { + +float toUnit(float meters, dai::DepthUnit unit) { + return meters * dai::getDepthUnitMultiplier(unit); +} + +float toMeters(float value, dai::DepthUnit unit) { + return value / dai::getDepthUnitMultiplier(unit); +} + +} // namespace + +TEST_CASE("DepthUnit multipliers", "[DepthUnit]") { + REQUIRE(dai::getDepthUnitMultiplier(dai::DepthUnit::METER) == Catch::Approx(1.0f)); + REQUIRE(dai::getDepthUnitMultiplier(dai::DepthUnit::CENTIMETER) == Catch::Approx(100.0f)); + REQUIRE(dai::getDepthUnitMultiplier(dai::DepthUnit::MILLIMETER) == Catch::Approx(1000.0f)); + REQUIRE(dai::getDepthUnitMultiplier(dai::DepthUnit::INCH) == Catch::Approx(39.3701f)); + REQUIRE(dai::getDepthUnitMultiplier(dai::DepthUnit::FOOT) == Catch::Approx(3.28084f)); + REQUIRE(dai::getDepthUnitMultiplier(dai::DepthUnit::CUSTOM) == Catch::Approx(1.0f)); +} + +TEST_CASE("DepthUnit conversions", "[DepthUnit]") { + constexpr float depthMeters = 2.5f; + + REQUIRE(toUnit(depthMeters, dai::DepthUnit::CENTIMETER) == Catch::Approx(250.0f)); + REQUIRE(toUnit(depthMeters, dai::DepthUnit::MILLIMETER) == Catch::Approx(2500.0f)); + REQUIRE(toUnit(depthMeters, dai::DepthUnit::FOOT) == Catch::Approx(8.2021f)); + + constexpr float depthMm = 750.0f; + REQUIRE(toMeters(depthMm, dai::DepthUnit::MILLIMETER) == Catch::Approx(0.75f)); +} From 1e8bb4208852744e97b18d85e559af01d52da44f Mon Sep 17 00:00:00 2001 From: MaticTonin Date: Tue, 13 Jan 2026 18:42:04 +0100 Subject: [PATCH 2/2] Adding missing docs and check for formatting --- ci/check_format.sh | 4 + include/depthai/basalt/BasaltVIO.hpp | 4 + include/depthai/common/ImgTransformations.hpp | 30 +++ include/depthai/common/Keypoint.hpp | 10 + include/depthai/common/KeypointsListT.hpp | 31 +++ include/depthai/common/Point2f.hpp | 9 + include/depthai/common/Point3d.hpp | 3 + include/depthai/common/Point3f.hpp | 3 + include/depthai/common/Quaterniond.hpp | 3 + include/depthai/common/Rect.hpp | 21 ++ include/depthai/common/RotatedRect.hpp | 13 + include/depthai/device/BoardConfig.hpp | 8 + include/depthai/device/CalibrationHandler.hpp | 1 + include/depthai/device/CallbackHandler.hpp | 1 + include/depthai/device/CrashDump.hpp | 1 + include/depthai/device/DeviceBootloader.hpp | 1 + include/depthai/device/Version.hpp | 3 +- include/depthai/pipeline/AssetManager.hpp | 18 ++ include/depthai/pipeline/Assets.hpp | 15 ++ include/depthai/pipeline/DeviceNode.hpp | 19 ++ include/depthai/pipeline/DeviceNodeGroup.hpp | 12 + include/depthai/pipeline/MessageQueue.hpp | 15 ++ include/depthai/pipeline/Node.hpp | 76 +++++- include/depthai/pipeline/Pipeline.hpp | 109 +++++++- include/depthai/pipeline/PipelineStateApi.hpp | 72 ++++++ include/depthai/pipeline/Subnode.hpp | 11 +- include/depthai/pipeline/ThreadedHostNode.hpp | 3 + include/depthai/pipeline/ThreadedNode.hpp | 18 ++ .../depthai/pipeline/datatype/ADatatype.hpp | 3 + include/depthai/pipeline/datatype/Buffer.hpp | 9 + .../pipeline/datatype/CameraControl.hpp | 9 + .../datatype/DynamicCalibrationControl.hpp | 24 ++ .../pipeline/datatype/ImageManipConfig.hpp | 155 ++++++++++- .../pipeline/datatype/ImgAnnotations.hpp | 3 + .../pipeline/datatype/ImgDetections.hpp | 12 + .../pipeline/datatype/ImgDetectionsT.hpp | 12 +- .../depthai/pipeline/datatype/ImgFrame.hpp | 9 + .../pipeline/datatype/MessageGroup.hpp | 14 +- include/depthai/pipeline/datatype/NNData.hpp | 51 ++++ .../pipeline/datatype/PipelineState.hpp | 9 + .../pipeline/datatype/PointCloudData.hpp | 30 +++ .../depthai/pipeline/datatype/RGBDData.hpp | 12 + .../pipeline/datatype/StreamMessageParser.hpp | 12 + .../pipeline/datatype/TransformData.hpp | 18 ++ include/depthai/pipeline/node/AprilTag.hpp | 3 + .../pipeline/node/DetectionNetwork.hpp | 11 +- .../depthai/pipeline/node/DetectionParser.hpp | 9 +- .../depthai/pipeline/node/EdgeDetector.hpp | 3 + .../depthai/pipeline/node/FeatureTracker.hpp | 3 + include/depthai/pipeline/node/IMU.hpp | 5 +- include/depthai/pipeline/node/ImageManip.hpp | 6 + .../pipeline/node/NeuralAssistedStereo.hpp | 3 + include/depthai/pipeline/node/NeuralDepth.hpp | 3 + .../pipeline/node/SpatialDetectionNetwork.hpp | 12 + .../node/SpatialLocationCalculator.hpp | 3 + include/depthai/pipeline/node/StereoDepth.hpp | 3 + include/depthai/pipeline/node/Thermal.hpp | 6 + include/depthai/pipeline/node/ToF.hpp | 6 + include/depthai/pipeline/node/UVC.hpp | 3 + .../depthai/pipeline/node/VideoEncoder.hpp | 6 + include/depthai/pipeline/node/Vpp.hpp | 6 + include/depthai/pipeline/node/Warp.hpp | 6 + .../depthai/pipeline/node/host/Display.hpp | 5 +- .../depthai/pipeline/node/host/HostNode.hpp | 6 + include/depthai/pipeline/node/host/RGBD.hpp | 9 + include/depthai/pipeline/node/host/Record.hpp | 33 +++ include/depthai/pipeline/node/host/Replay.hpp | 57 +++++ include/depthai/rtabmap/RTABMapSLAM.hpp | 6 + include/depthai/rtabmap/RTABMapVIO.hpp | 3 + include/depthai/xlink/XLinkConnection.hpp | 33 +++ include/depthai/xlink/XLinkStream.hpp | 101 ++++++++ scripts/check_public_docs.py | 242 ++++++++++++++++++ 72 files changed, 1450 insertions(+), 38 deletions(-) create mode 100644 scripts/check_public_docs.py diff --git a/ci/check_format.sh b/ci/check_format.sh index eb184bf31f..c6c354deeb 100755 --- a/ci/check_format.sh +++ b/ci/check_format.sh @@ -1,8 +1,12 @@ #!/bin/bash +set -euo pipefail # Perform code format (cmake target) cmake --build "$1" --target clangformat +# Check for missing public API docs (non-zero exit fails CI) +python3 scripts/check_public_docs.py + # Display diff git --no-pager diff diff --git a/include/depthai/basalt/BasaltVIO.hpp b/include/depthai/basalt/BasaltVIO.hpp index 05bd62198b..d034d327b9 100644 --- a/include/depthai/basalt/BasaltVIO.hpp +++ b/include/depthai/basalt/BasaltVIO.hpp @@ -23,6 +23,7 @@ namespace node { class BasaltVIO : public NodeCRTP { public: constexpr static const char* NAME = "BasaltVIO"; + /// Create a Basalt VIO node. BasaltVIO(); ~BasaltVIO(); @@ -59,12 +60,15 @@ class BasaltVIO : public NodeCRTP { * VIO configuration file. */ basalt::VioConfig vioConfig; + /// Set IMU update rate in Hz. void setImuUpdateRate(int rate) { imuUpdateRate = rate; } + /// Set path to the VIO configuration file. void setConfigPath(const std::string& path) { configPath = path; } + /// Use spec translation for camera-to-IMU extrinsics if available. void setUseSpecTranslation(bool use) { useSpecTranslation = use; } diff --git a/include/depthai/common/ImgTransformations.hpp b/include/depthai/common/ImgTransformations.hpp index 62ba8bc27d..639cc56682 100644 --- a/include/depthai/common/ImgTransformations.hpp +++ b/include/depthai/common/ImgTransformations.hpp @@ -152,6 +152,10 @@ struct ImgTransformation { */ float getVFov(bool source = false) const; + /** + * Retrieve currently set source crop rectangles. + * @return Vector of source crops + */ std::vector getSrcCrops() const; /** @@ -204,11 +208,37 @@ struct ImgTransformation { * @param scaleY Scale factor in the vertical direction */ ImgTransformation& addScale(float scaleX, float scaleY); + /** + * Append source crop rectangles. + * @param crops Vector of source crops to add + */ ImgTransformation& addSrcCrops(const std::vector& crops); + /** + * Set output image size. + * @param width Output width + * @param height Output height + */ ImgTransformation& setSize(size_t width, size_t height); + /** + * Set input image size. + * @param width Input width + * @param height Input height + */ ImgTransformation& setSourceSize(size_t width, size_t height); + /** + * Set source intrinsic matrix. + * @param intrinsicMatrix 3x3 intrinsic matrix + */ ImgTransformation& setIntrinsicMatrix(std::array, 3> intrinsicMatrix); + /** + * Set the source distortion model. + * @param model Distortion model + */ ImgTransformation& setDistortionModel(CameraModel model); + /** + * Set the source distortion coefficients. + * @param coefficients Distortion coefficients + */ ImgTransformation& setDistortionCoefficients(std::vector coefficients); /** diff --git a/include/depthai/common/Keypoint.hpp b/include/depthai/common/Keypoint.hpp index 5d0959352f..c78345e8c3 100644 --- a/include/depthai/common/Keypoint.hpp +++ b/include/depthai/common/Keypoint.hpp @@ -19,6 +19,10 @@ struct Keypoint { std::string labelName = ""; Keypoint() = default; + /** + * Construct a keypoint from 3D image coordinates. + * @throws std::invalid_argument if confidence is negative. + */ explicit Keypoint(Point3f imageCoordinates, float conf = 0.f, uint32_t label = 0, std::string labelName = "") : imageCoordinates(imageCoordinates), confidence(conf), label(label), labelName(labelName) { if(confidence < 0.f) { @@ -26,9 +30,15 @@ struct Keypoint { } } + /** + * Construct a keypoint from 2D image coordinates (z = 0). + */ explicit Keypoint(Point2f imageCoordinates, float confidence = 0.f, uint32_t label = 0, std::string labelName = "") : Keypoint(Point3f{imageCoordinates.x, imageCoordinates.y, 0.f}, confidence, label, labelName) {} + /** + * Construct a keypoint from explicit x/y/z coordinates. + */ explicit Keypoint(float x, float y, float z, float confidence = 0.f, uint32_t label = 0, std::string labelName = "") : Keypoint(Point3f{x, y, z}, confidence, label, labelName) {} diff --git a/include/depthai/common/KeypointsListT.hpp b/include/depthai/common/KeypointsListT.hpp index f271c9ce01..b4dec75c70 100644 --- a/include/depthai/common/KeypointsListT.hpp +++ b/include/depthai/common/KeypointsListT.hpp @@ -18,9 +18,16 @@ struct KeypointsListT { public: KeypointsListT() = default; + /** + * Construct with keypoints and edges. + * @throws std::runtime_error if any edge index is out of range. + */ explicit KeypointsListT(std::vector keypoints, std::vector edges) : keypoints(std::move(keypoints)), edges(std::move(edges)) { validateEdges(); } + /** + * Construct with keypoints only (no edges). + */ explicit KeypointsListT(std::vector keypoints) : keypoints(std::move(keypoints)) {} ~KeypointsListT() = default; @@ -32,28 +39,52 @@ struct KeypointsListT { using iterator = typename std::vector::iterator; using const_iterator = typename std::vector::const_iterator; + /** + * Iterator to the first keypoint. + */ iterator begin() noexcept { return keypoints.begin(); } + /** + * Iterator to one-past-the-last keypoint. + */ iterator end() noexcept { return keypoints.end(); } + /** + * Const iterator to the first keypoint. + */ const_iterator begin() const noexcept { return keypoints.begin(); } + /** + * Const iterator to one-past-the-last keypoint. + */ const_iterator end() const noexcept { return keypoints.end(); } + /** + * Const iterator to the first keypoint. + */ const_iterator cbegin() const noexcept { return keypoints.cbegin(); } + /** + * Const iterator to one-past-the-last keypoint. + */ const_iterator cend() const noexcept { return keypoints.cend(); } + /** + * Return true if the list is empty. + */ bool empty() const noexcept { return keypoints.empty(); } + /** + * Return the number of keypoints. + */ size_t size() const noexcept { return keypoints.size(); } diff --git a/include/depthai/common/Point2f.hpp b/include/depthai/common/Point2f.hpp index 2888635a50..00b17a792e 100644 --- a/include/depthai/common/Point2f.hpp +++ b/include/depthai/common/Point2f.hpp @@ -15,11 +15,17 @@ namespace dai { */ struct Point2f { Point2f() = default; + /** + * Construct a 2D point with explicit coordinates. + */ Point2f(float x, float y) { this->x = x; this->y = y; this->hasNormalized = false; } + /** + * Construct a 2D point and explicitly mark normalization. + */ Point2f(float x, float y, bool normalized) { this->x = x; this->y = y; @@ -30,6 +36,9 @@ struct Point2f { bool normalized = false; bool hasNormalized = false; + /** + * Return whether the point is normalized to [0,1]. + */ bool isNormalized() const { if(hasNormalized) { return normalized; diff --git a/include/depthai/common/Point3d.hpp b/include/depthai/common/Point3d.hpp index fe90bf5810..94653bf0ee 100644 --- a/include/depthai/common/Point3d.hpp +++ b/include/depthai/common/Point3d.hpp @@ -15,6 +15,9 @@ namespace dai { */ struct Point3d { Point3d() = default; + /** + * Construct a 3D point from coordinates. + */ Point3d(double x, double y, double z) : x(x), y(y), z(z) {} double x = 0, y = 0, z = 0; }; diff --git a/include/depthai/common/Point3f.hpp b/include/depthai/common/Point3f.hpp index e3bdf750a2..3e577404ab 100644 --- a/include/depthai/common/Point3f.hpp +++ b/include/depthai/common/Point3f.hpp @@ -15,6 +15,9 @@ namespace dai { */ struct Point3f { Point3f() = default; + /** + * Construct a 3D point from coordinates. + */ Point3f(float x, float y, float z) : x(x), y(y), z(z) {} float x = 0, y = 0, z = 0; }; diff --git a/include/depthai/common/Quaterniond.hpp b/include/depthai/common/Quaterniond.hpp index 4b461adf95..a1707b57cc 100644 --- a/include/depthai/common/Quaterniond.hpp +++ b/include/depthai/common/Quaterniond.hpp @@ -15,6 +15,9 @@ namespace dai { */ struct Quaterniond { Quaterniond() = default; + /** + * Construct a quaternion from components. + */ Quaterniond(double qx, double qy, double qz, double qw) : qx(qx), qy(qy), qz(qz), qw(qw) {} double qx = 0, qy = 0, qz = 0, qw = 1; }; diff --git a/include/depthai/common/Rect.hpp b/include/depthai/common/Rect.hpp index 23045047b7..8e6c45414d 100644 --- a/include/depthai/common/Rect.hpp +++ b/include/depthai/common/Rect.hpp @@ -18,15 +18,36 @@ namespace dai { struct Rect { // default constructor Rect() = default; + /** + * Construct a rectangle from top-left and size. + */ Rect(float x, float y, float width, float height) : x(x), y(y), width(width), height(height) {} + /** + * Construct a rectangle and explicitly mark normalization. + */ Rect(float x, float y, float width, float height, bool normalized) : x(x), y(y), width(width), height(height), normalized(normalized), hasNormalized(true) {} + /** + * Copy-construct a rectangle. + */ Rect(const Rect& r) : x(r.x), y(r.y), width(r.width), height(r.height), normalized(r.normalized), hasNormalized(r.hasNormalized) {} + /** + * Construct a rectangle from origin point and size. + */ Rect(const Point2f& org, const Size2f& sz) : x(org.x), y(org.y), width(sz.width), height(sz.height) {} + /** + * Construct a rectangle from origin point and size and explicit normalization. + */ Rect(const Point2f& org, const Size2f& sz, bool normalized) : x(org.x), y(org.y), width(sz.width), height(sz.height), normalized(normalized), hasNormalized(true) {} + /** + * Construct a rectangle from two corner points. + */ Rect(const Point2f& pt1, const Point2f& pt2) : x(std::min(pt1.x, pt2.x)), y(std::min(pt1.y, pt2.y)), width(std::max(pt1.x, pt2.x) - x), height(std::max(pt1.y, pt2.y) - y) {} + /** + * Construct a rectangle from two corner points with explicit normalization. + */ Rect(const Point2f& pt1, const Point2f& pt2, bool normalized) : x(std::min(pt1.x, pt2.x)), y(std::min(pt1.y, pt2.y)), diff --git a/include/depthai/common/RotatedRect.hpp b/include/depthai/common/RotatedRect.hpp index 7e2ea36b68..e523580430 100644 --- a/include/depthai/common/RotatedRect.hpp +++ b/include/depthai/common/RotatedRect.hpp @@ -19,21 +19,34 @@ struct RotatedRect { float angle = 0.f; RotatedRect() = default; + /** + * Construct a rotated rectangle from center/size and angle. + * @throws std::runtime_error if center and size normalization do not match. + */ RotatedRect(const Point2f& center, const Size2f& size, float angle) : center(center), size(size), angle(angle) { if(size.isNormalized() != center.isNormalized()) { throw std::runtime_error("Cannot create RotatedRect with mixed normalization"); } } + /** + * Construct a rotated rectangle from an axis-aligned rectangle and angle. + */ RotatedRect(const Rect& rect, float angle = 0.f) : center(rect.x + rect.width / 2.0f, rect.y + rect.height / 2.0f, rect.isNormalized()), size(rect.width, rect.height, rect.isNormalized()), angle(angle) {} + /** + * Convert to the outer axis-aligned rectangle. + */ operator Rect() const { const auto [minx, miny, maxx, maxy] = getOuterRect(); return Rect(minx, miny, maxx - minx, maxy - miny); } + /** + * Return whether coordinates are normalized to [0,1]. + */ bool isNormalized() const { if(size.isNormalized() != center.isNormalized()) { throw std::runtime_error("Cannot denormalize RotatedRect with mixed normalization"); diff --git a/include/depthai/device/BoardConfig.hpp b/include/depthai/device/BoardConfig.hpp index f9d55e79f8..0d98ba40c9 100644 --- a/include/depthai/device/BoardConfig.hpp +++ b/include/depthai/device/BoardConfig.hpp @@ -68,10 +68,15 @@ struct BoardConfig { Drive drive = MA_2; bool schmitt = false, slewFast = false; GPIO() = default; + /// Construct GPIO config with direction only. GPIO(Direction direction) : direction(direction) {} + /// Construct GPIO config with direction and level. GPIO(Direction direction, Level level) : direction(direction), level(level) {} + /// Construct GPIO config with direction, level, and pull. GPIO(Direction direction, Level level, Pull pull) : direction(direction), level(level), pull(pull) {} + /// Construct GPIO config with direction and mode. GPIO(Direction direction, Mode mode) : mode(mode), direction(direction) {} + /// Construct GPIO config with direction, mode, and pull. GPIO(Direction direction, Mode mode, Pull pull) : mode(mode), direction(direction), pull(pull) {} }; std::unordered_map gpio; @@ -138,6 +143,7 @@ struct BoardConfig { std::unordered_map camera; struct IMU { + /// Construct IMU config with default pin assignments. IMU() : bus(0), interrupt(53), wake(34), csGpio(8), boot(46), reset(45) {} int8_t bus, interrupt, wake, csGpio, boot, reset; }; @@ -149,7 +155,9 @@ struct BoardConfig { uint16_t width, height; ImgFrame::Type frameType; bool enable; + /// Construct UVC config with resolution; NV12 and enabled by default. UVC(uint16_t width, uint16_t height) : width(width), height(height), frameType(ImgFrame::Type::NV12), enable(true) {} + /// Construct UVC config with default 1920x1080 resolution. UVC() : UVC(1920, 1080) {} }; std::optional uvc; diff --git a/include/depthai/device/CalibrationHandler.hpp b/include/depthai/device/CalibrationHandler.hpp index 441b67d82a..ee1567568d 100644 --- a/include/depthai/device/CalibrationHandler.hpp +++ b/include/depthai/device/CalibrationHandler.hpp @@ -638,6 +638,7 @@ class CalibrationHandler { static constexpr bool value = false; }; template + /// RTABMap support required to access this API. void getRTABMapCameraModel(T...) { static_assert(dependent_false::value, "Library not configured with RTABMap support"); } diff --git a/include/depthai/device/CallbackHandler.hpp b/include/depthai/device/CallbackHandler.hpp index fbeb400c46..f8ce766dc1 100644 --- a/include/depthai/device/CallbackHandler.hpp +++ b/include/depthai/device/CallbackHandler.hpp @@ -18,6 +18,7 @@ class CallbackHandler { public: void setCallback(std::function(std::shared_ptr)> cb); + /// Create a handler for a stream with a processing callback. CallbackHandler(std::shared_ptr conn, const std::string& streamName, std::function(std::shared_ptr)> cb); diff --git a/include/depthai/device/CrashDump.hpp b/include/depthai/device/CrashDump.hpp index 91afb4cf5e..d6c2b77911 100644 --- a/include/depthai/device/CrashDump.hpp +++ b/include/depthai/device/CrashDump.hpp @@ -73,6 +73,7 @@ struct CrashDump { std::string depthaiCommitHash; std::string deviceId; + /// Serialize crash dump to JSON. nlohmann::json serializeToJson() const { std::vector data; utility::serialize(*this, data); diff --git a/include/depthai/device/DeviceBootloader.hpp b/include/depthai/device/DeviceBootloader.hpp index 17a01c50a3..b204622252 100644 --- a/include/depthai/device/DeviceBootloader.hpp +++ b/include/depthai/device/DeviceBootloader.hpp @@ -179,6 +179,7 @@ class DeviceBootloader { */ static std::vector getEmbeddedBootloaderBinary(Type type = DEFAULT_TYPE); + /// Default constructor is not available; a DeviceInfo is required. DeviceBootloader() = delete; /** diff --git a/include/depthai/device/Version.hpp b/include/depthai/device/Version.hpp index aa42ede004..1c173ee67c 100644 --- a/include/depthai/device/Version.hpp +++ b/include/depthai/device/Version.hpp @@ -25,6 +25,7 @@ struct Version { const std::optional& preReleaseVersion = std::nullopt, const std::string& buildInfo = ""); + /// Construct Version with build metadata and no pre-release tag. Version(unsigned major, unsigned minor, unsigned patch, const std::string& buildInfo) : Version(major, minor, patch, PreReleaseType::NONE, std::nullopt, buildInfo) {} bool operator==(const Version& other) const; @@ -54,4 +55,4 @@ struct Version { spimpl::impl_ptr pimpl; }; -} // namespace dai \ No newline at end of file +} // namespace dai diff --git a/include/depthai/pipeline/AssetManager.hpp b/include/depthai/pipeline/AssetManager.hpp index 1ddb8c95dc..a6427a4047 100644 --- a/include/depthai/pipeline/AssetManager.hpp +++ b/include/depthai/pipeline/AssetManager.hpp @@ -14,15 +14,24 @@ namespace dai { */ struct Asset { Asset() = default; + /** + * Construct an asset with a key. + */ explicit Asset(std::string k) : key(std::move(k)) {} const std::string key; std::vector data; std::uint32_t alignment = 1; + /** + * Return relative URI for this asset. + */ std::string getRelativeUri(); }; class AssetsMutable : public Assets { public: + /** + * Set asset metadata in the internal map. + */ void set(std::string, std::uint32_t offset, std::uint32_t size, std::uint32_t alignment); }; @@ -37,7 +46,13 @@ class AssetManager /*: public Assets*/ { std::string getRelativeKey(std::string key) const; public: + /** + * Construct an empty asset manager. + */ AssetManager(); + /** + * Construct an asset manager with a root path. + */ AssetManager(std::string rootPath); /** * Adds all assets in an array to the AssetManager @@ -92,6 +107,9 @@ class AssetManager /*: public Assets*/ { * @returns Shared pointer to asset */ std::shared_ptr set(const std::string& key, const std::vector& data, int alignment = 64); + /** + * Loads asset data under the specified key (move). + */ std::shared_ptr set(const std::string& key, std::vector&& data, int alignment = 64); /** diff --git a/include/depthai/pipeline/Assets.hpp b/include/depthai/pipeline/Assets.hpp index 8b44530335..b39a43f400 100644 --- a/include/depthai/pipeline/Assets.hpp +++ b/include/depthai/pipeline/Assets.hpp @@ -15,6 +15,9 @@ struct AssetView { std::uint8_t* data; std::uint32_t size; std::uint32_t alignment = 1; + /** + * Construct a view into asset data. + */ AssetView(std::uint8_t* d, std::uint32_t s, std::uint32_t a = 1) : data(d), size(s), alignment(a) {} }; @@ -32,19 +35,31 @@ class Assets { std::unordered_map map; public: + /** + * Set the backing storage for assets. + */ void setStorage(std::uint8_t* ps) { pStorageStart = ps; } + /** + * Return true if an asset key exists. + */ bool has(const std::string& key) { return (map.count(key) > 0); } + /** + * Get an asset view by key. + */ AssetView get(const std::string& key) { AssetInternal internal = map.at(key); return {pStorageStart + internal.offset, internal.size, internal.alignment}; } + /** + * Get all assets as key/view pairs. + */ std::vector> getAll() { std::vector> allAssets; for(const auto& kv : map) { diff --git a/include/depthai/pipeline/DeviceNode.hpp b/include/depthai/pipeline/DeviceNode.hpp index 41e654665e..f724babf18 100644 --- a/include/depthai/pipeline/DeviceNode.hpp +++ b/include/depthai/pipeline/DeviceNode.hpp @@ -13,11 +13,15 @@ class DeviceNode : public ThreadedNode { std::shared_ptr device; public: + /** Deleted default constructor. */ DeviceNode() = delete; virtual ~DeviceNode() = default; // virtual 'run' method virtual void run() override; + /** + * Indicates this node runs on the device by default. + */ bool runOnHost() const override { // By default, don't allow running on host, but can be overridden return false; @@ -33,9 +37,18 @@ class DeviceNode : public ThreadedNode { copyable_unique_ptr propertiesHolder; // Get properties + /** + * Return mutable properties for this node. + */ virtual Properties& getProperties(); + /** + * Set logging level for this node. + */ void setLogLevel(dai::LogLevel level) override; + /** + * Get current logging level for this node. + */ virtual dai::LogLevel getLogLevel() const override; protected: @@ -63,6 +76,9 @@ class DeviceNodeCRTP : public Base { virtual ~DeviceNodeCRTP() = default; /// Underlying properties Properties& properties; + /** + * Return the node name used by the pipeline. + */ const char* getName() const override { return Derived::NAME; }; @@ -71,6 +87,9 @@ class DeviceNodeCRTP : public Base { // }; // No public constructor, only a factory function. + /** + * Create and initialize a node instance. + */ template [[nodiscard]] static std::shared_ptr create(Args&&... args) { auto nodePtr = std::shared_ptr(new Derived(std::forward(args)...)); diff --git a/include/depthai/pipeline/DeviceNodeGroup.hpp b/include/depthai/pipeline/DeviceNodeGroup.hpp index a743275dec..2d73be10cb 100644 --- a/include/depthai/pipeline/DeviceNodeGroup.hpp +++ b/include/depthai/pipeline/DeviceNodeGroup.hpp @@ -9,6 +9,9 @@ namespace dai { class DeviceNodeGroup : public DeviceNode { public: + /** + * Return the node name used by the pipeline. + */ const char* getName() const final { return "DeviceNodeGroup"; } @@ -16,10 +19,19 @@ class DeviceNodeGroup : public DeviceNode { virtual ~DeviceNodeGroup(); using DeviceNode::DeviceNode; + /** + * Construct a device node group attached to a device. + */ DeviceNodeGroup(const std::shared_ptr& device) : DeviceNode(device, std::make_unique(), false) {} friend class PipelineImpl; + /** + * Set logging level for this node group. + */ void setLogLevel(dai::LogLevel level) override; + /** + * Get logging level for this node group. + */ dai::LogLevel getLogLevel() const override; }; diff --git a/include/depthai/pipeline/MessageQueue.hpp b/include/depthai/pipeline/MessageQueue.hpp index e3e37994bb..1673e3ea83 100644 --- a/include/depthai/pipeline/MessageQueue.hpp +++ b/include/depthai/pipeline/MessageQueue.hpp @@ -23,6 +23,9 @@ class MessageQueue : public std::enable_shared_from_this { class QueueException : public std::runtime_error { public: + /** + * Construct a queue exception with message. + */ explicit QueueException(const std::string& message) : std::runtime_error(message) {} ~QueueException() noexcept override; }; @@ -48,12 +51,21 @@ class MessageQueue : public std::enable_shared_from_this { public: // DataOutputQueue constructor + /** + * Construct a message queue with optional max size and blocking behavior. + */ explicit MessageQueue(unsigned int maxSize = 16, bool blocking = true); + /** + * Construct a named message queue with optional max size and blocking behavior. + */ explicit MessageQueue(std::string name, unsigned int maxSize = 16, bool blocking = true, utility::PipelineEventDispatcherInterface* pipelineEventDispatcher = nullptr); + /** + * Copy-construct a message queue. + */ MessageQueue(const MessageQueue& c) : enable_shared_from_this(c), queue(c.queue), @@ -61,6 +73,9 @@ class MessageQueue : public std::enable_shared_from_this { callbacks(c.callbacks), uniqueCallbackId(c.uniqueCallbackId), pipelineEventDispatcher(c.pipelineEventDispatcher){}; + /** + * Move-construct a message queue. + */ MessageQueue(MessageQueue&& m) noexcept : enable_shared_from_this(m), queue(std::move(m.queue)), diff --git a/include/depthai/pipeline/Node.hpp b/include/depthai/pipeline/Node.hpp index dc32923dc5..6ca212cf9f 100644 --- a/include/depthai/pipeline/Node.hpp +++ b/include/depthai/pipeline/Node.hpp @@ -75,9 +75,13 @@ class Node : public std::enable_shared_from_this { public: // Nodes must always be managed + /** Deleted copy constructor. */ Node(const Node&) = delete; + /** Deleted copy assignment. */ Node& operator=(const Node&) = delete; + /** Deleted move constructor. */ Node(Node&&) = delete; + /** Deleted move assignment. */ Node& operator=(Node&&) = delete; /// Node identificator. Unique for every node on a single Pipeline @@ -90,6 +94,9 @@ class Node : public std::enable_shared_from_this { class InputMap; class OutputMap; struct DatatypeHierarchy { + /** + * Construct a datatype hierarchy entry. + */ DatatypeHierarchy(DatatypeEnum d, bool c) : datatype(d), descendants(c) {} DatatypeEnum datatype; bool descendants; @@ -106,7 +113,13 @@ class Node : public std::enable_shared_from_this { static constexpr auto BLOCKING_QUEUE = true; static constexpr auto NON_BLOCKING_QUEUE = false; + /** + * Create a unique input name for this node. + */ std::string createUniqueInputName(); + /** + * Create a unique output name for this node. + */ std::string createUniqueOutputName(); protected: @@ -181,9 +194,15 @@ class Node : public std::enable_shared_from_this { } } + /** + * Return the parent node. + */ Node& getParent() { return parent; } + /** + * Return the parent node (const). + */ const Node& getParent() const { return parent; } @@ -351,7 +370,13 @@ class Node : public std::enable_shared_from_this { public: std::string name; + /** + * Construct an output map with an explicit name. + */ OutputMap(Node& parent, std::string name, OutputDescription defaultOutput, bool ref = true); + /** + * Construct an output map with the default name. + */ OutputMap(Node& parent, OutputDescription defaultOutput, bool ref = true); /// Create or modify an output Output& operator[](const std::string& key); @@ -513,13 +538,21 @@ class Node : public std::enable_shared_from_this { std::string name; // InputMap(Input defaultInput); // InputMap(std::string name, Input defaultInput); + /** + * Construct an input map with the default name. + */ InputMap(Node& parent, InputDescription defaultInput); + /** + * Construct an input map with an explicit name. + */ InputMap(Node& parent, std::string name, InputDescription defaultInput); /// Create or modify an input Input& operator[](const std::string& key); /// Create or modify an input with specified group Input& operator[](std::pair groupKey); - // Check if the input exists + /** + * Check if the input exists. + */ bool has(const std::string& key) const; }; @@ -543,7 +576,13 @@ class Node : public std::enable_shared_from_this { /// Connection between an Input and Output struct Connection { friend struct std::hash; + /** + * Construct a connection from output/input handles. + */ Connection(Output out, Input in); + /** + * Construct a connection from an internal connection. + */ Connection(ConnectionInternal c); Id outputId; std::string outputName; @@ -596,7 +635,13 @@ class Node : public std::enable_shared_from_this { public: // access + /** + * Return the parent pipeline instance. + */ Pipeline getParentPipeline(); + /** + * Return the parent pipeline instance (const). + */ const Pipeline getParentPipeline() const; /// Get alias @@ -620,6 +665,9 @@ class Node : public std::enable_shared_from_this { /// Stop node execution virtual void stop() {}; + /** + * Request the parent pipeline to stop. + */ void stopPipeline(); /// Build stages; @@ -653,10 +701,12 @@ class Node : public std::enable_shared_from_this { /// Retrieves reference to specific output Output* getOutputRef(std::string name); + /// Retrieves reference to specific output in a group. Output* getOutputRef(std::string group, std::string name); /// Retrieves reference to specific input Input* getInputRef(std::string name); + /// Retrieves reference to specific input in a group. Input* getInputRef(std::string group, std::string name); /// Retrieves reference to specific output map @@ -705,12 +755,33 @@ class Node : public std::enable_shared_from_this { void add(std::shared_ptr node); // Access to nodes + /** + * Return all nodes under this node. + */ std::vector> getAllNodes() const; + /** + * Return node by id if it exists, nullptr otherwise. + */ std::shared_ptr getNode(Node::Id id) const; + /** + * Return node by id if it exists, nullptr otherwise. + */ std::shared_ptr getNode(Node::Id id); + /** + * Remove a node from this node's map. + */ void remove(std::shared_ptr node); + /** + * Return a map of connections for this node. + */ ConnectionMap getConnectionMap(); + /** + * Link an output to an input. + */ void link(const Node::Output& out, const Node::Input& in); + /** + * Unlink an output from an input. + */ void unlink(const Node::Output& out, const Node::Input& in); /// Get a reference to internal node map @@ -723,6 +794,9 @@ class Node : public std::enable_shared_from_this { */ virtual bool runOnHost() const = 0; + /** + * Return the internal node map. + */ const NodeMap& getNodeMap() const { return nodeMap; } diff --git a/include/depthai/pipeline/Pipeline.hpp b/include/depthai/pipeline/Pipeline.hpp index ff91c75ff8..b99947b836 100644 --- a/include/depthai/pipeline/Pipeline.hpp +++ b/include/depthai/pipeline/Pipeline.hpp @@ -264,13 +264,22 @@ class Pipeline { std::shared_ptr pimpl; public: + /** + * Return the internal pipeline implementation pointer. + */ PipelineImpl* impl() { return pimpl.get(); } + /** + * Return the internal pipeline implementation pointer (const). + */ const PipelineImpl* impl() const { return pimpl.get(); } + /** + * Return pipeline source nodes. + */ std::vector> getSourceNodes() { return impl()->getSourceNodes(); } @@ -315,7 +324,9 @@ class Pipeline { */ PipelineSchema getDevicePipelineSchema(SerializationType type = DEFAULT_SERIALIZATION_TYPE, bool includePipelineDebugging = true) const; - // void loadAssets(AssetManager& assetManager); + /** + * Serialize pipeline schema and assets to the provided storage buffers. + */ void serialize(PipelineSchema& schema, Assets& assets, std::vector& assetStorage) const { impl()->serialize(schema, assets, assetStorage); } @@ -342,46 +353,65 @@ class Pipeline { impl()->add(node); } - /// Removes a node from pipeline + /** + * Remove a node from the pipeline. + */ void remove(std::shared_ptr node) { impl()->remove(node); } - /// Get a vector of all nodes + /** + * Return all nodes in the pipeline. + */ std::vector> getAllNodes() const { return impl()->getAllNodes(); } - /// Get node with id if it exists, nullptr otherwise + /** + * Return node by id if it exists, nullptr otherwise. + */ std::shared_ptr getNode(Node::Id id) const { return impl()->getNode(id); } - /// Get node with id if it exists, nullptr otherwise + /** + * Return node by id if it exists, nullptr otherwise. + */ std::shared_ptr getNode(Node::Id id) { return impl()->getNode(id); } - /// Get all connections + /** + * Return all connections. + */ std::vector getConnections() const { return impl()->getConnections(); } using NodeConnectionMap = PipelineImpl::NodeConnectionMap; + /** + * Return a map of node connections. + */ NodeConnectionMap getConnectionMap() const { return impl()->getConnectionMap(); } - /// Get pipelines AssetManager as reference + /** + * Return the pipeline asset manager (const). + */ const AssetManager& getAssetManager() const { return impl()->assetManager; } - /// Get pipelines AssetManager as reference + /** + * Return the pipeline asset manager. + */ AssetManager& getAssetManager() { return impl()->assetManager; } - /// Set a specific OpenVINO version to use with this pipeline + /** + * Set a specific OpenVINO version for this pipeline. + */ void setOpenVINOVersion(OpenVINO::Version version) { impl()->forceRequiredOpenVINOVersion = version; } @@ -440,7 +470,9 @@ class Pipeline { return impl()->getEepromId(); } - /// Set a camera IQ (Image Quality) tuning blob, used for all cameras + /** + * Set a camera tuning blob path used for all cameras. + */ void setCameraTuningBlobPath(const fs::path& path) { impl()->setCameraTuningBlobPath(path); } @@ -476,74 +508,125 @@ class Pipeline { impl()->setSippDmaBufferSize(sizeBytes); } - /// Sets board configuration + /** + * Set board configuration for the pipeline. + */ void setBoardConfig(BoardConfig board) { impl()->setBoardConfig(board); } - /// Gets board configuration + /** + * Get current board configuration. + */ BoardConfig getBoardConfig() const { return impl()->getBoardConfig(); } - /// Get device configuration needed for this pipeline + /** + * Get the device configuration for this pipeline. + */ Device::Config getDeviceConfig() const { return impl()->getDeviceConfig(); } + /** + * Return true if the pipeline is running. + */ bool isRunning() const { return impl()->isRunning(); } + /** + * Return true if the pipeline is built. + */ bool isBuilt() const { return impl()->isBuilt(); } + /** + * Build the pipeline. + */ void build() { impl()->build(); } + /** + * Build pipeline for device-only execution. + */ void buildDevice() { impl()->buildingOnHost = false; impl()->build(); } + /** + * Start pipeline execution. + */ void start() { impl()->start(); } + /** + * Wait for pipeline execution to finish. + */ void wait() { impl()->wait(); } + /** + * Stop pipeline execution. + */ void stop() { impl()->stop(); } + /** + * Process pending tasks with optional timeout. + */ void processTasks(bool waitForTasks = false, double timeoutSeconds = -1.0) { impl()->processTasks(waitForTasks, timeoutSeconds); } + /** + * Run the pipeline in the current thread. + */ void run() { impl()->run(); } /* * @note In case of a host only pipeline, this function returns a nullptr */ + /** + * Return the default device instance, if available. + */ std::shared_ptr getDefaultDevice() { return impl()->defaultDevice; } + /** + * Add a task to be executed by the pipeline. + */ void addTask(std::function task) { impl()->addTask(std::move(task)); } /// Record and Replay void enableHolisticRecord(const RecordConfig& config); + /** + * Enable holistic replay from a recording path. + */ void enableHolisticReplay(const std::string& pathToRecording); /// Pipeline debugging void enablePipelineDebugging(bool enable = true); // Access to pipeline state queues + /** + * Return pipeline state output queue. + */ std::shared_ptr getPipelineStateOut() const; + /** + * Return pipeline state request queue. + */ std::shared_ptr getPipelineStateRequest() const; // Pipeline state getters + /** + * Return pipeline state API helper. + */ PipelineStateApi getPipelineState(); }; diff --git a/include/depthai/pipeline/PipelineStateApi.hpp b/include/depthai/pipeline/PipelineStateApi.hpp index b2d1e61bc5..d3fd5349bd 100644 --- a/include/depthai/pipeline/PipelineStateApi.hpp +++ b/include/depthai/pipeline/PipelineStateApi.hpp @@ -28,12 +28,30 @@ class NodesStateApi { std::shared_ptr pipelineStateRequest; public: + /** + * Construct a nodes state API for a set of node ids. + */ explicit NodesStateApi(std::vector nodeIds, std::shared_ptr pipelineStateOut, std::shared_ptr pipelineStateRequest) : nodeIds(std::move(nodeIds)), pipelineStateOut(pipelineStateOut), pipelineStateRequest(pipelineStateRequest) {} + /** + * Return a summary pipeline state for the selected nodes. + */ PipelineState summary(); + /** + * Return a detailed pipeline state for the selected nodes. + */ PipelineState detailed(); + /** + * Return output queue state for each selected node. + */ std::unordered_map> outputs(); + /** + * Return input queue state for each selected node. + */ std::unordered_map> inputs(); + /** + * Return timing information for each selected node. + */ std::unordered_map> otherTimings(); }; class NodeStateApi { @@ -43,29 +61,68 @@ class NodeStateApi { std::shared_ptr pipelineStateRequest; public: + /** + * Construct a node state API for a specific node. + */ explicit NodeStateApi(Node::Id nodeId, std::shared_ptr pipelineStateOut, std::shared_ptr pipelineStateRequest) : nodeId(nodeId), pipelineStateOut(pipelineStateOut), pipelineStateRequest(pipelineStateRequest) {} + /** + * Return a summary state for this node. + */ NodeState summary() { return NodesStateApi({nodeId}, pipelineStateOut, pipelineStateRequest).summary().nodeStates[nodeId]; } + /** + * Return a detailed state for this node. + */ NodeState detailed() { return NodesStateApi({nodeId}, pipelineStateOut, pipelineStateRequest).detailed().nodeStates[nodeId]; } + /** + * Return output queue states for this node. + */ std::unordered_map outputs() { return NodesStateApi({nodeId}, pipelineStateOut, pipelineStateRequest).outputs()[nodeId]; } + /** + * Return input queue states for this node. + */ std::unordered_map inputs() { return NodesStateApi({nodeId}, pipelineStateOut, pipelineStateRequest).inputs()[nodeId]; } + /** + * Return timing information for this node. + */ std::unordered_map otherTimings() { return NodesStateApi({nodeId}, pipelineStateOut, pipelineStateRequest).otherTimings()[nodeId]; } + /** + * Return output queue state for specific outputs. + */ std::unordered_map outputs(const std::vector& outputNames); + /** + * Return output queue state for a specific output. + */ NodeState::OutputQueueState outputs(const std::string& outputName); + /** + * Return duration events for this node. + */ std::vector events(); + /** + * Return input queue state for specific inputs. + */ std::unordered_map inputs(const std::vector& inputNames); + /** + * Return input queue state for a specific input. + */ NodeState::InputQueueState inputs(const std::string& inputName); + /** + * Return timing info for specific timing names. + */ std::unordered_map otherTimings(const std::vector& timingNames); + /** + * Return timing info for a specific timing name. + */ NodeState::Timing otherTimings(const std::string& timingName); }; class PipelineStateApi { @@ -74,6 +131,9 @@ class PipelineStateApi { std::vector nodeIds; // empty means all nodes public: + /** + * Construct a pipeline state API for all nodes in a pipeline. + */ PipelineStateApi(std::shared_ptr pipelineStateOut, std::shared_ptr pipelineStateRequest, const std::vector>& allNodes) @@ -82,15 +142,27 @@ class PipelineStateApi { nodeIds.push_back(n->id); } } + /** + * Return a nodes state API for all nodes. + */ NodesStateApi nodes() { return NodesStateApi(nodeIds, pipelineStateOut, pipelineStateRequest); } + /** + * Return a nodes state API for a subset of nodes. + */ NodesStateApi nodes(const std::vector& nodeIds) { return NodesStateApi(nodeIds, pipelineStateOut, pipelineStateRequest); } + /** + * Return a node state API for a specific node. + */ NodeStateApi nodes(Node::Id nodeId) { return NodeStateApi(nodeId, pipelineStateOut, pipelineStateRequest); } + /** + * Request state asynchronously and invoke callback when available. + */ void stateAsync(std::function callback, std::optional config = std::nullopt); }; diff --git a/include/depthai/pipeline/Subnode.hpp b/include/depthai/pipeline/Subnode.hpp index d2d57c2cae..6f8f94cb31 100644 --- a/include/depthai/pipeline/Subnode.hpp +++ b/include/depthai/pipeline/Subnode.hpp @@ -12,6 +12,9 @@ class Subnode { std::shared_ptr node; public: + /** + * Construct a subnode attached to a parent node with an alias. + */ Subnode(Node& parent, std::string alias) { if(!parent.configureMode) { // Create node as well @@ -41,12 +44,18 @@ class Subnode { // Add reference parent.nodeRefs.push_back(&node); } + /** + * Access the underlying node reference. + */ T& operator*() const noexcept { return *std::static_pointer_cast(node).get(); } + /** + * Access the underlying node pointer. + */ T* operator->() const noexcept { return std::static_pointer_cast(node).get(); } }; -} // namespace dai \ No newline at end of file +} // namespace dai diff --git a/include/depthai/pipeline/ThreadedHostNode.hpp b/include/depthai/pipeline/ThreadedHostNode.hpp index 7becdfa900..6aca8f2104 100644 --- a/include/depthai/pipeline/ThreadedHostNode.hpp +++ b/include/depthai/pipeline/ThreadedHostNode.hpp @@ -11,6 +11,9 @@ class ThreadedHostNode : public ThreadedNode { ~ThreadedHostNode() override; + /** + * Indicates this node runs on host and is not serialized to device. + */ bool runOnHost() const final { // Host node don't contain the necessary information to be serialized and sent to the device return true; diff --git a/include/depthai/pipeline/ThreadedNode.hpp b/include/depthai/pipeline/ThreadedNode.hpp index 7ad9d940cb..c1db7351da 100644 --- a/include/depthai/pipeline/ThreadedNode.hpp +++ b/include/depthai/pipeline/ThreadedNode.hpp @@ -21,6 +21,9 @@ class ThreadedNode : public Node { using Node::Node; + /** + * Construct a threaded node. + */ ThreadedNode(); virtual ~ThreadedNode(); @@ -41,16 +44,31 @@ class ThreadedNode : public Node { virtual void onStop() {} // override the following methods + /** + * Start the node thread. + */ void start() override; + /** + * Wait for the node thread to finish. + */ void wait() override; + /** + * Stop the node thread. + */ void stop() override; // virtual 'run' method virtual void run() = 0; // check if still running + /** + * Return true if the node thread is running. + */ bool isRunning() const; + /** + * Main processing loop hook used by run() implementations. + */ bool mainLoop(); /** diff --git a/include/depthai/pipeline/datatype/ADatatype.hpp b/include/depthai/pipeline/datatype/ADatatype.hpp index 4b00e2c4cd..f3e709bb44 100644 --- a/include/depthai/pipeline/datatype/ADatatype.hpp +++ b/include/depthai/pipeline/datatype/ADatatype.hpp @@ -19,6 +19,9 @@ class ADatatype { #ifdef DEPTHAI_MESSAGES_NO_HEAP explicit ADatatype() = default; #else + /** + * Construct a datatype with an owned memory buffer. + */ explicit ADatatype() : data{std::make_shared(std::vector())} {}; #endif diff --git a/include/depthai/pipeline/datatype/Buffer.hpp b/include/depthai/pipeline/datatype/Buffer.hpp index 88e81604d8..c2fadb0d64 100644 --- a/include/depthai/pipeline/datatype/Buffer.hpp +++ b/include/depthai/pipeline/datatype/Buffer.hpp @@ -20,8 +20,17 @@ using VisualizeType = std::variant, std::shared_ class Buffer : public ADatatype { public: Buffer() = default; + /** + * Construct a buffer with a given size. + */ Buffer(size_t size); + /** + * Construct a buffer from a file descriptor. + */ Buffer(long fd); + /** + * Construct a buffer from a file descriptor and size. + */ Buffer(long fd, size_t size); ~Buffer() override; diff --git a/include/depthai/pipeline/datatype/CameraControl.hpp b/include/depthai/pipeline/datatype/CameraControl.hpp index 30b63600e4..8b998e818e 100644 --- a/include/depthai/pipeline/datatype/CameraControl.hpp +++ b/include/depthai/pipeline/datatype/CameraControl.hpp @@ -778,6 +778,9 @@ class CameraControl : public Buffer { bool enableHdr{false}; std::vector> miscControls; + /** + * Set or clear a command bit. + */ void setCommand(Command cmd, bool value = true) { uint64_t mask = 1ull << (uint8_t)cmd; if(value) { @@ -786,9 +789,15 @@ class CameraControl : public Buffer { cmdMask &= ~mask; } } + /** + * Clear a command bit. + */ void clearCommand(Command cmd) { setCommand(cmd, false); } + /** + * Return true if a command bit is set. + */ bool getCommand(Command cmd) const { return !!(cmdMask & (1ull << (uint8_t)cmd)); } diff --git a/include/depthai/pipeline/datatype/DynamicCalibrationControl.hpp b/include/depthai/pipeline/datatype/DynamicCalibrationControl.hpp index 51b6956801..fb6ecb0c75 100644 --- a/include/depthai/pipeline/datatype/DynamicCalibrationControl.hpp +++ b/include/depthai/pipeline/datatype/DynamicCalibrationControl.hpp @@ -52,6 +52,9 @@ class DynamicCalibrationControl : public Buffer { * @brief Command to perform a full calibration run. */ struct Calibrate { + /** + * Construct a calibrate command. + */ explicit Calibrate(bool force = false) : force(force) {} bool force = false; ///< Force calibration even when unnecessary. DEPTHAI_SERIALIZE(Calibrate, force); @@ -61,6 +64,9 @@ class DynamicCalibrationControl : public Buffer { * @brief Command to perform a calibration quality check. */ struct CalibrationQuality { + /** + * Construct a calibration quality command. + */ explicit CalibrationQuality(bool force = false) : force(force) {} bool force = false; ///< Force check even if previous quality is valid. DEPTHAI_SERIALIZE(CalibrationQuality, force); @@ -73,6 +79,9 @@ class DynamicCalibrationControl : public Buffer { * @param calibrationPeriod How often calibration should run (seconds) */ struct StartCalibration { + /** + * Construct a start calibration command. + */ explicit StartCalibration(float loadImagePeriod = 0.5f, float calibrationPeriod = 5.0f) : loadImagePeriod(loadImagePeriod), calibrationPeriod(calibrationPeriod) {} @@ -99,6 +108,9 @@ class DynamicCalibrationControl : public Buffer { */ struct ApplyCalibration { ApplyCalibration() = default; + /** + * Construct an apply calibration command. + */ explicit ApplyCalibration(const CalibrationHandler& calibration) : calibration(calibration) {} CalibrationHandler calibration; ///< Calibration data to apply. @@ -114,7 +126,13 @@ class DynamicCalibrationControl : public Buffer { * @brief Command to select the calibration performance mode. */ struct SetPerformanceMode { + /** + * Construct a performance mode command with default mode. + */ SetPerformanceMode() : performanceMode(PerformanceMode::DEFAULT) {} + /** + * Construct a performance mode command. + */ explicit SetPerformanceMode(PerformanceMode performanceMode) : performanceMode(performanceMode) {} PerformanceMode performanceMode; ///< Desired performance mode. @@ -141,8 +159,14 @@ class DynamicCalibrationControl : public Buffer { Command command{}; + /** + * Construct an empty control message. + */ DynamicCalibrationControl() {} + /** + * Construct a control message with a command. + */ explicit DynamicCalibrationControl(Command cmd) : command(std::move(cmd)) {} ~DynamicCalibrationControl() override; diff --git a/include/depthai/pipeline/datatype/ImageManipConfig.hpp b/include/depthai/pipeline/datatype/ImageManipConfig.hpp index 462898d9c1..df0d45407c 100644 --- a/include/depthai/pipeline/datatype/ImageManipConfig.hpp +++ b/include/depthai/pipeline/datatype/ImageManipConfig.hpp @@ -33,6 +33,9 @@ struct Translate : OpBase { ~Translate() override; Translate() = default; + /** + * Construct a translation operation. + */ Translate(float offsetX, float offsetY, bool normalized = false) : offsetX(offsetX), offsetY(offsetY), normalized(normalized) {} std::string toStr() const override { @@ -55,6 +58,9 @@ struct Rotate : OpBase { ~Rotate() override; Rotate() = default; + /** + * Construct a rotation operation. + */ explicit Rotate(float angle, bool center = true, float offsetX = 0, float offsetY = 0, bool normalized = false) : angle(angle), center(center), offsetX(offsetX), offsetY(offsetY), normalized(normalized) {} @@ -78,14 +84,23 @@ struct Resize : OpBase { ~Resize() override; Resize() = default; + /** + * Construct a resize operation. + */ Resize(float width, float height, bool normalized = false) : width(width), height(height), normalized(normalized), mode(VALUE) {} + /** + * Create a resize operation with FIT mode. + */ static Resize fit() { Resize r(0, 0); r.mode = FIT; return r; } + /** + * Create a resize operation with FILL mode. + */ static Resize fill() { Resize r(0, 0); r.mode = FILL; @@ -110,6 +125,9 @@ struct Flip : OpBase { ~Flip() override; Flip() = default; + /** + * Construct a flip operation. + */ explicit Flip(Direction direction, bool center = true) : direction(direction), center(center) {} std::string toStr() const override { @@ -128,6 +146,9 @@ struct Affine : OpBase { ~Affine() override; Affine() = default; + /** + * Construct an affine transformation. + */ explicit Affine(std::array matrix) : matrix(matrix) {} std::string toStr() const override { @@ -146,6 +167,9 @@ struct Perspective : OpBase { ~Perspective() override; Perspective() = default; + /** + * Construct a perspective transformation. + */ explicit Perspective(std::array matrix) : matrix(matrix) {} std::string toStr() const override { @@ -167,6 +191,9 @@ struct FourPoints : OpBase { ~FourPoints() override; FourPoints() = default; + /** + * Construct a four-point warp operation. + */ FourPoints(std::array src, std::array dst, bool normalized = false) : src(src), dst(dst), normalized(normalized) {} std::string toStr() const override { @@ -189,9 +216,18 @@ struct Crop : OpBase { ~Crop() override; + /** + * Construct a default crop operation. + */ Crop() : width(0), height(0), normalized(true), center(true) {} + /** + * Construct a crop operation. + */ Crop(float width, float height, bool normalized = false, bool center = false) : width(width), height(height), normalized(normalized), center(center) {} + /** + * Clone this crop operation. + */ Crop clone() const { return *this; } @@ -210,14 +246,38 @@ struct ManipOp { std::variant op; ManipOp() = default; - ManipOp(Translate op) : op(op) {} // NOLINT - ManipOp(Rotate op) : op(op) {} // NOLINT - ManipOp(Resize op) : op(op) {} // NOLINT - ManipOp(Flip op) : op(op) {} // NOLINT - ManipOp(Affine op) : op(op) {} // NOLINT + /** + * Construct from a Translate operation. + */ + ManipOp(Translate op) : op(op) {} // NOLINT + /** + * Construct from a Rotate operation. + */ + ManipOp(Rotate op) : op(op) {} // NOLINT + /** + * Construct from a Resize operation. + */ + ManipOp(Resize op) : op(op) {} // NOLINT + /** + * Construct from a Flip operation. + */ + ManipOp(Flip op) : op(op) {} // NOLINT + /** + * Construct from an Affine operation. + */ + ManipOp(Affine op) : op(op) {} // NOLINT + /** + * Construct from a Perspective operation. + */ ManipOp(Perspective op) : op(op) {} // NOLINT - ManipOp(FourPoints op) : op(op) {} // NOLINT - ManipOp(Crop op) : op(op) {} // NOLINT + /** + * Construct from a FourPoints operation. + */ + ManipOp(FourPoints op) : op(op) {} // NOLINT + /** + * Construct from a Crop operation. + */ + ManipOp(Crop op) : op(op) {} // NOLINT DEPTHAI_SERIALIZE(ManipOp, op); }; @@ -245,6 +305,9 @@ class ImageManipOpsBase : public ImageManipOpsEnums { C operations; template + /** + * Copy configuration into another ImageManipOpsBase container. + */ void cloneTo(ImageManipOpsBase& to) const { to.outputWidth = outputWidth; to.outputHeight = outputHeight; @@ -261,85 +324,136 @@ class ImageManipOpsBase : public ImageManipOpsEnums { to.operations.insert(to.operations.end(), operations.begin(), operations.end()); } + /** + * Return true if any warp-like operation is configured. + */ bool hasWarp(const size_t inputWidth, const size_t inputHeight) const { return operations.size() > 0 || (outputWidth != 0 && outputWidth != inputWidth) || (outputHeight != 0 && outputHeight != inputHeight) || undistort; } + /** + * Append a manipulation operation. + */ ImageManipOpsBase& addOp(ManipOp op) { operations.push_back(op); return *this; } + /** + * Append a perspective transform operation. + */ ImageManipOpsBase& transformPerspective(std::array matrix) { operations.emplace_back(Perspective(matrix)); return *this; } + /** + * Append an affine transform operation. + */ ImageManipOpsBase& transformAffine(std::array matrix) { operations.emplace_back(Affine(matrix)); return *this; } + /** + * Append a four-point transform operation. + */ ImageManipOpsBase& transformFourPoints(std::array src, std::array dst, bool normalizedCoords = false) { operations.emplace_back(FourPoints(src, dst, normalizedCoords)); return *this; } + /** + * Append a horizontal flip operation. + */ ImageManipOpsBase& flipHorizontal(bool center = true) { operations.emplace_back(Flip(Flip::Direction::HORIZONTAL, center)); return *this; } + /** + * Append a vertical flip operation. + */ ImageManipOpsBase& flipVertical(bool center = true) { operations.emplace_back(Flip(Flip::Direction::VERTICAL, center)); return *this; } + /** + * Append a resize operation. + */ ImageManipOpsBase& resize(float width, float height, bool normalized = false) { operations.emplace_back(Resize(width, height, normalized)); return *this; } + /** + * Append translate+crop operations. + */ ImageManipOpsBase& crop(float x, float y, float w, float h, bool normalized = false, bool center = false) { operations.emplace_back(Translate(-x, -y, normalized)); operations.emplace_back(Crop(w, h, normalized, center)); return *this; } + /** + * Append a fit-resize operation. + */ ImageManipOpsBase& resizeFit() { operations.emplace_back(Resize::fit()); return *this; } + /** + * Append a fill-resize operation. + */ ImageManipOpsBase& resizeFill() { operations.emplace_back(Resize::fill()); return *this; } + /** + * Append a resize-width operation keeping aspect ratio. + */ ImageManipOpsBase& resizeWidthKeepAspectRatio(float width, bool normalized = false) { operations.emplace_back(Resize(width, 0, normalized)); return *this; } + /** + * Append a resize-height operation keeping aspect ratio. + */ ImageManipOpsBase& resizeHeightKeepAspectRatio(float height, bool normalized = false) { operations.emplace_back(Resize(0, height, normalized)); return *this; } + /** + * Append a rotation in radians. + */ ImageManipOpsBase& rotateRadians(float angle, bool center = true, float offsetX = 0, float offsetY = 0, bool normalized = false) { operations.emplace_back(Rotate(angle, center, offsetX, offsetY, normalized)); return *this; } + /** + * Append a rotation in degrees. + */ ImageManipOpsBase& rotateDegrees(float angle, bool center = true, float offsetX = 0, float offsetY = 0, bool normalized = false) { return rotateRadians(angle * 3.14159265358979323846f / 180.0f, center, offsetX, offsetY, normalized); } + /** + * Append a translation operation. + */ ImageManipOpsBase& translate(float offsetX, float offsetY, bool normalizedCoords = false) { operations.emplace_back(Translate(offsetX, offsetY, normalizedCoords)); return *this; } + /** + * Set output size and reset resize mode. + */ ImageManipOpsBase& setOutputSize(float width, float height) { outputWidth = width; outputHeight = height; @@ -347,6 +461,9 @@ class ImageManipOpsBase : public ImageManipOpsEnums { return *this; } + /** + * Set output size and resize mode. + */ ImageManipOpsBase& setOutputResize(uint32_t width, uint32_t height, ResizeMode mode) { outputWidth = width; outputHeight = height; @@ -355,11 +472,17 @@ class ImageManipOpsBase : public ImageManipOpsEnums { return *this; } + /** + * Set whether resize operations are centered. + */ ImageManipOpsBase& setOutputCenter(bool c = true) { center = c; return *this; } + /** + * Set background color from RGB components. + */ ImageManipOpsBase& setBackgroundColor(uint32_t red, uint32_t green, uint32_t blue) { background = Background::COLOR; backgroundR = red; @@ -368,6 +491,9 @@ class ImageManipOpsBase : public ImageManipOpsEnums { return *this; } + /** + * Set background color from a grayscale value. + */ ImageManipOpsBase& setBackgroundColor(uint32_t val) { background = Background::COLOR; backgroundR = val; @@ -382,24 +508,39 @@ class ImageManipOpsBase : public ImageManipOpsEnums { // return *this; // } + /** + * Set output colormap. + */ ImageManipOpsBase& setColormap(Colormap clr) { colormap = clr; return *this; } + /** + * Enable or disable undistortion. + */ ImageManipOpsBase& setUndistort(bool undistort) { this->undistort = undistort; return *this; } + /** + * Return whether undistortion is enabled. + */ bool getUndistort() const { return undistort; } + /** + * Return the list of operations. + */ const C& getOperations() const { return this->operations; } + /** + * Clear all operations. + */ ImageManipOpsBase& clear() { operations.clear(); return *this; diff --git a/include/depthai/pipeline/datatype/ImgAnnotations.hpp b/include/depthai/pipeline/datatype/ImgAnnotations.hpp index ac7cc1694a..53bba9ff97 100644 --- a/include/depthai/pipeline/datatype/ImgAnnotations.hpp +++ b/include/depthai/pipeline/datatype/ImgAnnotations.hpp @@ -53,6 +53,9 @@ class ImgAnnotations : public Buffer, public ProtoSerializable { * Construct ImgAnnotations message. */ ImgAnnotations() = default; + /** + * Construct ImgAnnotations with a list of annotations. + */ explicit ImgAnnotations(std::vector annotations) : annotations(std::move(annotations)) {} virtual ~ImgAnnotations(); diff --git a/include/depthai/pipeline/datatype/ImgDetections.hpp b/include/depthai/pipeline/datatype/ImgDetections.hpp index e1129065fb..bd310fa754 100644 --- a/include/depthai/pipeline/datatype/ImgDetections.hpp +++ b/include/depthai/pipeline/datatype/ImgDetections.hpp @@ -40,9 +40,21 @@ struct ImgDetection { std::optional keypoints; ImgDetection() = default; + /** + * Construct a detection from a bounding box and label. + */ ImgDetection(const RotatedRect& boundingBox, float confidence, uint32_t label); + /** + * Construct a detection with label name. + */ ImgDetection(const RotatedRect& boundingBox, std::string labelName, float confidence, uint32_t label); + /** + * Construct a detection with keypoints. + */ ImgDetection(const RotatedRect& boundingBox, const KeypointsList& keypoints, float confidence, uint32_t label); + /** + * Construct a detection with keypoints and label name. + */ ImgDetection(const RotatedRect& boundingBox, const KeypointsList& keypoints, std::string labelName, float confidence, uint32_t label); /** diff --git a/include/depthai/pipeline/datatype/ImgDetectionsT.hpp b/include/depthai/pipeline/datatype/ImgDetectionsT.hpp index 99eb12cf75..885c516fb6 100644 --- a/include/depthai/pipeline/datatype/ImgDetectionsT.hpp +++ b/include/depthai/pipeline/datatype/ImgDetectionsT.hpp @@ -34,34 +34,34 @@ class ImgDetectionsT : public Buffer { * Common API */ - /* + /** * Returns the width of the segmentation mask. */ std::size_t getSegmentationMaskWidth() const; - /* + /** * Returns the height of the segmentation mask. */ std::size_t getSegmentationMaskHeight() const; - /* + /** * Sets the segmentation mask from a vector of bytes. * The size of the vector must be equal to width * height. */ void setSegmentationMask(const std::vector& mask, size_t width, size_t height); - /* + /** * Sets the segmentation mask from an ImgFrame. * @param frame Frame must be of type GRAY8 */ void setSegmentationMask(dai::ImgFrame& frame); - /* + /** * Returns a copy of the segmentation mask data as a vector of bytes. If mask data is not set, returns std::nullopt. */ std::optional> getMaskData() const; - /* + /** * Returns the segmentation mask as an ImgFrame. If mask data is not set, returns std::nullopt. */ std::optional getSegmentationMask() const; diff --git a/include/depthai/pipeline/datatype/ImgFrame.hpp b/include/depthai/pipeline/datatype/ImgFrame.hpp index caa51ca960..78773c78ef 100644 --- a/include/depthai/pipeline/datatype/ImgFrame.hpp +++ b/include/depthai/pipeline/datatype/ImgFrame.hpp @@ -72,8 +72,17 @@ class ImgFrame : public Buffer, public ProtoSerializable { * Timestamp is set to now */ ImgFrame(); + /** + * Construct ImgFrame backed by a file descriptor. + */ ImgFrame(long fd); + /** + * Construct ImgFrame with a preallocated data size. + */ ImgFrame(size_t size); + /** + * Construct ImgFrame backed by a file descriptor and size. + */ ImgFrame(long fd, size_t size); virtual ~ImgFrame(); diff --git a/include/depthai/pipeline/datatype/MessageGroup.hpp b/include/depthai/pipeline/datatype/MessageGroup.hpp index 35e22d46c4..d6784f86ee 100644 --- a/include/depthai/pipeline/datatype/MessageGroup.hpp +++ b/include/depthai/pipeline/datatype/MessageGroup.hpp @@ -21,10 +21,16 @@ class MessageGroup : public Buffer { /// Group std::shared_ptr operator[](const std::string& name); template + /** + * Retrieve a message by name and cast to type T. + */ std::shared_ptr get(const std::string& name) { return std::dynamic_pointer_cast(group[name]); } + /** + * Retrieve a message by name. + */ std::shared_ptr get(const std::string& name) { return group[name]; } @@ -35,6 +41,9 @@ class MessageGroup : public Buffer { // static_assert(std::is_base_of::value, "T must derive from ADatatype"); // group[name] = std::make_shared(value); // } + /** + * Add a message to the group. + */ void add(const std::string& name, const std::shared_ptr& value); // Iterators @@ -52,6 +61,9 @@ class MessageGroup : public Buffer { */ int64_t getIntervalNs() const; + /** + * Return number of messages in the group. + */ int64_t getNumMessages() const; /** @@ -66,4 +78,4 @@ class MessageGroup : public Buffer { DEPTHAI_SERIALIZE(MessageGroup, group, Buffer::ts, Buffer::tsDevice, Buffer::sequenceNum); }; -} // namespace dai \ No newline at end of file +} // namespace dai diff --git a/include/depthai/pipeline/datatype/NNData.hpp b/include/depthai/pipeline/datatype/NNData.hpp index fe5b850b9c..7c03a8270a 100644 --- a/include/depthai/pipeline/datatype/NNData.hpp +++ b/include/depthai/pipeline/datatype/NNData.hpp @@ -70,6 +70,9 @@ class NNData : public Buffer { * Construct NNData message. */ NNData() = default; + /** + * Construct NNData with a preallocated data size. + */ NNData(size_t size); virtual ~NNData(); @@ -145,11 +148,17 @@ class NNData : public Buffer { * @return NNData&: reference to this object */ template + /** + * Add a tensor from a 1xN vector with explicit data type. + */ NNData& addTensor(const std::string& name, const std::vector<_Ty>& data, dai::TensorInfo::DataType dataType) { return addTensor<_Ty>(name, xt::adapt(data, std::vector{1, data.size()}), dataType); }; // addTensor vector dispatch template + /** + * Add a tensor from a vector with type-based data type selection. + */ NNData& addTensor(const std::string& name, const std::vector<_Ty>& tensor) { if constexpr(std::is_same<_Ty, int>::value) { return addTensor(name, tensor, dai::TensorInfo::DataType::INT); @@ -168,27 +177,48 @@ class NNData : public Buffer { } } + /** + * Add an INT tensor from int data. + */ NNData& addTensor(const std::string& name, const std::vector& tensor) { return addTensor(name, tensor, dai::TensorInfo::DataType::INT); }; + /** + * Add a FP16 tensor from uint16_t data. + */ NNData& addTensor(const std::string& name, const std::vector& tensor) { return addTensor(name, tensor, dai::TensorInfo::DataType::FP16); }; + /** + * Add a FP32 tensor from float data. + */ NNData& addTensor(const std::string& name, const std::vector& tensor) { return addTensor(name, tensor, dai::TensorInfo::DataType::FP32); }; + /** + * Add a FP64 tensor from double data. + */ NNData& addTensor(const std::string& name, const std::vector& tensor) { return addTensor(name, tensor, dai::TensorInfo::DataType::FP64); }; + /** + * Add an INT8 tensor from int8 data. + */ NNData& addTensor(const std::string& name, const std::vector& tensor) { return addTensor(name, tensor, dai::TensorInfo::DataType::I8); }; + /** + * Add a U8F tensor from uint8 data. + */ NNData& addTensor(const std::string& name, const std::vector& tensor) { return addTensor(name, tensor, dai::TensorInfo::DataType::U8F); }; // addTensor dispatch template + /** + * Add a tensor from an xt::xarray with type-based data type selection. + */ NNData& addTensor(const std::string& name, const xt::xarray<_Ty>& tensor) { if constexpr(std::is_same<_Ty, int>::value) { return addTensor(name, tensor, dai::TensorInfo::DataType::INT); @@ -207,21 +237,39 @@ class NNData : public Buffer { } } + /** + * Add an INT tensor from int xt::xarray data. + */ NNData& addTensor(const std::string& name, const xt::xarray& tensor) { return addTensor(name, tensor, dai::TensorInfo::DataType::INT); }; + /** + * Add a FP16 tensor from uint16_t xt::xarray data. + */ NNData& addTensor(const std::string& name, const xt::xarray& tensor) { return addTensor(name, tensor, dai::TensorInfo::DataType::FP16); }; + /** + * Add a FP32 tensor from float xt::xarray data. + */ NNData& addTensor(const std::string& name, const xt::xarray& tensor) { return addTensor(name, tensor, dai::TensorInfo::DataType::FP32); }; + /** + * Add a FP64 tensor from double xt::xarray data. + */ NNData& addTensor(const std::string& name, const xt::xarray& tensor) { return addTensor(name, tensor, dai::TensorInfo::DataType::FP64); }; + /** + * Add an INT8 tensor from int8 xt::xarray data. + */ NNData& addTensor(const std::string& name, const xt::xarray& tensor) { return addTensor(name, tensor, dai::TensorInfo::DataType::I8); }; + /** + * Add a U8F tensor from uint8 xt::xarray data. + */ NNData& addTensor(const std::string& name, const xt::xarray& tensor) { return addTensor(name, tensor, dai::TensorInfo::DataType::U8F); }; @@ -475,6 +523,9 @@ class NNData : public Buffer { } template + /** + * Change tensor storage order in-place. + */ void changeStorageOrder(xt::xarray<_Ty>& array, TensorInfo::StorageOrder from, TensorInfo::StorageOrder to) { // Convert storage order to vector auto order2vec = [](TensorInfo::StorageOrder order) { diff --git a/include/depthai/pipeline/datatype/PipelineState.hpp b/include/depthai/pipeline/datatype/PipelineState.hpp index a007a48ca7..a3d2ab8c25 100644 --- a/include/depthai/pipeline/datatype/PipelineState.hpp +++ b/include/depthai/pipeline/datatype/PipelineState.hpp @@ -30,6 +30,9 @@ class NodeState { float fps = 0.0f; DurationStats durationStats; + /** + * Return true if timing stats are valid. + */ bool isValid() const { return durationStats.minMicros <= durationStats.maxMicros; } @@ -57,6 +60,9 @@ class NodeState { // Queue usage stats QueueStats queueStats; + /** + * Return true if timing stats are valid. + */ bool isValid() const { return timing.isValid(); } @@ -70,6 +76,9 @@ class NodeState { // Timing info about this output Timing timing; + /** + * Return true if timing stats are valid. + */ bool isValid() const { return timing.isValid(); } diff --git a/include/depthai/pipeline/datatype/PointCloudData.hpp b/include/depthai/pipeline/datatype/PointCloudData.hpp index 287261c98a..5187fbaa5c 100644 --- a/include/depthai/pipeline/datatype/PointCloudData.hpp +++ b/include/depthai/pipeline/datatype/PointCloudData.hpp @@ -39,9 +39,21 @@ class PointCloudData : public Buffer, public ProtoSerializable { PointCloudData() = default; virtual ~PointCloudData(); + /** + * Get point cloud points without color. + */ std::vector getPoints(); + /** + * Get point cloud points with color. + */ std::vector getPointsRGB(); + /** + * Set point cloud points without color. + */ void setPoints(const std::vector& points); + /** + * Set point cloud points with color. + */ void setPointsRGB(const std::vector& points); /** @@ -212,9 +224,21 @@ class PointCloudData : public Buffer, public ProtoSerializable { * Converts PointCloudData to pcl::PointCloud */ pcl::PointCloud::Ptr getPclData() const; + /** + * Converts PointCloudData to pcl::PointCloud + */ pcl::PointCloud::Ptr getPclDataRGB() const; + /** + * Set point cloud from pcl::PointCloud + */ void setPclData(const pcl::PointCloud::Ptr& cloud); + /** + * Set point cloud from pcl::PointCloud + */ void setPclData(const pcl::PointCloud::Ptr& cloud); + /** + * Set point cloud from pcl::PointCloud (alias) + */ void setPclDataRGB(const pcl::PointCloud::Ptr& cloud); #else template @@ -222,10 +246,16 @@ class PointCloudData : public Buffer, public ProtoSerializable { static constexpr bool value = false; }; template + /** + * Stub when PCL support is disabled. + */ void getPclData() const { static_assert(dependent_false::value, "Library not configured with PCL support"); } template + /** + * Stub when PCL support is disabled. + */ void setPclData(T...) { static_assert(dependent_false::value, "Library not configured with PCL support"); } diff --git a/include/depthai/pipeline/datatype/RGBDData.hpp b/include/depthai/pipeline/datatype/RGBDData.hpp index 2e426f632c..40576eff0f 100644 --- a/include/depthai/pipeline/datatype/RGBDData.hpp +++ b/include/depthai/pipeline/datatype/RGBDData.hpp @@ -21,9 +21,21 @@ class RGBDData : public Buffer { virtual ~RGBDData(); std::map> frames; + /** + * Set the RGB frame. + */ void setRGBFrame(const std::shared_ptr& frame); + /** + * Set the depth frame. + */ void setDepthFrame(const std::shared_ptr& frame); + /** + * Get the RGB frame. + */ std::shared_ptr getRGBFrame(); + /** + * Get the depth frame. + */ std::shared_ptr getDepthFrame(); void serialize(std::vector& metadata, DatatypeEnum& datatype) const override; diff --git a/include/depthai/pipeline/datatype/StreamMessageParser.hpp b/include/depthai/pipeline/datatype/StreamMessageParser.hpp index 967c92e596..2000048333 100644 --- a/include/depthai/pipeline/datatype/StreamMessageParser.hpp +++ b/include/depthai/pipeline/datatype/StreamMessageParser.hpp @@ -16,11 +16,23 @@ namespace dai { class StreamMessageParser { public: + /** + * Parse a message from a stream packet descriptor. + */ static std::shared_ptr parseMessage(StreamPacketDesc packet); + /** + * Parse a message from a raw stream packet descriptor. + */ static std::shared_ptr parseMessage(streamPacketDesc_t* const packet); // static std::vector serializeMessage(const std::shared_ptr& data); // static std::vector serializeMessage(const ADatatype& data); + /** + * Serialize metadata for a shared message. + */ static std::vector serializeMetadata(const std::shared_ptr& data); + /** + * Serialize metadata for a message. + */ static std::vector serializeMetadata(const ADatatype& data); }; } // namespace dai diff --git a/include/depthai/pipeline/datatype/TransformData.hpp b/include/depthai/pipeline/datatype/TransformData.hpp index f2219499b2..4c2f42bdce 100644 --- a/include/depthai/pipeline/datatype/TransformData.hpp +++ b/include/depthai/pipeline/datatype/TransformData.hpp @@ -22,13 +22,31 @@ class TransformData : public Buffer { * Construct TransformData message. */ TransformData(); + /** + * Construct from a Transform struct. + */ TransformData(const Transform& transform); + /** + * Construct from a 4x4 transform matrix. + */ TransformData(const std::array, 4>& data); + /** + * Construct from translation and quaternion components. + */ TransformData(double x, double y, double z, double qx, double qy, double qz, double qw); + /** + * Construct from translation and roll/pitch/yaw (radians). + */ TransformData(double x, double y, double z, double roll, double pitch, double yaw); #ifdef DEPTHAI_HAVE_RTABMAP_SUPPORT + /** + * Construct from an RTAB-Map transform. + */ TransformData(const rtabmap::Transform& transformRTABMap); + /** + * Convert to an RTAB-Map transform. + */ rtabmap::Transform getRTABMapTransform() const; #endif virtual ~TransformData(); diff --git a/include/depthai/pipeline/node/AprilTag.hpp b/include/depthai/pipeline/node/AprilTag.hpp index b85e319124..45d44ac2c7 100644 --- a/include/depthai/pipeline/node/AprilTag.hpp +++ b/include/depthai/pipeline/node/AprilTag.hpp @@ -26,6 +26,9 @@ class AprilTag : public DeviceNodeCRTP public: AprilTag() = default; + /** + * Construct an AprilTag node with properties. + */ AprilTag(std::unique_ptr props); /** diff --git a/include/depthai/pipeline/node/DetectionNetwork.hpp b/include/depthai/pipeline/node/DetectionNetwork.hpp index 74d72c7f4f..19b9cf305e 100644 --- a/include/depthai/pipeline/node/DetectionNetwork.hpp +++ b/include/depthai/pipeline/node/DetectionNetwork.hpp @@ -20,6 +20,9 @@ namespace node { */ class DetectionNetwork : public DeviceNodeGroup { public: + /** + * Construct a DetectionNetwork node bound to a device. + */ DetectionNetwork(const std::shared_ptr& device); [[nodiscard]] static std::shared_ptr create(const std::shared_ptr& device) { @@ -35,6 +38,9 @@ class DetectionNetwork : public DeviceNodeGroup { * @returns Shared pointer to DetectionNetwork node */ std::shared_ptr build(Node::Output& input, const NNArchive& nnArchive); + /** + * Build DetectionNetwork node with a model description. + */ std::shared_ptr build(const std::shared_ptr& input, NNModelDescription modelDesc, std::optional fps = std::nullopt, @@ -53,7 +59,7 @@ class DetectionNetwork : public DeviceNodeGroup { std::optional fps = std::nullopt, std::optional resizeMode = dai::ImgResizeMode::CROP); #ifdef DEPTHAI_HAVE_OPENCV_SUPPORT - /* + /** * @brief Build DetectionNetwork node. Connect ReplayVideo output to this node's input. Also call setNNArchive() with provided model description. * @param input: ReplayVideo node * @param modelDesc: Neural network model description @@ -215,6 +221,9 @@ class DetectionNetwork : public DeviceNodeGroup { std::vector>> getRequiredInputs() override; + /** + * Return class labels if available. + */ std::optional> getClasses() const; virtual void buildInternal() override; diff --git a/include/depthai/pipeline/node/DetectionParser.hpp b/include/depthai/pipeline/node/DetectionParser.hpp index 2a1af060a4..9d3f5ab236 100644 --- a/include/depthai/pipeline/node/DetectionParser.hpp +++ b/include/depthai/pipeline/node/DetectionParser.hpp @@ -101,8 +101,8 @@ class DetectionParser : public DeviceNodeCRTP + /** + * Set input image size from a tuple. */ void setInputImageSize(std::tuple size); @@ -145,7 +145,7 @@ class DetectionParser : public DeviceNodeCRTP& classes); - /* + /** * Sets the number of coordinates per bounding box. * @param coordinates Number of coordinates. Default is 4 */ @@ -283,6 +283,9 @@ class DetectionParser : public DeviceNodeCRTP props); /** diff --git a/include/depthai/pipeline/node/FeatureTracker.hpp b/include/depthai/pipeline/node/FeatureTracker.hpp index 4b453d3608..50f8f3e98f 100644 --- a/include/depthai/pipeline/node/FeatureTracker.hpp +++ b/include/depthai/pipeline/node/FeatureTracker.hpp @@ -27,6 +27,9 @@ class FeatureTracker : public DeviceNodeCRTP props); /** diff --git a/include/depthai/pipeline/node/IMU.hpp b/include/depthai/pipeline/node/IMU.hpp index 971fb0150f..2296de7f8e 100644 --- a/include/depthai/pipeline/node/IMU.hpp +++ b/include/depthai/pipeline/node/IMU.hpp @@ -72,9 +72,8 @@ class IMU : public DeviceNodeCRTP, public Source */ std::int32_t getMaxBatchReports() const; - /* - * Whether to perform firmware update or not. - * Default value: false. + /** + * Enable or disable firmware update behavior. */ void enableFirmwareUpdate(bool enable); }; diff --git a/include/depthai/pipeline/node/ImageManip.hpp b/include/depthai/pipeline/node/ImageManip.hpp index 6bc48c0900..bb1bd6825e 100644 --- a/include/depthai/pipeline/node/ImageManip.hpp +++ b/include/depthai/pipeline/node/ImageManip.hpp @@ -27,8 +27,14 @@ class ImageManip : public DeviceNodeCRTP props); + /** + * Build the node and return a shared pointer to it. + */ std::shared_ptr build() { return std::static_pointer_cast(shared_from_this()); } diff --git a/include/depthai/pipeline/node/NeuralAssistedStereo.hpp b/include/depthai/pipeline/node/NeuralAssistedStereo.hpp index af38bcf1da..62f7d307b8 100644 --- a/include/depthai/pipeline/node/NeuralAssistedStereo.hpp +++ b/include/depthai/pipeline/node/NeuralAssistedStereo.hpp @@ -40,6 +40,9 @@ class NeuralAssistedStereo : public DeviceNodeGroup { virtual ~NeuralAssistedStereo(); + /** + * Construct a NeuralAssistedStereo node bound to a device. + */ NeuralAssistedStereo(const std::shared_ptr& device); private: diff --git a/include/depthai/pipeline/node/NeuralDepth.hpp b/include/depthai/pipeline/node/NeuralDepth.hpp index 38a40d88d8..14bb7f0607 100644 --- a/include/depthai/pipeline/node/NeuralDepth.hpp +++ b/include/depthai/pipeline/node/NeuralDepth.hpp @@ -38,6 +38,9 @@ class NeuralDepth : public DeviceNodeCRTP initialConfig = std::make_shared(); + /** + * Build node by linking left/right inputs and selecting model. + */ std::shared_ptr build(Output& left, Output& right, DeviceModelZoo model = DeviceModelZoo::NEURAL_DEPTH_SMALL); Subnode sync{*this, "sync"}; Subnode messageDemux{*this, "messageDemux"}; diff --git a/include/depthai/pipeline/node/SpatialDetectionNetwork.hpp b/include/depthai/pipeline/node/SpatialDetectionNetwork.hpp index 8ca0a3801c..284584b120 100644 --- a/include/depthai/pipeline/node/SpatialDetectionNetwork.hpp +++ b/include/depthai/pipeline/node/SpatialDetectionNetwork.hpp @@ -31,6 +31,9 @@ using DepthSource = std::variant, std::shared_ptr { public: + /** + * Construct a spatial detection network bound to a device. + */ explicit SpatialDetectionNetwork(const std::shared_ptr& device) : DeviceNodeCRTP(device) #ifndef DEPTHAI_INTERNAL_DEVICE_BUILD_RVC4 @@ -47,6 +50,9 @@ class SpatialDetectionNetwork : public DeviceNodeCRTP props) : DeviceNodeCRTP(std::move(props)) #ifndef DEPTHAI_INTERNAL_DEVICE_BUILD_RVC4 @@ -64,6 +70,9 @@ class SpatialDetectionNetwork : public DeviceNodeCRTP props, bool confMode) : DeviceNodeCRTP(std::move(props), confMode) #ifndef DEPTHAI_INTERNAL_DEVICE_BUILD_RVC4 @@ -81,6 +90,9 @@ class SpatialDetectionNetwork : public DeviceNodeCRTP& device, std::unique_ptr props, bool confMode) : DeviceNodeCRTP(device, std::move(props), confMode) #ifndef DEPTHAI_INTERNAL_DEVICE_BUILD_RVC4 diff --git a/include/depthai/pipeline/node/SpatialLocationCalculator.hpp b/include/depthai/pipeline/node/SpatialLocationCalculator.hpp index 19cff2281d..56afc77451 100644 --- a/include/depthai/pipeline/node/SpatialLocationCalculator.hpp +++ b/include/depthai/pipeline/node/SpatialLocationCalculator.hpp @@ -23,6 +23,9 @@ class SpatialLocationCalculator : public DeviceNodeCRTP props); /** diff --git a/include/depthai/pipeline/node/StereoDepth.hpp b/include/depthai/pipeline/node/StereoDepth.hpp index 4c66873167..8c43a5ab8e 100644 --- a/include/depthai/pipeline/node/StereoDepth.hpp +++ b/include/depthai/pipeline/node/StereoDepth.hpp @@ -42,6 +42,9 @@ class StereoDepth : public DeviceNodeCRTP build(Node::Output& left, Node::Output& right, PresetMode presetMode = PresetMode::DEFAULT) { setDefaultProfilePreset(presetMode); left.link(this->left); diff --git a/include/depthai/pipeline/node/Thermal.hpp b/include/depthai/pipeline/node/Thermal.hpp index cf6782b21c..f763fd0a19 100644 --- a/include/depthai/pipeline/node/Thermal.hpp +++ b/include/depthai/pipeline/node/Thermal.hpp @@ -26,6 +26,9 @@ class Thermal : public DeviceNodeCRTP { public: Thermal() = default; + /** + * Construct a Thermal node with properties. + */ Thermal(std::unique_ptr props); /** @@ -61,6 +64,9 @@ class Thermal : public DeviceNodeCRTP { */ CameraBoardSocket getBoardSocket() const; + /** + * Set output frames per second. + */ void setFps(float fps); private: diff --git a/include/depthai/pipeline/node/ToF.hpp b/include/depthai/pipeline/node/ToF.hpp index 9cf7dee4cc..3be1c40d05 100644 --- a/include/depthai/pipeline/node/ToF.hpp +++ b/include/depthai/pipeline/node/ToF.hpp @@ -30,6 +30,9 @@ class ToFBase : public DeviceNodeCRTP { public: ToFBase() = default; + /** + * Construct a ToFBase node with properties. + */ ToFBase(std::unique_ptr props); /** @@ -79,6 +82,9 @@ class ToFBase : public DeviceNodeCRTP { class ToF : public DeviceNodeGroup { public: + /** + * Construct a ToF composite node bound to a device. + */ ToF(const std::shared_ptr& device) : DeviceNodeGroup(device), rawDepth{tofBase->depth}, diff --git a/include/depthai/pipeline/node/UVC.hpp b/include/depthai/pipeline/node/UVC.hpp index 4622d0a903..a1c6425f79 100644 --- a/include/depthai/pipeline/node/UVC.hpp +++ b/include/depthai/pipeline/node/UVC.hpp @@ -18,6 +18,9 @@ class UVC : public DeviceNodeCRTP { public: UVC() = default; + /** + * Construct a UVC node with properties. + */ UVC(std::unique_ptr props); virtual ~UVC(); diff --git a/include/depthai/pipeline/node/VideoEncoder.hpp b/include/depthai/pipeline/node/VideoEncoder.hpp index ca4e9c2b33..f748b1fccc 100644 --- a/include/depthai/pipeline/node/VideoEncoder.hpp +++ b/include/depthai/pipeline/node/VideoEncoder.hpp @@ -15,6 +15,9 @@ class VideoEncoder : public DeviceNodeCRTP build(Node::Output& input); /** @@ -125,6 +128,9 @@ class VideoEncoder : public DeviceNodeCRTP { Vpp() = default; + /** + * Construct a Vpp node with properties. + */ Vpp(std::unique_ptr props); virtual ~Vpp(); + /** + * Build the node by linking required inputs. + */ std::shared_ptr build(Output& leftInput, Output& rightInput, Output& disparityInput, Output& confidenceInput); void buildInternal() override; diff --git a/include/depthai/pipeline/node/Warp.hpp b/include/depthai/pipeline/node/Warp.hpp index 7caa4785b9..64a59c37a0 100644 --- a/include/depthai/pipeline/node/Warp.hpp +++ b/include/depthai/pipeline/node/Warp.hpp @@ -39,6 +39,9 @@ class Warp : public DeviceNodeCRTP { * @param size width and height in pixels */ void setOutputSize(std::tuple size); + /** + * Sets output frame size in pixels. + */ void setOutputSize(int width, int height); /** @@ -48,6 +51,9 @@ class Warp : public DeviceNodeCRTP { * @param height Height of mesh */ void setWarpMesh(const std::vector& meshData, int width, int height); + /** + * Set a custom warp mesh from x/y pairs. + */ void setWarpMesh(const std::vector>& meshData, int width, int height); /** diff --git a/include/depthai/pipeline/node/host/Display.hpp b/include/depthai/pipeline/node/host/Display.hpp index c34ed4a1cd..eb60955ec2 100644 --- a/include/depthai/pipeline/node/host/Display.hpp +++ b/include/depthai/pipeline/node/host/Display.hpp @@ -10,9 +10,12 @@ class Display : public dai::NodeCRTP { std::string name; public: + /** + * Construct a display node with an optional window name. + */ explicit Display(std::string name = "Display"); Input input{*this, {}}; void run() override; }; } // namespace node -} // namespace dai \ No newline at end of file +} // namespace dai diff --git a/include/depthai/pipeline/node/host/HostNode.hpp b/include/depthai/pipeline/node/host/HostNode.hpp index d87e7036a3..125de211a1 100644 --- a/include/depthai/pipeline/node/host/HostNode.hpp +++ b/include/depthai/pipeline/node/host/HostNode.hpp @@ -37,9 +37,15 @@ class HostNode : public ThreadedHostNode { sendProcessToPipeline = send; } + /** + * Sync on host by enabling host-side synchronization. + */ void runSyncingOnHost() { syncOnHost = true; } + /** + * Sync on device by disabling host-side synchronization. + */ void runSyncingOnDevice() { syncOnHost = false; } diff --git a/include/depthai/pipeline/node/host/RGBD.hpp b/include/depthai/pipeline/node/host/RGBD.hpp index d7f00b340e..239b42d945 100644 --- a/include/depthai/pipeline/node/host/RGBD.hpp +++ b/include/depthai/pipeline/node/host/RGBD.hpp @@ -30,6 +30,9 @@ class RGBD : public NodeCRTP { public: constexpr static const char* NAME = "RGBD"; + /** + * Construct an RGBD host node. + */ RGBD(); ~RGBD(); Subnode sync{*this, "sync"}; @@ -49,6 +52,9 @@ class RGBD : public NodeCRTP { */ Output rgbd{*this, {"rgbd", DEFAULT_GROUP, {{DatatypeEnum::RGBDData, true}}}}; + /** + * Build the RGBD node. + */ std::shared_ptr build(); /** @@ -73,6 +79,9 @@ class RGBD : public NodeCRTP { std::pair frameSize = std::make_pair(640, 400), std::optional fps = std::nullopt); + /** + * Set depth unit for point cloud output. + */ void setDepthUnit(StereoDepthConfig::AlgorithmControl::DepthUnit depthUnit); /** * @brief Use single-threaded CPU for processing diff --git a/include/depthai/pipeline/node/host/Record.hpp b/include/depthai/pipeline/node/host/Record.hpp index f197565037..2223792dac 100644 --- a/include/depthai/pipeline/node/host/Record.hpp +++ b/include/depthai/pipeline/node/host/Record.hpp @@ -40,13 +40,34 @@ class RecordVideo : public NodeCRTP { void run() override; + /** + * Get metadata output file path. + */ std::filesystem::path getRecordMetadataFile() const; + /** + * Get video output file path. + */ std::filesystem::path getRecordVideoFile() const; + /** + * Get current compression level. + */ CompressionLevel getCompressionLevel() const; + /** + * Set metadata output file path. + */ RecordVideo& setRecordMetadataFile(const std::filesystem::path& recordFile); + /** + * Set video output file path. + */ RecordVideo& setRecordVideoFile(const std::filesystem::path& recordFile); + /** + * Set compression level. + */ RecordVideo& setCompressionLevel(CompressionLevel compressionLevel); + /** + * Set target frames per second. + */ RecordVideo& setFps(unsigned int fps); private: @@ -75,10 +96,22 @@ class RecordMetadataOnly : public NodeCRTP void run() override; + /** + * Get record output file path. + */ std::filesystem::path getRecordFile() const; + /** + * Get current compression level. + */ CompressionLevel getCompressionLevel() const; + /** + * Set record output file path. + */ RecordMetadataOnly& setRecordFile(const std::filesystem::path& recordFile); + /** + * Set compression level. + */ RecordMetadataOnly& setCompressionLevel(CompressionLevel compressionLevel); private: diff --git a/include/depthai/pipeline/node/host/Replay.hpp b/include/depthai/pipeline/node/host/Replay.hpp index 0f3b69358f..8e615236a1 100644 --- a/include/depthai/pipeline/node/host/Replay.hpp +++ b/include/depthai/pipeline/node/host/Replay.hpp @@ -44,19 +44,58 @@ class ReplayVideo : public NodeCRTP { void run() override; + /** + * Get metadata input file path. + */ std::filesystem::path getReplayMetadataFile() const; + /** + * Get video input file path. + */ std::filesystem::path getReplayVideoFile() const; + /** + * Get output frame type. + */ ImgFrame::Type getOutFrameType() const; + /** + * Get output frame size. + */ std::tuple getSize() const; + /** + * Get replay FPS. + */ float getFps() const; + /** + * Return whether replay loops. + */ bool getLoop() const; + /** + * Set metadata input file path. + */ ReplayVideo& setReplayMetadataFile(const std::filesystem::path& replayFile); + /** + * Set video input file path. + */ ReplayVideo& setReplayVideoFile(const std::filesystem::path& replayVideo); + /** + * Set output frame type. + */ ReplayVideo& setOutFrameType(ImgFrame::Type outFrameType); + /** + * Set output frame size. + */ ReplayVideo& setSize(std::tuple size); + /** + * Set output frame size. + */ ReplayVideo& setSize(int width, int height); + /** + * Set replay FPS. + */ ReplayVideo& setFps(float fps); + /** + * Enable or disable looping. + */ ReplayVideo& setLoop(bool loop); }; @@ -82,12 +121,30 @@ class ReplayMetadataOnly : public NodeCRTP void run() override; + /** + * Get replay file path. + */ std::filesystem::path getReplayFile() const; + /** + * Get replay FPS. + */ float getFps() const; + /** + * Return whether replay loops. + */ bool getLoop() const; + /** + * Set replay file path. + */ ReplayMetadataOnly& setReplayFile(const std::filesystem::path& replayFile); + /** + * Set replay FPS. + */ ReplayMetadataOnly& setFps(float fps); + /** + * Enable or disable looping. + */ ReplayMetadataOnly& setLoop(bool loop); }; diff --git a/include/depthai/rtabmap/RTABMapSLAM.hpp b/include/depthai/rtabmap/RTABMapSLAM.hpp index 50319ca025..231c633b85 100644 --- a/include/depthai/rtabmap/RTABMapSLAM.hpp +++ b/include/depthai/rtabmap/RTABMapSLAM.hpp @@ -166,9 +166,15 @@ class RTABMapSLAM : public dai::NodeCRTP transform) { localTransform = transform->getRTABMapTransform(); } + /** + * Get transform between the device and world frames. + */ std::shared_ptr getLocalTransform() { return std::make_shared(localTransform); } diff --git a/include/depthai/rtabmap/RTABMapVIO.hpp b/include/depthai/rtabmap/RTABMapVIO.hpp index b2f1758d2a..ec382a1559 100644 --- a/include/depthai/rtabmap/RTABMapVIO.hpp +++ b/include/depthai/rtabmap/RTABMapVIO.hpp @@ -77,6 +77,9 @@ class RTABMapVIO : public NodeCRTP { */ void setUseFeatures(bool use); + /** + * Set transform between the device and world frames. + */ void setLocalTransform(std::shared_ptr transform) { localTransform = transform->getRTABMapTransform(); } diff --git a/include/depthai/xlink/XLinkConnection.hpp b/include/depthai/xlink/XLinkConnection.hpp index 24eaaf63a0..89d59ea892 100644 --- a/include/depthai/xlink/XLinkConnection.hpp +++ b/include/depthai/xlink/XLinkConnection.hpp @@ -26,16 +26,31 @@ namespace dai { */ struct DeviceInfo { DeviceInfo() = default; + /** + * Construct device info from explicit fields. + */ DeviceInfo(std::string name, std::string deviceId, XLinkDeviceState_t state, XLinkProtocol_t protocol, XLinkPlatform_t platform, XLinkError_t status); /** * Creates a DeviceInfo by checking whether supplied parameter is a DeviceID or IP/USB name * @param deviceIdOrName Either DeviceId, IP Address or USB port name */ explicit DeviceInfo(std::string deviceIdOrName); + /** + * Construct device info from an XLink device descriptor. + */ explicit DeviceInfo(const deviceDesc_t& desc); + /** + * Return the underlying XLink device descriptor. + */ deviceDesc_t getXLinkDeviceDesc() const; [[deprecated("Use getDeviceId() instead")]] std::string getMxId() const; + /** + * Return device id string. + */ std::string getDeviceId() const; + /** + * Return a string representation for logging. + */ std::string toString() const; std::string name = ""; @@ -95,15 +110,33 @@ class XLinkConnection { */ static ProfilingData getGlobalProfilingData(); + /** + * Construct a connection using a provided mvcmd binary. + */ XLinkConnection(const DeviceInfo& deviceDesc, std::vector mvcmdBinary, XLinkDeviceState_t expectedState = X_LINK_BOOTED); + /** + * Construct a connection using an mvcmd path. + */ XLinkConnection(const DeviceInfo& deviceDesc, std::filesystem::path pathToMvcmd, XLinkDeviceState_t expectedState = X_LINK_BOOTED); + /** + * Construct a connection to an already booted device. + */ explicit XLinkConnection(const DeviceInfo& deviceDesc, XLinkDeviceState_t expectedState = X_LINK_BOOTED); ~XLinkConnection(); + /** + * Configure reboot on destruction. + */ void setRebootOnDestruction(bool reboot); + /** + * Return whether reboot on destruction is enabled. + */ bool getRebootOnDestruction() const; + /** + * Return the XLink link id. + */ int getLinkId() const; /** diff --git a/include/depthai/xlink/XLinkStream.hpp b/include/depthai/xlink/XLinkStream.hpp index d53ef21e0b..9e0fe51c94 100644 --- a/include/depthai/xlink/XLinkStream.hpp +++ b/include/depthai/xlink/XLinkStream.hpp @@ -22,10 +22,20 @@ namespace dai { class StreamPacketDesc : public streamPacketDesc_t { public: + /** + * Construct an empty stream packet descriptor. + */ StreamPacketDesc() noexcept : streamPacketDesc_t{nullptr, 0, -1, {}, {}} {}; + /** Deleted copy constructor. */ StreamPacketDesc(const StreamPacketDesc&) = delete; + /** + * Move-construct a stream packet descriptor. + */ StreamPacketDesc(StreamPacketDesc&& other) noexcept; StreamPacketDesc& operator=(const StreamPacketDesc&) = delete; + /** + * Move-assign a stream packet descriptor. + */ StreamPacketDesc& operator=(StreamPacketDesc&& other) noexcept; ~StreamPacketDesc() noexcept; }; @@ -35,9 +45,15 @@ class StreamPacketMemory : public StreamPacketDesc, public Memory { public: StreamPacketMemory() = default; + /** + * Construct memory wrapper from a moved packet descriptor. + */ StreamPacketMemory(StreamPacketDesc&& d) : StreamPacketDesc(std::move(d)) { size = length; } + /** + * Assign memory wrapper from a moved packet descriptor. + */ StreamPacketMemory& operator=(StreamPacketDesc&& d) { StreamPacketDesc::operator=(std::move(d)); size = length; @@ -60,36 +76,106 @@ class XLinkStream { streamId_t streamId{INVALID_STREAM_ID}; public: + /** + * Construct an XLink stream with a maximum write size. + */ XLinkStream(const std::shared_ptr conn, const std::string& name, std::size_t maxWriteSize); + /** Deleted copy constructor. */ XLinkStream(const XLinkStream&) = delete; + /** + * Move-construct an XLink stream. + */ XLinkStream(XLinkStream&& stream); XLinkStream& operator=(const XLinkStream&) = delete; + /** + * Move-assign an XLink stream. + */ XLinkStream& operator=(XLinkStream&& stream); ~XLinkStream(); // Blocking + /** + * Write two buffers to the stream (blocking). + */ void write(span data, span data2); + /** + * Write a buffer to the stream (blocking). + */ void write(span data); + /** + * Write data from a file descriptor (blocking). + */ void write(long fd); + /** + * Write a file descriptor and an extra buffer (blocking). + */ void write(long fd, span data); + /** + * Write raw data to the stream (blocking). + */ void write(const void* data, std::size_t size); + /** + * Read data from the stream (blocking). + */ std::vector read(); + /** + * Read data from the stream with timeout (blocking). + */ std::vector read(std::chrono::milliseconds timeout); + /** + * Read data and capture receive timestamp (blocking). + */ std::vector read(XLinkTimespec& timestampReceived); + /** + * Read data into a provided buffer (blocking). + */ void read(std::vector& data); + /** + * Read data into a buffer and return file descriptor (blocking). + */ void read(std::vector& data, long& fd); + /** + * Read data into a buffer and capture receive timestamp (blocking). + */ void read(std::vector& data, XLinkTimespec& timestampReceived); + /** + * Read data into a buffer and return file descriptor and timestamp (blocking). + */ void read(std::vector& data, long& fd, XLinkTimespec& timestampReceived); // split write helper + /** + * Write data in chunks of a given split size. + */ void writeSplit(const void* data, std::size_t size, std::size_t split); + /** + * Write vector data in chunks of a given split size. + */ void writeSplit(const std::vector& data, std::size_t split); + /** + * Read a packet into a movable descriptor. + */ StreamPacketDesc readMove(); // Timeout + /** + * Write raw data with a timeout. + */ bool write(const void* data, std::size_t size, std::chrono::milliseconds timeout); + /** + * Write raw data with a timeout. + */ bool write(const std::uint8_t* data, std::size_t size, std::chrono::milliseconds timeout); + /** + * Write vector data with a timeout. + */ bool write(const std::vector& data, std::chrono::milliseconds timeout); + /** + * Read data with a timeout into a buffer. + */ bool read(std::vector& data, std::chrono::milliseconds timeout); + /** + * Read a packet with a timeout into a descriptor. + */ bool readMove(StreamPacketDesc& packet, const std::chrono::milliseconds timeout); // TODO optional readMove(timeout) -or- tuple readMove(timeout) @@ -100,7 +186,13 @@ class XLinkStream { // deprecated; unsafe leads to memory violations and/or memory leaks [[deprecated]] void readRawRelease(); + /** + * Return the stream id. + */ streamId_t getStreamId() const; + /** + * Return the stream name. + */ std::string getStreamName() const; }; @@ -111,17 +203,26 @@ struct XLinkError : public std::runtime_error { using std::runtime_error::runtime_error; ~XLinkError() override; + /** + * Construct an XLink error with status and stream name. + */ XLinkError(XLinkError_t statusID, std::string stream, const std::string& message) : runtime_error(message), status(statusID), streamName(std::move(stream)) {} }; struct XLinkReadError : public XLinkError { using XLinkError = XLinkError; ~XLinkReadError() override; + /** + * Construct a read error from status and stream name. + */ XLinkReadError(XLinkError_t status, const std::string& stream); }; struct XLinkWriteError : public XLinkError { using XLinkError = XLinkError; ~XLinkWriteError() override; + /** + * Construct a write error from status and stream name. + */ XLinkWriteError(XLinkError_t status, const std::string& stream); }; diff --git a/scripts/check_public_docs.py b/scripts/check_public_docs.py new file mode 100644 index 0000000000..d46d2af018 --- /dev/null +++ b/scripts/check_public_docs.py @@ -0,0 +1,242 @@ +#!/usr/bin/env python3 +import argparse +import os +import re +import sys +from dataclasses import dataclass +from pathlib import Path +from typing import Iterator, List, Optional, Tuple + + +DOC_LINE_RE = re.compile(r"\s*///") +DOC_BLOCK_START_RE = re.compile(r"\s*/\*\*") +DOC_BLOCK_END_RE = re.compile(r".*\*/\s*$") +ACCESS_RE = re.compile(r"^\s*(public|protected|private)\s*:\s*$") +IGNORE_LINE_RE = re.compile(r"\bDEPTHAI_SERIALIZE(?:_EXT)?\s*\(") +IGNORE_OVERRIDE_RE = re.compile(r"\boverride\b") +IGNORE_VIRTUAL_RE = re.compile(r"\bvirtual\b") +IGNORE_METHOD_NAME_RE = re.compile(r"^(getLINKiD|getLinkId)$") +IGNORE_CLASS_NAME_RE = re.compile(r".*(Impl|Internal|Private)$") +IGNORE_DIR_PARTS = { + "/pipeline/node/internal/", +} +IGNORE_FILES = { + "CapatibulityRange.hpp", + "CapabilityRange.hpp", + "Zoo.hpp", + "OpenVINO.hpp", + "Points3fRGBA.hpp", + "Point3fRGBA.hpp", + "Size2f.hpp", + "Variant.hpp", + "optional.hpp", + "ADatatypeSharedPtrSerialization.hpp", + "TesorInfo.hpp", + "TensorInfo.hpp", + "variant.hpp", +} +IGNORE_FILE_SUBSTRINGS = { + "Variant", +} +IGNORE_CONSTRUCTORS_FOR = { + "ImgTransformation", +} + +# Heuristic for function declarations/definitions in headers. +FUNC_RE = re.compile( + r""" + ^\s* + (?:template\s*<[^>]*>\s*)? # template + (?:inline\s+|virtual\s+|static\s+|constexpr\s+|friend\s+|explicit\s+|final\s+|override\s+)* # specifiers + (?:[\w:<>~*&]+(?:\s+[\w:<>~*&]+)*) # return type (requires at least one token) + \s+ # space between return type and name + \b([~\w:]+)\s* # name + \([^;{)]*\) # params + (?:\s*const|\s*noexcept|\s*override|\s*final|\s*=\s*0|\s*&|\s*&&|\s*->\s*[\w:<>]+)* # qualifiers + \s*(?:;|\{) # end or inline body + """, + re.VERBOSE, +) + + +@dataclass +class Context: + brace_depth: int + access: str + class_name: str + + +def iter_headers(root: Path) -> Iterator[Path]: + for dirpath, _, filenames in os.walk(root): + normalized = dirpath.replace("\\", "/") + if "/utility/" in normalized or normalized.endswith("/utility"): + continue + if any(part in normalized for part in IGNORE_DIR_PARTS) or normalized.endswith("/pipeline/node/internal"): + continue + for name in filenames: + if name in IGNORE_FILES or any(sub in name for sub in IGNORE_FILE_SUBSTRINGS): + continue + if name.endswith((".hpp", ".h")): + yield Path(dirpath) / name + + +def is_class_or_struct(line: str) -> Optional[Tuple[str, str]]: + match = re.search(r"\b(class|struct)\s+([A-Za-z_]\w*)\b", line) + if not match: + return None + return match.group(1), match.group(2) + + +def update_doc_state( + line: str, + in_doc_block: bool, + last_doc_end: Optional[int], + line_no: int, +) -> Tuple[bool, Optional[int]]: + if in_doc_block: + if DOC_BLOCK_END_RE.search(line): + return False, line_no + return True, last_doc_end + + if DOC_BLOCK_START_RE.search(line): + if DOC_BLOCK_END_RE.search(line): + return False, line_no + return True, last_doc_end + + if DOC_LINE_RE.search(line): + return False, line_no + + return False, last_doc_end + + +def is_method_candidate(line: str, class_name: str) -> Optional[str]: + stripped = line.lstrip() + if re.match(r"^[A-Za-z_]\w*\s+\w+\s*\([^)]*\)\s*;", stripped): + return None + if stripped.startswith("{") or stripped.startswith("}"): + return None + if stripped.startswith(("if ", "for ", "while ", "switch ", "catch ", "return ", "throw ", "else ", "do ", "case ", "default ")): + return None + if stripped.startswith(("//", "/*", "*", ":", ",")): + return None + if class_name: + ctor_re = rf"^\s*(?:explicit\s+)?{re.escape(class_name)}\s*\(" + if re.match(ctor_re, line): + if " = default" in line or "= default" in line: + return None + if class_name in IGNORE_CONSTRUCTORS_FOR: + return None + return class_name + match = FUNC_RE.match(line) + if not match: + return None + return match.group(1) + + +def has_intervening_code(lines: List[str], start: int, end: int) -> bool: + for idx in range(start, end): + text = lines[idx].strip() + if not text: + continue + if text.startswith("template"): + continue + if text in {"{", "}", "};"}: + continue + if text.startswith("//") or text.startswith("/*") or text.startswith("*"): + continue + return True + return False + + +def check_file(path: Path) -> List[Tuple[str, int, str]]: + lines = path.read_text(encoding="utf-8", errors="replace").splitlines() + results: List[Tuple[str, int, str]] = [] + ctx_stack: List[Context] = [] + brace_depth = 0 + access = "global" + last_doc_end: Optional[int] = None + in_doc_block = False + + for idx, line in enumerate(lines): + line_no = idx + 1 + + in_doc_block, last_doc_end = update_doc_state(line, in_doc_block, last_doc_end, line_no) + + access_match = ACCESS_RE.match(line) + if access_match and ctx_stack: + access = access_match.group(1) + ctx_stack[-1].access = access + + decl = is_class_or_struct(line) + if decl and "{" in line: + decl_kind, class_name = decl + default_access = "public" if decl_kind == "struct" else "private" + ctx_stack.append( + Context( + brace_depth=brace_depth + line.count("{") - line.count("}"), + access=default_access, + class_name=class_name, + ) + ) + access = default_access + + method_name = is_method_candidate(line, ctx_stack[-1].class_name if ctx_stack else "") + if method_name and ctx_stack and ctx_stack[-1].access == "public": + if IGNORE_LINE_RE.search(line): + continue + if IGNORE_OVERRIDE_RE.search(line): + continue + if IGNORE_VIRTUAL_RE.search(line): + continue + if IGNORE_METHOD_NAME_RE.match(method_name): + continue + if IGNORE_CLASS_NAME_RE.match(ctx_stack[-1].class_name): + continue + documented = False + if last_doc_end is not None: + doc_end_idx = last_doc_end - 1 + if not has_intervening_code(lines, doc_end_idx + 1, idx): + documented = True + if not documented: + results.append((str(path), line_no, line.strip())) + + brace_depth += line.count("{") - line.count("}") + while ctx_stack and brace_depth < ctx_stack[-1].brace_depth: + ctx_stack.pop() + access = ctx_stack[-1].access if ctx_stack else "global" + + return results + + +def main() -> int: + parser = argparse.ArgumentParser( + description="Report public methods without adjacent doc comments." + ) + parser.add_argument( + "root", + nargs="?", + default="include/depthai", + help="Root directory to scan (default: include/depthai)", + ) + args = parser.parse_args() + + root = Path(args.root) + if not root.exists(): + print(f"error: root not found: {root}", file=sys.stderr) + return 2 + + missing = [] + for header in iter_headers(root): + missing.extend(check_file(header)) + + for path, line_no, sig in missing: + print(f"{path}:{line_no}: {sig}") + + if missing: + print(f"error: {len(missing)} public methods are missing docs", file=sys.stderr) + return 1 + return 0 + + +if __name__ == "__main__": + raise SystemExit(main())