2018-05-10 09:46:34 +03:00
|
|
|
// Copyright 2018 Slightech Co., Ltd. All rights reserved.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
2018-04-04 05:50:27 +03:00
|
|
|
#include "device/device.h"
|
|
|
|
|
|
|
|
#include <glog/logging.h>
|
|
|
|
|
2018-04-08 07:23:33 +03:00
|
|
|
#include <algorithm>
|
2018-06-12 07:31:07 +03:00
|
|
|
#include <iterator>
|
2018-04-08 07:23:33 +03:00
|
|
|
#include <stdexcept>
|
2018-04-13 16:55:32 +03:00
|
|
|
#include <utility>
|
2018-04-08 07:23:33 +03:00
|
|
|
|
2018-04-04 10:52:10 +03:00
|
|
|
#include "device/device_s.h"
|
2018-05-31 10:39:42 +03:00
|
|
|
#include "internal/async_callback.h"
|
2018-04-09 17:24:34 +03:00
|
|
|
#include "internal/channels.h"
|
2018-04-04 10:52:10 +03:00
|
|
|
#include "internal/config.h"
|
2018-04-12 06:48:09 +03:00
|
|
|
#include "internal/motions.h"
|
2018-04-08 07:23:33 +03:00
|
|
|
#include "internal/streams.h"
|
2018-04-04 06:38:36 +03:00
|
|
|
#include "internal/strings.h"
|
2018-06-01 10:09:03 +03:00
|
|
|
#include "internal/times.h"
|
2018-04-04 10:52:10 +03:00
|
|
|
#include "internal/types.h"
|
2018-04-04 05:50:27 +03:00
|
|
|
#include "uvc/uvc.h"
|
|
|
|
|
|
|
|
MYNTEYE_BEGIN_NAMESPACE
|
|
|
|
|
2018-04-11 09:54:28 +03:00
|
|
|
namespace {
|
|
|
|
|
|
|
|
struct DeviceModel {
|
|
|
|
char type;
|
|
|
|
std::uint8_t generation;
|
|
|
|
std::uint8_t baseline_code;
|
|
|
|
std::uint8_t hardware_code;
|
|
|
|
std::uint8_t custom_code;
|
|
|
|
bool ir_fixed;
|
|
|
|
|
|
|
|
DeviceModel() = default;
|
|
|
|
explicit DeviceModel(std::string model) {
|
|
|
|
CHECK_GE(model.size(), 5);
|
|
|
|
type = model[0];
|
|
|
|
generation = model[1];
|
|
|
|
baseline_code = model[2];
|
|
|
|
hardware_code = model[3];
|
|
|
|
custom_code = model[4];
|
|
|
|
ir_fixed = (model.size() == 8) && model.substr(5) == "-IR";
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2018-06-12 07:31:07 +03:00
|
|
|
bool CheckSupports(
|
|
|
|
const Device *const device, const Stream &stream, bool fatal = true) {
|
|
|
|
if (device->Supports(stream)) {
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
auto &&supports = stream_supports_map.at(device->GetModel());
|
|
|
|
std::ostringstream ss;
|
|
|
|
std::copy(
|
|
|
|
supports.begin(), supports.end(),
|
|
|
|
std::ostream_iterator<Stream>(ss, ", "));
|
|
|
|
if (fatal) {
|
|
|
|
LOG(FATAL) << "Unsupported stream: " << stream
|
|
|
|
<< ". Please use these: " << ss.str();
|
|
|
|
} else {
|
|
|
|
LOG(WARNING) << "Unsupported stream: " << stream
|
|
|
|
<< ". Please use these: " << ss.str();
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-11 09:54:28 +03:00
|
|
|
} // namespace
|
|
|
|
|
2018-04-04 10:52:10 +03:00
|
|
|
Device::Device(const Model &model, std::shared_ptr<uvc::device> device)
|
2018-04-08 07:23:33 +03:00
|
|
|
: video_streaming_(false),
|
|
|
|
motion_tracking_(false),
|
|
|
|
model_(model),
|
|
|
|
device_(device),
|
2018-04-09 17:24:34 +03:00
|
|
|
streams_(nullptr),
|
2018-04-12 06:48:09 +03:00
|
|
|
channels_(std::make_shared<Channels>(device)),
|
|
|
|
motions_(std::make_shared<Motions>(channels_)) {
|
2018-04-04 05:50:27 +03:00
|
|
|
VLOG(2) << __func__;
|
2018-07-08 13:49:09 +03:00
|
|
|
//ReadAllInfos();
|
2018-04-04 05:50:27 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
Device::~Device() {
|
|
|
|
VLOG(2) << __func__;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::shared_ptr<Device> Device::Create(
|
|
|
|
const std::string &name, std::shared_ptr<uvc::device> device) {
|
2018-07-08 13:49:09 +03:00
|
|
|
if (name == "MYNTEYE" || name == "CX3-UVC") {
|
2018-04-04 10:52:10 +03:00
|
|
|
return std::make_shared<StandardDevice>(device);
|
2018-04-04 06:38:36 +03:00
|
|
|
} else if (strings::starts_with(name, "MYNT-EYE-")) {
|
|
|
|
// TODO(JohnZhao): Create different device by name, such as MYNT-EYE-S1000
|
2018-07-13 09:58:18 +03:00
|
|
|
std::string model_s = name.substr(9,5);
|
2018-04-11 09:54:28 +03:00
|
|
|
VLOG(2) << "MYNE EYE Model: " << model_s;
|
|
|
|
DeviceModel model(model_s);
|
2018-07-21 10:34:07 +03:00
|
|
|
if(model.type == 'S') {
|
2018-07-13 09:58:18 +03:00
|
|
|
switch (model.custom_code) {
|
|
|
|
case '0':
|
|
|
|
return std::make_shared<StandardDevice>(device);
|
|
|
|
case 'A':
|
|
|
|
return std::make_shared<StandardDevice>(device);
|
|
|
|
default:
|
2018-07-21 10:34:07 +03:00
|
|
|
LOG(FATAL) << "No such custom code now";
|
2018-07-13 09:58:18 +03:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
LOG(FATAL) << "MYNT EYE model is not supported now";
|
2018-04-11 09:54:28 +03:00
|
|
|
}
|
2018-04-04 06:38:36 +03:00
|
|
|
}
|
2018-04-04 05:50:27 +03:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2018-04-04 10:52:10 +03:00
|
|
|
bool Device::Supports(const Stream &stream) const {
|
2018-04-08 07:23:33 +03:00
|
|
|
auto &&supports = stream_supports_map.at(model_);
|
2018-04-04 10:52:10 +03:00
|
|
|
return supports.find(stream) != supports.end();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Device::Supports(const Capabilities &capability) const {
|
2018-04-08 07:23:33 +03:00
|
|
|
auto &&supports = capabilities_supports_map.at(model_);
|
2018-04-04 10:52:10 +03:00
|
|
|
return supports.find(capability) != supports.end();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Device::Supports(const Option &option) const {
|
2018-04-08 07:23:33 +03:00
|
|
|
auto &&supports = option_supports_map.at(model_);
|
2018-04-04 10:52:10 +03:00
|
|
|
return supports.find(option) != supports.end();
|
|
|
|
}
|
|
|
|
|
2018-05-04 10:57:12 +03:00
|
|
|
bool Device::Supports(const AddOns &addon) const {
|
|
|
|
CHECK_NOTNULL(device_info_);
|
|
|
|
auto &&hw_flag = device_info_->hardware_version.flag();
|
|
|
|
switch (addon) {
|
|
|
|
case AddOns::INFRARED:
|
|
|
|
return hw_flag[0];
|
|
|
|
case AddOns::INFRARED2:
|
|
|
|
return hw_flag[1];
|
2018-05-30 07:31:54 +03:00
|
|
|
default:
|
|
|
|
LOG(WARNING) << "Unknown add-on";
|
|
|
|
return false;
|
2018-05-04 10:57:12 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-08 07:23:33 +03:00
|
|
|
const std::vector<StreamRequest> &Device::GetStreamRequests(
|
|
|
|
const Capabilities &capability) const {
|
|
|
|
if (!Supports(capability)) {
|
2018-04-10 08:58:37 +03:00
|
|
|
LOG(FATAL) << "Unsupported capability: " << capability;
|
2018-04-08 07:23:33 +03:00
|
|
|
}
|
|
|
|
try {
|
|
|
|
auto &&cap_requests = stream_requests_map.at(model_);
|
|
|
|
return cap_requests.at(capability);
|
|
|
|
} catch (const std::out_of_range &e) {
|
|
|
|
LOG(FATAL) << "Stream request of " << capability << " of " << model_
|
|
|
|
<< " not found";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Device::ConfigStreamRequest(
|
|
|
|
const Capabilities &capability, const StreamRequest &request) {
|
|
|
|
auto &&requests = GetStreamRequests(capability);
|
|
|
|
if (std::find(requests.cbegin(), requests.cend(), request) ==
|
|
|
|
requests.cend()) {
|
2018-05-30 07:31:54 +03:00
|
|
|
LOG(WARNING) << "Config stream request of " << capability
|
|
|
|
<< " is not accpected";
|
|
|
|
return;
|
2018-04-08 07:23:33 +03:00
|
|
|
}
|
|
|
|
stream_config_requests_[capability] = request;
|
|
|
|
}
|
|
|
|
|
2018-04-04 10:52:10 +03:00
|
|
|
std::shared_ptr<DeviceInfo> Device::GetInfo() const {
|
|
|
|
return device_info_;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string Device::GetInfo(const Info &info) const {
|
|
|
|
CHECK_NOTNULL(device_info_);
|
|
|
|
switch (info) {
|
2018-05-30 07:31:54 +03:00
|
|
|
case Info::DEVICE_NAME:
|
2018-04-04 10:52:10 +03:00
|
|
|
return device_info_->name;
|
2018-05-30 07:31:54 +03:00
|
|
|
case Info::SERIAL_NUMBER:
|
2018-04-04 10:52:10 +03:00
|
|
|
return device_info_->serial_number;
|
2018-05-30 07:31:54 +03:00
|
|
|
case Info::FIRMWARE_VERSION:
|
2018-04-04 10:52:10 +03:00
|
|
|
return device_info_->firmware_version.to_string();
|
2018-05-30 07:31:54 +03:00
|
|
|
case Info::HARDWARE_VERSION:
|
2018-04-04 10:52:10 +03:00
|
|
|
return device_info_->hardware_version.to_string();
|
2018-05-30 07:31:54 +03:00
|
|
|
case Info::SPEC_VERSION:
|
2018-04-04 10:52:10 +03:00
|
|
|
return device_info_->spec_version.to_string();
|
2018-05-30 07:31:54 +03:00
|
|
|
case Info::LENS_TYPE:
|
2018-04-04 10:52:10 +03:00
|
|
|
return device_info_->lens_type.to_string();
|
2018-05-30 07:31:54 +03:00
|
|
|
case Info::IMU_TYPE:
|
2018-04-04 10:52:10 +03:00
|
|
|
return device_info_->imu_type.to_string();
|
2018-05-30 07:31:54 +03:00
|
|
|
case Info::NOMINAL_BASELINE:
|
2018-04-04 10:52:10 +03:00
|
|
|
return std::to_string(device_info_->nominal_baseline);
|
2018-05-30 07:31:54 +03:00
|
|
|
default:
|
|
|
|
LOG(WARNING) << "Unknown device info";
|
|
|
|
return "";
|
2018-04-04 10:52:10 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-19 17:44:40 +03:00
|
|
|
Intrinsics Device::GetIntrinsics(const Stream &stream) const {
|
2018-06-12 10:58:13 +03:00
|
|
|
bool ok;
|
|
|
|
return GetIntrinsics(stream, &ok);
|
|
|
|
}
|
|
|
|
|
|
|
|
Extrinsics Device::GetExtrinsics(const Stream &from, const Stream &to) const {
|
|
|
|
bool ok;
|
|
|
|
return GetExtrinsics(from, to, &ok);
|
|
|
|
}
|
|
|
|
|
|
|
|
MotionIntrinsics Device::GetMotionIntrinsics() const {
|
|
|
|
bool ok;
|
|
|
|
return GetMotionIntrinsics(&ok);
|
|
|
|
}
|
|
|
|
|
|
|
|
Extrinsics Device::GetMotionExtrinsics(const Stream &from) const {
|
|
|
|
bool ok;
|
|
|
|
return GetMotionExtrinsics(from, &ok);
|
|
|
|
}
|
|
|
|
|
|
|
|
Intrinsics Device::GetIntrinsics(const Stream &stream, bool *ok) const {
|
2018-04-19 17:44:40 +03:00
|
|
|
try {
|
2018-06-12 10:58:13 +03:00
|
|
|
*ok = true;
|
2018-04-19 17:44:40 +03:00
|
|
|
return stream_intrinsics_.at(stream);
|
|
|
|
} catch (const std::out_of_range &e) {
|
2018-06-12 10:58:13 +03:00
|
|
|
*ok = false;
|
2018-04-19 17:44:40 +03:00
|
|
|
LOG(WARNING) << "Intrinsics of " << stream << " not found";
|
|
|
|
return {};
|
|
|
|
}
|
2018-04-06 04:12:09 +03:00
|
|
|
}
|
|
|
|
|
2018-06-12 10:58:13 +03:00
|
|
|
Extrinsics Device::GetExtrinsics(
|
|
|
|
const Stream &from, const Stream &to, bool *ok) const {
|
2018-04-19 17:44:40 +03:00
|
|
|
try {
|
2018-06-12 10:58:13 +03:00
|
|
|
*ok = true;
|
2018-04-19 17:44:40 +03:00
|
|
|
return stream_from_extrinsics_.at(from).at(to);
|
|
|
|
} catch (const std::out_of_range &e) {
|
2018-04-29 09:47:35 +03:00
|
|
|
try {
|
2018-06-12 10:58:13 +03:00
|
|
|
*ok = true;
|
2018-04-29 09:47:35 +03:00
|
|
|
return stream_from_extrinsics_.at(to).at(from).Inverse();
|
|
|
|
} catch (const std::out_of_range &e) {
|
2018-06-12 10:58:13 +03:00
|
|
|
*ok = false;
|
2018-04-29 09:47:35 +03:00
|
|
|
LOG(WARNING) << "Extrinsics from " << from << " to " << to
|
|
|
|
<< " not found";
|
|
|
|
return {};
|
|
|
|
}
|
2018-04-19 17:44:40 +03:00
|
|
|
}
|
2018-04-06 04:12:09 +03:00
|
|
|
}
|
|
|
|
|
2018-06-12 10:58:13 +03:00
|
|
|
MotionIntrinsics Device::GetMotionIntrinsics(bool *ok) const {
|
2018-04-19 17:44:40 +03:00
|
|
|
if (motion_intrinsics_) {
|
2018-06-12 10:58:13 +03:00
|
|
|
*ok = true;
|
2018-04-19 17:44:40 +03:00
|
|
|
return *motion_intrinsics_;
|
|
|
|
} else {
|
2018-06-12 10:58:13 +03:00
|
|
|
*ok = false;
|
2018-04-19 17:44:40 +03:00
|
|
|
LOG(WARNING) << "Motion intrinsics not found";
|
|
|
|
return {};
|
|
|
|
}
|
2018-04-13 16:55:32 +03:00
|
|
|
}
|
|
|
|
|
2018-06-12 10:58:13 +03:00
|
|
|
Extrinsics Device::GetMotionExtrinsics(const Stream &from, bool *ok) const {
|
2018-04-19 17:44:40 +03:00
|
|
|
try {
|
2018-06-12 10:58:13 +03:00
|
|
|
*ok = true;
|
2018-04-19 17:44:40 +03:00
|
|
|
return motion_from_extrinsics_.at(from);
|
|
|
|
} catch (const std::out_of_range &e) {
|
2018-06-12 10:58:13 +03:00
|
|
|
*ok = false;
|
2018-04-19 17:44:40 +03:00
|
|
|
LOG(WARNING) << "Motion extrinsics from " << from << " not found";
|
|
|
|
return {};
|
|
|
|
}
|
2018-04-13 16:55:32 +03:00
|
|
|
}
|
|
|
|
|
2018-04-19 17:44:40 +03:00
|
|
|
void Device::SetIntrinsics(const Stream &stream, const Intrinsics &in) {
|
|
|
|
stream_intrinsics_[stream] = in;
|
2018-04-06 04:12:09 +03:00
|
|
|
}
|
|
|
|
|
2018-04-19 17:44:40 +03:00
|
|
|
void Device::SetExtrinsics(
|
|
|
|
const Stream &from, const Stream &to, const Extrinsics &ex) {
|
|
|
|
stream_from_extrinsics_[from][to] = ex;
|
2018-04-06 04:12:09 +03:00
|
|
|
}
|
|
|
|
|
2018-04-19 17:44:40 +03:00
|
|
|
void Device::SetMotionIntrinsics(const MotionIntrinsics &in) {
|
|
|
|
if (motion_intrinsics_ == nullptr) {
|
|
|
|
motion_intrinsics_ = std::make_shared<MotionIntrinsics>();
|
|
|
|
}
|
|
|
|
*motion_intrinsics_ = in;
|
2018-04-13 16:55:32 +03:00
|
|
|
}
|
|
|
|
|
2018-04-19 17:44:40 +03:00
|
|
|
void Device::SetMotionExtrinsics(const Stream &from, const Extrinsics &ex) {
|
|
|
|
motion_from_extrinsics_[from] = ex;
|
2018-04-13 16:55:32 +03:00
|
|
|
}
|
|
|
|
|
2018-04-10 11:00:38 +03:00
|
|
|
void Device::LogOptionInfos() const {
|
|
|
|
channels_->LogControlInfos();
|
|
|
|
}
|
|
|
|
|
2018-04-09 19:26:22 +03:00
|
|
|
OptionInfo Device::GetOptionInfo(const Option &option) const {
|
2018-04-10 08:58:37 +03:00
|
|
|
if (!Supports(option)) {
|
|
|
|
LOG(WARNING) << "Unsupported option: " << option;
|
|
|
|
return {0, 0, 0};
|
|
|
|
}
|
2018-04-09 19:26:22 +03:00
|
|
|
auto &&info = channels_->GetControlInfo(option);
|
|
|
|
return {info.min, info.max, info.def};
|
|
|
|
}
|
|
|
|
|
|
|
|
std::int32_t Device::GetOptionValue(const Option &option) const {
|
2018-04-10 08:58:37 +03:00
|
|
|
if (!Supports(option)) {
|
|
|
|
LOG(WARNING) << "Unsupported option: " << option;
|
|
|
|
return -1;
|
|
|
|
}
|
2018-04-09 19:26:22 +03:00
|
|
|
return channels_->GetControlValue(option);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Device::SetOptionValue(const Option &option, std::int32_t value) {
|
2018-04-10 08:58:37 +03:00
|
|
|
if (!Supports(option)) {
|
|
|
|
LOG(WARNING) << "Unsupported option: " << option;
|
|
|
|
return;
|
|
|
|
}
|
2018-04-09 19:26:22 +03:00
|
|
|
channels_->SetControlValue(option, value);
|
|
|
|
}
|
|
|
|
|
2018-04-10 11:00:38 +03:00
|
|
|
bool Device::RunOptionAction(const Option &option) const {
|
|
|
|
if (!Supports(option)) {
|
|
|
|
LOG(WARNING) << "Unsupported option: " << option;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return channels_->RunControlAction(option);
|
2018-04-09 19:26:22 +03:00
|
|
|
}
|
|
|
|
|
2018-04-06 04:12:09 +03:00
|
|
|
void Device::SetStreamCallback(
|
2018-05-31 10:39:42 +03:00
|
|
|
const Stream &stream, stream_callback_t callback, bool async) {
|
2018-06-12 07:31:07 +03:00
|
|
|
if (!CheckSupports(this, stream, false)) {
|
2018-04-06 04:12:09 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (callback) {
|
|
|
|
stream_callbacks_[stream] = callback;
|
2018-05-31 10:39:42 +03:00
|
|
|
if (async)
|
|
|
|
stream_async_callbacks_[stream] =
|
|
|
|
std::make_shared<stream_async_callback_t>(
|
|
|
|
to_string(stream), callback);
|
2018-04-06 04:12:09 +03:00
|
|
|
} else {
|
|
|
|
stream_callbacks_.erase(stream);
|
2018-05-31 10:39:42 +03:00
|
|
|
stream_async_callbacks_.erase(stream);
|
2018-04-06 04:12:09 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-31 10:39:42 +03:00
|
|
|
void Device::SetMotionCallback(motion_callback_t callback, bool async) {
|
2018-04-06 04:12:09 +03:00
|
|
|
motion_callback_ = callback;
|
2018-05-31 10:39:42 +03:00
|
|
|
if (callback) {
|
|
|
|
if (async)
|
|
|
|
motion_async_callback_ =
|
2018-05-31 15:36:17 +03:00
|
|
|
std::make_shared<motion_async_callback_t>("motion", callback, true);
|
2018-05-31 10:39:42 +03:00
|
|
|
} else {
|
|
|
|
motion_async_callback_ = nullptr;
|
|
|
|
}
|
2018-04-06 04:12:09 +03:00
|
|
|
}
|
|
|
|
|
2018-04-08 17:35:49 +03:00
|
|
|
bool Device::HasStreamCallback(const Stream &stream) const {
|
|
|
|
try {
|
|
|
|
return stream_callbacks_.at(stream) != nullptr;
|
|
|
|
} catch (const std::out_of_range &e) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Device::HasMotionCallback() const {
|
|
|
|
return motion_callback_ != nullptr;
|
|
|
|
}
|
|
|
|
|
2018-04-07 04:36:41 +03:00
|
|
|
void Device::Start(const Source &source) {
|
|
|
|
if (source == Source::VIDEO_STREAMING) {
|
|
|
|
StartVideoStreaming();
|
|
|
|
} else if (source == Source::MOTION_TRACKING) {
|
|
|
|
StartMotionTracking();
|
|
|
|
} else if (source == Source::ALL) {
|
|
|
|
Start(Source::VIDEO_STREAMING);
|
|
|
|
Start(Source::MOTION_TRACKING);
|
|
|
|
} else {
|
2018-05-30 07:31:54 +03:00
|
|
|
LOG(ERROR) << "Unsupported source :(";
|
2018-04-07 04:36:41 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Device::Stop(const Source &source) {
|
|
|
|
if (source == Source::VIDEO_STREAMING) {
|
|
|
|
StopVideoStreaming();
|
|
|
|
} else if (source == Source::MOTION_TRACKING) {
|
|
|
|
StopMotionTracking();
|
|
|
|
} else if (source == Source::ALL) {
|
|
|
|
Stop(Source::MOTION_TRACKING);
|
2018-04-14 17:28:43 +03:00
|
|
|
// Must stop motion tracking before video streaming and sleep a moment here
|
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
|
|
|
Stop(Source::VIDEO_STREAMING);
|
2018-04-07 04:36:41 +03:00
|
|
|
} else {
|
2018-05-30 07:31:54 +03:00
|
|
|
LOG(ERROR) << "Unsupported source :(";
|
2018-04-07 04:36:41 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-08 17:35:49 +03:00
|
|
|
void Device::WaitForStreams() {
|
|
|
|
CHECK(video_streaming_);
|
|
|
|
CHECK_NOTNULL(streams_);
|
|
|
|
streams_->WaitForStreams();
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<device::StreamData> Device::GetStreamDatas(const Stream &stream) {
|
|
|
|
CHECK(video_streaming_);
|
|
|
|
CHECK_NOTNULL(streams_);
|
2018-06-12 07:31:07 +03:00
|
|
|
CheckSupports(this, stream);
|
2018-06-01 11:50:15 +03:00
|
|
|
std::lock_guard<std::mutex> _(mtx_streams_);
|
2018-04-08 17:35:49 +03:00
|
|
|
return streams_->GetStreamDatas(stream);
|
|
|
|
}
|
|
|
|
|
|
|
|
device::StreamData Device::GetLatestStreamData(const Stream &stream) {
|
|
|
|
CHECK(video_streaming_);
|
|
|
|
CHECK_NOTNULL(streams_);
|
2018-06-12 07:31:07 +03:00
|
|
|
CheckSupports(this, stream);
|
2018-06-01 11:50:15 +03:00
|
|
|
std::lock_guard<std::mutex> _(mtx_streams_);
|
2018-04-08 17:35:49 +03:00
|
|
|
return streams_->GetLatestStreamData(stream);
|
|
|
|
}
|
|
|
|
|
2018-04-12 06:48:09 +03:00
|
|
|
void Device::EnableMotionDatas(std::size_t max_size) {
|
|
|
|
CHECK_NOTNULL(motions_);
|
|
|
|
motions_->EnableMotionDatas(max_size);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<device::MotionData> Device::GetMotionDatas() {
|
|
|
|
CHECK(motion_tracking_);
|
|
|
|
CHECK_NOTNULL(motions_);
|
|
|
|
return motions_->GetMotionDatas();
|
|
|
|
}
|
|
|
|
|
2018-04-08 07:23:33 +03:00
|
|
|
const StreamRequest &Device::GetStreamRequest(const Capabilities &capability) {
|
|
|
|
try {
|
2018-04-08 17:35:49 +03:00
|
|
|
return stream_config_requests_.at(capability);
|
2018-04-08 07:23:33 +03:00
|
|
|
} catch (const std::out_of_range &e) {
|
|
|
|
auto &&requests = GetStreamRequests(capability);
|
2018-05-30 07:31:54 +03:00
|
|
|
if (requests.size() >= 1) {
|
|
|
|
VLOG(2) << "Select the first one stream request of " << capability;
|
2018-04-08 07:23:33 +03:00
|
|
|
return requests[0];
|
|
|
|
} else {
|
|
|
|
LOG(FATAL) << "Please config the stream request of " << capability;
|
|
|
|
}
|
2018-04-06 04:28:17 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-08 07:23:33 +03:00
|
|
|
void Device::StartVideoStreaming() {
|
|
|
|
if (video_streaming_) {
|
|
|
|
LOG(WARNING) << "Cannot start video streaming without first stopping it";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-04-08 17:35:49 +03:00
|
|
|
streams_ = std::make_shared<Streams>(GetKeyStreams());
|
2018-04-08 07:23:33 +03:00
|
|
|
|
|
|
|
// if stream capabilities are supported with subdevices of device_
|
|
|
|
/*
|
|
|
|
Capabilities stream_capabilities[] = {
|
|
|
|
Capabilities::STEREO,
|
|
|
|
Capabilities::COLOR,
|
|
|
|
Capabilities::DEPTH,
|
|
|
|
Capabilities::POINTS,
|
|
|
|
Capabilities::FISHEYE,
|
|
|
|
Capabilities::INFRARED,
|
|
|
|
Capabilities::INFRARED2
|
|
|
|
};
|
|
|
|
for (auto &&capability : stream_capabilities) {
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
if (Supports(Capabilities::STEREO)) {
|
|
|
|
// do stream request selection if more than one request of each stream
|
|
|
|
auto &&stream_request = GetStreamRequest(Capabilities::STEREO);
|
2018-04-08 17:35:49 +03:00
|
|
|
|
2018-04-08 07:23:33 +03:00
|
|
|
streams_->ConfigStream(Capabilities::STEREO, stream_request);
|
|
|
|
uvc::set_device_mode(
|
|
|
|
*device_, stream_request.width, stream_request.height,
|
|
|
|
static_cast<int>(stream_request.format), stream_request.fps,
|
2018-05-15 12:32:04 +03:00
|
|
|
[this](const void *data, std::function<void()> continuation) {
|
2018-04-11 12:08:24 +03:00
|
|
|
// drop the first stereo stream data
|
|
|
|
static std::uint8_t drop_count = 1;
|
|
|
|
if (drop_count > 0) {
|
|
|
|
--drop_count;
|
2018-06-01 10:09:03 +03:00
|
|
|
continuation();
|
2018-04-11 12:08:24 +03:00
|
|
|
return;
|
|
|
|
}
|
2018-06-01 10:09:03 +03:00
|
|
|
// auto &&time_beg = times::now();
|
2018-06-01 11:50:15 +03:00
|
|
|
{
|
|
|
|
std::lock_guard<std::mutex> _(mtx_streams_);
|
|
|
|
if (streams_->PushStream(Capabilities::STEREO, data)) {
|
|
|
|
CallbackPushedStreamData(Stream::LEFT);
|
|
|
|
CallbackPushedStreamData(Stream::RIGHT);
|
|
|
|
}
|
2018-04-08 17:35:49 +03:00
|
|
|
}
|
2018-05-31 19:17:12 +03:00
|
|
|
continuation();
|
2018-06-07 06:19:58 +03:00
|
|
|
OnStereoStreamUpdate();
|
2018-06-01 10:09:03 +03:00
|
|
|
// VLOG(2) << "Stereo video callback cost "
|
2018-06-01 11:50:15 +03:00
|
|
|
// << times::count<times::milliseconds>(times::now() - time_beg)
|
|
|
|
// << " ms";
|
2018-04-08 07:23:33 +03:00
|
|
|
});
|
|
|
|
} else {
|
|
|
|
LOG(FATAL) << "Not any stream capabilities are supported by this device";
|
|
|
|
}
|
|
|
|
|
|
|
|
uvc::start_streaming(*device_, 0);
|
|
|
|
video_streaming_ = true;
|
|
|
|
}
|
2018-04-07 04:36:41 +03:00
|
|
|
|
2018-04-08 07:23:33 +03:00
|
|
|
void Device::StopVideoStreaming() {
|
|
|
|
if (!video_streaming_) {
|
|
|
|
LOG(WARNING) << "Cannot stop video streaming without first starting it";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
stop_streaming(*device_);
|
|
|
|
video_streaming_ = false;
|
|
|
|
}
|
2018-04-07 04:36:41 +03:00
|
|
|
|
|
|
|
void Device::StartMotionTracking() {
|
|
|
|
if (!Supports(Capabilities::IMU)) {
|
2018-04-08 07:23:33 +03:00
|
|
|
LOG(FATAL) << "IMU capability is not supported by this device";
|
|
|
|
}
|
|
|
|
if (motion_tracking_) {
|
|
|
|
LOG(WARNING) << "Cannot start motion tracking without first stopping it";
|
|
|
|
return;
|
2018-04-07 04:36:41 +03:00
|
|
|
}
|
2018-05-31 10:39:42 +03:00
|
|
|
motions_->SetMotionCallback(
|
|
|
|
std::bind(&Device::CallbackMotionData, this, std::placeholders::_1));
|
2018-06-07 06:19:58 +03:00
|
|
|
// motions_->StartMotionTracking();
|
2018-04-08 17:35:49 +03:00
|
|
|
motion_tracking_ = true;
|
2018-04-07 04:36:41 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void Device::StopMotionTracking() {
|
2018-04-08 07:23:33 +03:00
|
|
|
if (!motion_tracking_) {
|
|
|
|
LOG(WARNING) << "Cannot stop motion tracking without first starting it";
|
|
|
|
return;
|
|
|
|
}
|
2018-06-07 06:19:58 +03:00
|
|
|
// motions_->StopMotionTracking();
|
2018-04-08 17:35:49 +03:00
|
|
|
motion_tracking_ = false;
|
2018-04-07 04:36:41 +03:00
|
|
|
}
|
|
|
|
|
2018-06-07 06:19:58 +03:00
|
|
|
void Device::OnStereoStreamUpdate() {}
|
|
|
|
|
2018-04-13 16:55:32 +03:00
|
|
|
void Device::ReadAllInfos() {
|
2018-04-08 17:35:49 +03:00
|
|
|
device_info_ = std::make_shared<DeviceInfo>();
|
2018-04-13 11:08:47 +03:00
|
|
|
|
|
|
|
CHECK_NOTNULL(channels_);
|
|
|
|
Channels::img_params_t img_params;
|
|
|
|
Channels::imu_params_t imu_params;
|
2018-04-13 16:55:32 +03:00
|
|
|
if (!channels_->GetFiles(device_info_.get(), &img_params, &imu_params)) {
|
2018-05-30 07:31:54 +03:00
|
|
|
LOG(FATAL) << "Read device infos failed. Please upgrade your firmware to "
|
|
|
|
"the latest version.";
|
2018-04-13 16:55:32 +03:00
|
|
|
}
|
2018-04-19 17:44:40 +03:00
|
|
|
VLOG(2) << "Device info: {name: " << device_info_->name
|
2018-04-19 12:23:02 +03:00
|
|
|
<< ", serial_number: " << device_info_->serial_number
|
|
|
|
<< ", firmware_version: "
|
|
|
|
<< device_info_->firmware_version.to_string()
|
|
|
|
<< ", hardware_version: "
|
|
|
|
<< device_info_->hardware_version.to_string()
|
|
|
|
<< ", spec_version: " << device_info_->spec_version.to_string()
|
|
|
|
<< ", lens_type: " << device_info_->lens_type.to_string()
|
|
|
|
<< ", imu_type: " << device_info_->imu_type.to_string()
|
2018-04-19 17:44:40 +03:00
|
|
|
<< ", nominal_baseline: " << device_info_->nominal_baseline << "}";
|
2018-04-13 11:08:47 +03:00
|
|
|
|
2018-04-08 17:35:49 +03:00
|
|
|
device_info_->name = uvc::get_name(*device_);
|
2018-04-19 12:23:02 +03:00
|
|
|
if (img_params.ok) {
|
2018-04-19 17:44:40 +03:00
|
|
|
SetIntrinsics(Stream::LEFT, img_params.in_left);
|
|
|
|
SetIntrinsics(Stream::RIGHT, img_params.in_right);
|
|
|
|
SetExtrinsics(Stream::LEFT, Stream::RIGHT, img_params.ex_left_to_right);
|
|
|
|
VLOG(2) << "Intrinsics left: {" << GetIntrinsics(Stream::LEFT) << "}";
|
|
|
|
VLOG(2) << "Intrinsics right: {" << GetIntrinsics(Stream::RIGHT) << "}";
|
|
|
|
VLOG(2) << "Extrinsics left to right: {"
|
|
|
|
<< GetExtrinsics(Stream::LEFT, Stream::RIGHT) << "}";
|
2018-04-19 12:23:02 +03:00
|
|
|
} else {
|
2018-04-19 17:44:40 +03:00
|
|
|
LOG(WARNING) << "Intrinsics & extrinsics not exist";
|
2018-04-19 12:23:02 +03:00
|
|
|
}
|
|
|
|
if (imu_params.ok) {
|
2018-04-19 17:44:40 +03:00
|
|
|
SetMotionIntrinsics({imu_params.in_accel, imu_params.in_gyro});
|
|
|
|
SetMotionExtrinsics(Stream::LEFT, imu_params.ex_left_to_imu);
|
|
|
|
VLOG(2) << "Motion intrinsics: {" << GetMotionIntrinsics() << "}";
|
|
|
|
VLOG(2) << "Motion extrinsics left to imu: {"
|
|
|
|
<< GetMotionExtrinsics(Stream::LEFT) << "}";
|
2018-04-19 12:23:02 +03:00
|
|
|
} else {
|
2018-04-19 17:44:40 +03:00
|
|
|
LOG(WARNING) << "Motion intrinsics & extrinsics not exist";
|
2018-04-13 16:55:32 +03:00
|
|
|
}
|
2018-04-06 04:12:09 +03:00
|
|
|
}
|
|
|
|
|
2018-05-31 10:39:42 +03:00
|
|
|
void Device::CallbackPushedStreamData(const Stream &stream) {
|
|
|
|
if (HasStreamCallback(stream)) {
|
|
|
|
auto &&datas = streams_->stream_datas(stream);
|
|
|
|
// if (datas.size() > 0) {}
|
|
|
|
auto &&data = datas.back();
|
|
|
|
if (stream_async_callbacks_.find(stream) != stream_async_callbacks_.end()) {
|
|
|
|
stream_async_callbacks_.at(stream)->PushData(data);
|
|
|
|
} else {
|
|
|
|
stream_callbacks_.at(stream)(data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Device::CallbackMotionData(const device::MotionData &data) {
|
|
|
|
if (HasMotionCallback()) {
|
|
|
|
if (motion_async_callback_) {
|
|
|
|
motion_async_callback_->PushData(data);
|
|
|
|
} else {
|
|
|
|
motion_callback_(data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-04 05:50:27 +03:00
|
|
|
MYNTEYE_END_NAMESPACE
|