16 Camera(imageRate, localTransform)
19 computeOdometry_(computeOdometry),
33 device_->imuSensor()->unregisterCallback(imuId_);
36 device_->tofCamera()->unregisterColorDepthImageCallback(tofId_);
39 device_->slam()->stop();
41 if(device_->imuSensor())
42 device_->imuSensor()->stop();
44 if(device_->colorCamera())
45 device_->colorCamera()->stop();
47 if(device_->tofCamera())
48 device_->tofCamera()->stop();
58 auto devices = xv::getDevices(3);
61 UERROR(
"Timeout for SeerSense device detection.");
64 device_ = devices.begin()->second;
67 device_->imuSensor()->start();
68 imuId_ = device_->imuSensor()->registerCallback([
this](
const xv::Imu & xvImu) {
69 if(xvImu.hostTimestamp > 0)
71 if(isInterIMUPublishing())
73 IMU imu(cv::Vec3d(xvImu.gyro[0], xvImu.gyro[1], xvImu.gyro[2]), cv::Mat::eye(3,3,CV_64FC1),
74 cv::Vec3d(xvImu.accel[0], xvImu.accel[1], xvImu.accel[2]), cv::Mat::eye(3,3,CV_64FC1),
75 this->getLocalTransform());
76 this->postInterIMU(imu, xvImu.hostTimestamp);
80 UScopeMutex lock(imuMutex_);
81 imuBuffer_.emplace_hint(imuBuffer_.end(), xvImu.hostTimestamp,
82 std::make_pair(cv::Vec3d(xvImu.gyro[0], xvImu.gyro[1], xvImu.gyro[2]), cv::Vec3d(xvImu.accel[0], xvImu.accel[1], xvImu.accel[2])));
90 device_->slam()->start(xv::Slam::Mode::Mixed);
93 auto frameRate = xv::TofCamera::Framerate::FPS_30;
94 if(this->getImageRate() > 25)
95 frameRate = xv::TofCamera::Framerate::FPS_30;
96 else if(this->getImageRate() > 20)
97 frameRate = xv::TofCamera::Framerate::FPS_25;
98 else if(this->getImageRate() > 15)
99 frameRate = xv::TofCamera::Framerate::FPS_20;
100 else if(this->getImageRate() > 10)
101 frameRate = xv::TofCamera::Framerate::FPS_15;
102 else if(this->getImageRate() > 5)
103 frameRate = xv::TofCamera::Framerate::FPS_10;
104 else if(this->getImageRate() > 0)
105 frameRate = xv::TofCamera::Framerate::FPS_5;
107 UASSERT(device_->colorCamera());
108 device_->colorCamera()->setResolution(xv::ColorCamera::Resolution::RGB_640x480);
109 device_->colorCamera()->start();
111 device_->tofCamera()->setSonyTofSetting(xv::TofCamera::SonyTofLibMode::IQMIX_DF, xv::TofCamera::Resolution::QVGA, frameRate);
112 device_->tofCamera()->start();
114 UASSERT(!device_->tofCamera()->calibration().empty());
115 auto xvTofCalib = device_->tofCamera()->calibration()[0];
116 UASSERT(!xvTofCalib.pdcm.empty());
117 cv::Mat
D(1, xvTofCalib.pdcm[0].distor.size(), CV_64FC1, xvTofCalib.pdcm[0].distor.begin());
118 cv::Mat
R = cv::Mat::eye(3, 3, CV_64FC1);
119 cv::Mat
P = cv::Mat::eye(3, 4, CV_64FC1);
120 P.at<
double>(0,0) = xvTofCalib.pdcm[0].fx;
121 P.at<
double>(1,1) = xvTofCalib.pdcm[0].fy;
122 P.at<
double>(0,2) = xvTofCalib.pdcm[0].u0;
123 P.at<
double>(1,2) = xvTofCalib.pdcm[0].v0;
124 cv::Mat
K =
P.colRange(0, 3);
125 cameraModel_ = CameraModel(device_->id(), cv::Size(xvTofCalib.pdcm[0].w, xvTofCalib.pdcm[0].h), K, D, R,
P,
126 this->getLocalTransform() * Transform(
127 xvTofCalib.pose.rotation()[0], xvTofCalib.pose.rotation()[1], xvTofCalib.pose.rotation()[2], xvTofCalib.pose.translation()[0],
128 xvTofCalib.pose.rotation()[3], xvTofCalib.pose.rotation()[4], xvTofCalib.pose.rotation()[5], xvTofCalib.pose.translation()[1],
129 xvTofCalib.pose.rotation()[6], xvTofCalib.pose.rotation()[7], xvTofCalib.pose.rotation()[8], xvTofCalib.pose.translation()[2]
131 UASSERT(cameraModel_.isValidForRectification());
132 cameraModel_.initRectificationMap();
134 lastData_ = std::pair<double, std::pair<cv::Mat, cv::Mat>>();
135 tofId_ = device_->tofCamera()->registerColorDepthImageCallback([
this](
const xv::DepthColorImage & xvDepthColorImage) {
136 if(xvDepthColorImage.hostTimestamp > 0)
138 cv::Mat color = cv::Mat::zeros(cameraModel_.imageSize(), CV_8UC3);
139 color.forEach<cv::Vec3b>([&](cv::Vec3b& pixel,
const int position[]) ->
void {
140 const auto rgb =
reinterpret_cast<std::uint8_t const *
>(xvDepthColorImage.data.get() + (
position[0]*cameraModel_.imageWidth()+
position[1]) * 7);
141 pixel = cv::Vec3b(rgb[2], rgb[1], rgb[0]);
143 cv::Mat depth = cv::Mat::zeros(cameraModel_.imageSize(), CV_32FC1);
144 depth.forEach<
float>([&](
float &pixel,
const int position[]) ->
void {
145 pixel = *
reinterpret_cast<float const *
>(xvDepthColorImage.data.get() + (
position[0]*cameraModel_.imageWidth()+
position[1]) * 7 + 3);
148 bool notify = !lastData_.first;
149 lastData_ = std::make_pair(xvDepthColorImage.hostTimestamp, std::make_pair(color, depth));
151 dataReady_.release();
157 UERROR(
"CameraSeerSense: RTAB-Map is not built with XVisio SDK support!");
162 bool CameraSeerSense::isCalibrated()
const
167 std::string CameraSeerSense::getSerial()
const
170 return device_->id();
175 bool CameraSeerSense::odomProvided()
const
178 return computeOdometry_;
184 bool CameraSeerSense::getPose(
double stamp,
Transform & pose, cv::Mat & covariance,
double maxWaitTime)
188 if(computeOdometry_ && device_->slam()->getPoseAt(xvPose, stamp))
190 pose = this->getLocalTransform() *
192 xvPose.transform().rotation()[0], xvPose.transform().rotation()[1], xvPose.transform().rotation()[2], xvPose.transform().translation()[0],
193 xvPose.transform().rotation()[3], xvPose.transform().rotation()[4], xvPose.transform().rotation()[5], xvPose.transform().translation()[1],
194 xvPose.transform().rotation()[6], xvPose.transform().rotation()[7], xvPose.transform().rotation()[8], xvPose.transform().translation()[2]) *
195 this->getLocalTransform().
inverse();
196 covariance = cv::Mat::eye(6, 6, CV_64FC1) * 0.0005;
207 if(!dataReady_.acquire(1, 3000))
209 UERROR(
"Did not receive frame since 3 seconds...");
215 cameraModel_.rectifyImage(lastData_.second.first, cv::INTER_CUBIC),
216 cameraModel_.rectifyImage(lastData_.second.second, cv::INTER_NEAREST),
217 cameraModel_,
this->getNextSeqID(), lastData_.first);
218 lastData_ = std::pair<double, std::pair<cv::Mat, cv::Mat>>();
221 if(!isInterIMUPublishing())
224 std::map<double, std::pair<cv::Vec3d, cv::Vec3d>>::const_iterator iterA, iterB;
227 while(imuBuffer_.empty() || imuBuffer_.rbegin()->first <
data.stamp())
234 iterB = imuBuffer_.lower_bound(
data.stamp());
236 if(iterA != imuBuffer_.begin())
238 if(iterA == iterB ||
data.stamp() == iterB->first)
240 gyro = iterB->second.first;
241 acc = iterB->second.second;
243 else if(
data.stamp() > iterA->first &&
data.stamp() < iterB->first)
245 float t = (
data.stamp()-iterA->first) / (iterB->first-iterA->first);
246 gyro = iterA->second.first +
t*(iterB->second.first - iterA->second.first);
247 acc = iterA->second.second +
t*(iterB->second.second - iterA->second.second);
249 imuBuffer_.erase(imuBuffer_.begin(), iterB);
252 data.setIMU(
IMU(gyro, cv::Mat::eye(3, 3, CV_64FC1), acc, cv::Mat::eye(3, 3, CV_64FC1), this->getLocalTransform()));
256 if(computeOdometry_ && device_->slam()->getPoseAt(xvPose,
data.stamp()))
258 info->odomPose = this->getLocalTransform() *
260 xvPose.transform().rotation()[0], xvPose.transform().rotation()[1], xvPose.transform().rotation()[2], xvPose.transform().translation()[0],
261 xvPose.transform().rotation()[3], xvPose.transform().rotation()[4], xvPose.transform().rotation()[5], xvPose.transform().translation()[1],
262 xvPose.transform().rotation()[6], xvPose.transform().rotation()[7], xvPose.transform().rotation()[8], xvPose.transform().translation()[2]) *
263 this->getLocalTransform().
inverse();
264 info->odomCovariance = cv::Mat::eye(6, 6, CV_64FC1) * 0.0005;
267 UERROR(
"CameraSeerSense: RTAB-Map is not built with XVisio SDK support!");