35 #include <sl/Camera.hpp> 43 static cv::Mat slMat2cvMat(sl::Mat& input) {
44 #if ZED_SDK_MAJOR_VERSION < 3 47 switch (input.getDataType()) {
48 case sl::MAT_TYPE_32F_C1: cv_type = CV_32FC1;
break;
49 case sl::MAT_TYPE_32F_C2: cv_type = CV_32FC2;
break;
50 case sl::MAT_TYPE_32F_C3: cv_type = CV_32FC3;
break;
51 case sl::MAT_TYPE_32F_C4: cv_type = CV_32FC4;
break;
52 case sl::MAT_TYPE_8U_C1: cv_type = CV_8UC1;
break;
53 case sl::MAT_TYPE_8U_C2: cv_type = CV_8UC2;
break;
54 case sl::MAT_TYPE_8U_C3: cv_type = CV_8UC3;
break;
55 case sl::MAT_TYPE_8U_C4: cv_type = CV_8UC4;
break;
60 return cv::Mat(input.getHeight(), input.getWidth(), cv_type, input.getPtr<sl::uchar1>(sl::MEM_CPU));
64 switch (input.getDataType()) {
65 case sl::MAT_TYPE::F32_C1: cv_type = CV_32FC1;
break;
66 case sl::MAT_TYPE::F32_C2: cv_type = CV_32FC2;
break;
67 case sl::MAT_TYPE::F32_C3: cv_type = CV_32FC3;
break;
68 case sl::MAT_TYPE::F32_C4: cv_type = CV_32FC4;
break;
69 case sl::MAT_TYPE::U8_C1: cv_type = CV_8UC1;
break;
70 case sl::MAT_TYPE::U8_C2: cv_type = CV_8UC2;
break;
71 case sl::MAT_TYPE::U8_C3: cv_type = CV_8UC3;
break;
72 case sl::MAT_TYPE::U8_C4: cv_type = CV_8UC4;
break;
77 return cv::Mat(input.getHeight(), input.getWidth(), cv_type, input.getPtr<sl::uchar1>(sl::MEM::CPU));
81 Transform zedPoseToTransform(
const sl::Pose & pose)
84 pose.pose_data.m[0], pose.pose_data.m[1], pose.pose_data.m[2], pose.pose_data.m[3],
85 pose.pose_data.m[4], pose.pose_data.m[5], pose.pose_data.m[6], pose.pose_data.m[7],
86 pose.pose_data.m[8], pose.pose_data.m[9], pose.pose_data.m[10], pose.pose_data.m[11]);
89 #if ZED_SDK_MAJOR_VERSION < 3 90 IMU zedIMUtoIMU(
const sl::IMUData & imuData,
const Transform & imuLocalTransform)
92 sl::Orientation
orientation = imuData.pose_data.getOrientation();
95 Transform opticalTransform(0, 0, 1, 0, -1, 0, 0, 0, 0, -1, 0, 0);
96 Transform orientationT(0,0,0, orientation.ox, orientation.oy, orientation.oz, orientation.ow);
97 orientationT = opticalTransform * orientationT;
99 static double deg2rad = 0.017453293;
100 Eigen::Vector4d accT = Eigen::Vector4d(imuData.linear_acceleration.v[0], imuData.linear_acceleration.v[1], imuData.linear_acceleration.v[2], 1);
101 Eigen::Vector4d gyrT = Eigen::Vector4d(imuData.angular_velocity.v[0]*deg2rad, imuData.angular_velocity.v[1]*deg2rad, imuData.angular_velocity.v[2]*deg2rad, 1);
103 cv::Mat orientationCov = (cv::Mat_<double>(3,3)<<
104 imuData.pose_covariance[21], imuData.pose_covariance[22], imuData.pose_covariance[23],
105 imuData.pose_covariance[27], imuData.pose_covariance[28], imuData.pose_covariance[29],
106 imuData.pose_covariance[33], imuData.pose_covariance[34], imuData.pose_covariance[35]);
107 cv::Mat angCov = (cv::Mat_<double>(3,3)<<
108 imuData.angular_velocity_convariance.r[0], imuData.angular_velocity_convariance.r[1], imuData.angular_velocity_convariance.r[2],
109 imuData.angular_velocity_convariance.r[3], imuData.angular_velocity_convariance.r[4], imuData.angular_velocity_convariance.r[5],
110 imuData.angular_velocity_convariance.r[6], imuData.angular_velocity_convariance.r[7], imuData.angular_velocity_convariance.r[8]);
111 cv::Mat accCov = (cv::Mat_<double>(3,3)<<
112 imuData.linear_acceleration_convariance.r[0], imuData.linear_acceleration_convariance.r[1], imuData.linear_acceleration_convariance.r[2],
113 imuData.linear_acceleration_convariance.r[3], imuData.linear_acceleration_convariance.r[4], imuData.linear_acceleration_convariance.r[5],
114 imuData.linear_acceleration_convariance.r[6], imuData.linear_acceleration_convariance.r[7], imuData.linear_acceleration_convariance.r[8]);
116 Eigen::Quaternionf
quat = orientationT.getQuaternionf();
119 cv::Vec4d(quat.x(), quat.y(), quat.z(), quat.w()),
121 cv::Vec3d(gyrT[0], gyrT[1], gyrT[2]),
123 cv::Vec3d(accT[0], accT[1], accT[2]),
128 IMU zedIMUtoIMU(
const sl::SensorsData & sensorData,
const Transform & imuLocalTransform)
130 sl::Orientation orientation = sensorData.imu.pose.getOrientation();
133 Transform opticalTransform(0, 0, 1, 0, -1, 0, 0, 0, 0, -1, 0, 0);
134 Transform orientationT(0,0,0, orientation.ox, orientation.oy, orientation.oz, orientation.ow);
135 orientationT = opticalTransform * orientationT;
137 static double deg2rad = 0.017453293;
138 Eigen::Vector4d accT = Eigen::Vector4d(sensorData.imu.linear_acceleration.v[0], sensorData.imu.linear_acceleration.v[1], sensorData.imu.linear_acceleration.v[2], 1);
139 Eigen::Vector4d gyrT = Eigen::Vector4d(sensorData.imu.angular_velocity.v[0]*deg2rad, sensorData.imu.angular_velocity.v[1]*deg2rad, sensorData.imu.angular_velocity.v[2]*deg2rad, 1);
141 cv::Mat orientationCov = (cv::Mat_<double>(3,3)<<
142 sensorData.imu.pose_covariance.r[0], sensorData.imu.pose_covariance.r[1], sensorData.imu.pose_covariance.r[2],
143 sensorData.imu.pose_covariance.r[3], sensorData.imu.pose_covariance.r[4], sensorData.imu.pose_covariance.r[5],
144 sensorData.imu.pose_covariance.r[6], sensorData.imu.pose_covariance.r[7], sensorData.imu.pose_covariance.r[8]);
145 cv::Mat angCov = (cv::Mat_<double>(3,3)<<
146 sensorData.imu.angular_velocity_covariance.r[0], sensorData.imu.angular_velocity_covariance.r[1], sensorData.imu.angular_velocity_covariance.r[2],
147 sensorData.imu.angular_velocity_covariance.r[3], sensorData.imu.angular_velocity_covariance.r[4], sensorData.imu.angular_velocity_covariance.r[5],
148 sensorData.imu.angular_velocity_covariance.r[6], sensorData.imu.angular_velocity_covariance.r[7], sensorData.imu.angular_velocity_covariance.r[8]);
149 cv::Mat accCov = (cv::Mat_<double>(3,3)<<
150 sensorData.imu.linear_acceleration_covariance.r[0], sensorData.imu.linear_acceleration_covariance.r[1], sensorData.imu.linear_acceleration_covariance.r[2],
151 sensorData.imu.linear_acceleration_covariance.r[3], sensorData.imu.linear_acceleration_covariance.r[4], sensorData.imu.linear_acceleration_covariance.r[5],
152 sensorData.imu.linear_acceleration_covariance.r[6], sensorData.imu.linear_acceleration_covariance.r[7], sensorData.imu.linear_acceleration_covariance.r[8]);
154 Eigen::Quaternionf quat = orientationT.getQuaternionf();
157 cv::Vec4d(quat.x(), quat.y(), quat.z(), quat.w()),
159 cv::Vec3d(gyrT[0], gyrT[1], gyrT[2]),
161 cv::Vec3d(accT[0], accT[1], accT[2]),
167 class ZedIMUThread:
public UThread 170 ZedIMUThread(
float rate, sl::Camera * zed,
const Transform & imuLocalTransform,
bool accurate)
176 accurate_ = accurate;
177 imuLocalTransform_ = imuLocalTransform;
180 virtual void mainLoopBegin()
182 frameRateTimer_.start();
184 virtual void mainLoop()
186 double delay = 1000.0/double(rate_);
187 int sleepTime = delay - 1000.0f*frameRateTimer_.getElapsedTime();
198 while(frameRateTimer_.getElapsedTime() < delay-0.000001)
208 frameRateTimer_.start();
210 #if ZED_SDK_MAJOR_VERSION < 3 212 bool res = zed_->getIMUData(imudata, sl::TIME_REFERENCE_IMAGE);
213 if(res == sl::SUCCESS && imudata.valid)
218 sl::SensorsData sensordata;
219 sl::ERROR_CODE res = zed_->getSensorsData(sensordata, sl::TIME_REFERENCE::IMAGE);
220 if(res == sl::ERROR_CODE::SUCCESS && sensordata.imu.is_available)
229 Transform imuLocalTransform_;
249 bool computeOdometry,
252 bool selfCalibration,
254 int texturenessConfidenceThr) :
255 Camera(imageRate, localTransform)
260 usbDevice_(deviceId),
262 resolution_(resolution),
264 selfCalibration_(selfCalibration),
265 sensingMode_(sensingMode),
266 confidenceThr_(confidenceThr),
267 texturenessConfidenceThr_(texturenessConfidenceThr),
268 computeOdometry_(computeOdometry),
270 force3DoF_(odomForce3DoF),
271 publishInterIMU_(
false),
272 imuPublishingThread_(0)
277 #if ZED_SDK_MAJOR_VERSION < 3 278 UASSERT(resolution_ >= sl::RESOLUTION_HD2K && resolution_ <sl::RESOLUTION_LAST);
279 UASSERT(quality_ >= sl::DEPTH_MODE_NONE && quality_ <sl::DEPTH_MODE_LAST);
280 UASSERT(sensingMode_ >= sl::SENSING_MODE_STANDARD && sensingMode_ <sl::SENSING_MODE_LAST);
281 UASSERT(confidenceThr_ >= 0 && confidenceThr_ <=100);
283 sl::RESOLUTION res =
static_cast<sl::RESOLUTION
>(resolution_);
284 sl::DEPTH_MODE qual =
static_cast<sl::DEPTH_MODE
>(quality_);
285 sl::SENSING_MODE sens =
static_cast<sl::SENSING_MODE
>(sensingMode_);
287 UASSERT(res >= sl::RESOLUTION::HD2K && res < sl::RESOLUTION::LAST);
288 UASSERT(qual >= sl::DEPTH_MODE::NONE && qual < sl::DEPTH_MODE::LAST);
289 UASSERT(sens >= sl::SENSING_MODE::STANDARD && sens < sl::SENSING_MODE::LAST);
290 UASSERT(confidenceThr_ >= 0 && confidenceThr_ <=100);
291 UASSERT(texturenessConfidenceThr_ >= 0 && texturenessConfidenceThr_ <=100);
297 const std::string & filePath,
301 bool computeOdometry,
304 bool selfCalibration,
306 int texturenessConfidenceThr) :
307 Camera(imageRate, localTransform)
313 svoFilePath_(filePath),
316 selfCalibration_(selfCalibration),
317 sensingMode_(sensingMode),
318 confidenceThr_(confidenceThr),
319 texturenessConfidenceThr_(texturenessConfidenceThr),
320 computeOdometry_(computeOdometry),
322 force3DoF_(odomForce3DoF),
323 publishInterIMU_(
false),
324 imuPublishingThread_(0)
329 #if ZED_SDK_MAJOR_VERSION < 3 330 UASSERT(resolution_ >= sl::RESOLUTION_HD2K && resolution_ <sl::RESOLUTION_LAST);
331 UASSERT(quality_ >= sl::DEPTH_MODE_NONE && quality_ <sl::DEPTH_MODE_LAST);
332 UASSERT(sensingMode_ >= sl::SENSING_MODE_STANDARD && sensingMode_ <sl::SENSING_MODE_LAST);
333 UASSERT(confidenceThr_ >= 0 && confidenceThr_ <=100);
335 sl::RESOLUTION res =
static_cast<sl::RESOLUTION
>(resolution_);
336 sl::DEPTH_MODE qual =
static_cast<sl::DEPTH_MODE
>(quality_);
337 sl::SENSING_MODE sens =
static_cast<sl::SENSING_MODE
>(sensingMode_);
339 UASSERT(res >= sl::RESOLUTION::HD2K && res < sl::RESOLUTION::LAST);
340 UASSERT(qual >= sl::DEPTH_MODE::NONE && qual < sl::DEPTH_MODE::LAST);
341 UASSERT(sens >= sl::SENSING_MODE::STANDARD && sens < sl::SENSING_MODE::LAST);
342 UASSERT(confidenceThr_ >= 0 && confidenceThr_ <=100);
343 UASSERT(texturenessConfidenceThr_ >= 0 && texturenessConfidenceThr_ <=100);
351 if(imuPublishingThread_)
353 imuPublishingThread_->join(
true);
355 delete imuPublishingThread_;
363 publishInterIMU_ = enabled;
371 if(imuPublishingThread_)
373 imuPublishingThread_->join(
true);
374 delete imuPublishingThread_;
375 imuPublishingThread_=0;
385 sl::InitParameters param;
386 param.camera_resolution=
static_cast<sl::RESOLUTION
>(resolution_);
388 param.depth_mode=(sl::DEPTH_MODE)quality_;
389 #if ZED_SDK_MAJOR_VERSION < 3 390 param.camera_linux_id=usbDevice_;
391 param.coordinate_units=sl::UNIT_METER;
392 param.coordinate_system=(sl::COORDINATE_SYSTEM)sl::COORDINATE_SYSTEM_IMAGE ;
394 param.coordinate_units=sl::UNIT::METER;
395 param.coordinate_system=sl::COORDINATE_SYSTEM::IMAGE ;
397 param.sdk_verbose=
true;
399 param.depth_minimum_distance=-1;
400 param.camera_disable_self_calib=!selfCalibration_;
402 sl::ERROR_CODE r = sl::ERROR_CODE::SUCCESS;
405 UINFO(
"svo file = %s", svoFilePath_.c_str());
406 zed_ =
new sl::Camera();
407 #if ZED_SDK_MAJOR_VERSION < 3 408 param.svo_input_filename=svoFilePath_.c_str();
410 param.input.setFromSVOFile(svoFilePath_.c_str());
412 r = zed_->open(param);
416 #if ZED_SDK_MAJOR_VERSION >= 3 417 param.input.setFromCameraID(usbDevice_);
419 UINFO(
"Resolution=%d imagerate=%f device=%d", resolution_,
getImageRate(), usbDevice_);
420 zed_ =
new sl::Camera();
421 r = zed_->open(param);
424 if(r!=sl::ERROR_CODE::SUCCESS)
426 UERROR(
"Camera initialization failed: \"%s\"", toString(r).c_str());
432 #if ZED_SDK_MAJOR_VERSION < 3 433 UINFO(
"Init ZED: Mode=%d Unit=%d CoordinateSystem=%d Verbose=false device=-1 minDist=-1 self-calibration=%s vflip=false",
434 quality_, sl::UNIT_METER, sl::COORDINATE_SYSTEM_IMAGE , selfCalibration_?
"true":
"false");
436 if(quality_!=sl::DEPTH_MODE_NONE)
438 zed_->setConfidenceThreshold(confidenceThr_);
441 UINFO(
"Init ZED: Mode=%d Unit=%d CoordinateSystem=%d Verbose=false device=-1 minDist=-1 self-calibration=%s vflip=false",
442 quality_, sl::UNIT::METER, sl::COORDINATE_SYSTEM::IMAGE , selfCalibration_?
"true":
"false");
450 if (computeOdometry_)
452 #if ZED_SDK_MAJOR_VERSION < 3 453 sl::TrackingParameters tparam;
454 tparam.enable_spatial_memory=
false;
455 r = zed_->enableTracking(tparam);
457 sl::PositionalTrackingParameters tparam;
458 tparam.enable_area_memory=
false;
459 r = zed_->enablePositionalTracking(tparam);
461 if(r!=sl::ERROR_CODE::SUCCESS)
463 UERROR(
"Camera tracking initialization failed: \"%s\"", toString(r).c_str());
467 sl::CameraInformation infos = zed_->getCameraInformation();
468 sl::CalibrationParameters *stereoParams = &(infos.calibration_parameters );
469 sl::Resolution res = stereoParams->left_cam.image_size;
472 stereoParams->left_cam.fx,
473 stereoParams->left_cam.fy,
474 stereoParams->left_cam.cx,
475 stereoParams->left_cam.cy,
477 this->getLocalTransform(),
478 cv::Size(res.width, res.height));
480 UINFO(
"Calibration: fx=%f, fy=%f, cx=%f, cy=%f, baseline=%f, width=%d, height=%d, transform=%s",
481 stereoParams->left_cam.fx,
482 stereoParams->left_cam.fy,
483 stereoParams->left_cam.cx,
484 stereoParams->left_cam.cy,
488 this->getLocalTransform().prettyPrint().c_str());
490 #if ZED_SDK_MAJOR_VERSION < 3 491 if(infos.camera_model == sl::MODEL_ZED_M)
493 if(infos.camera_model != sl::MODEL::ZED)
497 UINFO(
"IMU local transform: %s (imu2cam=%s))",
498 imuLocalTransform_.prettyPrint().c_str(),
499 zedPoseToTransform(infos.camera_imu_transform).prettyPrint().c_str());
503 imuPublishingThread_ =
new ZedIMUThread(200, zed_, imuLocalTransform_,
true);
504 imuPublishingThread_->start();
510 UERROR(
"CameraStereoZED: RTAB-Map is not built with ZED sdk support!");
518 return stereoModel_.isValidForProjection();
529 return uFormat(
"%x", zed_->getCameraInformation ().serial_number);
538 return computeOdometry_;
548 if (computeOdometry_ && zed_)
552 #if ZED_SDK_MAJOR_VERSION < 3 557 sl::TRACKING_STATE tracking_state = zed_->getPosition(p);
558 if (tracking_state == sl::TRACKING_STATE_OK)
560 if(zed_->grab()!=sl::ERROR_CODE::SUCCESS)
564 sl::POSITIONAL_TRACKING_STATE tracking_state = zed_->getPosition(p);
565 if (tracking_state == sl::POSITIONAL_TRACKING_STATE::OK)
568 int trackingConfidence = p.pose_confidence;
570 if (trackingConfidence>0)
572 pose = zedPoseToTransform(p);
586 covariance = cv::Mat::eye(6, 6, CV_64FC1) * 9999.0f;
592 covariance = cv::Mat::eye(6, 6, CV_64FC1) * 1.0f / float(trackingConfidence);
593 UDEBUG(
"Run %s (var=%f)", pose.
prettyPrint().c_str(), 1.0f / float(trackingConfidence));
599 covariance = cv::Mat::eye(6, 6, CV_64FC1) * 9999.0f;
601 UWARN(
"ZED lost! (trackingConfidence=%d)", trackingConfidence);
606 covariance = cv::Mat::eye(6, 6, CV_64FC1) * 9999.0f;
608 UWARN(
"ZED lost! (trackingConfidence=%d)", trackingConfidence);
613 UWARN(
"Tracking not ok: state=\"%s\"", toString(tracking_state).c_str());
624 #if ZED_SDK_MAJOR_VERSION < 3 625 sl::RuntimeParameters rparam((sl::SENSING_MODE)sensingMode_, quality_ > 0, quality_ > 0, sl::REFERENCE_FRAME_CAMERA);
627 sl::RuntimeParameters rparam((sl::SENSING_MODE)sensingMode_, quality_ > 0, confidenceThr_, texturenessConfidenceThr_, sl::REFERENCE_FRAME::CAMERA);
633 #if ZED_SDK_MAJOR_VERSION < 3 634 bool res = zed_->grab(rparam);
639 res = zed_->grab(rparam);
646 bool imuReceived =
true;
649 res = zed_->grab(rparam);
652 if(imuPublishingThread_ == 0 && !imuLocalTransform_.isNull())
654 sl::SensorsData imudatatmp;
655 res = zed_->getSensorsData(imudatatmp, sl::TIME_REFERENCE::IMAGE);
656 imuReceived = res == sl::ERROR_CODE::SUCCESS && imudatatmp.imu.is_available && imudatatmp.imu.timestamp.data_ns != 0;
661 if(res==sl::ERROR_CODE::SUCCESS)
666 #if ZED_SDK_MAJOR_VERSION < 3 667 zed_->retrieveImage(tmp,sl::VIEW_LEFT);
669 zed_->retrieveImage(tmp,sl::VIEW::LEFT);
671 cv::Mat rgbaLeft = slMat2cvMat(tmp);
674 cv::cvtColor(rgbaLeft, left, cv::COLOR_BGRA2BGR);
681 #if ZED_SDK_MAJOR_VERSION < 3 682 zed_->retrieveMeasure(tmp,sl::MEASURE_DEPTH);
684 zed_->retrieveMeasure(tmp,sl::MEASURE::DEPTH);
686 slMat2cvMat(tmp).copyTo(depth);
693 #if ZED_SDK_MAJOR_VERSION < 3 694 sl::Mat tmp;zed_->retrieveImage(tmp,sl::VIEW_RIGHT );
696 sl::Mat tmp;zed_->retrieveImage(tmp,sl::VIEW::RIGHT );
698 cv::Mat rgbaRight = slMat2cvMat(tmp);
700 cv::cvtColor(rgbaRight, right, cv::COLOR_BGRA2GRAY);
705 if(imuPublishingThread_ == 0)
707 #if ZED_SDK_MAJOR_VERSION < 3 709 res = zed_->getIMUData(imudata, sl::TIME_REFERENCE_IMAGE);
710 if(res == sl::SUCCESS && imudata.valid)
712 sl::SensorsData imudata;
713 res = zed_->getSensorsData(imudata, sl::TIME_REFERENCE::IMAGE);
714 if(res == sl::ERROR_CODE::SUCCESS && imudata.imu.is_available)
718 data.
setIMU(zedIMUtoIMU(imudata, imuLocalTransform_));
722 if (computeOdometry_ && info)
725 #if ZED_SDK_MAJOR_VERSION < 3 726 sl::TRACKING_STATE tracking_state = zed_->getPosition(pose);
727 if (tracking_state == sl::TRACKING_STATE_OK)
729 sl::POSITIONAL_TRACKING_STATE tracking_state = zed_->getPosition(pose);
730 if (tracking_state == sl::POSITIONAL_TRACKING_STATE::OK)
733 int trackingConfidence = pose.pose_confidence;
735 if (trackingConfidence>0)
737 info->
odomPose = zedPoseToTransform(pose);
757 info->
odomCovariance = cv::Mat::eye(6, 6, CV_64FC1) * 1.0f / float(trackingConfidence);
765 UWARN(
"ZED lost! (trackingConfidence=%d)", trackingConfidence);
772 UWARN(
"ZED lost! (trackingConfidence=%d)", trackingConfidence);
777 UWARN(
"Tracking not ok: state=\"%s\"", toString(tracking_state).c_str());
783 UERROR(
"CameraStereoZed: Failed to grab images after 2 seconds!");
787 UWARN(
"CameraStereoZed: end of stream is reached!");
791 UERROR(
"CameraStereoZED: RTAB-Map is not built with ZED sdk support!");
static void post(UEvent *event, bool async=true, const UEventsSender *sender=0)
virtual bool odomProvided() const
highp_quat quat
Quaternion of default single-precision floating-point numbers.
virtual ~CameraStereoZed()
Some conversion functions.
#define UASSERT(condition)
const Transform & getLocalTransform() const
virtual bool getPose(double stamp, Transform &pose, cv::Mat &covariance)
virtual std::string getSerial() const
float getImageRate() const
void uSleep(unsigned int ms)
virtual bool isCalibrated() const
void setIMU(const IMU &imu)
CameraStereoZed(int deviceId, int resolution=2, int quality=1, int sensingMode=0, int confidenceThr=100, bool computeOdometry=false, float imageRate=0.0f, const Transform &localTransform=Transform::getIdentity(), bool selfCalibration=true, bool odomForce3DoF=false, int texturenessConfidenceThr=90)
void publishInterIMU(bool enabled)
virtual bool init(const std::string &calibrationFolder=".", const std::string &cameraName="")
std::string UTILITE_EXP uFormat(const char *fmt,...)
virtual SensorData captureImage(CameraInfo *info=0)
GLM_FUNC_DECL detail::tmat4x4< T, P > orientation(detail::tvec3< T, P > const &Normal, detail::tvec3< T, P > const &Up)