Skip to content

Commit 25987fc

Browse files
authored
Merge pull request #1316 from luxonis/fix/create_subnodes
Fix method responsible for creating python subnodes (createSubnode)
2 parents 22ecd00 + cd33cd7 commit 25987fc

File tree

6 files changed

+31
-15
lines changed

6 files changed

+31
-15
lines changed

bindings/python/src/pipeline/node/HostNodeBindings.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,11 @@ void bind_hostnode(pybind11::module& m, void* pCallstack) {
172172
173173
# Create a subnode as part of this user node
174174
def createSubnode(self, class_, *args, **kwargs):
175-
return self.getParentPipeline().create(class_, *args, **kwargs)
175+
pipeline = self.getParentPipeline()
176+
child_node = pipeline.create(class_, *args, **kwargs)
177+
pipeline.remove(child_node) # necessary so that the node is only registered once
178+
self.add(child_node)
179+
return child_node
176180
177181
node.HostNode.createSubnode = createSubnode
178182
node.ThreadedHostNode.createSubnode = createSubnode

bindings/python/src/pipeline/node/NodeBindings.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,8 @@ void NodeBindings::bind(pybind11::module& m, void* pCallstack) {
430430
.def("getAssetManager",
431431
static_cast<AssetManager& (Node::*)()>(&Node::getAssetManager),
432432
py::return_value_policy::reference_internal,
433-
DOC(dai, Node, getAssetManager));
433+
DOC(dai, Node, getAssetManager))
434+
.def("add", &Node::add, py::arg("node"), DOC(dai, Node, add));
434435

435436
// TODO(themarpe) - refactor, threaded node could be separate from Node
436437
pyThreadedNode.def("trace", [](dai::ThreadedNode& node, const std::string& msg) { node.logger->trace(msg); })

src/pipeline/Node.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -587,9 +587,9 @@ void Node::add(std::shared_ptr<Node> node) {
587587
void Node::remove(std::shared_ptr<Node> node) {
588588
// Remove the connection to the removed node and all it's children from all the nodes in the pipeline
589589
auto pipeline = parent.lock();
590-
if(pipeline == nullptr) {
591-
throw std::runtime_error("Pipeline is null");
592-
}
590+
591+
DAI_CHECK_V(pipeline != nullptr, "Pipeline is null");
592+
DAI_CHECK_V(!pipeline->isBuilt(), "Cannot remove node from pipeline once it is built.");
593593

594594
for(auto& n : pipeline->nodes) {
595595
for(auto& childNode : node->nodeMap) {

src/pipeline/Pipeline.cpp

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "pipeline/node/DetectionNetwork.hpp"
1414
#include "utility/Compression.hpp"
1515
#include "utility/Environment.hpp"
16+
#include "utility/ErrorMacros.hpp"
1617
#include "utility/HolisticRecordReplay.hpp"
1718
#include "utility/Logging.hpp"
1819
#include "utility/Platform.hpp"
@@ -438,13 +439,9 @@ BoardConfig PipelineImpl::getBoardConfig() const {
438439

439440
// Remove node capability
440441
void PipelineImpl::remove(std::shared_ptr<Node> toRemove) {
441-
if(toRemove->parent.lock() == nullptr) {
442-
throw std::invalid_argument("Cannot remove a node that is not a part of any pipeline");
443-
}
444-
445-
if(toRemove->parent.lock() != parent.pimpl) {
446-
throw std::invalid_argument("Cannot remove a node that is not a part of this pipeline");
447-
}
442+
DAI_CHECK_V(!isBuilt(), "Cannot remove node from pipeline once it is built.");
443+
DAI_CHECK_V(toRemove->parent.lock() != nullptr, "Cannot remove a node that is not a part of any pipeline");
444+
DAI_CHECK_V(toRemove->parent.lock() == parent.pimpl, "Cannot remove a node that is not a part of this pipeline");
448445

449446
// First remove the node from the pipeline directly
450447
auto it = std::remove(nodes.begin(), nodes.end(), toRemove);

src/pipeline/ThreadedNode.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "utility/Environment.hpp"
66
#include "utility/Logging.hpp"
77
#include "utility/Platform.hpp"
8+
#include "utility/ErrorMacros.hpp"
89

910
namespace dai {
1011
ThreadedNode::ThreadedNode() {
@@ -17,6 +18,11 @@ ThreadedNode::ThreadedNode() {
1718
}
1819

1920
void ThreadedNode::start() {
21+
22+
// A node should not be started if it is already running
23+
// We would be creating multiple threads for the same node
24+
DAI_CHECK_V(!isRunning(), "Node with id {} is already running. Cannot start it again. Node name: {}", id, getName());
25+
2026
onStart();
2127
// Start the thread
2228
running = true;

src/pipeline/node/Camera.cpp

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,19 @@ class Camera::Impl {
4646
}
4747

4848
void buildStage1(Camera& parent) {
49+
size_t numUnconnectedOutputs = 0;
4950
for(const auto& outputRequest : outputRequests) {
50-
DAI_CHECK(!parent.dynamicOutputs[std::to_string(outputRequest.id)].getQueueConnections().empty()
51-
|| !parent.dynamicOutputs[std::to_string(outputRequest.id)].getConnections().empty(),
52-
"Always call output->createOutputQueue() or output->link(*) after calling dai::node::Camera::requestOutput()");
51+
bool hasQueue = !parent.dynamicOutputs[std::to_string(outputRequest.id)].getQueueConnections().empty();
52+
bool hasConnections = !parent.dynamicOutputs[std::to_string(outputRequest.id)].getConnections().empty();
53+
if(!hasQueue && !hasConnections) {
54+
++numUnconnectedOutputs;
55+
}
5356
}
57+
58+
DAI_CHECK_V(numUnconnectedOutputs == 0,
59+
"Always call output->createOutputQueue() or output->link(*) after calling dai::node::Camera::requestOutput(). There is(are) {} requested "
60+
"Camera output(s) with no connected inputs or created output queues.",
61+
numUnconnectedOutputs);
5462
}
5563
};
5664

0 commit comments

Comments
 (0)