diff --git a/.gitignore b/.gitignore
index 31ffce55b1fcf9926b1a3184893002b164a22259..47b63fc13658f5c9417837fa6f95fd985216438e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,4 @@
build
devel
.catkin_workspace
-src/CMakeLists.txt
\ No newline at end of file
+src/CMakeLists.txt
diff --git a/src/binocular/CMakeLists.txt b/src/binocular/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..bf88ce21674138e51094b133759039aa5efb191b
--- /dev/null
+++ b/src/binocular/CMakeLists.txt
@@ -0,0 +1,241 @@
+cmake_minimum_required(VERSION 2.8.3)
+project(binocular)
+
+enable_language(C)
+enable_language(CXX)
+enable_language(CUDA)
+find_package(CUDA REQUIRED)
+include_directories(${CUDA_INCLUDE_DIRS})
+cuda_select_nvcc_arch_flags(NVCC_FLAGS "Auto")
+string (REPLACE ";" " " CUDA_ARCH_FLAGS_SPACE_SEPARATED "${NVCC_FLAGS}")
+set(CMAKE_CUDA_FLAGS "${CUDA_ARCH_FLAGS_SPACE_SEPARATED}")
+set(CMAKE_CXX_STANDARD 11)
+find_package(OpenCV)
+add_definitions(-DGPU)
+add_definitions(-DCUDNN)
+## Compile as C++11, supported in ROS Kinetic and newer
+# add_compile_options(-std=c++11)
+
+## Find catkin macros and libraries
+## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
+## is used, also find other catkin packages
+find_package(catkin REQUIRED COMPONENTS
+ message_generation
+ roscpp
+ rospy
+ sensor_msgs
+ std_msgs
+ config
+ common
+ seuimage
+ darknet
+)
+
+## System dependencies are found with CMake's conventions
+# find_package(Boost REQUIRED COMPONENTS system)
+
+
+## Uncomment this if the package has a setup.py. This macro ensures
+## modules and global scripts declared therein get installed
+## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html
+# catkin_python_setup()
+
+################################################
+## Declare ROS messages, services and actions ##
+################################################
+
+## To declare and build messages, services or actions from within this
+## package, follow these steps:
+## * Let MSG_DEP_SET be the set of packages whose message types you use in
+## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...).
+## * In the file package.xml:
+## * add a build_depend tag for "message_generation"
+## * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET
+## * If MSG_DEP_SET isn't empty the following dependency has been pulled in
+## but can be declared for certainty nonetheless:
+## * add a exec_depend tag for "message_runtime"
+## * In this file (CMakeLists.txt):
+## * add "message_generation" and every package in MSG_DEP_SET to
+## find_package(catkin REQUIRED COMPONENTS ...)
+## * add "message_runtime" and every package in MSG_DEP_SET to
+## catkin_package(CATKIN_DEPENDS ...)
+## * uncomment the add_*_files sections below as needed
+## and list every .msg/.srv/.action file to be processed
+## * uncomment the generate_messages entry below
+## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...)
+
+## Generate messages in the 'msg' folder
+# add_message_files(
+# FILES
+# CameraProperty.msg
+# )
+
+## Generate services in the 'srv' folder
+# add_service_files(
+# FILES
+# CameraInfo.srv
+# )
+
+## Generate actions in the 'action' folder
+# add_action_files(
+# FILES
+# Action1.action
+# Action2.action
+# )
+
+## Generate added messages and services with any dependencies listed here
+# generate_messages(
+# DEPENDENCIES
+# std_msgs
+# )
+
+################################################
+## Declare ROS dynamic reconfigure parameters ##
+################################################
+
+## To declare and build dynamic reconfigure parameters within this
+## package, follow these steps:
+## * In the file package.xml:
+## * add a build_depend and a exec_depend tag for "dynamic_reconfigure"
+## * In this file (CMakeLists.txt):
+## * add "dynamic_reconfigure" to
+## find_package(catkin REQUIRED COMPONENTS ...)
+## * uncomment the "generate_dynamic_reconfigure_options" section below
+## and list every .cfg file to be processed
+
+## Generate dynamic reconfigure parameters in the 'cfg' folder
+# generate_dynamic_reconfigure_options(
+# cfg/DynReconf1.cfg
+# cfg/DynReconf2.cfg
+# )
+
+###################################
+## catkin specific configuration ##
+###################################
+## The catkin_package macro generates cmake config files for your package
+## Declare things to be passed to dependent projects
+## INCLUDE_DIRS: uncomment this if your package contains header files
+## LIBRARIES: libraries you create in this project that dependent projects also need
+## CATKIN_DEPENDS: catkin_packages dependent projects also need
+## DEPENDS: system dependencies of this project that dependent projects also need
+catkin_package(
+# INCLUDE_DIRS include
+# LIBRARIES vision
+# CATKIN_DEPENDS message_generation roscpp rospy sensor_msgs std_msgs
+# DEPENDS system_lib
+)
+
+###########
+## Build ##
+###########
+
+## Specify additional locations of header files
+## Your package locations should be listed before other locations
+include_directories(
+ include
+ ${catkin_INCLUDE_DIRS}
+)
+
+
+## Declare a C++ library
+# add_library(${PROJECT_NAME}
+# src/${PROJECT_NAME}/vision.cpp
+# )
+
+## Add cmake target dependencies of the library
+## as an example, code may need to be generated before libraries
+## either from message generation or dynamic reconfigure
+# add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
+
+## Declare a C++ executable
+## With catkin_make all packages are built within a single CMake context
+## The recommended prefix ensures that target names across packages don't collide
+# add_executable(camera src/camera.cpp src/vision_parser.cpp)
+set(CAMERA_FILES src/MYNTeye.cpp)
+add_executable(binocular src/Binocular.cpp ${CAMERA_FILES})
+# add_executable(sim_vision src/SimVision.cpp src/camera/TpCamera.cpp)
+## Rename C++ executable without prefix
+## The above recommended prefix causes long target names, the following renames the
+## target back to the shorter version for ease of user use
+## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node"
+# set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "")
+
+## Add cmake target dependencies of the executable
+## same as for the library above
+# add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
+
+## Specify libraries to link a library or executable target against
+# target_link_libraries(camera
+# ${catkin_LIBRARIES}
+# MVSDK
+# config
+# )
+
+target_link_libraries(binocular
+ ${catkin_LIBRARIES}
+ cuda
+ cudart
+ darknet
+ seuimage
+ mynteye
+ opencv_core
+ opencv_imgproc
+ opencv_imgcodecs
+ config
+ pthread
+)
+
+#############
+## Install ##
+#############
+
+# all install targets should use catkin DESTINATION variables
+# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html
+
+## Mark executable scripts (Python etc.) for installation
+## in contrast to setup.py, you can choose the destination
+# install(PROGRAMS
+# scripts/my_python_script
+# DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
+# )
+
+## Mark executables for installation
+## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_executables.html
+# install(TARGETS ${PROJECT_NAME}_node
+# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
+# )
+
+## Mark libraries for installation
+## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_libraries.html
+# install(TARGETS ${PROJECT_NAME}
+# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
+# LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
+# RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION}
+# )
+
+## Mark cpp header files for installation
+# install(DIRECTORY include/${PROJECT_NAME}/
+# DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
+# FILES_MATCHING PATTERN "*.h"
+# PATTERN ".svn" EXCLUDE
+# )
+
+## Mark other files for installation (e.g. launch and bag files, etc.)
+# install(FILES
+# # myfile1
+# # myfile2
+# DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}
+# )
+
+#############
+## Testing ##
+#############
+
+## Add gtest based cpp test target and link libraries
+# catkin_add_gtest(${PROJECT_NAME}-test test/test_vision.cpp)
+# if(TARGET ${PROJECT_NAME}-test)
+# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME})
+# endif()
+
+## Add folders to be run by python nosetests
+# catkin_add_nosetests(test)
diff --git a/src/binocular/launch/binocular.launch b/src/binocular/launch/binocular.launch
new file mode 100644
index 0000000000000000000000000000000000000000..13ec2cc7577750d3316958dee9be3ec04be1d67d
--- /dev/null
+++ b/src/binocular/launch/binocular.launch
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/binocular/package.xml b/src/binocular/package.xml
new file mode 100644
index 0000000000000000000000000000000000000000..cce8ee863618899d3e6f7f591f78fb958c3d3b0d
--- /dev/null
+++ b/src/binocular/package.xml
@@ -0,0 +1,80 @@
+
+
+ binocular
+ 0.0.0
+ The binocular package
+
+
+
+
+ Sciroccogti
+
+
+
+
+
+ Apache2
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ catkin
+ message_generation
+ roscpp
+ rospy
+ sensor_msgs
+ std_msgs
+ common
+ config
+ seuimage
+ darknet
+ roscpp
+ rospy
+ sensor_msgs
+ std_msgs
+ message_generation
+ roscpp
+ rospy
+ sensor_msgs
+ std_msgs
+ message_runtime
+ common
+ seuimage
+ darknet
+
+
+
+
+
+
+
diff --git a/src/binocular/src/Binocular.cpp b/src/binocular/src/Binocular.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..920e493e544dad7e0229cc706d9aab223a0d4fab
--- /dev/null
+++ b/src/binocular/src/Binocular.cpp
@@ -0,0 +1,335 @@
+#include "Binocular.hpp"
+
+int main(int argc, char **argv)
+{
+ ros::init(argc, argv, "binocular");
+ ros::NodeHandle node;
+ if (!CameraInit())
+ {
+ ROS_ERROR("failed in opening binocular camera");
+ }
+ BinocularInit();
+ imagePublisher = node.advertise("/result/binocular/compressed", 1);
+ resultPublisher = node.advertise("/result/binocular/imgproc", 1);
+ ros::ServiceServer typeServer = node.advertiseService("/setting/sendtype", SendTypeService);
+ camera->Run();
+ ros::Timer timer = node.createTimer(ros::Duration(0.05), Run);
+ ros::spin();
+ camera->Close();
+ return 0;
+}
+
+void Run(const ros::TimerEvent &event)
+{
+ if (!ros::ok())
+ {
+ return;
+ }
+ bool ret;
+ uint32_t image_time;
+ MYNTdata raw = camera->GetData(image_time);
+ ret = srcMat.upload(raw.color);
+
+ if (!ret)
+ {
+ ROS_ERROR("upload error");
+ return;
+ }
+ if (GET_CHANNELS(camera->type) == 1) // Bayer
+ {
+ ret = CudaBayerToRGB(srcMat, rgbMat, 1.12, 0.85, 1.37);
+ //ret = BayerToRGB(srcMat, rgbMat);
+ ret = Resize(rgbMat, dstMat);
+ ret = dstMat.copyTo(relMat);
+ }
+ else if (GET_CHANNELS(camera->type) == 2) // YUYV
+ {
+ ret = YUV422ToRGB(srcMat, rgbMat);
+ ret = Resize(rgbMat, dstMat);
+ ret = dstMat.copyTo(relMat);
+ }
+ else if (GET_CHANNELS(camera->type) == 3) // RGB
+ {
+ ret = Resize(srcMat, dstMat);
+ ret = dstMat.copyTo(relMat);
+ }
+ else
+ {
+ ROS_ERROR("channel error");
+ }
+ ret = RGBToHSV(relMat, netMat);
+
+ if (!ret)
+ {
+ ROS_ERROR("Resize to net error");
+ return;
+ }
+
+ ret = RGB8uTo32fNorm(netMat, netfMat);
+ if (!ret)
+ {
+ ROS_ERROR("RGB8uTo32fNorm error");
+ return;
+ }
+
+ ret = PackedToPlanar(netfMat, yoloMat);
+ if (!ret)
+ {
+ ROS_ERROR("PackedToPlanar error");
+ return;
+ }
+
+ layer l = yolo.layers[yolo.n - 1];
+ network_predict1(yolo, yoloMat.data());
+ int nboxes = 0;
+ float nms = 0.45;
+ detection *dets = get_network_boxes(&yolo, width, height,
+ 0.5, 0.5, 0, 1, &nboxes, 0);
+
+ if (nms)
+ {
+ do_nms_sort(dets, nboxes, l.classes, nms);
+ }
+
+ std::vector ball_dets, post_dets;
+ ball_dets.clear();
+ post_dets.clear();
+
+ for (int i = 0; i < nboxes; i++)
+ {
+ int id = 0;
+ for (int j = 0; j < l.classes; j++)
+ {
+ if (dets[i].prob[j] > dets[i].prob[id])
+ id = j;
+ }
+ if (id == 0)
+ {
+ if (dets[i].prob[id] >= ballFilter.min_prob)
+ {
+ int bx = (dets[i].bbox.x - dets[i].bbox.w / 2.0) * width;
+ int by = (dets[i].bbox.y - dets[i].bbox.h / 2.0) * height;
+ int bw = dets[i].bbox.w * width, bh = dets[i].bbox.h * height + 1;
+ ball_dets.push_back(DetObject(0, dets[i].prob[id], bx, by, bw, bh));
+ }
+ }
+ else if (id == 1)
+ {
+ if (dets[i].prob[id] >= postFilter.min_prob)
+ {
+ int px = (dets[i].bbox.x - dets[i].bbox.w / 2.0) * width;
+ int py = (dets[i].bbox.y - dets[i].bbox.h / 2.0) * height;
+ int pw = dets[i].bbox.w * width, ph = dets[i].bbox.h * height;
+ post_dets.push_back(DetObject(1, dets[i].prob[id], px, py, pw, ph));
+ }
+ }
+ }
+ std::sort(ball_dets.rbegin(), ball_dets.rend());
+ std::sort(post_dets.rbegin(), post_dets.rend());
+ free_detections(dets, nboxes);
+
+ common::ImageResult imgResult;
+ imgResult.stamp = image_time;
+ if (!ball_dets.empty())
+ {
+ imgResult.has_ball = true;
+ imgResult.ball.x = ball_dets[0].x + ball_dets[0].w / 2;
+ imgResult.ball.y = ball_dets[0].y + ball_dets[0].h;
+ }
+ for (uint32_t i = 0; i < post_dets.size() && i < 2; i++)
+ {
+ imgResult.has_post = true;
+ ObjInfo tmp;
+ tmp.x = ball_dets[i].x + ball_dets[i].w / 2;
+ tmp.y = ball_dets[i].y + ball_dets[i].h / 3 * 2;
+ imgResult.posts.push_back(tmp);
+ }
+ resultPublisher.publish(imgResult);
+
+ if (send_type > 0)
+ {
+ cv::Mat rgb(height, width, CV_8UC3);
+ if (!dstMat.download(rgb))
+ {
+ ROS_ERROR("download error");
+ return;
+ }
+ cv::Mat bgr;
+ cv::cvtColor(rgb, bgr, CV_RGB2BGR);
+
+ if (send_type > 1)
+ {
+ if (!ball_dets.empty())
+ {
+ cv::Rect ball_roi(ball_dets[0].x, ball_dets[0].y, ball_dets[0].w, ball_dets[0].h);
+ cv::rectangle(bgr, ball_roi, cv::Scalar(255, 0, 0), 2);
+ int ball_dist = CountDistance(raw.depth, ball_roi);
+ ROS_INFO("ball_dist=%d", ball_dist); // TODO: 接入接口而不是什么INFO!
+ }
+
+ for (uint32_t i = 0; i < post_dets.size() && i < 2; i++)
+ {
+ cv::Rect post_roi(post_dets[0].x, post_dets[0].y, post_dets[0].w, post_dets[0].h);
+ cv::rectangle(bgr, post_roi, cv::Scalar(0, 0, 255), 2);
+ int post_dist = CountDistance(raw.depth, post_roi);
+ ROS_INFO("post_dist=%d", post_dist); // TODO: 接入接口而不是什么INFO!
+ }
+ }
+ cv::imshow("binocular", bgr);
+ ImagePublish(bgr);
+ }
+}
+
+bool CameraInit()
+{
+ camera = std::make_shared();
+ if (camera->Open())
+ return true;
+ return false;
+}
+
+bool BinocularInit()
+{
+ std::string visionfile;
+ try
+ {
+ ros::param::get("vision_file", visionfile);
+ }
+ catch (ros::InvalidNameException &e)
+ {
+ ROS_ERROR("%s", e.what());
+ return false;
+ }
+
+ std::string vision_root = visionfile.substr(0, visionfile.find_last_of("/") + 1);
+ std::string yolo_cfg, weights;
+ if (visionfile.empty())
+ return false;
+ common::bpt::ptree pt;
+ if (!common::get_tree_from_file(visionfile, pt))
+ {
+ ROS_ERROR("parse file: [%s] failed", visionfile.c_str());
+ return false;
+ }
+ yolo_cfg = vision_root + pt.get("cfg_file");
+ weights = vision_root + pt.get("weights_file");
+ ballFilter.min_prob = pt.get("dets.prob.ball");
+ ballFilter.r_range = get_config_vector(pt, "dets.boxes.ball.ratio");
+ ballFilter.w_range = get_config_vector(pt, "dets.boxes.ball.width");
+ ballFilter.h_range = get_config_vector(pt, "dets.boxes.ball.height");
+ postFilter.min_prob = pt.get("dets.prob.post");
+ postFilter.r_range = get_config_vector(pt, "dets.boxes.post.ratio");
+ postFilter.w_range = get_config_vector(pt, "dets.boxes.post.width");
+ postFilter.h_range = get_config_vector(pt, "dets.boxes.post.height");
+
+ yolo.gpu_index = 0;
+ yolo = parse_network_cfg_custom((char *)(yolo_cfg.c_str()), 1, 0);
+ load_weights(&yolo, const_cast((char *)(weights.c_str())));
+ set_batch_network(&yolo, 1);
+ fuse_conv_batchnorm(yolo);
+ calculate_binary_weights(yolo);
+ srand(2222222);
+ cudaSetDevice(0);
+
+ if (!MallocMemory())
+ {
+ ROS_ERROR("MallocMemory failed");
+ return false;
+ }
+ return true;
+}
+
+int CountDistance(cv::Mat &mat, cv::Rect roi)
+{
+ cv::Mat depth_cop = mat(roi).clone();
+
+ int count[2] = {0, 0};
+
+ std::vector depth_vector;
+ depth_vector.clear();
+
+ ushort *p = depth_cop.ptr();
+ for (size_t i = 0; i < depth_cop.total(); i++)
+ {
+ if (*p != 0)
+ depth_vector.push_back((float)*p);
+ p++;
+ }
+
+ cv::Mat labels;
+ std::vector centers;
+ if (depth_vector.size() < 2) // N < K 时
+ {
+ return 0;
+ }
+ else
+ {
+ // kmeans 只接收CV_32F
+ cv::kmeans(depth_vector, 2, labels, cv::TermCriteria(cv::TermCriteria::EPS + cv::TermCriteria::COUNT, 5, 1.0), 3, cv::KMEANS_PP_CENTERS, centers);
+
+ for (size_t i = 0; i < depth_vector.size(); i++)
+ {
+ count[labels.data[i]]++;
+ }
+ return centers[0] > centers[1] ? centers[0] : centers[1];
+ }
+}
+
+void ImagePublish(const cv::Mat &bgr)
+{
+ sensor_msgs::CompressedImage image;
+ std::vector buf;
+ cv::imencode(".jpg", bgr, buf);
+ image.header.stamp = ros::Time::now();
+ image.header.frame_id = "binocular";
+ image.format = "jpeg";
+ image.data.resize(buf.size());
+ memcpy(&image.data[0], &(buf[0]), buf.size());
+ imagePublisher.publish(image);
+}
+
+bool MallocMemory()
+{
+ if (camera.get() == nullptr)
+ return false;
+ bool ret;
+ ret = srcMat.create(camera->height, camera->width, GET_CHANNELS(camera->type));
+ if (!ret)
+ return false;
+
+ ret = rgbMat.create(camera->height, camera->width, 3);
+ if (!ret)
+ return false;
+
+ ret = dstMat.create(height, width, 3);
+ if (!ret)
+ return false;
+
+ ret = relMat.create(height, width, 3);
+ if (!ret)
+ return false;
+
+ ret = hsvMat.create(height, width, 3);
+ if (!ret)
+ return false;
+
+ ret = netMat.create(yolo.h, yolo.w, 3);
+ if (!ret)
+ return false;
+
+ ret = netfMat.create(yolo.h, yolo.w, 3);
+ if (!ret)
+ return false;
+
+ ret = yoloMat.create(yolo.h, yolo.w, 3);
+ if (!ret)
+ return false;
+
+ return true;
+}
+
+bool SendTypeService(SetInt::Request &req, SetInt::Response &res)
+{
+ send_type = req.number;
+ return true;
+}
\ No newline at end of file
diff --git a/src/binocular/src/Binocular.hpp b/src/binocular/src/Binocular.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..3d4def4ad92c2d10f6c2eb935464a9e9b641261c
--- /dev/null
+++ b/src/binocular/src/Binocular.hpp
@@ -0,0 +1,44 @@
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "MYNTeye.hpp"
+
+using namespace seuimage;
+using namespace common;
+
+bool MallocMemory();
+void NetworkInit(std::string cfg, std::string wts);
+bool BinocularInit();
+bool CameraInit();
+void Run(const ros::TimerEvent &event);
+int CountDistance(cv::Mat &mat, cv::Rect roi);
+
+void ImagePublish(const cv::Mat &bgr);
+bool SendTypeService(SetInt::Request &req, SetInt::Response &res);
+
+const int width = 640; // 仅发布左眼
+const int height = 400;
+CudaMatC srcMat;
+CudaMatC rgbMat;
+CudaMatC dstMat;
+CudaMatC hsvMat;
+CudaMatC relMat;
+CudaMatC netMat;
+CudaMatF netfMat;
+CudaMatF yoloMat;
+network yolo;
+
+ObjectFilter ballFilter, postFilter;
+std::atomic_int send_type(0);
+std::shared_ptr camera;
+ros::Publisher imagePublisher;
+ros::Publisher resultPublisher;
+
diff --git a/src/binocular/src/MYNTeye.cpp b/src/binocular/src/MYNTeye.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0c8eade18e2167182dee21d9ae9e7bc92d3e9999
--- /dev/null
+++ b/src/binocular/src/MYNTeye.cpp
@@ -0,0 +1,91 @@
+#include "MYNTeye.hpp"
+
+using namespace mynteye;
+
+MYNTeye::MYNTeye()
+{
+ raw_.color = cv::Mat(height, width, type);
+ raw_.depth = cv::Mat(height, width, depth_type);
+ alive_ = false;
+}
+
+MYNTeye::~MYNTeye()
+{
+ if (td_.joinable())
+ {
+ td_.join();
+ }
+}
+
+bool MYNTeye::Open()
+{
+ Context context;
+ auto &&devices = context.devices();
+ if (!devices.size())
+ {
+ return false;
+ }
+
+ auto &&device = devices[0];
+ api_ = API::Create(device);
+ if (!api_)
+ {
+ return false;
+ }
+
+ const StreamRequest request(2 * width, height, Format::YUYV, 30);
+ api_->ConfigStreamRequest(request);
+ api_->EnableStreamData(Stream::LEFT_RECTIFIED);
+ api_->EnableStreamData(Stream::RIGHT_RECTIFIED);
+ api_->SetDisparityComputingMethodType(DisparityComputingMethod::BM);
+ api_->EnableStreamData(Stream::DEPTH);
+ // auto exposure
+ api_->SetOptionValue(Option::EXPOSURE_MODE, 0);
+ // max_gain: range [0,255], default 8
+ api_->SetOptionValue(Option::MAX_GAIN, 8);
+ // max_exposure_time: range [0,655], default 333
+ api_->SetOptionValue(Option::MAX_EXPOSURE_TIME, 333);
+ // desired_brightness: range [1,255], default 122
+ api_->SetOptionValue(Option::DESIRED_BRIGHTNESS, 122);
+ // min_exposure_time: range [0,655], default 0
+ api_->SetOptionValue(Option::MIN_EXPOSURE_TIME, 0);
+
+ api_->Start(Source::VIDEO_STREAMING);
+
+ return true;
+}
+
+bool MYNTeye::Close()
+{
+ alive_ = false;
+ return true;
+}
+
+void MYNTeye::Run()
+{
+ alive_ = true;
+ td_ = std::move(std::thread([this]() {
+ while (alive_)
+ {
+ api_->WaitForStreams(); // TODO: 这行应该放在哪?
+ auto &&left_data = api_->GetStreamData(Stream::LEFT_RECTIFIED);
+ auto &&depth_data = api_->GetStreamData(Stream::DEPTH);
+ if (!left_data.frame.empty() && !depth_data.frame.empty()) // && !right_data.frame.empty())
+ {
+ raw_mutex_.lock();
+ time_ = get_clock();
+ memcpy(raw_.color.data, left_data.frame.data, width * height);
+ memcpy(raw_.depth.data, depth_data.frame.data, width * height);
+ raw_mutex_.unlock();
+ }
+ usleep(100);
+ }
+ }));
+}
+
+MYNTdata &MYNTeye::GetData(uint32_t &t)
+{
+ std::lock_guard lk(raw_mutex_);
+ t = time_;
+ return raw_;
+}
\ No newline at end of file
diff --git a/src/binocular/src/MYNTeye.hpp b/src/binocular/src/MYNTeye.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..e8e70b450cde7c517e66eab78bacbd9ffb23c194
--- /dev/null
+++ b/src/binocular/src/MYNTeye.hpp
@@ -0,0 +1,40 @@
+#ifndef __MYNTEYE_HPP
+#define __MYNTEYE_HPP
+
+#include
+#include
+#include "mynteye/api/api.h"
+#include "mynteye/device/context.h"
+#define GET_CHANNELS(t) (((t)>>CV_CN_SHIFT)+1)
+
+struct MYNTdata
+{
+ cv::Mat color;
+ cv::Mat depth;
+};
+
+class MYNTeye
+{
+public:
+ MYNTeye();
+ ~MYNTeye();
+ bool Open();
+ bool Close();
+ // bool Available(); 好像没什么意义,Open()返回的就够了
+ void Run();
+ MYNTdata &GetData(uint32_t &t);
+ const int width = 640;
+ const int height = 400;
+ const int type = CV_8UC3;
+ const int depth_type = CV_16UC1;
+
+protected:
+ bool alive_;
+ std::thread td_;
+ std::shared_ptr api_;
+ MYNTdata raw_;
+ uint32_t time_;
+ mutable std::mutex raw_mutex_;
+};
+
+#endif
\ No newline at end of file