OAK Internal Sync & DepthAI HF-Net Support (#1193)

* Using Sync Node

* Using normalized IR intensity

* Set IMU output frequency to 200 Hz

* set sync threshold properly

* add depthai hfnet local head

* fix DB error

* add depthai hfnet global head

* fix data delay if image rate is set manually
This commit is contained in:
Borong Yuan
2024-03-28 03:29:06 +08:00
committed by GitHub
parent bc6d390fb6
commit bfeb487dba
5 changed files with 104 additions and 104 deletions

View File

@@ -62,8 +62,8 @@ CameraDepthAI::CameraDepthAI(
alphaScaling_(0.0),
imuPublished_(true),
publishInterIMU_(false),
dotProjectormA_(0.0),
floodLightmA_(200.0),
dotIntensity_(0.0),
floodIntensity_(0.0),
detectFeatures_(0),
useHarrisDetector_(false),
minDistance_(7.0),
@@ -127,11 +127,11 @@ void CameraDepthAI::setIMU(bool imuPublished, bool publishInterIMU)
#endif
}
void CameraDepthAI::setIrBrightness(float dotProjectormA, float floodLightmA)
void CameraDepthAI::setIrIntensity(float dotIntensity, float floodIntensity)
{
#ifdef RTABMAP_DEPTHAI
dotProjectormA_ = dotProjectormA;
floodLightmA_ = floodLightmA;
dotIntensity_ = dotIntensity;
floodIntensity_ = floodIntensity;
#else
UERROR("CameraDepthAI: RTAB-Map is not built with depthai-core support!");
#endif
@@ -235,51 +235,45 @@ bool CameraDepthAI::init(const std::string & calibrationFolder, const std::strin
imu = p.create<dai::node::IMU>();
std::shared_ptr<dai::node::FeatureTracker> gfttDetector;
std::shared_ptr<dai::node::ImageManip> manip;
std::shared_ptr<dai::node::NeuralNetwork> superPointNetwork;
std::shared_ptr<dai::node::NeuralNetwork> neuralNetwork;
if(detectFeatures_ == 1)
{
gfttDetector = p.create<dai::node::FeatureTracker>();
}
else if(detectFeatures_ == 2)
else if(detectFeatures_ >= 2)
{
if(!blobPath_.empty())
{
manip = p.create<dai::node::ImageManip>();
superPointNetwork = p.create<dai::node::NeuralNetwork>();
neuralNetwork = p.create<dai::node::NeuralNetwork>();
}
else
{
UWARN("Missing SuperPoint blob file!");
UWARN("Missing MyriadX blob file!");
detectFeatures_ = 0;
}
}
auto xoutLeftOrColor = p.create<dai::node::XLinkOut>();
auto xoutDepthOrRight = p.create<dai::node::XLinkOut>();
auto sync = p.create<dai::node::Sync>();
auto xoutCamera = p.create<dai::node::XLinkOut>();
std::shared_ptr<dai::node::XLinkOut> xoutIMU;
if(imuPublished_)
xoutIMU = p.create<dai::node::XLinkOut>();
std::shared_ptr<dai::node::XLinkOut> xoutFeatures;
if(detectFeatures_)
xoutFeatures = p.create<dai::node::XLinkOut>();
// XLinkOut
xoutLeftOrColor->setStreamName(outputMode_<2?"rectified_left":"rectified_color");
xoutDepthOrRight->setStreamName(outputMode_?"depth":"rectified_right");
xoutCamera->setStreamName("camera");
if(imuPublished_)
xoutIMU->setStreamName("imu");
if(detectFeatures_)
xoutFeatures->setStreamName("features");
monoLeft->setResolution((dai::MonoCameraProperties::SensorResolution)resolution_);
monoRight->setResolution((dai::MonoCameraProperties::SensorResolution)resolution_);
monoLeft->setCamera("left");
monoRight->setCamera("right");
if(detectFeatures_ == 2)
if(detectFeatures_ >= 2)
{
if(this->getImageRate() <= 0 || this->getImageRate() > 15)
{
UWARN("On-device SuperPoint enabled, image rate is limited to 15 FPS!");
UWARN("On-device SuperPoint or HF-Net enabled, image rate is limited to 15 FPS!");
monoLeft->setFps(15);
monoRight->setFps(15);
}
@@ -325,6 +319,7 @@ bool CameraDepthAI::init(const std::string & calibrationFolder, const std::strin
if(alphaScaling_ > -1.0f)
colorCam->setCalibrationAlpha(alphaScaling_);
}
this->setImageRate(0);
// Using VideoEncoder on PoE devices, Subpixel is not supported
if(deviceToUse.protocol == X_LINK_TCP_IP || mxidOrName_.find(".") != std::string::npos)
@@ -336,22 +331,24 @@ bool CameraDepthAI::init(const std::string & calibrationFolder, const std::strin
if(outputMode_ < 2)
{
stereo->rectifiedLeft.link(leftOrColorEnc->input);
leftOrColorEnc->bitstream.link(sync->inputs["left"]);
}
else
{
colorCam->video.link(leftOrColorEnc->input);
leftOrColorEnc->bitstream.link(sync->inputs["color"]);
}
if(outputMode_)
{
depthOrRightEnc->setQuality(100);
stereo->disparity.link(depthOrRightEnc->input);
depthOrRightEnc->bitstream.link(sync->inputs["depth"]);
}
else
{
stereo->rectifiedRight.link(depthOrRightEnc->input);
depthOrRightEnc->bitstream.link(sync->inputs["right"]);
}
leftOrColorEnc->bitstream.link(xoutLeftOrColor->input);
depthOrRightEnc->bitstream.link(xoutDepthOrRight->input);
}
else
{
@@ -363,24 +360,27 @@ bool CameraDepthAI::init(const std::string & calibrationFolder, const std::strin
stereo->initialConfig.set(config);
if(outputMode_ < 2)
{
stereo->rectifiedLeft.link(xoutLeftOrColor->input);
stereo->rectifiedLeft.link(sync->inputs["left"]);
}
else
{
monoLeft->setResolution(dai::MonoCameraProperties::SensorResolution::THE_400_P);
monoRight->setResolution(dai::MonoCameraProperties::SensorResolution::THE_400_P);
colorCam->video.link(xoutLeftOrColor->input);
colorCam->video.link(sync->inputs["color"]);
}
if(outputMode_)
stereo->depth.link(xoutDepthOrRight->input);
stereo->depth.link(sync->inputs["depth"]);
else
stereo->rectifiedRight.link(xoutDepthOrRight->input);
stereo->rectifiedRight.link(sync->inputs["right"]);
}
sync->setSyncThreshold(std::chrono::milliseconds(int(500 / monoLeft->getFps())));
sync->out.link(xoutCamera->input);
if(imuPublished_)
{
// enable ACCELEROMETER_RAW and GYROSCOPE_RAW at 100 hz rate
imu->enableIMUSensor({dai::IMUSensor::ACCELEROMETER_RAW, dai::IMUSensor::GYROSCOPE_RAW}, 100);
// enable ACCELEROMETER_RAW and GYROSCOPE_RAW at 200 hz rate
imu->enableIMUSensor({dai::IMUSensor::ACCELEROMETER_RAW, dai::IMUSensor::GYROSCOPE_RAW}, 200);
// above this threshold packets will be sent in batch of X, if the host is not blocked and USB bandwidth is available
imu->setBatchReportThreshold(1);
// maximum number of IMU packets in a batch, if it's reached device will block sending until host can receive it
@@ -403,20 +403,20 @@ bool CameraDepthAI::init(const std::string & calibrationFolder, const std::strin
cfg.featureMaintainer.minimumDistanceBetweenFeatures = minDistance_ * minDistance_;
gfttDetector->initialConfig.set(cfg);
stereo->rectifiedLeft.link(gfttDetector->inputImage);
gfttDetector->outputFeatures.link(xoutFeatures->input);
gfttDetector->outputFeatures.link(sync->inputs["feat"]);
}
else if(detectFeatures_ == 2)
else if(detectFeatures_ >= 2)
{
manip->setKeepAspectRatio(false);
manip->setMaxOutputFrameSize(320 * 200);
manip->initialConfig.setResize(320, 200);
superPointNetwork->setBlobPath(blobPath_);
superPointNetwork->setNumInferenceThreads(2);
superPointNetwork->setNumNCEPerInferenceThread(1);
superPointNetwork->input.setBlocking(false);
neuralNetwork->setBlobPath(blobPath_);
neuralNetwork->setNumInferenceThreads(2);
neuralNetwork->setNumNCEPerInferenceThread(1);
neuralNetwork->input.setBlocking(false);
stereo->rectifiedLeft.link(manip->inputImage);
manip->out.link(superPointNetwork->input);
superPointNetwork->out.link(xoutFeatures->input);
manip->out.link(neuralNetwork->input);
neuralNetwork->out.link(sync->inputs["feat"]);
}
device_.reset(new dai::Device(p, deviceToUse));
@@ -503,6 +503,7 @@ bool CameraDepthAI::init(const std::string & calibrationFolder, const std::strin
UINFO("IMU disabled");
}
cameraQueue_ = device_->getOutputQueue("camera", 8, false);
if(imuPublished_)
{
imuLocalTransform_ = this->getLocalTransform() * imuLocalTransform_;
@@ -534,16 +535,11 @@ bool CameraDepthAI::init(const std::string & calibrationFolder, const std::strin
}
});
}
leftOrColorQueue_ = device_->getOutputQueue(outputMode_<2?"rectified_left":"rectified_color", 8, false);
rightOrDepthQueue_ = device_->getOutputQueue(outputMode_?"depth":"rectified_right", 8, false);
if(detectFeatures_)
featuresQueue_ = device_->getOutputQueue("features", 8, false);
std::vector<std::tuple<std::string, int, int>> irDrivers = device_->getIrDrivers();
if(!irDrivers.empty())
if(!device_->getIrDrivers().empty())
{
device_->setIrLaserDotProjectorBrightness(dotProjectormA_);
device_->setIrFloodLightBrightness(floodLightmA_);
device_->setIrLaserDotProjectorIntensity(dotIntensity_);
device_->setIrFloodLightIntensity(floodIntensity_);
}
uSleep(2000); // avoid bad frames on start
@@ -577,16 +573,11 @@ SensorData CameraDepthAI::captureImage(CameraInfo * info)
SensorData data;
#ifdef RTABMAP_DEPTHAI
auto messageGroup = cameraQueue_->get<dai::MessageGroup>();
auto rectifLeftOrColor = messageGroup->get<dai::ImgFrame>(outputMode_<2?"left":"color");
auto rectifRightOrDepth = messageGroup->get<dai::ImgFrame>(outputMode_?"depth":"right");
cv::Mat leftOrColor, depthOrRight;
auto rectifLeftOrColor = leftOrColorQueue_->get<dai::ImgFrame>();
auto rectifRightOrDepth = rightOrDepthQueue_->get<dai::ImgFrame>();
while(rectifLeftOrColor->getSequenceNum() < rectifRightOrDepth->getSequenceNum())
rectifLeftOrColor = leftOrColorQueue_->get<dai::ImgFrame>();
while(rectifLeftOrColor->getSequenceNum() > rectifRightOrDepth->getSequenceNum())
rectifRightOrDepth = rightOrDepthQueue_->get<dai::ImgFrame>();
double stamp = std::chrono::duration<double>(rectifLeftOrColor->getTimestampDevice(dai::CameraExposureOffset::MIDDLE).time_since_epoch()).count();
if(device_->getDeviceInfo().protocol == X_LINK_TCP_IP || mxidOrName_.find(".") != std::string::npos)
{
leftOrColor = cv::imdecode(rectifLeftOrColor->getData(), cv::IMREAD_ANYCOLOR);
@@ -604,6 +595,7 @@ SensorData CameraDepthAI::captureImage(CameraInfo * info)
depthOrRight = rectifRightOrDepth->getCvFrame();
}
double stamp = std::chrono::duration<double>(rectifLeftOrColor->getTimestampDevice(dai::CameraExposureOffset::MIDDLE).time_since_epoch()).count();
if(outputMode_)
data = SensorData(leftOrColor, depthOrRight, stereoModel_.left(), this->getNextSeqID(), stamp);
else
@@ -660,28 +652,30 @@ SensorData CameraDepthAI::captureImage(CameraInfo * info)
if(detectFeatures_ == 1)
{
auto features = featuresQueue_->get<dai::TrackedFeatures>();
while(features->getSequenceNum() < rectifLeftOrColor->getSequenceNum())
features = featuresQueue_->get<dai::TrackedFeatures>();
auto detectedFeatures = features->trackedFeatures;
auto features = messageGroup->get<dai::TrackedFeatures>("feat")->trackedFeatures;
std::vector<cv::KeyPoint> keypoints;
for(auto& feature : detectedFeatures)
for(auto& feature : features)
keypoints.emplace_back(cv::KeyPoint(feature.position.x, feature.position.y, 3));
data.setFeatures(keypoints, std::vector<cv::Point3f>(), cv::Mat());
}
else if(detectFeatures_ == 2)
else if(detectFeatures_ >= 2)
{
auto features = featuresQueue_->get<dai::NNData>();
while(features->getSequenceNum() < rectifLeftOrColor->getSequenceNum())
features = featuresQueue_->get<dai::NNData>();
auto heatmap = features->getLayerFp16("heatmap");
auto desc = features->getLayerFp16("desc");
cv::Mat scores(200, 320, CV_32FC1, heatmap.data());
cv::resize(scores, scores, targetSize_, 0, 0, cv::INTER_CUBIC);
auto features = messageGroup->get<dai::NNData>("feat");
std::vector<float> scores_dense, local_descriptor_map, global_descriptor;
if(detectFeatures_ == 2)
{
scores_dense = features->getLayerFp16("heatmap");
local_descriptor_map = features->getLayerFp16("desc");
}
else if(detectFeatures_ == 3)
{
scores_dense = features->getLayerFp16("pred/local_head/detector/Squeeze");
local_descriptor_map = features->getLayerFp16("pred/local_head/descriptor/transpose");
global_descriptor = features->getLayerFp16("pred/global_head/l2_normalize_1");
}
cv::Mat scores(200, 320, CV_32FC1, scores_dense.data());
cv::resize(scores, scores, targetSize_, 0, 0, cv::INTER_CUBIC);
if(nms_)
{
cv::Mat dilated_scores(targetSize_, CV_32FC1);
@@ -714,10 +708,11 @@ SensorData CameraDepthAI::captureImage(CameraInfo * info)
keypoints.emplace_back(cv::KeyPoint(kpt, 8, -1, response));
}
cv::Mat coarse_desc(25, 40, CV_32FC(256), desc.data());
coarse_desc.forEach<cv::Vec<float, 256>>([&](cv::Vec<float, 256>& descriptor, const int position[]) -> void {
cv::normalize(descriptor, descriptor);
});
cv::Mat coarse_desc(25, 40, CV_32FC(256), local_descriptor_map.data());
if(detectFeatures_ == 2)
coarse_desc.forEach<cv::Vec<float, 256>>([&](cv::Vec<float, 256>& descriptor, const int position[]) -> void {
cv::normalize(descriptor, descriptor);
});
cv::Mat mapX(keypoints.size(), 1, CV_32FC1);
cv::Mat mapY(keypoints.size(), 1, CV_32FC1);
for(size_t i=0; i<keypoints.size(); ++i)
@@ -734,6 +729,8 @@ SensorData CameraDepthAI::captureImage(CameraInfo * info)
descriptors = descriptors.reshape(1);
data.setFeatures(keypoints, std::vector<cv::Point3f>(), descriptors);
if(detectFeatures_ == 3)
data.addGlobalDescriptor(GlobalDescriptor(1, cv::Mat(1, global_descriptor.size(), CV_32FC1, global_descriptor.data())));
}
#else