Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cast node #1019

Merged
merged 27 commits into from
May 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
1a48df9
DataQueue: catch packet parsing errors and return a null packet inste…
alex-luxonis Feb 21, 2024
90b92ac
StreamMessageParser: add more details (size etc) to the 'bad packet' …
alex-luxonis Feb 21, 2024
272be36
TMP FW with more logging for bad-packet debugging. Fix ImageManip pot…
alex-luxonis Mar 8, 2024
981324a
Try to fix a FW memory alignment issue
alex-luxonis Mar 12, 2024
21a2dc8
Add cast node
SzabolcsGergely Mar 23, 2024
a8ea8d2
Update Cast node with fixes
SzabolcsGergely Mar 26, 2024
10e6107
Handle multi input NN
SzabolcsGergely Mar 27, 2024
028115f
Device: add RPC setXLinkRateLimit for device transmit bandwidth throt…
alex-luxonis Apr 10, 2024
fde473e
FW, BL: fix a potential bootup/reboot failure,
alex-luxonis May 8, 2024
a295f44
(fix mistake in previous commit, FW ver was put in the wrong place)
alex-luxonis May 10, 2024
42121bb
Merge 'bad_packet_continue' into bootup_stability_fixes
alex-luxonis May 10, 2024
cba9e06
Revert "DataQueue: catch packet parsing errors and return a null pack…
alex-luxonis May 10, 2024
7381dea
Merge 'origin/develop' into bootup_stability_fixes
alex-luxonis May 14, 2024
22141d7
BL: update to 0.0.28 release version (bootup/restart fixes)
alex-luxonis May 14, 2024
0b70c02
StreamMessageParser: check end-of-packet bytes, warn on mismatch,
alex-luxonis May 14, 2024
9176486
Merge remote-tracking branch 'origin/develop' into HEAD
SzabolcsGergely May 15, 2024
3b6b688
FW: update after merge. Fix style - `make clangformat`
alex-luxonis May 15, 2024
84cf333
Merge pull request #1020 from luxonis/bootup_stability_fixes
alex-luxonis May 15, 2024
3672f78
Fix CI
moratom May 15, 2024
2ac4531
DeviceBootloader: warning for potentially unstable flashed bootloader…
alex-luxonis May 16, 2024
5b4b8b8
FW: fix for MessageGroup parsing after the added end-of-packet marker
alex-luxonis May 16, 2024
f8d1976
StreamMessageParser: apply end-of-packet marker in both directions
alex-luxonis May 16, 2024
0126c7a
FW: stream parser marker merged, other changes: warp FP16
alex-luxonis May 17, 2024
6f85d04
Update FW
SzabolcsGergely May 17, 2024
acc1ad6
FW: ToF double raw stream FPS internally to get depth at configured FPS,
alex-luxonis May 20, 2024
7e50521
Update FW; handle edge cases
SzabolcsGergely May 20, 2024
6ab82d3
Merge remote-tracking branch 'origin/cast_node' into HEAD
SzabolcsGergely May 20, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .github/workflows/main.workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ jobs:
exclude:
- os: windows-latest
cmake: '3.10.x'
- os: macos-latest # Skip the old cmake on latest macos - doesn't handle ARM64 aarch correctly
cmake: '3.10.x'

steps:
- name: Cache .hunter folder
Expand Down Expand Up @@ -333,4 +335,4 @@ jobs:
upload_url: ${{ steps.createRelease.outputs.upload_url }}
asset_path: ${{ github.workspace }}/depthai-core-${{ steps.tag.outputs.version }}-win32-no-opencv.zip
asset_name: depthai-core-${{ steps.tag.outputs.version }}-win32-no-opencv.zip
asset_content_type: application/octet-stream
asset_content_type: application/octet-stream
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@ add_library(${TARGET_CORE_NAME}
src/pipeline/node/DetectionParser.cpp
src/pipeline/node/UVC.cpp
src/pipeline/node/PointCloud.cpp
src/pipeline/node/Cast.cpp
src/pipeline/datatype/Buffer.cpp
src/pipeline/datatype/ImgFrame.cpp
src/pipeline/datatype/EncodedFrame.cpp
Expand Down
4 changes: 2 additions & 2 deletions cmake/Depthai/DepthaiBootloaderConfig.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ set(DEPTHAI_BOOTLOADER_MATURITY "release")
# set(DEPTHAI_BOOTLOADER_MATURITY "snapshot")

# "version if applicable"
set(DEPTHAI_BOOTLOADER_VERSION "0.0.27")
# set(DEPTHAI_BOOTLOADER_VERSION "0.0.24+57c26493754e2f00e57f6594b0b1a317f762d5f2")
set(DEPTHAI_BOOTLOADER_VERSION "0.0.28")
# set(DEPTHAI_BOOTLOADER_VERSION "0.0.27+5fb331f993adceeeda72202c233a9e3939ab3dab")
2 changes: 1 addition & 1 deletion cmake/Depthai/DepthaiDeviceSideConfig.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
set(DEPTHAI_DEVICE_SIDE_MATURITY "snapshot")

# "full commit hash of device side binary"
set(DEPTHAI_DEVICE_SIDE_COMMIT "aace8f1c8098546e743f69fc9b3b856d43aed457")
set(DEPTHAI_DEVICE_SIDE_COMMIT "045361e9d6601e4c20d016182b93dce4159ec38b")

# "version if applicable"
set(DEPTHAI_DEVICE_SIDE_VERSION "")
10 changes: 10 additions & 0 deletions include/depthai/device/DeviceBase.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,16 @@ class DeviceBase {
*/
int getXLinkChunkSize();

/**
* Sets the maximum transmission rate for the XLink connection on device side,
* using a simple token bucket algorithm. Useful for bandwidth throttling
*
* @param maxRateBytesPerSecond Rate limit in Bytes/second
* @param burstSize Size in Bytes for how much to attempt to send once, 0 = auto
* @param waitUs Time in microseconds to wait for replenishing tokens, 0 = auto
*/
void setXLinkRateLimit(int maxRateBytesPerSecond, int burstSize = 0, int waitUs = 0);

/**
* Get the Device Info object o the device which is currently running
*
Expand Down
67 changes: 67 additions & 0 deletions include/depthai/pipeline/node/Cast.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#pragma once

#include <depthai/pipeline/Node.hpp>

#include "depthai/pipeline/datatype/Tracklets.hpp"

// standard
#include <fstream>

// shared
#include <depthai-shared/properties/CastProperties.hpp>

namespace dai {
namespace node {

/**
* @brief Cast node.
*/
class Cast : public NodeCRTP<Node, Cast, CastProperties> {
public:
constexpr static const char* NAME = "Cast";

Cast(const std::shared_ptr<PipelineImpl>& par, int64_t nodeId);
Cast(const std::shared_ptr<PipelineImpl>& par, int64_t nodeId, std::unique_ptr<Properties> props);

/**
* Input NNData or ImgFrame message.
*/
Input input{*this, "input", Input::Type::SReceiver, false, 4, true, {{DatatypeEnum::ImgFrame, false}, {DatatypeEnum::NNData, false}}};

/**
* Output ImgFrame message.
*/
Output output{*this, "output", Output::Type::MSender, {{DatatypeEnum::ImgFrame, false}}};

/**
* Passthrough input message.
*/
Output passthroughInput{*this, "passthroughInput", Output::Type::MSender, {{DatatypeEnum::ImgFrame, false}, {DatatypeEnum::NNData, false}}};

/**
* Set number of frames in pool
* @param numFramesPool Number of frames in pool
*/
Cast& setNumFramesPool(int numFramesPool);

/**
* Set output frame type
* @param outputType Output frame type
*/
Cast& setOutputFrameType(dai::RawImgFrame::Type outputType);

/**
* Set scale
* @param scale Scale
*/
Cast& setScale(float scale);

/**
* Set offset
* @param offset Offset
*/
Cast& setOffset(float offset);
};

} // namespace node
} // namespace dai
4 changes: 4 additions & 0 deletions src/device/DeviceBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1219,6 +1219,10 @@ int DeviceBase::getXLinkChunkSize() {
return pimpl->rpcClient->call("getXLinkChunkSize").as<int>();
}

void DeviceBase::setXLinkRateLimit(int maxRateBytesPerSecond, int burstSize, int waitUs) {
pimpl->rpcClient->call("setXLinkRateLimit", maxRateBytesPerSecond, burstSize, waitUs);
}

DeviceInfo DeviceBase::getDeviceInfo() const {
return deviceInfo;
}
Expand Down
13 changes: 13 additions & 0 deletions src/device/DeviceBootloader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,19 @@ void DeviceBootloader::init(bool embeddedMvcmd, const dai::Path& pathToMvcmd, tl
// Retrieve bootloader version
version = requestVersion();
flashedVersion = version;

auto recommendedMinVersion = DeviceBootloader::Version(0, 0, 28);
if(version < recommendedMinVersion) {
logger::warn(
"[{}] [{}] Flashed bootloader version {}, less than {} is susceptible to bootup/restart failure. Upgrading is advised, flashing "
"main/factory (not user) bootloader. Available: {}",
deviceInfo.mxid,
deviceInfo.name,
version.toString(),
recommendedMinVersion.toString(),
getEmbeddedBootloaderVersion().toString());
}

if(version >= Version(0, 0, 12)) {
// If version is adequate, do an in memory boot.

Expand Down
55 changes: 38 additions & 17 deletions src/pipeline/datatype/StreamMessageParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
#include <XLink/XLinkPublicDefines.h>
#include <spdlog/spdlog.h>

#include "utility/Logging.hpp"

// project
#include "depthai/pipeline/datatype/ADatatype.hpp"
#include "depthai/pipeline/datatype/AprilTagConfig.hpp"
Expand Down Expand Up @@ -67,6 +69,8 @@

namespace dai {

static constexpr std::array<uint8_t, 16> endOfPacketMarker = {0xAB, 0xCD, 0xEF, 0x01, 0x23, 0x45, 0x67, 0x89, 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0};

// Reads int from little endian format
inline int readIntLE(uint8_t* data) {
return data[0] + data[1] * 256 + data[2] * 256 * 256 + data[3] * 256 * 256 * 256;
Expand All @@ -85,28 +89,40 @@ inline std::shared_ptr<T> parseDatatype(std::uint8_t* metadata, size_t size, std
}

static std::tuple<DatatypeEnum, size_t, size_t> parseHeader(streamPacketDesc_t* const packet) {
if(packet->length < 8) {
throw std::runtime_error("Bad packet, couldn't parse (not enough data)");
if(packet->length < 24) {
throw std::runtime_error(fmt::format("Bad packet, couldn't parse (not enough data), total size {}", packet->length));
}
const std::uint32_t packetLength = packet->length - endOfPacketMarker.size();
const int serializedObjectSize = readIntLE(packet->data + packetLength - 4);
const auto objectType = static_cast<DatatypeEnum>(readIntLE(packet->data + packetLength - 8));

uint8_t* marker = packet->data + packetLength;
if(memcmp(marker, endOfPacketMarker.data(), endOfPacketMarker.size()) != 0) {
std::string hex;
for(std::uint32_t i = 0; i < endOfPacketMarker.size(); i++) {
hex += fmt::format("{:02X}", marker[i]);
}
logger::warn("StreamMessageParser end-of-packet marker mismatch, got: " + hex);
}
const int serializedObjectSize = readIntLE(packet->data + packet->length - 4);
const auto objectType = static_cast<DatatypeEnum>(readIntLE(packet->data + packet->length - 8));

const auto info = fmt::format(", total size {}, type {}, metadata size {}", packet->length, objectType, serializedObjectSize);

if(serializedObjectSize < 0) {
throw std::runtime_error("Bad packet, couldn't parse (metadata size negative)");
} else if(serializedObjectSize > static_cast<int>(packet->length)) {
throw std::runtime_error("Bad packet, couldn't parse (metadata size larger than packet length)");
throw std::runtime_error("Bad packet, couldn't parse (metadata size negative)" + info);
} else if(serializedObjectSize > static_cast<int>(packetLength)) {
throw std::runtime_error("Bad packet, couldn't parse (metadata size larger than packet length)" + info);
}
if(static_cast<int>(packet->length) - 8 - serializedObjectSize < 0) {
throw std::runtime_error("Bad packet, couldn't parse (data too small)");
if(static_cast<int>(packetLength) - 8 - serializedObjectSize < 0) {
throw std::runtime_error("Bad packet, couldn't parse (data too small)" + info);
}
const std::uint32_t bufferLength = packet->length - 8 - serializedObjectSize;
if(bufferLength > packet->length) {
throw std::runtime_error("Bad packet, couldn't parse (data too large)");
const std::uint32_t bufferLength = packetLength - 8 - serializedObjectSize;
if(bufferLength > packetLength) {
throw std::runtime_error("Bad packet, couldn't parse (data too large)" + info);
}
auto* const metadataStart = packet->data + bufferLength;

if(metadataStart < packet->data || metadataStart >= packet->data + packet->length) {
throw std::runtime_error("Bad packet, couldn't parse (metadata out of bounds)");
if(metadataStart < packet->data || metadataStart >= packet->data + packetLength) {
throw std::runtime_error("Bad packet, couldn't parse (metadata out of bounds)" + info);
}

return {objectType, serializedObjectSize, bufferLength};
Expand Down Expand Up @@ -217,7 +233,8 @@ std::shared_ptr<RawBuffer> StreamMessageParser::parseMessage(streamPacketDesc_t*
break;
}

throw std::runtime_error("Bad packet, couldn't parse");
throw std::runtime_error(
fmt::format("Bad packet, couldn't parse, total size {}, type {}, metadata size {}", packet->length, objectType, serializedObjectSize));
}

std::shared_ptr<ADatatype> StreamMessageParser::parseMessageToADatatype(streamPacketDesc_t* const packet, DatatypeEnum& objectType) {
Expand Down Expand Up @@ -324,8 +341,10 @@ std::shared_ptr<ADatatype> StreamMessageParser::parseMessageToADatatype(streamPa
break;
}

throw std::runtime_error("Bad packet, couldn't parse (invalid message type)");
throw std::runtime_error(fmt::format(
"Bad packet, couldn't parse (invalid message type), total size {}, type {}, metadata size {}", packet->length, objectType, serializedObjectSize));
}

std::shared_ptr<ADatatype> StreamMessageParser::parseMessageToADatatype(streamPacketDesc_t* const packet) {
DatatypeEnum objectType;
return parseMessageToADatatype(packet, objectType);
Expand All @@ -337,6 +356,7 @@ std::vector<std::uint8_t> StreamMessageParser::serializeMessage(const RawBuffer&
// 2. serialize and append metadata
// 3. append datatype enum (4B LE)
// 4. append size (4B LE) of serialized metadata
// 5. append 16-byte marker/canary

DatatypeEnum datatype;
std::vector<std::uint8_t> metadata;
Expand All @@ -350,11 +370,12 @@ std::vector<std::uint8_t> StreamMessageParser::serializeMessage(const RawBuffer&
for(int i = 0; i < 4; i++) leMetadataSize[i] = (metadataSize >> i * 8) & 0xFF;

std::vector<std::uint8_t> ser;
ser.reserve(data.data.size() + metadata.size() + leDatatype.size() + leMetadataSize.size());
ser.reserve(data.data.size() + metadata.size() + leDatatype.size() + leMetadataSize.size() + endOfPacketMarker.size());
ser.insert(ser.end(), data.data.begin(), data.data.end());
ser.insert(ser.end(), metadata.begin(), metadata.end());
ser.insert(ser.end(), leDatatype.begin(), leDatatype.end());
ser.insert(ser.end(), leMetadataSize.begin(), leMetadataSize.end());
ser.insert(ser.end(), endOfPacketMarker.begin(), endOfPacketMarker.end());

return ser;
}
Expand Down
36 changes: 36 additions & 0 deletions src/pipeline/node/Cast.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#include "depthai/pipeline/node/Cast.hpp"

#include "spdlog/fmt/fmt.h"

namespace dai {
namespace node {

Cast::Cast(const std::shared_ptr<PipelineImpl>& par, int64_t nodeId) : Cast(par, nodeId, std::make_unique<Cast::Properties>()) {}
Cast::Cast(const std::shared_ptr<PipelineImpl>& par, int64_t nodeId, std::unique_ptr<Properties> props)
: NodeCRTP<Node, Cast, CastProperties>(par, nodeId, std::move(props)) {
setInputRefs({&input});
setOutputRefs({&output, &passthroughInput});
}

Cast& Cast::setNumFramesPool(int numFramesPool) {
properties.numFramesPool = numFramesPool;
return *this;
}

Cast& Cast::setOutputFrameType(dai::RawImgFrame::Type outputType) {
properties.outputType = outputType;
return *this;
}

Cast& Cast::setScale(float scale) {
properties.scale = scale;
return *this;
}

Cast& Cast::setOffset(float offset) {
properties.offset = offset;
return *this;
}

} // namespace node
} // namespace dai
29 changes: 24 additions & 5 deletions tests/src/stream_message_parser_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

// TODO(themarpe) - fuzz me instead

constexpr auto MARKER_SIZE = 16;

TEST_CASE("Correct message") {
dai::ImgFrame frm;
auto ser = dai::StreamMessageParser::serializeMessage(frm);
Expand All @@ -20,12 +22,29 @@ TEST_CASE("Correct message") {
REQUIRE(ser == ser2);
}

TEST_CASE("Correct message, but padding corrupted, a warning should be printed") {
dai::ImgFrame frm;
auto ser = dai::StreamMessageParser::serializeMessage(frm);
ser[ser.size() - 1] = 0x55;

streamPacketDesc_t packet;
packet.data = ser.data();
packet.length = ser.size();

auto des = dai::StreamMessageParser::parseMessageToADatatype(&packet);
auto ser2 = dai::StreamMessageParser::serializeMessage(des);
// Just for the binary compare to match, cause the same corruption in re-serialized msg
ser2[ser.size() - 1] = 0x55;

REQUIRE(ser == ser2);
}

TEST_CASE("Incorrect message bad size") {
dai::ImgFrame frm;
auto ser = dai::StreamMessageParser::serializeMessage(frm);

// wreak havoc on serialized data
ser[ser.size() - 1] = 100;
ser[ser.size() - 1 - MARKER_SIZE] = 100;

streamPacketDesc_t packet;
packet.data = ser.data();
Expand All @@ -39,7 +58,7 @@ TEST_CASE("Incorrect message negative size") {
auto ser = dai::StreamMessageParser::serializeMessage(frm);

// wreak havoc on serialized data
ser[ser.size() - 1] = 200;
ser[ser.size() - 1 - MARKER_SIZE] = 200;

streamPacketDesc_t packet;
packet.data = ser.data();
Expand Down Expand Up @@ -87,7 +106,7 @@ TEST_CASE("Raw - Incorrect message bad size") {
auto ser = dai::StreamMessageParser::serializeMessage(frm);

// wreak havoc on serialized data
ser[ser.size() - 1] = 100;
ser[ser.size() - 1 - MARKER_SIZE] = 100;

streamPacketDesc_t packet;
packet.data = ser.data();
Expand All @@ -101,7 +120,7 @@ TEST_CASE("Raw - Incorrect message negative size") {
auto ser = dai::StreamMessageParser::serializeMessage(frm);

// wreak havoc on serialized data
ser[ser.size() - 1] = 200;
ser[ser.size() - 1 - MARKER_SIZE] = 200;

streamPacketDesc_t packet;
packet.data = ser.data();
Expand All @@ -128,4 +147,4 @@ TEST_CASE("Raw - Incorrect message too small size 2") {
packet.length = ser.size();

REQUIRE_THROWS(dai::StreamMessageParser::parseMessage(&packet));
}
}
Loading