diff --git a/depthai_ros_driver/include/depthai_ros_driver/dai_nodes/nn/detection.hpp b/depthai_ros_driver/include/depthai_ros_driver/dai_nodes/nn/detection.hpp index fbaeb3cc..5167b4fd 100644 --- a/depthai_ros_driver/include/depthai_ros_driver/dai_nodes/nn/detection.hpp +++ b/depthai_ros_driver/include/depthai_ros_driver/dai_nodes/nn/detection.hpp @@ -76,7 +76,9 @@ class Detection : public BaseNode { height)); ptPub = image_transport::create_camera_publisher(getROSNode(), "~/" + getName() + "/passthrough/image_raw"); - ptQ->addCallback(std::bind(sensor_helpers::imgCB, std::placeholders::_1, std::placeholders::_2, *imageConverter, ptPub, infoManager)); + ptQ->addCallback([this](const std::string& name, const std::shared_ptr& data) { + sensor_helpers::imgCB(name, data, *imageConverter, ptPub, infoManager); + }); } }; void link(dai::Node::Input in, int /*linkType*/) override { @@ -140,4 +142,4 @@ class Detection : public BaseNode { } // namespace nn } // namespace dai_nodes -} // namespace depthai_ros_driver \ No newline at end of file +} // namespace depthai_ros_driver diff --git a/depthai_ros_driver/include/depthai_ros_driver/dai_nodes/nn/spatial_detection.hpp b/depthai_ros_driver/include/depthai_ros_driver/dai_nodes/nn/spatial_detection.hpp index 4cf8e620..865e0930 100644 --- a/depthai_ros_driver/include/depthai_ros_driver/dai_nodes/nn/spatial_detection.hpp +++ b/depthai_ros_driver/include/depthai_ros_driver/dai_nodes/nn/spatial_detection.hpp @@ -78,7 +78,9 @@ class SpatialDetection : public BaseNode { height)); ptPub = image_transport::create_camera_publisher(getROSNode(), "~/" + getName() + "/passthrough/image_raw"); - ptQ->addCallback(std::bind(sensor_helpers::imgCB, std::placeholders::_1, std::placeholders::_2, *ptImageConverter, ptPub, ptInfoMan)); + ptQ->addCallback([this](const std::string& name, const std::shared_ptr& data) { + sensor_helpers::imgCB(name, data, *ptImageConverter, ptPub, ptInfoMan); + }); } if(ph->getParam("i_enable_passthrough_depth")) { @@ -98,8 +100,9 @@ class SpatialDetection : public BaseNode { getROSNode()->get_parameter("stereo.i_height").as_int())); ptDepthPub = image_transport::create_camera_publisher(getROSNode(), "~/" + getName() + "/passthrough_depth/image_raw"); - ptDepthQ->addCallback( - std::bind(sensor_helpers::imgCB, std::placeholders::_1, std::placeholders::_2, *ptDepthImageConverter, ptDepthPub, ptDepthInfoMan)); + ptDepthQ->addCallback([this](const std::string& name, const std::shared_ptr& data) { + sensor_helpers::imgCB(name, data, *ptDepthImageConverter, ptDepthPub, ptDepthInfoMan); + }); } }; void link(dai::Node::Input in, int /*linkType = 0*/) override { @@ -173,4 +176,4 @@ class SpatialDetection : public BaseNode { } // namespace nn } // namespace dai_nodes -} // namespace depthai_ros_driver \ No newline at end of file +} // namespace depthai_ros_driver diff --git a/depthai_ros_driver/include/depthai_ros_driver/dai_nodes/sensors/mono.hpp b/depthai_ros_driver/include/depthai_ros_driver/dai_nodes/sensors/mono.hpp index 76bf1bcb..27df3f18 100644 --- a/depthai_ros_driver/include/depthai_ros_driver/dai_nodes/sensors/mono.hpp +++ b/depthai_ros_driver/include/depthai_ros_driver/dai_nodes/sensors/mono.hpp @@ -4,6 +4,7 @@ #include "depthai_ros_driver/dai_nodes/sensors/sensor_helpers.hpp" #include "image_transport/camera_publisher.hpp" #include "image_transport/image_transport.hpp" +#include "image_transport/publisher.hpp" namespace dai { class Pipeline; @@ -13,6 +14,7 @@ class DataInputQueue; class ADatatype; namespace node { class MonoCamera; +class EdgeDetector; class XLinkIn; class XLinkOut; class VideoEncoder; @@ -56,16 +58,21 @@ class Mono : public BaseNode { private: std::unique_ptr imageConverter; image_transport::CameraPublisher monoPub; + image_transport::Publisher edgesPub; std::shared_ptr infoManager; std::shared_ptr monoCamNode; + std::shared_ptr edgeDetectorNode; std::shared_ptr videoEnc; + std::shared_ptr edgesVideoEnc; std::unique_ptr ph; std::shared_ptr monoQ; + std::shared_ptr edgesQ; std::shared_ptr controlQ; std::shared_ptr xoutMono; + std::shared_ptr xoutEdges; std::shared_ptr xinControl; - std::string monoQName, controlQName; + std::string monoQName, edgesQName, controlQName; }; } // namespace dai_nodes -} // namespace depthai_ros_driver \ No newline at end of file +} // namespace depthai_ros_driver diff --git a/depthai_ros_driver/include/depthai_ros_driver/dai_nodes/sensors/rgb.hpp b/depthai_ros_driver/include/depthai_ros_driver/dai_nodes/sensors/rgb.hpp index 8414105c..16a4decf 100644 --- a/depthai_ros_driver/include/depthai_ros_driver/dai_nodes/sensors/rgb.hpp +++ b/depthai_ros_driver/include/depthai_ros_driver/dai_nodes/sensors/rgb.hpp @@ -3,6 +3,7 @@ #include "depthai_ros_driver/dai_nodes/base_node.hpp" #include "image_transport/camera_publisher.hpp" #include "image_transport/image_transport.hpp" +#include "image_transport/publisher.hpp" #include "sensor_msgs/msg/camera_info.hpp" namespace dai { @@ -14,6 +15,7 @@ enum class CameraBoardSocket; class ADatatype; namespace node { class ColorCamera; +class EdgeDetector; class XLinkIn; class XLinkOut; class VideoEncoder; @@ -61,16 +63,18 @@ class RGB : public BaseNode { private: std::unique_ptr imageConverter; image_transport::CameraPublisher rgbPub, previewPub; + image_transport::Publisher edgesPub; std::shared_ptr infoManager, previewInfoManager; std::shared_ptr colorCamNode; - std::shared_ptr videoEnc; + std::shared_ptr edgeDetectorNode; + std::shared_ptr videoEnc, edgesVideoEnc; std::unique_ptr ph; - std::shared_ptr colorQ, previewQ; + std::shared_ptr colorQ, previewQ, edgesQ; std::shared_ptr controlQ; - std::shared_ptr xoutColor, xoutPreview; + std::shared_ptr xoutColor, xoutPreview, xoutEdges; std::shared_ptr xinControl; - std::string ispQName, previewQName, controlQName; + std::string ispQName, previewQName, controlQName, edgesQName; }; } // namespace dai_nodes -} // namespace depthai_ros_driver \ No newline at end of file +} // namespace depthai_ros_driver diff --git a/depthai_ros_driver/include/depthai_ros_driver/dai_nodes/sensors/sensor_helpers.hpp b/depthai_ros_driver/include/depthai_ros_driver/dai_nodes/sensors/sensor_helpers.hpp index 06c2b7e6..52b521ad 100644 --- a/depthai_ros_driver/include/depthai_ros_driver/dai_nodes/sensors/sensor_helpers.hpp +++ b/depthai_ros_driver/include/depthai_ros_driver/dai_nodes/sensors/sensor_helpers.hpp @@ -9,6 +9,7 @@ #include "depthai-shared/properties/VideoEncoderProperties.hpp" #include "depthai/pipeline/datatype/ADatatype.hpp" #include "image_transport/camera_publisher.hpp" +#include "image_transport/publisher.hpp" #include "sensor_msgs/msg/camera_info.hpp" namespace dai { @@ -44,12 +45,24 @@ struct ImageSensor { }; extern std::vector availableSensors; +void imgCB(const std::string& /*name*/, + const std::shared_ptr& data, + dai::ros::ImageConverter& converter, + image_transport::Publisher& pub); + void imgCB(const std::string& /*name*/, const std::shared_ptr& data, dai::ros::ImageConverter& converter, image_transport::CameraPublisher& pub, std::shared_ptr infoManager); +void compressedImgCB(const std::string& /*name*/, + const std::shared_ptr& data, + dai::ros::ImageConverter& converter, + image_transport::Publisher& pub, + std::shared_ptr infoManager, + dai::RawImgFrame::Type dataType); + void compressedImgCB(const std::string& /*name*/, const std::shared_ptr& data, dai::ros::ImageConverter& converter, @@ -68,4 +81,4 @@ std::shared_ptr createEncoder(std::shared_ptr left; std::unique_ptr right; std::unique_ptr ph; + std::shared_ptr configQ; std::shared_ptr stereoQ, leftRectQ, rightRectQ; + std::shared_ptr xinConfig; std::shared_ptr xoutStereo, xoutLeftRect, xoutRightRect; - std::string stereoQName, leftRectQName, rightRectQName; + std::string stereoQName, leftRectQName, rightRectQName, configQName; StereoSensorInfo leftSensInfo, rightSensInfo; + std::shared_ptr config; }; } // namespace dai_nodes -} // namespace depthai_ros_driver \ No newline at end of file +} // namespace depthai_ros_driver diff --git a/depthai_ros_driver/include/depthai_ros_driver/param_handlers/imu_param_handler.hpp b/depthai_ros_driver/include/depthai_ros_driver/param_handlers/imu_param_handler.hpp index 713bf148..2bd6d8ed 100644 --- a/depthai_ros_driver/include/depthai_ros_driver/param_handlers/imu_param_handler.hpp +++ b/depthai_ros_driver/include/depthai_ros_driver/param_handlers/imu_param_handler.hpp @@ -9,6 +9,7 @@ #include "depthai_ros_driver/param_handlers/base_param_handler.hpp" namespace dai { +enum class IMUSensor; namespace node { class IMU; } @@ -30,10 +31,14 @@ class ImuParamHandler : public BaseParamHandler { ~ImuParamHandler(); void declareParams(std::shared_ptr imu, const std::string& imuType); dai::CameraControl setRuntimeParams(const std::vector& params) override; + std::unordered_map imuAccelerometerModeMap; + std::unordered_map imuGyroscopeModeMap; + std::unordered_map imuMagnetometerModeMap; + std::unordered_map imuRotationModeMap; std::unordered_map imuSyncMethodMap; std::unordered_map imuMessagetTypeMap; imu::ImuMsgType getMsgType(); dai::ros::ImuSyncMethod getSyncMethod(); }; } // namespace param_handlers -} // namespace depthai_ros_driver \ No newline at end of file +} // namespace depthai_ros_driver diff --git a/depthai_ros_driver/include/depthai_ros_driver/param_handlers/sensor_param_handler.hpp b/depthai_ros_driver/include/depthai_ros_driver/param_handlers/sensor_param_handler.hpp index 87aa3ed2..056ec356 100644 --- a/depthai_ros_driver/include/depthai_ros_driver/param_handlers/sensor_param_handler.hpp +++ b/depthai_ros_driver/include/depthai_ros_driver/param_handlers/sensor_param_handler.hpp @@ -14,6 +14,7 @@ namespace dai { namespace node { class MonoCamera; class ColorCamera; +class EdgeDetector; } // namespace node } // namespace dai @@ -29,6 +30,7 @@ class SensorParamHandler : public BaseParamHandler { explicit SensorParamHandler(rclcpp::Node* node, const std::string& name); ~SensorParamHandler(); void declareCommonParams(); + void declareParams(std::shared_ptr edgeDetector); void declareParams(std::shared_ptr monoCam, dai::CameraBoardSocket socket, dai_nodes::sensor_helpers::ImageSensor sensor, @@ -45,4 +47,4 @@ class SensorParamHandler : public BaseParamHandler { std::unordered_map fSyncModeMap; }; } // namespace param_handlers -} // namespace depthai_ros_driver \ No newline at end of file +} // namespace depthai_ros_driver diff --git a/depthai_ros_driver/include/depthai_ros_driver/utils.hpp b/depthai_ros_driver/include/depthai_ros_driver/utils.hpp index b370dd3b..6c7a6a0a 100644 --- a/depthai_ros_driver/include/depthai_ros_driver/utils.hpp +++ b/depthai_ros_driver/include/depthai_ros_driver/utils.hpp @@ -24,4 +24,4 @@ T getValFromMap(const std::string& name, const std::unordered_map device) { imageManip->initialConfig.getResizeWidth())); ptPub = image_transport::create_camera_publisher(getROSNode(), "~/" + getName() + "/passthrough/image_raw"); - ptQ->addCallback(std::bind(sensor_helpers::imgCB, std::placeholders::_1, std::placeholders::_2, *imageConverter, ptPub, infoManager)); + ptQ->addCallback([this](const std::string& name, const std::shared_ptr& data) { + sensor_helpers::imgCB(name, data, *imageConverter, ptPub, infoManager); + }); } } @@ -132,4 +134,4 @@ void Segmentation::updateParams(const std::vector& params) { } } // namespace nn } // namespace dai_nodes -} // namespace depthai_ros_driver \ No newline at end of file +} // namespace depthai_ros_driver diff --git a/depthai_ros_driver/src/dai_nodes/sensors/mono.cpp b/depthai_ros_driver/src/dai_nodes/sensors/mono.cpp index 66de75a1..e2968d88 100644 --- a/depthai_ros_driver/src/dai_nodes/sensors/mono.cpp +++ b/depthai_ros_driver/src/dai_nodes/sensors/mono.cpp @@ -4,6 +4,7 @@ #include "depthai/device/DataQueue.hpp" #include "depthai/device/Device.hpp" #include "depthai/pipeline/Pipeline.hpp" +#include "depthai/pipeline/node/EdgeDetector.hpp" #include "depthai/pipeline/node/MonoCamera.hpp" #include "depthai/pipeline/node/VideoEncoder.hpp" #include "depthai/pipeline/node/XLinkIn.hpp" @@ -12,6 +13,7 @@ #include "depthai_ros_driver/param_handlers/sensor_param_handler.hpp" #include "image_transport/camera_publisher.hpp" #include "image_transport/image_transport.hpp" +#include "image_transport/publisher.hpp" #include "rclcpp/node.hpp" namespace depthai_ros_driver { @@ -28,16 +30,27 @@ Mono::Mono(const std::string& daiNodeName, monoCamNode = pipeline->create(); ph = std::make_unique(node, daiNodeName); ph->declareParams(monoCamNode, socket, sensor, publish); + if(ph->getParam("i_enable_edge_detection")) { + edgeDetectorNode = pipeline->create(); + ph->declareParams(edgeDetectorNode); + } setXinXout(pipeline); RCLCPP_DEBUG(node->get_logger(), "Node %s created", daiNodeName.c_str()); } Mono::~Mono() = default; void Mono::setNames() { monoQName = getName() + "_mono"; + edgesQName = getName() + "_edges"; controlQName = getName() + "_control"; } void Mono::setXinXout(std::shared_ptr pipeline) { + if(ph->getParam("i_enable_edge_detection")) { + monoCamNode->out.link(edgeDetectorNode->inputImage); + edgeDetectorNode->setMaxOutputFrameSize( + monoCamNode->getResolutionWidth() * + monoCamNode->getResolutionHeight()); + } if(ph->getParam("i_publish_topic")) { xoutMono = pipeline->create(); xoutMono->setStreamName(monoQName); @@ -48,6 +61,17 @@ void Mono::setXinXout(std::shared_ptr pipeline) { } else { monoCamNode->out.link(xoutMono->input); } + if(ph->getParam("i_enable_edge_detection")) { + xoutEdges = pipeline->create(); + xoutEdges->setStreamName(edgesQName); + if(ph->getParam("i_low_bandwidth")) { + edgesVideoEnc = sensor_helpers::createEncoder(pipeline, ph->getParam("i_low_bandwidth_quality")); + edgeDetectorNode->outputImage.link(edgesVideoEnc->input); + edgesVideoEnc->bitstream.link(xoutEdges->input); + } else { + edgeDetectorNode->outputImage.link(xoutEdges->input); + } + } } xinControl = pipeline->create(); xinControl->setStreamName(controlQName); @@ -61,6 +85,10 @@ void Mono::setupQueues(std::shared_ptr device) { imageConverter = std::make_unique(tfPrefix + "_camera_optical_frame", false, ph->getParam("i_get_base_device_timestamp")); monoPub = image_transport::create_camera_publisher(getROSNode(), "~/" + getName() + "/image_raw"); + if(ph->getParam("i_enable_edge_detection")) { + edgesQ = device->getOutputQueue(edgesQName, ph->getParam("i_max_q_size"), false); + edgesPub = image_transport::create_publisher(getROSNode(), "~/" + getName() + "/image_edges"); + } infoManager = std::make_shared( getROSNode()->create_sub_node(std::string(getROSNode()->get_name()) + "/" + getName()).get(), "/" + getName()); if(ph->getParam("i_calibration_file").empty()) { @@ -74,15 +102,24 @@ void Mono::setupQueues(std::shared_ptr device) { infoManager->loadCameraInfo(ph->getParam("i_calibration_file")); } if(ph->getParam("i_low_bandwidth")) { - monoQ->addCallback(std::bind(sensor_helpers::compressedImgCB, - std::placeholders::_1, - std::placeholders::_2, - *imageConverter, - monoPub, - infoManager, - dai::RawImgFrame::Type::GRAY8)); + monoQ->addCallback([this](const std::string& name, const std::shared_ptr& data) { + sensor_helpers::compressedImgCB(name, data, *imageConverter, monoPub, infoManager, dai::RawImgFrame::Type::GRAY8); + }); + + if(ph->getParam("i_enable_edge_detection")) { + edgesQ->addCallback([this](const std::string& name, const std::shared_ptr& data) { + sensor_helpers::compressedImgCB(name, data, *imageConverter, edgesPub, infoManager, dai::RawImgFrame::Type::GRAY8); + }); + } } else { - monoQ->addCallback(std::bind(sensor_helpers::imgCB, std::placeholders::_1, std::placeholders::_2, *imageConverter, monoPub, infoManager)); + monoQ->addCallback([this](const std::string& name, const std::shared_ptr& data) { + sensor_helpers::imgCB(name, data, *imageConverter, monoPub, infoManager); + }); + if(ph->getParam("i_enable_edge_detection")) { + edgesQ->addCallback([this](const std::string& name, const std::shared_ptr& data) { + sensor_helpers::imgCB(name, data, *imageConverter, edgesPub); + }); + } } } controlQ = device->getInputQueue(controlQName); @@ -91,6 +128,9 @@ void Mono::closeQueues() { if(ph->getParam("i_publish_topic")) { monoQ->close(); } + if(ph->getParam("i_enable_edge_detection")) { + edgesQ->close(); + } controlQ->close(); } diff --git a/depthai_ros_driver/src/dai_nodes/sensors/rgb.cpp b/depthai_ros_driver/src/dai_nodes/sensors/rgb.cpp index 2ac136a5..fd4cf605 100644 --- a/depthai_ros_driver/src/dai_nodes/sensors/rgb.cpp +++ b/depthai_ros_driver/src/dai_nodes/sensors/rgb.cpp @@ -5,6 +5,7 @@ #include "depthai/device/Device.hpp" #include "depthai/pipeline/Pipeline.hpp" #include "depthai/pipeline/node/ColorCamera.hpp" +#include "depthai/pipeline/node/EdgeDetector.hpp" #include "depthai/pipeline/node/VideoEncoder.hpp" #include "depthai/pipeline/node/XLinkIn.hpp" #include "depthai/pipeline/node/XLinkOut.hpp" @@ -13,6 +14,7 @@ #include "depthai_ros_driver/param_handlers/sensor_param_handler.hpp" #include "image_transport/camera_publisher.hpp" #include "image_transport/image_transport.hpp" +#include "image_transport/publisher.hpp" #include "rclcpp/node.hpp" namespace depthai_ros_driver { @@ -29,17 +31,28 @@ RGB::RGB(const std::string& daiNodeName, colorCamNode = pipeline->create(); ph = std::make_unique(node, daiNodeName); ph->declareParams(colorCamNode, socket, sensor, publish); + if(ph->getParam("i_enable_edge_detection")) { + edgeDetectorNode = pipeline->create(); + ph->declareParams(edgeDetectorNode); + } setXinXout(pipeline); RCLCPP_DEBUG(node->get_logger(), "Node %s created", daiNodeName.c_str()); } RGB::~RGB() = default; void RGB::setNames() { ispQName = getName() + "_isp"; + edgesQName = getName() + "_edges"; previewQName = getName() + "_preview"; controlQName = getName() + "_control"; } void RGB::setXinXout(std::shared_ptr pipeline) { + if(ph->getParam("i_enable_edge_detection")) { + colorCamNode->video.link(edgeDetectorNode->inputImage); + edgeDetectorNode->setMaxOutputFrameSize( + colorCamNode->getVideoWidth() * + colorCamNode->getVideoHeight()); + } if(ph->getParam("i_publish_topic")) { xoutColor = pipeline->create(); xoutColor->setStreamName(ispQName); @@ -53,6 +66,17 @@ void RGB::setXinXout(std::shared_ptr pipeline) { else colorCamNode->video.link(xoutColor->input); } + if(ph->getParam("i_enable_edge_detection")) { + xoutEdges = pipeline->create(); + xoutEdges->setStreamName(edgesQName); + if(ph->getParam("i_low_bandwidth")) { + edgesVideoEnc = sensor_helpers::createEncoder(pipeline, ph->getParam("i_low_bandwidth_quality")); + edgeDetectorNode->outputImage.link(edgesVideoEnc->input); + edgesVideoEnc->bitstream.link(xoutEdges->input); + } else { + edgeDetectorNode->outputImage.link(xoutEdges->input); + } + } } if(ph->getParam("i_enable_preview")) { xoutPreview = pipeline->create(); @@ -85,16 +109,28 @@ void RGB::setupQueues(std::shared_ptr device) { } rgbPub = image_transport::create_camera_publisher(getROSNode(), "~/" + getName() + "/image_raw"); colorQ = device->getOutputQueue(ispQName, ph->getParam("i_max_q_size"), false); + if(ph->getParam("i_enable_edge_detection")) { + edgesQ = device->getOutputQueue(edgesQName, ph->getParam("i_max_q_size"), false); + edgesPub = image_transport::create_publisher(getROSNode(), "~/" + getName() + "/image_edges"); + } if(ph->getParam("i_low_bandwidth")) { - colorQ->addCallback(std::bind(sensor_helpers::compressedImgCB, - std::placeholders::_1, - std::placeholders::_2, - *imageConverter, - rgbPub, - infoManager, - dai::RawImgFrame::Type::BGR888i)); + colorQ->addCallback([this](const std::string& name, const std::shared_ptr& data) { + sensor_helpers::compressedImgCB(name, data, *imageConverter, rgbPub, infoManager, dai::RawImgFrame::Type::BGR888i); + }); + if(ph->getParam("i_enable_edge_detection")) { + edgesQ->addCallback([this](const std::string& name, const std::shared_ptr& data) { + sensor_helpers::compressedImgCB(name, data, *imageConverter, edgesPub, infoManager, dai::RawImgFrame::Type::GRAY8); + }); + } } else { - colorQ->addCallback(std::bind(sensor_helpers::imgCB, std::placeholders::_1, std::placeholders::_2, *imageConverter, rgbPub, infoManager)); + colorQ->addCallback([this](const std::string& name, const std::shared_ptr& data) { + sensor_helpers::imgCB(name, data, *imageConverter, rgbPub, infoManager); + }); + if(ph->getParam("i_enable_edge_detection")) { + edgesQ->addCallback([this](const std::string& name, const std::shared_ptr& data) { + sensor_helpers::imgCB(name, data, *imageConverter, edgesPub); + }); + } } } if(ph->getParam("i_enable_preview")) { @@ -114,7 +150,9 @@ void RGB::setupQueues(std::shared_ptr device) { } else { infoManager->loadCameraInfo(ph->getParam("i_calibration_file")); } - previewQ->addCallback(std::bind(sensor_helpers::imgCB, std::placeholders::_1, std::placeholders::_2, *imageConverter, previewPub, previewInfoManager)); + previewQ->addCallback([this](const std::string& name, const std::shared_ptr& data) { + sensor_helpers::imgCB(name, data, *imageConverter, previewPub, previewInfoManager); + }); }; controlQ = device->getInputQueue(controlQName); } @@ -126,6 +164,9 @@ void RGB::closeQueues() { previewQ->close(); } } + if(ph->getParam("i_enable_edge_detection")) { + edgesQ->close(); + } controlQ->close(); } diff --git a/depthai_ros_driver/src/dai_nodes/sensors/sensor_helpers.cpp b/depthai_ros_driver/src/dai_nodes/sensors/sensor_helpers.cpp index 35af62cd..f3bfcc64 100644 --- a/depthai_ros_driver/src/dai_nodes/sensors/sensor_helpers.cpp +++ b/depthai_ros_driver/src/dai_nodes/sensors/sensor_helpers.cpp @@ -91,6 +91,22 @@ std::vector availableSensors{ {"IMX582", {"48mp", "12mp", "4k"}, true}, {"LCM48", {"48mp", "12mp", "4k"}, true}, }; +void compressedImgCB(const std::string& /*name*/, + const std::shared_ptr& data, + dai::ros::ImageConverter& converter, + image_transport::Publisher& pub, + std::shared_ptr infoManager, + dai::RawImgFrame::Type dataType) { + auto img = std::dynamic_pointer_cast(data); + std::deque deq; + const auto info = infoManager->getCameraInfo(); + converter.toRosMsgFromBitStream(img, deq, dataType, info); + while(deq.size() > 0) { + auto currMsg = deq.front(); + pub.publish(currMsg); + deq.pop_front(); + } +} void compressedImgCB(const std::string& /*name*/, const std::shared_ptr& data, dai::ros::ImageConverter& converter, @@ -108,6 +124,19 @@ void compressedImgCB(const std::string& /*name*/, deq.pop_front(); } } +void imgCB(const std::string& /*name*/, + const std::shared_ptr& data, + dai::ros::ImageConverter& converter, + image_transport::Publisher& pub) { + auto img = std::dynamic_pointer_cast(data); + std::deque deq; + converter.toRosMsg(img, deq); + while(deq.size() > 0) { + auto currMsg = deq.front(); + pub.publish(currMsg); + deq.pop_front(); + } +} void imgCB(const std::string& /*name*/, const std::shared_ptr& data, dai::ros::ImageConverter& converter, @@ -148,4 +177,4 @@ std::shared_ptr createEncoder(std::shared_ptr(node, daiNodeName); ph->declareParams(stereoCamNode, rightInfo.name); + config = std::make_shared(); + config->set(stereoCamNode->initialConfig.get()); setXinXout(pipeline); left->link(stereoCamNode->left); right->link(stereoCamNode->right); @@ -43,9 +46,14 @@ void Stereo::setNames() { stereoQName = getName() + "_stereo"; leftRectQName = getName() + "_left_rect"; rightRectQName = getName() + "_right_rect"; + configQName = getName() + "_config"; } void Stereo::setXinXout(std::shared_ptr pipeline) { + xinConfig = pipeline->create(); + xinConfig->setStreamName(configQName); + xinConfig->out.link(stereoCamNode->inputConfig); + if(ph->getParam("i_publish_topic")) { xoutStereo = pipeline->create(); xoutStereo->setStreamName(stereoQName); @@ -105,15 +113,13 @@ void Stereo::setupLeftRectQueue(std::shared_ptr device) { encType = dai::RawImgFrame::Type::BGR888i; } if(ph->getParam("i_left_rect_low_bandwidth")) { - leftRectQ->addCallback(std::bind(sensor_helpers::compressedImgCB, - std::placeholders::_1, - std::placeholders::_2, - *leftRectConv, - leftRectPub, - leftRectIM, - encType)); + leftRectQ->addCallback([this, encType](const std::string& name, const std::shared_ptr& data) { + sensor_helpers::compressedImgCB(name, data, *leftRectConv, leftRectPub, leftRectIM, encType); + }); } else { - leftRectQ->addCallback(std::bind(sensor_helpers::imgCB, std::placeholders::_1, std::placeholders::_2, *leftRectConv, leftRectPub, leftRectIM)); + leftRectQ->addCallback([this](const std::string& name, const std::shared_ptr& data) { + sensor_helpers::imgCB(name, data, *leftRectConv, leftRectPub, leftRectIM); + }); } } @@ -136,15 +142,13 @@ void Stereo::setupRightRectQueue(std::shared_ptr device) { encType = dai::RawImgFrame::Type::BGR888i; } if(ph->getParam("i_right_rect_low_bandwidth")) { - rightRectQ->addCallback(std::bind(sensor_helpers::compressedImgCB, - std::placeholders::_1, - std::placeholders::_2, - *rightRectConv, - rightRectPub, - rightRectIM, - encType)); + rightRectQ->addCallback([this, encType](const std::string& name, const std::shared_ptr& data) { + sensor_helpers::compressedImgCB(name, data, *rightRectConv, rightRectPub, rightRectIM, encType); + }); } else { - rightRectQ->addCallback(std::bind(sensor_helpers::imgCB, std::placeholders::_1, std::placeholders::_2, *rightRectConv, rightRectPub, rightRectIM)); + rightRectQ->addCallback([this](const std::string& name, const std::shared_ptr& data) { + sensor_helpers::imgCB(name, data, *rightRectConv, rightRectPub, rightRectIM); + }); } } @@ -173,23 +177,24 @@ void Stereo::setupStereoQueue(std::shared_ptr device) { if(ph->getParam("i_low_bandwidth")) { if(ph->getParam("i_output_disparity")) { - stereoQ->addCallback(std::bind(sensor_helpers::compressedImgCB, - std::placeholders::_1, - std::placeholders::_2, - *stereoConv, - stereoPub, - stereoIM, - dai::RawImgFrame::Type::GRAY8)); + stereoQ->addCallback([this](const std::string& name, const std::shared_ptr& data) { + sensor_helpers::compressedImgCB(name, data, *stereoConv, stereoPub, stereoIM, dai::RawImgFrame::Type::GRAY8); + }); } else { // converting disp->depth - stereoQ->addCallback(std::bind( - sensor_helpers::compressedImgCB, std::placeholders::_1, std::placeholders::_2, *stereoConv, stereoPub, stereoIM, dai::RawImgFrame::Type::RAW8)); + stereoQ->addCallback([this](const std::string& name, const std::shared_ptr& data) { + sensor_helpers::compressedImgCB(name, data, *stereoConv, stereoPub, stereoIM, dai::RawImgFrame::Type::RAW8); + }); } } else { if(ph->getParam("i_output_disparity")) { - stereoQ->addCallback(std::bind(sensor_helpers::imgCB, std::placeholders::_1, std::placeholders::_2, *stereoConv, stereoPub, stereoIM)); + stereoQ->addCallback([this](const std::string& name, const std::shared_ptr& data) { + sensor_helpers::imgCB(name, data, *stereoConv, stereoPub, stereoIM); + }); } - stereoQ->addCallback(std::bind(sensor_helpers::imgCB, std::placeholders::_1, std::placeholders::_2, *stereoConv, stereoPub, stereoIM)); + stereoQ->addCallback([this](const std::string& name, const std::shared_ptr& data) { + sensor_helpers::imgCB(name, data, *stereoConv, stereoPub, stereoIM); + }); } } @@ -205,6 +210,7 @@ void Stereo::setupQueues(std::shared_ptr device) { if(ph->getParam("i_publish_right_rect")) { setupRightRectQueue(device); } + configQ = device->getInputQueue(configQName); } void Stereo::closeQueues() { left->closeQueues(); @@ -218,6 +224,7 @@ void Stereo::closeQueues() { if(ph->getParam("i_publish_right_rect")) { rightRectQ->close(); } + configQ->close(); } void Stereo::link(dai::Node::Input in, int /*linkType*/) { @@ -235,6 +242,13 @@ dai::Node::Input Stereo::getInput(int linkType) { } void Stereo::updateParams(const std::vector& params) { + for(const auto& p : params) { + if(p.get_name() == ph->getFullParamName("i_stereo_conf_threshold")) { + config->setConfidenceThreshold(p.get_value()); + configQ->send(config); + break; + } + } ph->setRuntimeParams(params); } diff --git a/depthai_ros_driver/src/param_handlers/imu_param_handler.cpp b/depthai_ros_driver/src/param_handlers/imu_param_handler.cpp index 879817e9..0f1c26ae 100644 --- a/depthai_ros_driver/src/param_handlers/imu_param_handler.cpp +++ b/depthai_ros_driver/src/param_handlers/imu_param_handler.cpp @@ -1,6 +1,7 @@ #include "depthai_ros_driver/param_handlers/imu_param_handler.hpp" #include "depthai/pipeline/node/IMU.hpp" +#include "depthai-shared/properties/IMUProperties.hpp" #include "depthai_bridge/ImuConverter.hpp" #include "depthai_ros_driver/utils.hpp" #include "rclcpp/logger.hpp" @@ -14,29 +15,91 @@ void ImuParamHandler::declareParams(std::shared_ptr imu, const s imuSyncMethodMap = { {"COPY", dai::ros::ImuSyncMethod::COPY}, {"LINEAR_INTERPOLATE_GYRO", dai::ros::ImuSyncMethod::LINEAR_INTERPOLATE_GYRO}, - {"LINEAR_INTERPOLATE_ACCEL", dai::ros::ImuSyncMethod::LINEAR_INTERPOLATE_ACCEL}, - }; + {"LINEAR_INTERPOLATE_ACCEL", dai::ros::ImuSyncMethod::LINEAR_INTERPOLATE_ACCEL}}; imuMessagetTypeMap = { - {"IMU", imu::ImuMsgType::IMU}, {"IMU_WITH_MAG", imu::ImuMsgType::IMU_WITH_MAG}, {"IMU_WITH_MAG_SPLIT", imu::ImuMsgType::IMU_WITH_MAG_SPLIT}}; + {"IMU", imu::ImuMsgType::IMU}, + {"IMU_WITH_MAG", imu::ImuMsgType::IMU_WITH_MAG}, + {"IMU_WITH_MAG_SPLIT", imu::ImuMsgType::IMU_WITH_MAG_SPLIT}}; + imuAccelerometerModeMap = { + {"RAW", dai::IMUSensor::ACCELEROMETER_RAW}, + {"CALIBRATED", dai::IMUSensor::ACCELEROMETER}, + {"LINEAR", dai::IMUSensor::LINEAR_ACCELERATION}, + {"GRAVITY", dai::IMUSensor::GRAVITY}}; + imuGyroscopeModeMap = { + {"RAW", dai::IMUSensor::GYROSCOPE_RAW}, + {"CALIBRATED", dai::IMUSensor::GYROSCOPE_CALIBRATED}, + {"UNCALIBRATED", dai::IMUSensor::GYROSCOPE_UNCALIBRATED}}; + imuMagnetometerModeMap = { + {"RAW", dai::IMUSensor::MAGNETOMETER_RAW}, + {"CALIBRATED", dai::IMUSensor::MAGNETOMETER_CALIBRATED}, + {"UNCALIBRATED", dai::IMUSensor::MAGNETOMETER_UNCALIBRATED}}; + imuRotationModeMap = { + {"DEFAULT", dai::IMUSensor::ROTATION_VECTOR}, + {"GAME", dai::IMUSensor::GAME_ROTATION_VECTOR}, + {"GEOMAGNETIC", dai::IMUSensor::GEOMAGNETIC_ROTATION_VECTOR}, + {"ARVR_STABILIZED", dai::IMUSensor::ARVR_STABILIZED_ROTATION_VECTOR}, + {"ARVR_STABILIZED_GAME", dai::IMUSensor::ARVR_STABILIZED_GAME_ROTATION_VECTOR}}; + declareAndLogParam("i_get_base_device_timestamp", false); declareAndLogParam("i_message_type", "IMU"); declareAndLogParam("i_sync_method", "LINEAR_INTERPOLATE_ACCEL"); - declareAndLogParam("i_acc_cov", 0.0); - declareAndLogParam("i_gyro_cov", 0.0); - declareAndLogParam("i_rot_cov", -1.0); - declareAndLogParam("i_mag_cov", 0.0); - bool rotationAvailable = imuType == "BNO086"; - if(declareAndLogParam("i_enable_rotation", false)) { - if(rotationAvailable) { - imu->enableIMUSensor(dai::IMUSensor::ROTATION_VECTOR, declareAndLogParam("i_rot_freq", 400)); - imu->enableIMUSensor(dai::IMUSensor::MAGNETOMETER_CALIBRATED, declareAndLogParam("i_mag_freq", 100)); + + if (declareAndLogParam("i_enable_acc", true)) { + const std::string accelerometerModeName = + utils::getUpperCaseStr(declareAndLogParam("i_acc_mode", "raw")); + const dai::IMUSensor accelerometerMode = + utils::getValFromMap(accelerometerModeName, imuAccelerometerModeMap); + const int accelerometerFreq = declareAndLogParam("i_acc_freq", 400); + declareAndLogParam("i_acc_cov", 0.0); + + imu->enableIMUSensor(accelerometerMode, accelerometerFreq); + } + + if (declareAndLogParam("i_enable_gyro", true)) { + const std::string gyroscopeModeName = + utils::getUpperCaseStr(declareAndLogParam("i_gyro_mode", "raw")); + const dai::IMUSensor gyroscopeMode = + utils::getValFromMap(gyroscopeModeName, imuGyroscopeModeMap); + const int gyroscopeFreq = declareAndLogParam("i_gyro_freq", 400); + declareAndLogParam("i_gyro_cov", 0.0); + + imu->enableIMUSensor(gyroscopeMode, gyroscopeFreq); + } + + const bool magnetometerAvailable = imuType == "BNO086"; + if (declareAndLogParam("i_enable_mag", magnetometerAvailable)) { + if (magnetometerAvailable) { + const std::string magnetometerModeName = + utils::getUpperCaseStr(declareAndLogParam("i_mag_mode", "raw")); + const dai::IMUSensor magnetometerMode = + utils::getValFromMap(magnetometerModeName, imuMagnetometerModeMap); + const int magnetometerFreq = declareAndLogParam("i_mag_freq", 100); + declareAndLogParam("i_mag_cov", 0.0); + + imu->enableIMUSensor(magnetometerMode, magnetometerFreq); + } else { + RCLCPP_ERROR(getROSNode()->get_logger(), "Magnetometer enabled but not available with current sensor"); + declareAndLogParam("i_enable_mag", false, true); + } + } + + const bool rotationAvailable = imuType == "BNO086"; + if (declareAndLogParam("i_enable_rotation", false)) { + if (rotationAvailable) { + const std::string rotationModeName = + utils::getUpperCaseStr(declareAndLogParam("i_rot_mode", "default")); + const dai::IMUSensor rotationMode = + utils::getValFromMap(rotationModeName, imuRotationModeMap); + const int rotationFreq = declareAndLogParam("i_rot_freq", 400); + declareAndLogParam("i_rot_cov", -1.0); + + imu->enableIMUSensor(rotationMode, rotationFreq); } else { RCLCPP_ERROR(getROSNode()->get_logger(), "Rotation enabled but not available with current sensor"); declareAndLogParam("i_enable_rotation", false, true); } } - imu->enableIMUSensor(dai::IMUSensor::ACCELEROMETER_RAW, declareAndLogParam("i_acc_freq", 400)); - imu->enableIMUSensor(dai::IMUSensor::GYROSCOPE_RAW, declareAndLogParam("i_gyro_freq", 400)); + imu->setBatchReportThreshold(declareAndLogParam("i_batch_report_threshold", 1)); imu->setMaxBatchReports(declareAndLogParam("i_max_batch_reports", 10)); } @@ -54,4 +117,4 @@ dai::CameraControl ImuParamHandler::setRuntimeParams(const std::vector("i_disable_node", false); declareAndLogParam("i_get_base_device_timestamp", false); declareAndLogParam("i_board_socket_id", 0); + declareAndLogParam("i_enable_edge_detection", false); fSyncModeMap = { {"OFF", dai::CameraControl::FrameSyncMode::OFF}, {"OUTPUT", dai::CameraControl::FrameSyncMode::OUTPUT}, @@ -33,6 +35,54 @@ void SensorParamHandler::declareCommonParams() { }; } +template +std::vector flatten(const std::vector>& matrix) { + std::vector vector; + for(const auto& row : matrix) { + vector.reserve(vector.size() + row.size()); + for(const auto& coeff : row) { + vector.push_back(static_cast(coeff)); + } + } + return vector; +} + +template +std::vector> reshape(const std::vector& vector, size_t nrows, size_t ncols) { + std::vector> matrix(nrows, std::vector(ncols)); + assert(vector.size() == nrows * ncols); + for(size_t i = 0; i < nrows; ++i) { + for(size_t j = 0; j < ncols; ++j) { + matrix[i][j] = static_cast(vector[j + i * ncols]); + } + } + return matrix; +} + +void SensorParamHandler::declareParams(std::shared_ptr edgeDetector) { + dai::EdgeDetectorConfigData configData = edgeDetector->initialConfig.getConfigData(); + const auto horizontalKernelCoeffs = declareAndLogParam>( + "i_edge_detection_horizontal_kernel", flatten(configData.sobelFilterHorizontalKernel)); + const auto verticalKernelCoeffs = declareAndLogParam>( + "i_edge_detection_vertical_kernel", flatten(configData.sobelFilterVerticalKernel)); + if(!horizontalKernelCoeffs.empty()) { + if(horizontalKernelCoeffs.size() == 9u) { + configData.sobelFilterHorizontalKernel = reshape(horizontalKernelCoeffs, 3u, 3u); + } else { + RCLCPP_ERROR(getROSNode()->get_logger(), "Horizontal kernel should be 3x3, ignoring"); + } + } + if(!verticalKernelCoeffs.empty()) { + if(verticalKernelCoeffs.size() == 9u) { + configData.sobelFilterVerticalKernel = reshape(verticalKernelCoeffs, 3u, 3u); + } else { + RCLCPP_ERROR(getROSNode()->get_logger(), "Vertical kernel should be 3x3, ignoring"); + } + } + edgeDetector->initialConfig.setSobelFilterKernels( + configData.sobelFilterHorizontalKernel, configData.sobelFilterVerticalKernel); +} + void SensorParamHandler::declareParams(std::shared_ptr monoCam, dai::CameraBoardSocket socket, dai_nodes::sensor_helpers::ImageSensor, @@ -173,4 +223,4 @@ dai::CameraControl SensorParamHandler::setRuntimeParams(const std::vector s declareAndLogParam("i_output_disparity", false); declareAndLogParam("i_get_base_device_timestamp", false); declareAndLogParam("i_publish_topic", true); - + declareAndLogParam("i_publish_left_rect", false); declareAndLogParam("i_left_rect_low_bandwidth", false); declareAndLogParam("i_left_rect_low_bandwidth_quality", 50); @@ -76,8 +76,9 @@ void StereoParamHandler::declareParams(std::shared_ptr s } } declareAndLogParam("i_board_socket_id", static_cast(socket)); + stereo->setDepthAlign(dai::StereoDepthConfig::AlgorithmControl::DepthAlign::CENTER); stereo->setDepthAlign(socket); - + if(declareAndLogParam("i_set_input_size", false)) { stereo->setInputResolution(declareAndLogParam("i_input_width", 1280), declareAndLogParam("i_input_height", 720)); } @@ -138,4 +139,4 @@ dai::CameraControl StereoParamHandler::setRuntimeParams(const std::vector