diff --git a/host/core/disparity_stream_post_processor.cpp b/host/core/disparity_stream_post_processor.cpp index 78d524452..e49b21089 100644 --- a/host/core/disparity_stream_post_processor.cpp +++ b/host/core/disparity_stream_post_processor.cpp @@ -34,8 +34,9 @@ void DisparityStreamPostProcessor::prepareDepthColorAndNotifyObservers( const StreamData &data ) { - // TODO: remove hardcode - StreamInfo depth_si(c_stream_out_color.c_str(), 720*1280*3, { 720, 1280, 3}); + StreamInfo depth_si(c_stream_out_color.c_str(), + data_info.dimensions[0] * data_info.dimensions[1] * 3, + {data_info.dimensions[0], data_info.dimensions[1], 3}); std::vector depth_raw(depth_si.size); const unsigned char* disp_uc = (const unsigned char*) data.data; diff --git a/host/core/host_data_packet.hpp b/host/core/host_data_packet.hpp index e8f8de3dd..f43fbeffc 100644 --- a/host/core/host_data_packet.hpp +++ b/host/core/host_data_packet.hpp @@ -115,8 +115,8 @@ struct HostDataPacket sizeof(std::uint16_t), /* size of one scalar */ py::format_descriptor::format(), /* data type */ 2, //ndim, /* number of dimensions */ - {720, 1280}, //shape, /* shape of the matrix */ - {1280*2, 1*2} //strides /* strides for each axis */ + {dimensions[0], dimensions[1]}, //shape, /* shape of the matrix */ + {dimensions[1]*2, 1*2} //strides /* strides for each axis */ )); } else diff --git a/host/core/nnet/nnet_packet.hpp b/host/core/nnet/nnet_packet.hpp index 0917cf88f..c9e3ef323 100644 --- a/host/core/nnet/nnet_packet.hpp +++ b/host/core/nnet/nnet_packet.hpp @@ -54,6 +54,11 @@ class NNetPacket return getTensor(it->second); } } + + py::object getMetadata() { + // TODO + return _tensors_raw_data[0]->getMetadata(); + } #endif std::shared_ptr getTensorEntryContainer() diff --git a/host/core/nnet/tensor_entry_container.hpp b/host/core/nnet/tensor_entry_container.hpp index c8ab27c3d..d61707c63 100644 --- a/host/core/nnet/tensor_entry_container.hpp +++ b/host/core/nnet/tensor_entry_container.hpp @@ -30,7 +30,8 @@ class TensorEntryContainer for (size_t i = 1; i < _tensors_info->size(); ++i) { - assert((*_tensors_info)[i].getEntriesNumber() == number); + // TODO do we really need this assert? + //assert((*_tensors_info)[i].getEntriesNumber() == number); } return number; diff --git a/host/core/nnet/tensor_info_helper.hpp b/host/core/nnet/tensor_info_helper.hpp index 8f77ea0c3..e640cb55a 100644 --- a/host/core/nnet/tensor_info_helper.hpp +++ b/host/core/nnet/tensor_info_helper.hpp @@ -39,8 +39,6 @@ bool parseTensorInfosFromJsonString(const std::string& json_str, std::vector(); + if (stage > 1) { + printf("INFO: Suffixing output_tensor_name for stage %d: %s", + stage, tensor_info.output_tensor_name.c_str()); + tensor_info.output_tensor_name += "_stage"; + tensor_info.output_tensor_name += '0' + stage; + printf(" -> %s\n", tensor_info.output_tensor_name.c_str()); + } for (auto &v : tensor_it.at("output_dimensions")) { tensor_info.output_dimensions.push_back(v.get()); } tensor_info.output_entry_iteration_index = tensor_it.at("output_entry_iteration_index").get(); for (auto &v : tensor_it.at("output_properties_dimensions")) { tensor_info.output_properties_dimensions.push_back(v.get()); } @@ -180,8 +188,6 @@ bool parseTensorInfosFromJsonFile(const std::string& json_fpath, std::vector rgb_cam_supported_configs = static std::unordered_map mono_cam_supported_configs = { {720, 0}, + {800, 1}, + {400, 2}, }; #define WARNING "\033[1;5;31m" @@ -124,6 +126,21 @@ bool HostPipelineConfig::initWithJSON(const json &json_obj) ai.blob_file_config = ai_obj.at("blob_file_config").get(); } + if (ai_obj.contains("blob_file2")) + { + ai.blob_file2 = ai_obj.at("blob_file2").get(); + } + + if (ai_obj.contains("blob_file_config2")) + { + ai.blob_file_config2 = ai_obj.at("blob_file_config2").get(); + } + + if (ai_obj.contains("camera_input")) + { + ai.camera_input = ai_obj.at("camera_input").get(); + } + if (ai_obj.contains("calc_dist_to_bb")) { ai.calc_dist_to_bb = ai_obj.at("calc_dist_to_bb").get(); @@ -161,13 +178,13 @@ bool HostPipelineConfig::initWithJSON(const json &json_obj) } - if (ai_obj.contains("NCEs")) + if (ai_obj.contains("NN_engines")) { - ai.NCEs = ai_obj.at("NCEs").get(); + ai.NN_engines = ai_obj.at("NN_engines").get(); } - if (ai.NCEs < 0 || ai.NCEs > 2) + if (ai.NN_engines < 0 || ai.NN_engines > 2) { - std::cerr << WARNING "ai.NCEs should be in the range [0 .. 2]\n" ENDC; + std::cerr << WARNING "ai.NN_engines should be in the range [0 .. 2]\n" ENDC; break; } @@ -274,7 +291,7 @@ bool HostPipelineConfig::initWithJSON(const json &json_obj) auto& rgb_camera_conf_obj = camera_conf_obj.at("rgb"); rgb_cam_config.resolution_h = rgb_camera_conf_obj.at("resolution_h").get(); - rgb_cam_config.fps = rgb_camera_conf_obj.at("fps").get(); + rgb_cam_config.fps = rgb_camera_conf_obj.at("fps").get(); auto it = rgb_cam_supported_configs.find(rgb_cam_config.resolution_h); @@ -289,13 +306,21 @@ bool HostPipelineConfig::initWithJSON(const json &json_obj) break; } } + // Defaults if the resolution width is not specified + if (rgb_cam_config.resolution_w == 0) { + if (rgb_cam_config.resolution_h == 1080) + rgb_cam_config.resolution_w = 1920; + if (rgb_cam_config.resolution_h == 2160) + rgb_cam_config.resolution_w = 3840; + } if (camera_conf_obj.contains("mono")) { auto& mono_camera_conf_obj = camera_conf_obj.at("mono"); - + if (mono_camera_conf_obj.contains("resolution_w")) + mono_cam_config.resolution_w = mono_camera_conf_obj.at("resolution_w").get(); mono_cam_config.resolution_h = mono_camera_conf_obj.at("resolution_h").get(); - mono_cam_config.fps = mono_camera_conf_obj.at("fps").get(); + mono_cam_config.fps = mono_camera_conf_obj.at("fps").get(); auto it = mono_cam_supported_configs.find(mono_cam_config.resolution_h); @@ -310,6 +335,13 @@ bool HostPipelineConfig::initWithJSON(const json &json_obj) break; } } + // Defaults if the resolution width is not specified + if (mono_cam_config.resolution_w == 0) { + if (mono_cam_config.resolution_h == 400) + mono_cam_config.resolution_w = 640; + if (mono_cam_config.resolution_h == 720 || mono_cam_config.resolution_h == 800) + mono_cam_config.resolution_w = 1280; + } } result = true; diff --git a/host/core/pipeline/host_pipeline_config.hpp b/host/core/pipeline/host_pipeline_config.hpp index e8541437b..1f2f2068c 100644 --- a/host/core/pipeline/host_pipeline_config.hpp +++ b/host/core/pipeline/host_pipeline_config.hpp @@ -31,11 +31,14 @@ struct HostPipelineConfig { std::string blob_file; std::string blob_file_config; + std::string blob_file2; + std::string blob_file_config2; + std::string camera_input = "rgb"; bool calc_dist_to_bb = false; bool keep_aspect_ratio = true; int32_t shaves = 7; int32_t cmx_slices = 7; - int32_t NCEs = 1; + int32_t NN_engines = 1; } ai; struct OT @@ -61,14 +64,16 @@ struct HostPipelineConfig struct RGBCamConfig { - int32_t resolution_h; - int32_t fps; + int32_t resolution_w = 0; //auto + int32_t resolution_h = 1080; + float fps = 30.f; } rgb_cam_config; struct MonoCamConfig { - int32_t resolution_h; - int32_t fps; + int32_t resolution_w = 0; //auto + int32_t resolution_h = 720; + float fps = 30.f; } mono_cam_config; diff --git a/host/py_module/py_bindings.cpp b/host/py_module/py_bindings.cpp index 90f30fec5..08e32456d 100644 --- a/host/py_module/py_bindings.cpp +++ b/host/py_module/py_bindings.cpp @@ -100,7 +100,7 @@ void wdog_thread(int& wd_timeout_ms) } static std::thread wd_thread; -static int wd_timeout_ms = 3000; +static int wd_timeout_ms = 6000; int wdog_start(void) { static int once = 1; @@ -382,6 +382,8 @@ std::shared_ptr create_pipeline( break; } + int num_stages = config.ai.blob_file2.empty() ? 1 : 2; + // read tensor info std::vector tensors_info; if (parseTensorInfosFromJsonFile(config.ai.blob_file_config, tensors_info)) @@ -393,6 +395,18 @@ std::shared_ptr create_pipeline( std::cout << "There is no cnn configuration file or error in it\'s parsing: " << config.ai.blob_file_config.c_str() << "\n"; } + if (num_stages > 1) + { + if (parseTensorInfosFromJsonFile(config.ai.blob_file_config2, tensors_info)) + { + std::cout << "CNN configurations read: " << config.ai.blob_file_config2.c_str() << "\n"; + } + else + { + std::cout << "There is no cnn configuration file or error in it\'s parsing: " << config.ai.blob_file_config2.c_str() << "\n"; + } + } + // pipeline configurations json // homography @@ -461,29 +475,39 @@ std::shared_ptr create_pipeline( {"_streams", json::array()} }; + json_config_obj["camera"]["rgb"]["resolution_w"] = config.rgb_cam_config.resolution_w; json_config_obj["camera"]["rgb"]["resolution_h"] = config.rgb_cam_config.resolution_h; json_config_obj["camera"]["rgb"]["fps"] = config.rgb_cam_config.fps; + json_config_obj["camera"]["mono"]["resolution_w"] = config.mono_cam_config.resolution_w; json_config_obj["camera"]["mono"]["resolution_h"] = config.mono_cam_config.resolution_h; json_config_obj["camera"]["mono"]["fps"] = config.mono_cam_config.fps; - HostDataReader _blob_reader; - int size_blob = 0; - if (!config.ai.blob_file.empty()) - { - if (!_blob_reader.init(config.ai.blob_file)) + std::string blob_file[] = {config.ai.blob_file, config.ai.blob_file2}; + + HostDataReader _blob_reader[num_stages]; + int size_blob[num_stages]; + for (int stage = 0; stage < num_stages; stage++) + { + if (!blob_file[stage].empty()) { - std::cerr << WARNING "depthai: Error opening blob file: " << config.ai.blob_file << "\n" ENDC; - break; + if (!_blob_reader[stage].init(blob_file[stage])) + { + std::cerr << WARNING "depthai: Error opening blob file: " << blob_file[stage] << "\n" ENDC; + break; + } + size_blob[stage] = _blob_reader[stage].getSize(); } - size_blob = _blob_reader.getSize(); } - json_config_obj["ai"]["blob_size"] = size_blob; + json_config_obj["ai"]["blob0_size"] = size_blob[0]; + json_config_obj["ai"]["blob1_size"] = (num_stages > 1) ? size_blob[1] : 0; json_config_obj["ai"]["calc_dist_to_bb"] = config.ai.calc_dist_to_bb; json_config_obj["ai"]["keep_aspect_ratio"] = config.ai.keep_aspect_ratio; json_config_obj["ai"]["shaves"] = config.ai.shaves; json_config_obj["ai"]["cmx_slices"] = config.ai.cmx_slices; - json_config_obj["ai"]["NCEs"] = config.ai.NCEs; + json_config_obj["ai"]["NCEs"] = config.ai.NN_engines; + json_config_obj["ai"]["camera_input"] = config.ai.camera_input; + json_config_obj["ai"]["num_stages"] = num_stages; json_config_obj["ot"]["max_tracklets"] = config.ot.max_tracklets; json_config_obj["ot"]["confidence_threshold"] = config.ot.confidence_threshold; @@ -495,8 +519,15 @@ std::shared_ptr create_pipeline( for (const auto &stream : config.streams) { + if (c_streams_myriad_to_pc[stream.name].dimensions[0] == MONO_RES_AUTO) { + c_streams_myriad_to_pc[stream.name].dimensions[0] = config.mono_cam_config.resolution_h; + c_streams_myriad_to_pc[stream.name].dimensions[1] = config.mono_cam_config.resolution_w; + } + if (stream.name == "depth_color_h") { + c_streams_myriad_to_pc["disparity"].dimensions[0] = c_streams_myriad_to_pc[stream.name].dimensions[0]; + c_streams_myriad_to_pc["disparity"].dimensions[1] = c_streams_myriad_to_pc[stream.name].dimensions[1]; add_disparity_post_processing_color = true; json obj = { {"name", "disparity"} }; if (0.f != stream.max_fps) { obj["max_fps"] = stream.max_fps; }; @@ -513,20 +544,7 @@ std::shared_ptr create_pipeline( if (!stream.data_type.empty()) { obj["data_type"] = stream.data_type; }; if (0.f != stream.max_fps) { obj["max_fps"] = stream.max_fps; }; - // TODO: temporary solution - if (stream.name == "depth_sipp") - // { - // obj["data_type"] = "uint8"; - // c_streams_myriad_to_pc["depth_sipp"] = StreamInfo("depth_sipp", 0, { 720, 1280} ); - // } - { - obj["data_type"] = "uint16"; - c_streams_myriad_to_pc["depth_sipp"] = StreamInfo("depth_sipp", 0, { 720, 1280}, 2 ); - } - // { - // obj["data_type"] = "rgb"; - // c_streams_myriad_to_pc["depth_sipp"] = StreamInfo("depth_sipp", 2764800, { 720, 1280, 3} ); - // } + if (stream.name == "depth_sipp"){obj["data_type"] = "uint16"; } json_config_obj["_pipeline"]["_streams"].push_back(obj); pipeline_device_streams.push_back(stream.name); @@ -563,89 +581,95 @@ std::shared_ptr create_pipeline( } else { - std::vector buff_blob(size_blob); + for (int stage = 0; stage < num_stages; stage++) + { + std::vector buff_blob(size_blob[stage]); - std::cout << "Read: " << _blob_reader.readData(buff_blob.data(), size_blob) << std::endl; + std::cout << "Read: " << _blob_reader[stage].readData(buff_blob.data(), size_blob[stage]) << std::endl; - // inBlob - StreamInfo blobInfo; - blobInfo.name = "inBlob"; - blobInfo.size = size_blob; + // inBlob + StreamInfo blobInfo; + blobInfo.name = "inBlob"; + blobInfo.size = size_blob[stage]; - if (!g_xlink->openWriteAndCloseStream(blobInfo, buff_blob.data())) - { - std::cout << "depthai: pipelineConfig write error: Blob size too big: " << size_blob << "\n"; - break; - } - printf("depthai: done sending Blob file %s\n", config.ai.blob_file.c_str()); + if (!g_xlink->openWriteAndCloseStream(blobInfo, buff_blob.data())) + { + std::cout << "depthai: pipelineConfig write error: Blob size too big: " << size_blob[stage] << "\n"; + break; + } + printf("depthai: done sending Blob file %s\n", blob_file[stage].c_str()); - // outBlob - StreamInfo outBlob; - outBlob.name = "outBlob"; - //TODO: remove asserts considering StreamInfo size - outBlob.size = 1; + // outBlob + StreamInfo outBlob; + outBlob.name = "outBlob"; + //TODO: remove asserts considering StreamInfo size + outBlob.size = 1; - cnn_info cnn_input_info; + cnn_info cnn_input_info; - static char cnn_info_arr[sizeof(cnn_info)]; - g_xlink->openReadAndCloseStream( - outBlob, - (void*)cnn_info_arr, - sizeof(cnn_info) - ); + static char cnn_info_arr[sizeof(cnn_info)]; + g_xlink->openReadAndCloseStream( + outBlob, + (void*)cnn_info_arr, + sizeof(cnn_info) + ); - memcpy(&cnn_input_info, &cnn_info_arr, sizeof(cnn_input_info)); - - printf("CNN input width: %d\n", cnn_input_info.cnn_input_width); - printf("CNN input height: %d\n", cnn_input_info.cnn_input_height); - printf("CNN input num channels: %d\n", cnn_input_info.cnn_input_num_channels); - printf("CNN to depth bounding-box mapping: start(%d, %d), max_size(%d, %d)\n", - cnn_input_info.nn_to_depth.offset_x, - cnn_input_info.nn_to_depth.offset_y, - cnn_input_info.nn_to_depth.max_width, - cnn_input_info.nn_to_depth.max_height); - nn_to_depth_mapping["off_x"] = cnn_input_info.nn_to_depth.offset_x; - nn_to_depth_mapping["off_y"] = cnn_input_info.nn_to_depth.offset_y; - nn_to_depth_mapping["max_w"] = cnn_input_info.nn_to_depth.max_width; - nn_to_depth_mapping["max_h"] = cnn_input_info.nn_to_depth.max_height; - - // update tensor infos - assert(!(tensors_info.size() > (sizeof(cnn_input_info.offsets)/sizeof(cnn_input_info.offsets[0])))); - - for (int i = 0; i < tensors_info.size(); i++) - { - tensors_info[i].nnet_input_width = cnn_input_info.cnn_input_width; - tensors_info[i].nnet_input_height = cnn_input_info.cnn_input_height; - tensors_info[i].offset = cnn_input_info.offsets[i]; - } + memcpy(&cnn_input_info, &cnn_info_arr, sizeof(cnn_input_info)); - c_streams_myriad_to_pc["previewout"].dimensions = { - cnn_input_info.cnn_input_num_channels, - cnn_input_info.cnn_input_height, - cnn_input_info.cnn_input_width - }; + printf("CNN input width: %d\n", cnn_input_info.cnn_input_width); + printf("CNN input height: %d\n", cnn_input_info.cnn_input_height); + printf("CNN input num channels: %d\n", cnn_input_info.cnn_input_num_channels); + if (stage == 0) + { + printf("CNN to depth bounding-box mapping: start(%d, %d), max_size(%d, %d)\n", + cnn_input_info.nn_to_depth.offset_x, + cnn_input_info.nn_to_depth.offset_y, + cnn_input_info.nn_to_depth.max_width, + cnn_input_info.nn_to_depth.max_height); + nn_to_depth_mapping["off_x"] = cnn_input_info.nn_to_depth.offset_x; + nn_to_depth_mapping["off_y"] = cnn_input_info.nn_to_depth.offset_y; + nn_to_depth_mapping["max_w"] = cnn_input_info.nn_to_depth.max_width; + nn_to_depth_mapping["max_h"] = cnn_input_info.nn_to_depth.max_height; + } + // update tensor infos + assert(!(tensors_info.size() > (sizeof(cnn_input_info.offsets)/sizeof(cnn_input_info.offsets[0])))); + + if (stage == 0) { + for (int i = 0; i < tensors_info.size(); i++) + { + tensors_info[i].nnet_input_width = cnn_input_info.cnn_input_width; + tensors_info[i].nnet_input_height = cnn_input_info.cnn_input_height; + tensors_info[i].offset = cnn_input_info.offsets[i]; + } + + c_streams_myriad_to_pc["previewout"].dimensions = { + cnn_input_info.cnn_input_num_channels, + cnn_input_info.cnn_input_height, + cnn_input_info.cnn_input_width + }; + } + // check CMX slices & used shaves + if (cnn_input_info.number_of_cmx_slices > config.ai.cmx_slices) + { + std::cerr << WARNING "Error: Blob is compiled for " << cnn_input_info.number_of_cmx_slices + << " cmx slices but device is configured to calculate on " << config.ai.cmx_slices << "\n" ENDC; + break; + } - // check CMX slices & used shaves - if (cnn_input_info.number_of_cmx_slices > config.ai.cmx_slices) - { - std::cerr << WARNING "Error: Blob is compiled for " << cnn_input_info.number_of_cmx_slices - << " cmx slices but device is configured to calculate on " << config.ai.cmx_slices << "\n" ENDC; - break; - } + if (cnn_input_info.number_of_shaves > config.ai.shaves) + { + std::cerr << WARNING "Error: Blob is compiled for " << cnn_input_info.number_of_shaves + << " shaves but device is configured to calculate on " << config.ai.shaves << "\n" ENDC; + break; + } - if (cnn_input_info.number_of_shaves > config.ai.shaves) - { - std::cerr << WARNING "Error: Blob is compiled for " << cnn_input_info.number_of_shaves - << " shaves but device is configured to calculate on " << config.ai.shaves << "\n" ENDC; - break; - } - - if(!cnn_input_info.satisfied_resources) - { - std::cerr << WARNING "ERROR: requested CNN resources overlaps with RGB camera \n" ENDC; - break; - } + if(!cnn_input_info.satisfied_resources) + { + std::cerr << WARNING "ERROR: requested CNN resources overlaps with RGB camera \n" ENDC; + break; + } + } } @@ -867,6 +891,7 @@ PYBIND11_MODULE(depthai, m) .def("getCategory", &FrameMetadata::getCategory) .def("getInstanceNum", &FrameMetadata::getInstanceNum) .def("getSequenceNum", &FrameMetadata::getSequenceNum) + .def("getCameraName", &FrameMetadata::getCameraName) ; // ObjectTracker struct binding @@ -923,6 +948,7 @@ PYBIND11_MODULE(depthai, m) .def("get_tensor", &NNetPacket::getTensor, py::return_value_policy::copy) .def("get_tensor", &NNetPacket::getTensorByName, py::return_value_policy::copy) .def("entries", &NNetPacket::getTensorEntryContainer, py::return_value_policy::copy) + .def("getMetadata", &NNetPacket::getMetadata, py::return_value_policy::copy) ; // for te in nnet_packet.ENTRIES() diff --git a/shared/depthai_constants.hpp b/shared/depthai_constants.hpp index 885242c38..9916ed8b6 100644 --- a/shared/depthai_constants.hpp +++ b/shared/depthai_constants.hpp @@ -13,6 +13,12 @@ #include "metadata/capture_metadata.hpp" +#define MONO_RES_AUTO (-2) +#define MONO_MAX_W 1280 +#define MONO_MAX_H 800 +#define MONO_MAX_SIZE(n_planes, elem_size) \ + (MONO_MAX_W * MONO_MAX_H * (n_planes) * (elem_size) + sizeof(FrameMetadata)) + // TODO: remove next constant std::unordered_map g_streams_pc_to_myriad = { @@ -23,13 +29,13 @@ std::unordered_map g_streams_pc_to_myriad = std::unordered_map c_streams_myriad_to_pc = { - {"left", StreamInfo("left", 921600 + sizeof(FrameMetadata), { 720, 1280} )}, - {"right", StreamInfo("right", 921600 + sizeof(FrameMetadata), { 720, 1280} )}, - {"disparity", StreamInfo("disparity", 921600, { 720, 1280} )}, + {"left", StreamInfo("left", MONO_MAX_SIZE(1,1), { MONO_RES_AUTO, 0} )}, + {"right", StreamInfo("right", MONO_MAX_SIZE(1,1), { MONO_RES_AUTO, 0} )}, + {"disparity", StreamInfo("disparity", MONO_MAX_SIZE(1,1), { MONO_RES_AUTO, 0} )}, // {"depth", StreamInfo("depth", 921600, { 720, 1280} )}, - {"depth_sipp", StreamInfo("depth_sipp", 0, { 720, 1280}, 2 )}, - {"depth_color_h", StreamInfo("depth_color_h", 720*1280*3, { 720, 1280, 3} )}, + {"depth_sipp", StreamInfo("depth_sipp", MONO_MAX_SIZE(1,2), { MONO_RES_AUTO, 0}, 2 )}, + {"depth_color_h", StreamInfo("depth_color_h", MONO_MAX_SIZE(3,1), { MONO_RES_AUTO, 0, 3} )}, {"metaout", StreamInfo("metaout", 4*1024*1024)}, // 4 mb max metaout size {"previewout", StreamInfo("previewout", 1920256)}, diff --git a/shared/metadata/frame_metadata.hpp b/shared/metadata/frame_metadata.hpp index 6addd1eeb..69d025d84 100644 --- a/shared/metadata/frame_metadata.hpp +++ b/shared/metadata/frame_metadata.hpp @@ -85,5 +85,9 @@ struct FrameMetadata { return seqNo; } + std::string getCameraName() { + const std::string camName[] = {"rgb", "left", "right"}; + return camName[instNo]; + } -}; \ No newline at end of file +};