mirror of
https://github.com/introlab/rtabmap.git
synced 2026-09-14 15:30:19 +08:00
Compare commits
92
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e4873e770a | ||
|
|
3148ae2d76 | ||
|
|
8819b42f24 | ||
|
|
bf45a0cba2 | ||
|
|
4be07fc3e9 | ||
|
|
4e32e8846c | ||
|
|
6468245317 | ||
|
|
169b79215d | ||
|
|
4a09c4bdcf | ||
|
|
3505611fb5 | ||
|
|
55228aa574 | ||
|
|
e800662bac | ||
|
|
33e9abdfad | ||
|
|
cd10cafd0e | ||
|
|
736cf0efc7 | ||
|
|
4f6d8b1fbe | ||
|
|
8fa216bd9d | ||
|
|
661a05b0da | ||
|
|
0809946c66 | ||
|
|
4857d43146 | ||
|
|
b7ada1992e | ||
|
|
2ee3445728 | ||
|
|
4142ff003c | ||
|
|
542f06ec24 | ||
|
|
dacf724ea6 | ||
|
|
274903dd63 | ||
|
|
c19f81ac12 | ||
|
|
846bd59d0b | ||
|
|
6e1f07e097 | ||
|
|
1ca2c25a10 | ||
|
|
c5ec4f337b | ||
|
|
554b08256b | ||
|
|
a2b0de2a4d | ||
|
|
fb6659e29d | ||
|
|
db00f55981 | ||
|
|
ffdb2eb855 | ||
|
|
13679cc52a | ||
|
|
4769fc235f | ||
|
|
ff5695878c | ||
|
|
6029b6283d | ||
|
|
86ac63ab19 | ||
|
|
de5610bd08 | ||
|
|
7a9a5d2ef9 | ||
|
|
b6d4c6f024 | ||
|
|
ff3c6c8e06 | ||
|
|
e2007a8f82 | ||
|
|
bda18bc517 | ||
|
|
d00717b068 | ||
|
|
c7be9a23ee | ||
|
|
caffb56246 | ||
|
|
d5cfd8013d | ||
|
|
415a2778f1 | ||
|
|
6e55525a7b | ||
|
|
7eae992d6f | ||
|
|
2509b6ee09 | ||
|
|
45ddce938a | ||
|
|
6e0081e248 | ||
|
|
bf39c5295b | ||
|
|
8842d0c0e3 | ||
|
|
511be5f663 | ||
|
|
ae5ce029d6 | ||
|
|
798466bb05 | ||
|
|
0902ccc340 | ||
|
|
208f1e5b7c | ||
|
|
b40d9610ed | ||
|
|
35385e299d | ||
|
|
6acfc62196 | ||
|
|
eb9999d7b1 | ||
|
|
69a2aacc8e | ||
|
|
013bd0c72a | ||
|
|
89ece8cd4e | ||
|
|
360a153565 | ||
|
|
63d40b2240 | ||
|
|
cb60443a33 | ||
|
|
609d45ac9b | ||
|
|
b542d6a0db | ||
|
|
c7b84c60bc | ||
|
|
55509c6c27 | ||
|
|
00695731fe | ||
|
|
09d2f7d232 | ||
|
|
e906b40e50 | ||
|
|
1b675c3dcb | ||
|
|
d2673ed2fa | ||
|
|
cc9fd439fe | ||
|
|
fbdc3780c7 | ||
|
|
c44837a4cb | ||
|
|
91285e5e97 | ||
|
|
abc3ebee8c | ||
|
|
1af139134e | ||
|
|
7d377d26df | ||
|
|
7041d5fd34 | ||
|
|
c19da22ca4 |
+15
@@ -52,6 +52,21 @@ matrix:
|
|||||||
- mkdir -p build && cd build
|
- mkdir -p build && cd build
|
||||||
- cmake ..
|
- cmake ..
|
||||||
- make
|
- make
|
||||||
|
|
||||||
|
- dist: focal
|
||||||
|
install:
|
||||||
|
- sudo sh -c 'echo "deb http://packages.ros.org/ros/ubuntu focal main" > /etc/apt/sources.list.d/ros-latest.list'
|
||||||
|
- wget http://packages.ros.org/ros.key -O - | sudo apt-key add -
|
||||||
|
- sudo apt-get update
|
||||||
|
- sudo apt-get update && sudo apt-get install dpkg
|
||||||
|
- sudo apt-get -y install ros-noetic-rtabmap-ros
|
||||||
|
- sudo apt-get -y remove ros-noetic-rtabmap
|
||||||
|
|
||||||
|
script:
|
||||||
|
- source /opt/ros/noetic/setup.bash
|
||||||
|
- mkdir -p build && cd build
|
||||||
|
- cmake ..
|
||||||
|
- make
|
||||||
|
|
||||||
notifications:
|
notifications:
|
||||||
email:
|
email:
|
||||||
|
|||||||
+42
-18
@@ -20,8 +20,8 @@ SET(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake_modules")
|
|||||||
# VERSION
|
# VERSION
|
||||||
#######################
|
#######################
|
||||||
SET(RTABMAP_MAJOR_VERSION 0)
|
SET(RTABMAP_MAJOR_VERSION 0)
|
||||||
SET(RTABMAP_MINOR_VERSION 19)
|
SET(RTABMAP_MINOR_VERSION 20)
|
||||||
SET(RTABMAP_PATCH_VERSION 7)
|
SET(RTABMAP_PATCH_VERSION 2)
|
||||||
SET(RTABMAP_VERSION
|
SET(RTABMAP_VERSION
|
||||||
${RTABMAP_MAJOR_VERSION}.${RTABMAP_MINOR_VERSION}.${RTABMAP_PATCH_VERSION})
|
${RTABMAP_MAJOR_VERSION}.${RTABMAP_MINOR_VERSION}.${RTABMAP_PATCH_VERSION})
|
||||||
|
|
||||||
@@ -163,7 +163,8 @@ ELSE()
|
|||||||
option(WITH_QT "Include Qt support" ON)
|
option(WITH_QT "Include Qt support" ON)
|
||||||
ENDIF()
|
ENDIF()
|
||||||
option(WITH_ORB_OCTREE "Include ORB Octree feature support" ON)
|
option(WITH_ORB_OCTREE "Include ORB Octree feature support" ON)
|
||||||
option(WITH_SP_TORCH "Include SuperPoint Torch feature support" ON)
|
option(WITH_SUPERPOINT_TORCH "Include SuperPoint Torch feature support" ON)
|
||||||
|
option(WITH_PYMATCHER "Include Python3 matchers support" OFF)
|
||||||
option(WITH_FREENECT "Include Freenect support" ON)
|
option(WITH_FREENECT "Include Freenect support" ON)
|
||||||
option(WITH_FREENECT2 "Include Freenect2 support" ON)
|
option(WITH_FREENECT2 "Include Freenect2 support" ON)
|
||||||
option(WITH_K4W2 "Include Kinect for Windows v2 support" ON)
|
option(WITH_K4W2 "Include Kinect for Windows v2 support" ON)
|
||||||
@@ -321,12 +322,19 @@ IF(WITH_QT)
|
|||||||
ENDIF(QT4_FOUND OR Qt5_FOUND)
|
ENDIF(QT4_FOUND OR Qt5_FOUND)
|
||||||
ENDIF(WITH_QT)
|
ENDIF(WITH_QT)
|
||||||
|
|
||||||
IF(WITH_SP_TORCH)
|
IF(WITH_SUPERPOINT_TORCH)
|
||||||
FIND_PACKAGE(Torch QUIET)
|
FIND_PACKAGE(Torch QUIET)
|
||||||
IF(TORCH_FOUND)
|
IF(TORCH_FOUND)
|
||||||
MESSAGE(STATUS "Found Torch: ${TORCH_INCLUDE_DIRS}")
|
MESSAGE(STATUS "Found Torch: ${TORCH_INCLUDE_DIRS}")
|
||||||
ENDIF(TORCH_FOUND)
|
ENDIF(TORCH_FOUND)
|
||||||
ENDIF(WITH_SP_TORCH)
|
ENDIF(WITH_SUPERPOINT_TORCH)
|
||||||
|
|
||||||
|
IF(WITH_PYMATCHER)
|
||||||
|
FIND_PACKAGE(Python3 COMPONENTS Interpreter Development)
|
||||||
|
IF(Python3_FOUND)
|
||||||
|
MESSAGE(STATUS "Found Python3")
|
||||||
|
ENDIF(Python3_FOUND)
|
||||||
|
ENDIF(WITH_PYMATCHER)
|
||||||
|
|
||||||
IF(WITH_FREENECT)
|
IF(WITH_FREENECT)
|
||||||
FIND_PACKAGE(Freenect QUIET)
|
FIND_PACKAGE(Freenect QUIET)
|
||||||
@@ -463,7 +471,7 @@ ENDIF(WITH_REALSENSE)
|
|||||||
IF(WITH_REALSENSE2)
|
IF(WITH_REALSENSE2)
|
||||||
IF(WIN32)
|
IF(WIN32)
|
||||||
FIND_PACKAGE(RealSense2 QUIET)
|
FIND_PACKAGE(RealSense2 QUIET)
|
||||||
ELSE()
|
ELSE()
|
||||||
FIND_PACKAGE(realsense2 QUIET)
|
FIND_PACKAGE(realsense2 QUIET)
|
||||||
ENDIF()
|
ENDIF()
|
||||||
IF(realsense2_FOUND)
|
IF(realsense2_FOUND)
|
||||||
@@ -592,7 +600,7 @@ IF(WITH_ORB_SLAM2 AND NOT G2O_FOUND)
|
|||||||
ENDIF(ORB_SLAM2_FOUND)
|
ENDIF(ORB_SLAM2_FOUND)
|
||||||
ENDIF(WITH_ORB_SLAM2 AND NOT G2O_FOUND)
|
ENDIF(WITH_ORB_SLAM2 AND NOT G2O_FOUND)
|
||||||
|
|
||||||
IF(loam_velodyne_FOUND OR PCL_VERSION VERSION_GREATER "1.9.1")
|
IF(loam_velodyne_FOUND OR PCL_VERSION VERSION_GREATER "1.9.1" OR TORCH_FOUND)
|
||||||
#LOAM and PCL>=1.10 require c++14
|
#LOAM and PCL>=1.10 require c++14
|
||||||
IF(NOT MSVC)
|
IF(NOT MSVC)
|
||||||
include(CheckCXXCompilerFlag)
|
include(CheckCXXCompilerFlag)
|
||||||
@@ -664,6 +672,10 @@ ENDIF(APPLE AND BUILD_AS_BUNDLE)
|
|||||||
SET(CONF_DEPENDENCIES
|
SET(CONF_DEPENDENCIES
|
||||||
${ZLIB_LIBRARIES}
|
${ZLIB_LIBRARIES}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# OpenCV2 has nonfree if OPENCV_NONFREE_FOUND
|
||||||
|
# OpenCV<=3.4.2 has nonfree if OPENCV_XFEATURES2D_FOUND
|
||||||
|
# OpenCV>3.4.2 has nonfree if OPENCV_XFEATURES2D_FOUND and OPENCV_ENABLE_NONFREE is defined
|
||||||
IF(NOT (OPENCV_NONFREE_FOUND OR OPENCV_XFEATURES2D_FOUND))
|
IF(NOT (OPENCV_NONFREE_FOUND OR OPENCV_XFEATURES2D_FOUND))
|
||||||
SET(NONFREE "//")
|
SET(NONFREE "//")
|
||||||
ELSEIF(OpenCV_VERSION VERSION_GREATER "3.4.2")
|
ELSEIF(OpenCV_VERSION VERSION_GREATER "3.4.2")
|
||||||
@@ -826,7 +838,10 @@ IF(NOT WITH_ORB_OCTREE)
|
|||||||
SET(ORB_OCTREE "//")
|
SET(ORB_OCTREE "//")
|
||||||
ENDIF()
|
ENDIF()
|
||||||
IF(NOT TORCH_FOUND)
|
IF(NOT TORCH_FOUND)
|
||||||
SET(SP_TORCH "//")
|
SET(SUPERPOINT_TORCH "//")
|
||||||
|
ENDIF()
|
||||||
|
IF(NOT Python3_FOUND)
|
||||||
|
SET(PYMATCHER "//")
|
||||||
ENDIF()
|
ENDIF()
|
||||||
IF(ADD_VTK_GUI_SUPPORT_QT_TO_CONF)
|
IF(ADD_VTK_GUI_SUPPORT_QT_TO_CONF)
|
||||||
SET(CONF_VTK_QT true)
|
SET(CONF_VTK_QT true)
|
||||||
@@ -841,9 +856,6 @@ IF(NOT WITH_MADGWICK)
|
|||||||
SET(MADGWICK "//")
|
SET(MADGWICK "//")
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
IF(NOT (OpenCV_FOUND AND NOT (OpenCV_VERSION_MAJOR LESS 3)))
|
|
||||||
SET(OPENCV3 "//")
|
|
||||||
ENDIF(NOT (OpenCV_FOUND AND NOT (OpenCV_VERSION_MAJOR LESS 3)))
|
|
||||||
CONFIGURE_FILE(Version.h.in ${PROJECT_SOURCE_DIR}/corelib/include/${PROJECT_PREFIX}/core/Version.h)
|
CONFIGURE_FILE(Version.h.in ${PROJECT_SOURCE_DIR}/corelib/include/${PROJECT_PREFIX}/core/Version.h)
|
||||||
|
|
||||||
ADD_SUBDIRECTORY( utilite )
|
ADD_SUBDIRECTORY( utilite )
|
||||||
@@ -1046,9 +1058,13 @@ IF(OpenCV_FOUND)
|
|||||||
ENDIF()
|
ENDIF()
|
||||||
ELSE()
|
ELSE()
|
||||||
IF(OPENCV_XFEATURES2D_FOUND)
|
IF(OPENCV_XFEATURES2D_FOUND)
|
||||||
MESSAGE(STATUS " *With OpenCV ${OpenCV_VERSION} xfeatures2d module (SIFT/SURF/BRIEF/FREAK) = YES (License: Non commercial)")
|
IF(NONFREE STREQUAL "//")
|
||||||
|
MESSAGE(STATUS " *With OpenCV ${OpenCV_VERSION} xfeatures2d = YES, nonfree = NO (License: BSD)")
|
||||||
|
ELSE()
|
||||||
|
MESSAGE(STATUS " *With OpenCV ${OpenCV_VERSION} xfeatures2d = YES, nonfree = YES (License: Non commercial)")
|
||||||
|
ENDIF()
|
||||||
ELSE()
|
ELSE()
|
||||||
MESSAGE(STATUS " *With OpenCV ${OpenCV_VERSION} xfeatures2d module (SIFT/SURF/BRIEF/FREAK) = NO (not found, License: BSD)")
|
MESSAGE(STATUS " *With OpenCV ${OpenCV_VERSION} xfeatures2d = NO, nonfree = NO (License: BSD)")
|
||||||
ENDIF()
|
ENDIF()
|
||||||
ENDIF()
|
ENDIF()
|
||||||
ENDIF(OpenCV_FOUND)
|
ENDIF(OpenCV_FOUND)
|
||||||
@@ -1057,7 +1073,7 @@ IF(QT4_FOUND)
|
|||||||
MESSAGE(STATUS " With Qt4 = YES (License: Open Source or Commercial)")
|
MESSAGE(STATUS " With Qt4 = YES (License: Open Source or Commercial)")
|
||||||
MESSAGE(STATUS " With VTK ${VTK_MAJOR_VERSION}.${VTK_MINOR_VERSION} = YES (License: BSD)")
|
MESSAGE(STATUS " With VTK ${VTK_MAJOR_VERSION}.${VTK_MINOR_VERSION} = YES (License: BSD)")
|
||||||
ELSEIF(Qt5_FOUND)
|
ELSEIF(Qt5_FOUND)
|
||||||
MESSAGE(STATUS " With Qt5 = YES (License: Open Source or Commercial)")
|
MESSAGE(STATUS " With Qt ${Qt5_VERSION} = YES (License: Open Source or Commercial)")
|
||||||
MESSAGE(STATUS " With VTK ${VTK_MAJOR_VERSION}.${VTK_MINOR_VERSION} = YES (License: BSD)")
|
MESSAGE(STATUS " With VTK ${VTK_MAJOR_VERSION}.${VTK_MINOR_VERSION} = YES (License: BSD)")
|
||||||
|
|
||||||
ELSEIF(NOT WITH_QT)
|
ELSEIF(NOT WITH_QT)
|
||||||
@@ -1079,11 +1095,19 @@ MESSAGE(STATUS " With ORB OcTree = NO (WITH_ORB_OCTREE=OFF)")
|
|||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
IF(TORCH_FOUND)
|
IF(TORCH_FOUND)
|
||||||
MESSAGE(STATUS " With SupertPoint Torch = YES (License: GPLv3) libtorch=${Torch_VERSION}")
|
MESSAGE(STATUS " With SupertPoint = YES (License: GPLv3) libtorch=${Torch_VERSION}")
|
||||||
ELSEIF(NOT WITH_SP_TORCH)
|
ELSEIF(NOT WITH_SUPERPOINT_TORCH)
|
||||||
MESSAGE(STATUS " With SupertPoint Torch = NO (WITH_SP_TORCH=OFF)")
|
MESSAGE(STATUS " With SupertPoint = NO (WITH_SUPERPOINT_TORCH=OFF)")
|
||||||
ELSE()
|
ELSE()
|
||||||
MESSAGE(STATUS " With SupertPoint Torch = NO (libtorch not found)")
|
MESSAGE(STATUS " With SupertPoint = NO (libtorch not found)")
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
IF(Python3_FOUND)
|
||||||
|
MESSAGE(STATUS " With Python3 = YES (License: PSF)")
|
||||||
|
ELSEIF(NOT WITH_PYMATCHER)
|
||||||
|
MESSAGE(STATUS " With Python3 = NO (WITH_PYMATCHER=OFF)")
|
||||||
|
ELSE()
|
||||||
|
MESSAGE(STATUS " With Python3 = NO (python3 not found)")
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
IF(WITH_MADGWICK)
|
IF(WITH_MADGWICK)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
rtabmap 
|
rtabmap 
|
||||||
=======
|
=======
|
||||||
|
|
||||||
[](http://introlab.github.io/rtabmap)
|
[](http://introlab.github.io/rtabmap)
|
||||||
@@ -7,7 +7,7 @@ rtabmap ](https://travis-ci.org/introlab/rtabmap) Windows: [](https://ci.appveyor.com/project/matlabbe/rtabmap/branch/master)
|
Linux: [](https://travis-ci.org/introlab/rtabmap) Windows: [](https://ci.appveyor.com/project/matlabbe/rtabmap/branch/master)
|
||||||
|
|
||||||
[release-image]: https://img.shields.io/badge/release-0.18.0-green.svg?style=flat
|
[release-image]: https://img.shields.io/badge/release-0.20.2-green.svg?style=flat
|
||||||
[releases]: https://github.com/introlab/rtabmap/releases
|
[releases]: https://github.com/introlab/rtabmap/releases
|
||||||
|
|
||||||
[license-image]: https://img.shields.io/badge/license-BSD-green.svg?style=flat
|
[license-image]: https://img.shields.io/badge/license-BSD-green.svg?style=flat
|
||||||
|
|||||||
+2
-2
@@ -44,7 +44,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
@GTSAM@#define RTABMAP_GTSAM
|
@GTSAM@#define RTABMAP_GTSAM
|
||||||
@CERES@#define RTABMAP_CERES
|
@CERES@#define RTABMAP_CERES
|
||||||
@VERTIGO@#define RTABMAP_VERTIGO
|
@VERTIGO@#define RTABMAP_VERTIGO
|
||||||
@OPENCV3@#define RTABMAP_OPENCV3
|
|
||||||
@OPENNI2@#define RTABMAP_OPENNI2
|
@OPENNI2@#define RTABMAP_OPENNI2
|
||||||
@FREENECT@#define RTABMAP_FREENECT
|
@FREENECT@#define RTABMAP_FREENECT
|
||||||
@FREENECT2@#define RTABMAP_FREENECT2
|
@FREENECT2@#define RTABMAP_FREENECT2
|
||||||
@@ -73,7 +72,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
@VINS@#define RTABMAP_VINS
|
@VINS@#define RTABMAP_VINS
|
||||||
@ORB_SLAM2@#define RTABMAP_ORB_SLAM2
|
@ORB_SLAM2@#define RTABMAP_ORB_SLAM2
|
||||||
@ORB_OCTREE@#define RTABMAP_ORB_OCTREE
|
@ORB_OCTREE@#define RTABMAP_ORB_OCTREE
|
||||||
@SP_TORCH@#define RTABMAP_SP_TORCH
|
@SUPERPOINT_TORCH@#define RTABMAP_SUPERPOINT_TORCH
|
||||||
|
@PYMATCHER@#define RTABMAP_PYMATCHER
|
||||||
@MADGWICK@#define RTABMAP_MADGWICK
|
@MADGWICK@#define RTABMAP_MADGWICK
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -57,7 +57,7 @@
|
|||||||
android:excludeFromRecents="true"
|
android:excludeFromRecents="true"
|
||||||
android:exported="false"
|
android:exported="false"
|
||||||
android:launchMode="singleTop"
|
android:launchMode="singleTop"
|
||||||
android:theme="@android:style/Theme.Material.Light.Dialog.Alert" />
|
android:theme="@style/ThemeApp" />
|
||||||
|
|
||||||
<provider
|
<provider
|
||||||
android:name="android.support.v4.content.FileProvider"
|
android:name="android.support.v4.content.FileProvider"
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ set(sources
|
|||||||
scene.cpp
|
scene.cpp
|
||||||
point_cloud_drawable.cpp
|
point_cloud_drawable.cpp
|
||||||
graph_drawable.cpp
|
graph_drawable.cpp
|
||||||
|
background_renderer.cc
|
||||||
tango-gl/axis.cpp
|
tango-gl/axis.cpp
|
||||||
tango-gl/camera.cpp
|
tango-gl/camera.cpp
|
||||||
tango-gl/conversions.cpp
|
tango-gl/conversions.cpp
|
||||||
|
|||||||
+181
-195
@@ -34,47 +34,31 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
namespace rtabmap {
|
namespace rtabmap {
|
||||||
|
|
||||||
#ifdef DEPTH_TEST
|
|
||||||
// Camera Callbacks
|
|
||||||
static void CameraDeviceOnDisconnected(void* context, ACameraDevice* device) {
|
|
||||||
LOGE("Camera(id: %s) is disconnected.\n", ACameraDevice_getId(device));
|
|
||||||
}
|
|
||||||
static void CameraDeviceOnError(void* context, ACameraDevice* device,
|
|
||||||
int error) {
|
|
||||||
LOGE("Error(code: %d) on Camera(id: %s).\n", error,
|
|
||||||
ACameraDevice_getId(device));
|
|
||||||
}
|
|
||||||
// Capture Callbacks
|
|
||||||
bool g_captureSessionReady = false;
|
|
||||||
static void CaptureSessionOnReady(void* context,
|
|
||||||
ACameraCaptureSession* session) {
|
|
||||||
LOGI("Session is ready.\n");
|
|
||||||
g_captureSessionReady = true;
|
|
||||||
}
|
|
||||||
static void CaptureSessionOnActive(void* context,
|
|
||||||
ACameraCaptureSession* session) {
|
|
||||||
LOGI("Session is activated.\n");
|
|
||||||
}
|
|
||||||
#endif // DEPTH_TEST
|
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
// CameraARCore
|
// CameraARCore
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
CameraARCore::CameraARCore(void* env, void* context, void* activity, bool smoothing):
|
CameraARCore::CameraARCore(void* env, void* context, void* activity, bool depthFromMotion, bool smoothing):
|
||||||
CameraMobile(smoothing),
|
CameraMobile(smoothing),
|
||||||
env_(env),
|
env_(env),
|
||||||
context_(context),
|
context_(context),
|
||||||
activity_(activity),
|
activity_(activity),
|
||||||
arInstallRequested_(false)
|
arInstallRequested_(false),
|
||||||
|
textureId_(9999),
|
||||||
|
uvs_initialized_(false),
|
||||||
|
updateOcclusionImage_(false),
|
||||||
|
depthFromMotion_(depthFromMotion)
|
||||||
{
|
{
|
||||||
glGenTextures(1, &textureId_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CameraARCore::~CameraARCore() {
|
CameraARCore::~CameraARCore() {
|
||||||
// Disconnect ARCore service
|
// Disconnect ARCore service
|
||||||
close();
|
close();
|
||||||
|
|
||||||
glDeleteTextures(1, &textureId_);
|
if(textureId_ != 9999)
|
||||||
|
{
|
||||||
|
glDeleteTextures(1, &textureId_);
|
||||||
|
textureId_ = 9999;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -146,132 +130,10 @@ std::string CameraARCore::getSerial() const
|
|||||||
return "ARCore";
|
return "ARCore";
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEPTH_TEST
|
|
||||||
void OnImageCallback(void *ctx, AImageReader *reader) {
|
|
||||||
reinterpret_cast<CameraARCore *>(ctx)->imageCallback(reader);
|
|
||||||
}
|
|
||||||
void CameraARCore::imageCallback(AImageReader *reader) {
|
|
||||||
int32_t format;
|
|
||||||
media_status_t status = AImageReader_getFormat(reader, &format);
|
|
||||||
UWARN("format=%d", format);
|
|
||||||
UASSERT_MSG(status == AMEDIA_OK, "Failed to get the media format");
|
|
||||||
|
|
||||||
if (format == AIMAGE_FORMAT_DEPTH16) {
|
|
||||||
// Create a thread and write out the jpeg files
|
|
||||||
AImage *image = nullptr;
|
|
||||||
media_status_t status = AImageReader_acquireNextImage(reader, &image);
|
|
||||||
UASSERT_MSG(status == AMEDIA_OK && image, "Image is not available");
|
|
||||||
|
|
||||||
int planeCount;
|
|
||||||
status = AImage_getNumberOfPlanes(image, &planeCount);
|
|
||||||
UASSERT_MSG(status == AMEDIA_OK && planeCount == 1,
|
|
||||||
uFormat("Error: getNumberOfPlanes() planceCount = %d", planeCount).c_str());
|
|
||||||
uint8_t *data = nullptr;
|
|
||||||
int len = 0;
|
|
||||||
int stride;
|
|
||||||
int width;
|
|
||||||
int height;
|
|
||||||
AImage_getWidth(image, &width);
|
|
||||||
AImage_getHeight(image, &height);
|
|
||||||
AImage_getPlaneRowStride(image, 0, &stride);
|
|
||||||
AImage_getPlaneData(image, 0, &data, &len);
|
|
||||||
|
|
||||||
cv::Mat output(height, width, CV_16UC1);
|
|
||||||
uint16_t *dataShort = (uint16_t *)data;
|
|
||||||
uint16_t max=0x0;
|
|
||||||
for (int y = 0; y < output.rows; ++y)
|
|
||||||
{
|
|
||||||
for (int x = 0; x < output.cols; ++x)
|
|
||||||
{
|
|
||||||
uint16_t depthSample = dataShort[y*output.cols + x];
|
|
||||||
uint16_t depthRange = (depthSample & 0x1FFF); // first 3 bits are confidence
|
|
||||||
output.at<uint16_t>(y,x) = depthRange;
|
|
||||||
if(depthRange > max)
|
|
||||||
{
|
|
||||||
max = depthRange;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
UWARN("width=%d, height=%d, bytes=%d stride=%d max=%dmm",
|
|
||||||
width, height, len, stride, (int)max);
|
|
||||||
|
|
||||||
std::string path = "/storage/emulated/0/RTAB-Map/depth.png";
|
|
||||||
cv::imwrite(path, output);
|
|
||||||
UWARN("depth image saved to %s", path.c_str());
|
|
||||||
|
|
||||||
AImage_delete(image);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif // DEPTH_TEST
|
|
||||||
|
|
||||||
bool CameraARCore::init(const std::string & calibrationFolder, const std::string & cameraName)
|
bool CameraARCore::init(const std::string & calibrationFolder, const std::string & cameraName)
|
||||||
{
|
{
|
||||||
close();
|
close();
|
||||||
|
|
||||||
#ifdef DEPTH_TEST
|
|
||||||
///////////////////////////
|
|
||||||
// Depth image using camera2 API
|
|
||||||
/////////////////////////////
|
|
||||||
camera_status_t cameraStatus = ACAMERA_OK;
|
|
||||||
|
|
||||||
cameraManager_ = ACameraManager_create();
|
|
||||||
|
|
||||||
deviceStateCallbacks_.onDisconnected = CameraDeviceOnDisconnected;
|
|
||||||
deviceStateCallbacks_.onError = CameraDeviceOnError;
|
|
||||||
|
|
||||||
const char * cameraId = "0";
|
|
||||||
cameraStatus = ACameraManager_openCamera(cameraManager_, cameraId, &deviceStateCallbacks_, &cameraDevice_);
|
|
||||||
UASSERT_MSG(cameraStatus == ACAMERA_OK, uFormat("Failed to open camera device (id: %s)",
|
|
||||||
cameraId).c_str());
|
|
||||||
|
|
||||||
// Currently only working resolution on Huawei P30 Pro
|
|
||||||
cv::Size size(240, 180);
|
|
||||||
int format = AIMAGE_FORMAT_DEPTH16;
|
|
||||||
|
|
||||||
media_status_t mediaStatus = AImageReader_new(size.width, size.height, format, 2, &imageReader_);
|
|
||||||
UASSERT_MSG(imageReader_ && mediaStatus == AMEDIA_OK, uFormat("Failed to create AImageReader %dx%d format=%d",
|
|
||||||
size.width, size.height, format).c_str());
|
|
||||||
|
|
||||||
AImageReader_ImageListener listener{
|
|
||||||
.context = this,
|
|
||||||
.onImageAvailable = OnImageCallback,
|
|
||||||
};
|
|
||||||
AImageReader_setImageListener(imageReader_, &listener);
|
|
||||||
|
|
||||||
//
|
|
||||||
ANativeWindow *nativeWindow;
|
|
||||||
mediaStatus = AImageReader_getWindow(imageReader_, &nativeWindow);
|
|
||||||
UASSERT_MSG(mediaStatus == AMEDIA_OK, "Could not get ANativeWindow");
|
|
||||||
|
|
||||||
outputNativeWindow_ = nativeWindow;
|
|
||||||
ACaptureSessionOutputContainer_create(&captureSessionOutputContainer_);
|
|
||||||
ANativeWindow_acquire(outputNativeWindow_);
|
|
||||||
ACaptureSessionOutput_create(outputNativeWindow_, &sessionOutput_);
|
|
||||||
ACaptureSessionOutputContainer_add(captureSessionOutputContainer_, sessionOutput_);
|
|
||||||
ACameraOutputTarget_create(outputNativeWindow_, &cameraOutputTarget_);
|
|
||||||
|
|
||||||
cameraStatus = ACameraDevice_createCaptureRequest(cameraDevice_, TEMPLATE_RECORD, &captureRequest_);
|
|
||||||
UASSERT_MSG(cameraStatus == ACAMERA_OK,
|
|
||||||
uFormat("Failed to create preview capture request (id: %s, status=%d)",
|
|
||||||
cameraId, cameraStatus).c_str());
|
|
||||||
|
|
||||||
ACaptureRequest_addTarget(captureRequest_, cameraOutputTarget_);
|
|
||||||
|
|
||||||
captureSessionStateCallbacks_.onReady = CaptureSessionOnReady;
|
|
||||||
captureSessionStateCallbacks_.onActive = CaptureSessionOnActive;
|
|
||||||
ACameraDevice_createCaptureSession(
|
|
||||||
cameraDevice_,
|
|
||||||
captureSessionOutputContainer_, // outputs
|
|
||||||
&captureSessionStateCallbacks_, // callbacks
|
|
||||||
&captureSession_);
|
|
||||||
|
|
||||||
ACameraCaptureSession_setRepeatingRequest(captureSession_, nullptr, 1,
|
|
||||||
&captureRequest_, nullptr);
|
|
||||||
|
|
||||||
// Don't start ARCore as we cannot use both at the same time
|
|
||||||
return true;
|
|
||||||
#endif // DEPTH_TEST
|
|
||||||
|
|
||||||
UScopeMutex lock(arSessionMutex_);
|
UScopeMutex lock(arSessionMutex_);
|
||||||
|
|
||||||
ArInstallStatus install_status;
|
ArInstallStatus install_status;
|
||||||
@@ -302,10 +164,19 @@ bool CameraARCore::init(const std::string & calibrationFolder, const std::string
|
|||||||
UASSERT(ArSession_create(env_, context_, &arSession_) == AR_SUCCESS);
|
UASSERT(ArSession_create(env_, context_, &arSession_) == AR_SUCCESS);
|
||||||
UASSERT(arSession_);
|
UASSERT(arSession_);
|
||||||
|
|
||||||
|
int32_t is_depth_supported = 0;
|
||||||
|
ArSession_isDepthModeSupported(arSession_, AR_DEPTH_MODE_AUTOMATIC, &is_depth_supported);
|
||||||
|
|
||||||
ArConfig_create(arSession_, &arConfig_);
|
ArConfig_create(arSession_, &arConfig_);
|
||||||
UASSERT(arConfig_);
|
UASSERT(arConfig_);
|
||||||
|
|
||||||
ArConfig_setFocusMode(arSession_, arConfig_, AR_FOCUS_MODE_FIXED);
|
if (is_depth_supported!=0) {
|
||||||
|
ArConfig_setDepthMode(arSession_, arConfig_, AR_DEPTH_MODE_AUTOMATIC);
|
||||||
|
} else {
|
||||||
|
ArConfig_setDepthMode(arSession_, arConfig_, AR_DEPTH_MODE_DISABLED);
|
||||||
|
}
|
||||||
|
|
||||||
|
ArConfig_setFocusMode(arSession_, arConfig_, AR_FOCUS_MODE_AUTO);
|
||||||
UASSERT(ArSession_configure(arSession_, arConfig_) == AR_SUCCESS);
|
UASSERT(ArSession_configure(arSession_, arConfig_) == AR_SUCCESS);
|
||||||
|
|
||||||
ArFrame_create(arSession_, &arFrame_);
|
ArFrame_create(arSession_, &arFrame_);
|
||||||
@@ -361,9 +232,6 @@ bool CameraARCore::init(const std::string & calibrationFolder, const std::string
|
|||||||
|
|
||||||
deviceTColorCamera_ = opticalRotation;
|
deviceTColorCamera_ = opticalRotation;
|
||||||
|
|
||||||
// Required as ArSession_update does some off-screen OpenGL stuff...
|
|
||||||
ArSession_setCameraTextureName(arSession_, textureId_);
|
|
||||||
|
|
||||||
if (ArSession_resume(arSession_) != ArStatus::AR_SUCCESS)
|
if (ArSession_resume(arSession_) != ArStatus::AR_SUCCESS)
|
||||||
{
|
{
|
||||||
UERROR("Cannot resume camera!");
|
UERROR("Cannot resume camera!");
|
||||||
@@ -410,45 +278,8 @@ void CameraARCore::close()
|
|||||||
}
|
}
|
||||||
arPose_ = nullptr;
|
arPose_ = nullptr;
|
||||||
|
|
||||||
#ifdef DEPTH_TEST
|
|
||||||
|
|
||||||
if(captureSession_!=nullptr)
|
|
||||||
{
|
|
||||||
g_captureSessionReady = false;
|
|
||||||
ACameraCaptureSession_stopRepeating(captureSession_);
|
|
||||||
double start = UTimer::now();
|
|
||||||
while(g_captureSessionReady != true && UTimer::now()-start < 2.0){
|
|
||||||
uSleep(100);
|
|
||||||
UWARN("Waiting session to close.... max 2 seconds");
|
|
||||||
}
|
|
||||||
//ACameraCaptureSession_close(captureSession_); // FIXME: this crashes?!
|
|
||||||
captureSession_ = nullptr;
|
|
||||||
|
|
||||||
ACaptureRequest_removeTarget(captureRequest_, cameraOutputTarget_);
|
|
||||||
ACaptureRequest_free(captureRequest_);
|
|
||||||
ACameraOutputTarget_free(cameraOutputTarget_);
|
|
||||||
captureRequest_ = nullptr;
|
|
||||||
cameraOutputTarget_ = nullptr;
|
|
||||||
|
|
||||||
ACaptureSessionOutputContainer_remove(captureSessionOutputContainer_, sessionOutput_);
|
|
||||||
ANativeWindow_release(outputNativeWindow_);
|
|
||||||
ACaptureSessionOutputContainer_free(captureSessionOutputContainer_);
|
|
||||||
ACaptureSessionOutput_free(sessionOutput_);
|
|
||||||
captureSessionOutputContainer_ = nullptr;
|
|
||||||
sessionOutput_ = nullptr;
|
|
||||||
|
|
||||||
ACameraDevice_close(cameraDevice_);
|
|
||||||
cameraDevice_ = nullptr;
|
|
||||||
|
|
||||||
ACameraManager_delete(cameraManager_);
|
|
||||||
cameraManager_ = nullptr;
|
|
||||||
|
|
||||||
AImageReader_delete(imageReader_);
|
|
||||||
imageReader_ = nullptr;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
CameraMobile::close();
|
CameraMobile::close();
|
||||||
|
occlusionImage_ = cv::Mat();
|
||||||
}
|
}
|
||||||
|
|
||||||
LaserScan CameraARCore::scanFromPointCloudData(
|
LaserScan CameraARCore::scanFromPointCloudData(
|
||||||
@@ -499,6 +330,20 @@ LaserScan CameraARCore::scanFromPointCloudData(
|
|||||||
return LaserScan();
|
return LaserScan();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CameraARCore::setScreenRotationAndSize(ScreenRotation colorCameraToDisplayRotation, int width, int height)
|
||||||
|
{
|
||||||
|
CameraMobile::setScreenRotationAndSize(colorCameraToDisplayRotation, width, height);
|
||||||
|
if(arSession_)
|
||||||
|
{
|
||||||
|
int ret = static_cast<int>(colorCameraToDisplayRotation) + 1; // remove 90deg camera rotation
|
||||||
|
if (ret > 3) {
|
||||||
|
ret -= 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
ArSession_setDisplayGeometry(arSession_, ret, width, height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SensorData CameraARCore::captureImage(CameraInfo * info)
|
SensorData CameraARCore::captureImage(CameraInfo * info)
|
||||||
{
|
{
|
||||||
UScopeMutex lock(arSessionMutex_);
|
UScopeMutex lock(arSessionMutex_);
|
||||||
@@ -510,15 +355,44 @@ SensorData CameraARCore::captureImage(CameraInfo * info)
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(textureId_ == 9999)
|
||||||
|
{
|
||||||
|
glGenTextures(1, &textureId_);
|
||||||
|
glBindTexture(GL_TEXTURE_EXTERNAL_OES, textureId_);
|
||||||
|
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
}
|
||||||
|
ArSession_setCameraTextureName(arSession_, textureId_);
|
||||||
|
|
||||||
// Update session to get current frame and render camera background.
|
// Update session to get current frame and render camera background.
|
||||||
if (ArSession_update(arSession_, arFrame_) != AR_SUCCESS) {
|
if (ArSession_update(arSession_, arFrame_) != AR_SUCCESS) {
|
||||||
LOGE("CameraARCore::captureImage() ArSession_update error");
|
LOGE("CameraARCore::captureImage() ArSession_update error");
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If display rotation changed (also includes view size change), we need to
|
||||||
|
// re-query the uv coordinates for the on-screen portion of the camera image.
|
||||||
|
int32_t geometry_changed = 0;
|
||||||
|
ArFrame_getDisplayGeometryChanged(arSession_, arFrame_, &geometry_changed);
|
||||||
|
if (geometry_changed != 0 || !uvs_initialized_) {
|
||||||
|
ArFrame_transformCoordinates2d(
|
||||||
|
arSession_, arFrame_, AR_COORDINATES_2D_OPENGL_NORMALIZED_DEVICE_COORDINATES,
|
||||||
|
BackgroundRenderer::kNumVertices, BackgroundRenderer_kVertices, AR_COORDINATES_2D_TEXTURE_NORMALIZED,
|
||||||
|
transformed_uvs_);
|
||||||
|
UASSERT(transformed_uvs_);
|
||||||
|
uvs_initialized_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
ArCamera* ar_camera;
|
ArCamera* ar_camera;
|
||||||
ArFrame_acquireCamera(arSession_, arFrame_, &ar_camera);
|
ArFrame_acquireCamera(arSession_, arFrame_, &ar_camera);
|
||||||
|
|
||||||
|
ArCamera_getViewMatrix(arSession_, ar_camera, glm::value_ptr(viewMatrix_));
|
||||||
|
ArCamera_getProjectionMatrix(arSession_, ar_camera,
|
||||||
|
/*near=*/0.1f, /*far=*/100.f,
|
||||||
|
glm::value_ptr(projectionMatrix_));
|
||||||
|
|
||||||
ArTrackingState camera_tracking_state;
|
ArTrackingState camera_tracking_state;
|
||||||
ArCamera_getTrackingState(arSession_, ar_camera, &camera_tracking_state);
|
ArCamera_getTrackingState(arSession_, ar_camera, &camera_tracking_state);
|
||||||
|
|
||||||
@@ -551,17 +425,55 @@ SensorData CameraARCore::captureImage(CameraInfo * info)
|
|||||||
ArPointCloud * pointCloud = nullptr;
|
ArPointCloud * pointCloud = nullptr;
|
||||||
ArFrame_acquirePointCloud(arSession_, arFrame_, &pointCloud);
|
ArFrame_acquirePointCloud(arSession_, arFrame_, &pointCloud);
|
||||||
|
|
||||||
|
int32_t is_depth_supported = 0;
|
||||||
|
ArSession_isDepthModeSupported(arSession_, AR_DEPTH_MODE_AUTOMATIC, &is_depth_supported);
|
||||||
|
|
||||||
ArImage * image = nullptr;
|
ArImage * image = nullptr;
|
||||||
ArStatus status = ArFrame_acquireCameraImage(arSession_, arFrame_, &image);
|
ArStatus status = ArFrame_acquireCameraImage(arSession_, arFrame_, &image);
|
||||||
if(status == AR_SUCCESS)
|
if(status == AR_SUCCESS)
|
||||||
{
|
{
|
||||||
|
if(is_depth_supported && (updateOcclusionImage_||depthFromMotion_))
|
||||||
|
{
|
||||||
|
LOGD("Acquire depth image!");
|
||||||
|
ArImage * depthImage = nullptr;
|
||||||
|
ArFrame_acquireDepthImage(arSession_, arFrame_, &depthImage);
|
||||||
|
|
||||||
|
ArImageFormat format;
|
||||||
|
ArImage_getFormat(arSession_, depthImage, &format);
|
||||||
|
if(format == AR_IMAGE_FORMAT_DEPTH16)
|
||||||
|
{
|
||||||
|
LOGD("Depth format detected!");
|
||||||
|
int planeCount;
|
||||||
|
ArImage_getNumberOfPlanes(arSession_, depthImage, &planeCount);
|
||||||
|
LOGD("planeCount=%d", planeCount);
|
||||||
|
UASSERT_MSG(planeCount == 1, uFormat("Error: getNumberOfPlanes() planceCount = %d", planeCount).c_str());
|
||||||
|
const uint8_t *data = nullptr;
|
||||||
|
int len = 0;
|
||||||
|
int stride;
|
||||||
|
int depth_width;
|
||||||
|
int depth_height;
|
||||||
|
ArImage_getWidth(arSession_, depthImage, &depth_width);
|
||||||
|
ArImage_getHeight(arSession_, depthImage, &depth_height);
|
||||||
|
ArImage_getPlaneRowStride(arSession_, depthImage, 0, &stride);
|
||||||
|
ArImage_getPlaneData(arSession_, depthImage, 0, &data, &len);
|
||||||
|
|
||||||
|
LOGD("width=%d, height=%d, bytes=%d stride=%d", depth_width, depth_height, len, stride);
|
||||||
|
|
||||||
|
occlusionImage_ = cv::Mat(depth_height, depth_width, CV_16UC1, (void*)data).clone();
|
||||||
|
|
||||||
|
float scaleX = (float)depth_width / (float)width;
|
||||||
|
float scaleY = (float)depth_height / (float)height;
|
||||||
|
occlusionModel_ = CameraModel(fx*scaleX, fy*scaleY, cx*scaleX, cy*scaleY, pose*deviceTColorCamera_, 0, cv::Size(depth_width, depth_height));
|
||||||
|
}
|
||||||
|
ArImage_release(depthImage);
|
||||||
|
}
|
||||||
|
|
||||||
int64_t timestamp_ns;
|
int64_t timestamp_ns;
|
||||||
ArImageFormat format;
|
ArImageFormat format;
|
||||||
ArImage_getTimestamp(arSession_, image, ×tamp_ns);
|
ArImage_getTimestamp(arSession_, image, ×tamp_ns);
|
||||||
ArImage_getFormat(arSession_, image, &format);
|
ArImage_getFormat(arSession_, image, &format);
|
||||||
if(format == AR_IMAGE_FORMAT_YUV_420_888)
|
if(format == AR_IMAGE_FORMAT_YUV_420_888)
|
||||||
{
|
{
|
||||||
|
|
||||||
#ifndef DISABLE_LOG
|
#ifndef DISABLE_LOG
|
||||||
int32_t num_planes;
|
int32_t num_planes;
|
||||||
ArImage_getNumberOfPlanes(arSession_, image, &num_planes);
|
ArImage_getNumberOfPlanes(arSession_, image, &num_planes);
|
||||||
@@ -623,7 +535,7 @@ SensorData CameraARCore::captureImage(CameraInfo * info)
|
|||||||
LOGI("pointCloud empty");
|
LOGI("pointCloud empty");
|
||||||
}
|
}
|
||||||
|
|
||||||
data = SensorData(scan, rgb, cv::Mat(), model, 0, stamp);
|
data = SensorData(scan, rgb, depthFromMotion_?occlusionImage_:cv::Mat(), model, 0, stamp);
|
||||||
data.setFeatures(kpts, kpts3, cv::Mat());
|
data.setFeatures(kpts, kpts3, cv::Mat());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -662,21 +574,49 @@ void CameraARCore::capturePoseOnly()
|
|||||||
UScopeMutex lock(arSessionMutex_);
|
UScopeMutex lock(arSessionMutex_);
|
||||||
//LOGI("Capturing image...");
|
//LOGI("Capturing image...");
|
||||||
|
|
||||||
SensorData data;
|
|
||||||
if(!arSession_)
|
if(!arSession_)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(textureId_ == 9999)
|
||||||
|
{
|
||||||
|
glGenTextures(1, &textureId_);
|
||||||
|
glBindTexture(GL_TEXTURE_EXTERNAL_OES, textureId_);
|
||||||
|
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
}
|
||||||
|
ArSession_setCameraTextureName(arSession_, textureId_);
|
||||||
|
|
||||||
// Update session to get current frame and render camera background.
|
// Update session to get current frame and render camera background.
|
||||||
if (ArSession_update(arSession_, arFrame_) != AR_SUCCESS) {
|
if (ArSession_update(arSession_, arFrame_) != AR_SUCCESS) {
|
||||||
LOGE("CameraARCore::captureImage() ArSession_update error");
|
LOGE("CameraARCore::capturePoseOnly() ArSession_update error");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If display rotation changed (also includes view size change), we need to
|
||||||
|
// re-query the uv coordinates for the on-screen portion of the camera image.
|
||||||
|
int32_t geometry_changed = 0;
|
||||||
|
ArFrame_getDisplayGeometryChanged(arSession_, arFrame_, &geometry_changed);
|
||||||
|
if (geometry_changed != 0 || !uvs_initialized_) {
|
||||||
|
ArFrame_transformCoordinates2d(
|
||||||
|
arSession_, arFrame_, AR_COORDINATES_2D_OPENGL_NORMALIZED_DEVICE_COORDINATES,
|
||||||
|
BackgroundRenderer::kNumVertices, BackgroundRenderer_kVertices, AR_COORDINATES_2D_TEXTURE_NORMALIZED,
|
||||||
|
transformed_uvs_);
|
||||||
|
UASSERT(transformed_uvs_);
|
||||||
|
uvs_initialized_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
ArCamera* ar_camera;
|
ArCamera* ar_camera;
|
||||||
ArFrame_acquireCamera(arSession_, arFrame_, &ar_camera);
|
ArFrame_acquireCamera(arSession_, arFrame_, &ar_camera);
|
||||||
|
|
||||||
|
ArCamera_getViewMatrix(arSession_, ar_camera, glm::value_ptr(viewMatrix_));
|
||||||
|
ArCamera_getProjectionMatrix(arSession_, ar_camera,
|
||||||
|
/*near=*/0.1f, /*far=*/100.f,
|
||||||
|
glm::value_ptr(projectionMatrix_));
|
||||||
|
|
||||||
ArTrackingState camera_tracking_state;
|
ArTrackingState camera_tracking_state;
|
||||||
ArCamera_getTrackingState(arSession_, ar_camera, &camera_tracking_state);
|
ArCamera_getTrackingState(arSession_, ar_camera, &camera_tracking_state);
|
||||||
|
|
||||||
@@ -694,6 +634,52 @@ void CameraARCore::capturePoseOnly()
|
|||||||
pose = rtabmap::rtabmap_world_T_opengl_world * pose * rtabmap::opengl_world_T_rtabmap_world;
|
pose = rtabmap::rtabmap_world_T_opengl_world * pose * rtabmap::opengl_world_T_rtabmap_world;
|
||||||
this->poseReceived(pose);
|
this->poseReceived(pose);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32_t is_depth_supported = 0;
|
||||||
|
ArSession_isDepthModeSupported(arSession_, AR_DEPTH_MODE_AUTOMATIC, &is_depth_supported);
|
||||||
|
|
||||||
|
if(is_depth_supported && updateOcclusionImage_)
|
||||||
|
{
|
||||||
|
LOGD("Acquire depth image!");
|
||||||
|
ArImage * depthImage = nullptr;
|
||||||
|
ArFrame_acquireDepthImage(arSession_, arFrame_, &depthImage);
|
||||||
|
|
||||||
|
ArImageFormat format;
|
||||||
|
ArImage_getFormat(arSession_, depthImage, &format);
|
||||||
|
if(format == AR_IMAGE_FORMAT_DEPTH16)
|
||||||
|
{
|
||||||
|
LOGD("Depth format detected!");
|
||||||
|
int planeCount;
|
||||||
|
ArImage_getNumberOfPlanes(arSession_, depthImage, &planeCount);
|
||||||
|
LOGD("planeCount=%d", planeCount);
|
||||||
|
UASSERT_MSG(planeCount == 1, uFormat("Error: getNumberOfPlanes() planceCount = %d", planeCount).c_str());
|
||||||
|
const uint8_t *data = nullptr;
|
||||||
|
int len = 0;
|
||||||
|
int stride;
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
ArImage_getWidth(arSession_, depthImage, &width);
|
||||||
|
ArImage_getHeight(arSession_, depthImage, &height);
|
||||||
|
ArImage_getPlaneRowStride(arSession_, depthImage, 0, &stride);
|
||||||
|
ArImage_getPlaneData(arSession_, depthImage, 0, &data, &len);
|
||||||
|
|
||||||
|
LOGD("width=%d, height=%d, bytes=%d stride=%d", width, height, len, stride);
|
||||||
|
|
||||||
|
occlusionImage_ = cv::Mat(height, width, CV_16UC1, (void*)data).clone();
|
||||||
|
|
||||||
|
float fx,fy, cx, cy;
|
||||||
|
int32_t rgb_width, rgb_height;
|
||||||
|
ArCamera_getImageIntrinsics(arSession_, ar_camera, arCameraIntrinsics_);
|
||||||
|
ArCameraIntrinsics_getFocalLength(arSession_, arCameraIntrinsics_, &fx, &fy);
|
||||||
|
ArCameraIntrinsics_getPrincipalPoint(arSession_, arCameraIntrinsics_, &cx, &cy);
|
||||||
|
ArCameraIntrinsics_getImageDimensions(arSession_, arCameraIntrinsics_, &rgb_width, &rgb_height);
|
||||||
|
|
||||||
|
float scaleX = (float)width / (float)rgb_width;
|
||||||
|
float scaleY = (float)height / (float)rgb_height;
|
||||||
|
occlusionModel_ = CameraModel(fx*scaleX, fy*scaleY, cx*scaleX, cy*scaleY, pose*deviceTColorCamera_, 0, cv::Size(width, height));
|
||||||
|
}
|
||||||
|
ArImage_release(depthImage);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ArCamera_release(ar_camera);
|
ArCamera_release(ar_camera);
|
||||||
|
|||||||
@@ -38,14 +38,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <rtabmap/utilite/UEvent.h>
|
#include <rtabmap/utilite/UEvent.h>
|
||||||
#include <rtabmap/utilite/UTimer.h>
|
#include <rtabmap/utilite/UTimer.h>
|
||||||
#include <boost/thread/mutex.hpp>
|
#include <boost/thread/mutex.hpp>
|
||||||
|
#include <background_renderer.h>
|
||||||
|
|
||||||
#include <arcore_c_api.h>
|
#include <arcore_c_api.h>
|
||||||
#ifdef DEPTH_TEST
|
|
||||||
#include <camera/NdkCameraDevice.h>
|
#include <camera/NdkCameraDevice.h>
|
||||||
#include <camera/NdkCameraManager.h>
|
#include <camera/NdkCameraManager.h>
|
||||||
#include <media/NdkImageReader.h>
|
#include <media/NdkImageReader.h>
|
||||||
#include <android/native_window.h>
|
#include <android/native_window.h>
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace rtabmap {
|
namespace rtabmap {
|
||||||
|
|
||||||
@@ -61,19 +60,28 @@ public:
|
|||||||
std::vector<cv::Point3f> * kpts3D = 0);
|
std::vector<cv::Point3f> * kpts3D = 0);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CameraARCore(void* env, void* context, void* activity, bool smoothing = false);
|
CameraARCore(void* env, void* context, void* activity, bool depthFromMotion = false, bool smoothing = false);
|
||||||
virtual ~CameraARCore();
|
virtual ~CameraARCore();
|
||||||
|
|
||||||
|
bool uvsInitialized() const {return uvs_initialized_;}
|
||||||
|
const float* uvsTransformed() const {return transformed_uvs_;}
|
||||||
|
void getVPMatrices(glm::mat4 & view, glm::mat4 & projection) const {view=viewMatrix_; projection=projectionMatrix_;}
|
||||||
|
|
||||||
|
void updateOcclusionImage(bool enabled) {updateOcclusionImage_ = enabled;}
|
||||||
|
const cv::Mat & getOcclusionImage(CameraModel * model=0) const {if(model)*model=occlusionModel_; return occlusionImage_; }
|
||||||
|
|
||||||
|
virtual void setScreenRotationAndSize(ScreenRotation colorCameraToDisplayRotation, int width, int height);
|
||||||
|
|
||||||
virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = "");
|
virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = "");
|
||||||
|
void setupGL();
|
||||||
virtual void close(); // close Tango connection
|
virtual void close(); // close Tango connection
|
||||||
virtual std::string getSerial() const;
|
virtual std::string getSerial() const;
|
||||||
|
GLuint getTextureId() const {return textureId_;}
|
||||||
|
|
||||||
#ifdef DEPTH_TEST
|
|
||||||
void imageCallback(AImageReader *reader);
|
void imageCallback(AImageReader *reader);
|
||||||
#endif // DEPTH_TEST
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual SensorData captureImage(CameraInfo * info = 0);
|
virtual SensorData captureImage(CameraInfo * info = 0); // should be called in opengl thread
|
||||||
virtual void capturePoseOnly();
|
virtual void capturePoseOnly();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -92,22 +100,15 @@ private:
|
|||||||
GLuint textureId_;
|
GLuint textureId_;
|
||||||
UMutex arSessionMutex_;
|
UMutex arSessionMutex_;
|
||||||
|
|
||||||
#ifdef DEPTH_TEST
|
float transformed_uvs_[BackgroundRenderer::kNumVertices*2];
|
||||||
// Camera variables
|
bool uvs_initialized_ = false;
|
||||||
ACameraDevice* cameraDevice_ = nullptr;
|
glm::mat4 viewMatrix_;
|
||||||
ACaptureRequest* captureRequest_ = nullptr;
|
glm::mat4 projectionMatrix_;
|
||||||
ACameraOutputTarget* cameraOutputTarget_ = nullptr;
|
|
||||||
ACaptureSessionOutput* sessionOutput_ = nullptr;
|
|
||||||
ACaptureSessionOutputContainer* captureSessionOutputContainer_ = nullptr;
|
|
||||||
ACameraCaptureSession* captureSession_ = nullptr;
|
|
||||||
ANativeWindow *outputNativeWindow_ = nullptr;
|
|
||||||
|
|
||||||
ACameraDevice_StateCallbacks deviceStateCallbacks_;
|
bool updateOcclusionImage_;
|
||||||
ACameraCaptureSession_stateCallbacks captureSessionStateCallbacks_;
|
cv::Mat occlusionImage_;
|
||||||
|
CameraModel occlusionModel_;
|
||||||
ACameraManager* cameraManager_ = nullptr;
|
bool depthFromMotion_;
|
||||||
AImageReader* imageReader_ = nullptr;
|
|
||||||
#endif // DEPTH_TEST
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} /* namespace rtabmap */
|
} /* namespace rtabmap */
|
||||||
|
|||||||
@@ -207,6 +207,7 @@ void CameraMobile::mainLoop()
|
|||||||
// Rotate image depending on the camera orientation
|
// Rotate image depending on the camera orientation
|
||||||
if(colorCameraToDisplayRotation_ == ROTATION_90)
|
if(colorCameraToDisplayRotation_ == ROTATION_90)
|
||||||
{
|
{
|
||||||
|
UDEBUG("ROTATION_90");
|
||||||
cv::Mat rgb, depth;
|
cv::Mat rgb, depth;
|
||||||
cv::Mat rgbt(data.imageRaw().cols, data.imageRaw().rows, data.imageRaw().type());
|
cv::Mat rgbt(data.imageRaw().cols, data.imageRaw().rows, data.imageRaw().type());
|
||||||
cv::flip(data.imageRaw(),rgb,1);
|
cv::flip(data.imageRaw(),rgb,1);
|
||||||
@@ -226,9 +227,18 @@ void CameraMobile::mainLoop()
|
|||||||
model.localTransform()*rtabmap::Transform(0,-1,0,0, 1,0,0,0, 0,0,1,0));
|
model.localTransform()*rtabmap::Transform(0,-1,0,0, 1,0,0,0, 0,0,1,0));
|
||||||
model.setImageSize(sizet);
|
model.setImageSize(sizet);
|
||||||
data.setRGBDImage(rgb, depth, model);
|
data.setRGBDImage(rgb, depth, model);
|
||||||
|
|
||||||
|
std::vector<cv::KeyPoint> keypoints = data.keypoints();
|
||||||
|
for(size_t i=0; i<keypoints.size(); ++i)
|
||||||
|
{
|
||||||
|
keypoints[i].pt.x = data.keypoints()[i].pt.y;
|
||||||
|
keypoints[i].pt.y = rgb.rows - data.keypoints()[i].pt.x;
|
||||||
|
}
|
||||||
|
data.setFeatures(keypoints, data.keypoints3D(), cv::Mat());
|
||||||
}
|
}
|
||||||
else if(colorCameraToDisplayRotation_ == ROTATION_180)
|
else if(colorCameraToDisplayRotation_ == ROTATION_180)
|
||||||
{
|
{
|
||||||
|
UDEBUG("ROTATION_180");
|
||||||
cv::Mat rgb, depth;
|
cv::Mat rgb, depth;
|
||||||
cv::flip(data.imageRaw(),rgb,1);
|
cv::flip(data.imageRaw(),rgb,1);
|
||||||
cv::flip(rgb,rgb,0);
|
cv::flip(rgb,rgb,0);
|
||||||
@@ -244,9 +254,18 @@ void CameraMobile::mainLoop()
|
|||||||
model.localTransform()*rtabmap::Transform(0,0,0,0,0,1,0));
|
model.localTransform()*rtabmap::Transform(0,0,0,0,0,1,0));
|
||||||
model.setImageSize(sizet);
|
model.setImageSize(sizet);
|
||||||
data.setRGBDImage(rgb, depth, model);
|
data.setRGBDImage(rgb, depth, model);
|
||||||
|
|
||||||
|
std::vector<cv::KeyPoint> keypoints = data.keypoints();
|
||||||
|
for(size_t i=0; i<keypoints.size(); ++i)
|
||||||
|
{
|
||||||
|
keypoints[i].pt.x = rgb.cols - data.keypoints()[i].pt.x;
|
||||||
|
keypoints[i].pt.y = rgb.rows - data.keypoints()[i].pt.y;
|
||||||
|
}
|
||||||
|
data.setFeatures(keypoints, data.keypoints3D(), cv::Mat());
|
||||||
}
|
}
|
||||||
else if(colorCameraToDisplayRotation_ == ROTATION_270)
|
else if(colorCameraToDisplayRotation_ == ROTATION_270)
|
||||||
{
|
{
|
||||||
|
UDEBUG("ROTATION_270");
|
||||||
cv::Mat rgb(data.imageRaw().cols, data.imageRaw().rows, data.imageRaw().type());
|
cv::Mat rgb(data.imageRaw().cols, data.imageRaw().rows, data.imageRaw().type());
|
||||||
cv::transpose(data.imageRaw(),rgb);
|
cv::transpose(data.imageRaw(),rgb);
|
||||||
cv::flip(rgb,rgb,1);
|
cv::flip(rgb,rgb,1);
|
||||||
@@ -263,6 +282,14 @@ void CameraMobile::mainLoop()
|
|||||||
model.localTransform()*rtabmap::Transform(0,1,0,0, -1,0,0,0, 0,0,1,0));
|
model.localTransform()*rtabmap::Transform(0,1,0,0, -1,0,0,0, 0,0,1,0));
|
||||||
model.setImageSize(sizet);
|
model.setImageSize(sizet);
|
||||||
data.setRGBDImage(rgb, depth, model);
|
data.setRGBDImage(rgb, depth, model);
|
||||||
|
|
||||||
|
std::vector<cv::KeyPoint> keypoints = data.keypoints();
|
||||||
|
for(size_t i=0; i<keypoints.size(); ++i)
|
||||||
|
{
|
||||||
|
keypoints[i].pt.x = rgb.cols - data.keypoints()[i].pt.y;
|
||||||
|
keypoints[i].pt.y = data.keypoints()[i].pt.x;
|
||||||
|
}
|
||||||
|
data.setFeatures(keypoints, data.keypoints3D(), cv::Mat());
|
||||||
}
|
}
|
||||||
|
|
||||||
rtabmap::Transform pose = info.odomPose;
|
rtabmap::Transform pose = info.odomPose;
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ public:
|
|||||||
const CameraModel & getCameraModel() const {return model_;}
|
const CameraModel & getCameraModel() const {return model_;}
|
||||||
const Transform & getDeviceTColorCamera() const {return deviceTColorCamera_;}
|
const Transform & getDeviceTColorCamera() const {return deviceTColorCamera_;}
|
||||||
void setSmoothing(bool enabled) {smoothing_ = enabled;}
|
void setSmoothing(bool enabled) {smoothing_ = enabled;}
|
||||||
void setScreenRotation(ScreenRotation colorCameraToDisplayRotation) {colorCameraToDisplayRotation_ = colorCameraToDisplayRotation;}
|
virtual void setScreenRotationAndSize(ScreenRotation colorCameraToDisplayRotation, int width, int height) {colorCameraToDisplayRotation_ = colorCameraToDisplayRotation;}
|
||||||
void setGPS(const GPS & gps);
|
void setGPS(const GPS & gps);
|
||||||
void addEnvSensor(int type, float value);
|
void addEnvSensor(int type, float value);
|
||||||
void setData(const SensorData & data, const Transform & pose);
|
void setData(const SensorData & data, const Transform & pose);
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <pcl/surface/poisson.h>
|
#include <pcl/surface/poisson.h>
|
||||||
#include <pcl/surface/vtk_smoothing/vtk_mesh_quadric_decimation.h>
|
#include <pcl/surface/vtk_smoothing/vtk_mesh_quadric_decimation.h>
|
||||||
|
|
||||||
|
|
||||||
#define LOW_RES_PIX 2
|
#define LOW_RES_PIX 2
|
||||||
//#define DEBUG_RENDERING_PERFORMANCE
|
//#define DEBUG_RENDERING_PERFORMANCE
|
||||||
|
|
||||||
@@ -263,7 +264,7 @@ void RTABMapApp::setScreenRotation(int displayRotation, int cameraRotation)
|
|||||||
boost::mutex::scoped_lock lock(cameraMutex_);
|
boost::mutex::scoped_lock lock(cameraMutex_);
|
||||||
if(camera_)
|
if(camera_)
|
||||||
{
|
{
|
||||||
camera_->setScreenRotation(rotation);
|
camera_->setScreenRotationAndSize(main_scene_.getScreenRotation(), main_scene_.getViewPortWidth(), main_scene_.getViewPortHeight());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -398,11 +399,15 @@ int RTABMapApp::openDatabase(const std::string & databasePath, bool databaseInMe
|
|||||||
std::multimap<int, rtabmap::Link> links;
|
std::multimap<int, rtabmap::Link> links;
|
||||||
LOGI("Loading full map from database...");
|
LOGI("Loading full map from database...");
|
||||||
UEventsManager::post(new rtabmap::RtabmapEventInit(rtabmap::RtabmapEventInit::kInfo, "Loading data from database..."));
|
UEventsManager::post(new rtabmap::RtabmapEventInit(rtabmap::RtabmapEventInit::kInfo, "Loading data from database..."));
|
||||||
rtabmap_->get3DMap(
|
rtabmap_->getGraph(
|
||||||
signatures,
|
|
||||||
poses,
|
poses,
|
||||||
links,
|
links,
|
||||||
true,
|
true,
|
||||||
|
true,
|
||||||
|
&signatures,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
true);
|
true);
|
||||||
|
|
||||||
if(signatures.size() && poses.empty())
|
if(signatures.size() && poses.empty())
|
||||||
@@ -653,6 +658,10 @@ bool RTABMapApp::isBuiltWith(int cameraDriver) const
|
|||||||
|
|
||||||
bool RTABMapApp::startCamera(JNIEnv* env, jobject iBinder, jobject context, jobject activity, int driver)
|
bool RTABMapApp::startCamera(JNIEnv* env, jobject iBinder, jobject context, jobject activity, int driver)
|
||||||
{
|
{
|
||||||
|
//ccapp = new computer_vision::ComputerVisionApplication();
|
||||||
|
//ccapp->OnResume(env, context, activity);
|
||||||
|
//return true;
|
||||||
|
|
||||||
cameraDriver_ = driver;
|
cameraDriver_ = driver;
|
||||||
LOGW("startCamera() camera driver=%d", cameraDriver_);
|
LOGW("startCamera() camera driver=%d", cameraDriver_);
|
||||||
boost::mutex::scoped_lock lock(cameraMutex_);
|
boost::mutex::scoped_lock lock(cameraMutex_);
|
||||||
@@ -681,8 +690,7 @@ bool RTABMapApp::startCamera(JNIEnv* env, jobject iBinder, jobject context, jobj
|
|||||||
else if(cameraDriver_ == 1)
|
else if(cameraDriver_ == 1)
|
||||||
{
|
{
|
||||||
#ifdef RTABMAP_ARCORE
|
#ifdef RTABMAP_ARCORE
|
||||||
camera_ = new rtabmap::CameraARCore(env, context, activity, smoothing_);
|
camera_ = new rtabmap::CameraARCore(env, context, activity, depthFromMotion_, smoothing_);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
UERROR("RTAB-Map is not built with ARCore support!");
|
UERROR("RTAB-Map is not built with ARCore support!");
|
||||||
#endif
|
#endif
|
||||||
@@ -708,7 +716,7 @@ bool RTABMapApp::startCamera(JNIEnv* env, jobject iBinder, jobject context, jobj
|
|||||||
|
|
||||||
if(camera_->init())
|
if(camera_->init())
|
||||||
{
|
{
|
||||||
camera_->setScreenRotation(main_scene_.getScreenRotation());
|
camera_->setScreenRotationAndSize(main_scene_.getScreenRotation(), main_scene_.getViewPortWidth(), main_scene_.getViewPortHeight());
|
||||||
|
|
||||||
//update mesh decimation based on camera calibration
|
//update mesh decimation based on camera calibration
|
||||||
LOGI("Cloud density level %d", cloudDensityLevel_);
|
LOGI("Cloud density level %d", cloudDensityLevel_);
|
||||||
@@ -933,6 +941,11 @@ void RTABMapApp::SetViewPort(int width, int height)
|
|||||||
{
|
{
|
||||||
UINFO("");
|
UINFO("");
|
||||||
main_scene_.SetupViewPort(width, height);
|
main_scene_.SetupViewPort(width, height);
|
||||||
|
boost::mutex::scoped_lock lock(cameraMutex_);
|
||||||
|
if(camera_)
|
||||||
|
{
|
||||||
|
camera_->setScreenRotationAndSize(main_scene_.getScreenRotation(), main_scene_.getViewPortWidth(), main_scene_.getViewPortHeight());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class PostRenderEvent : public UEvent
|
class PostRenderEvent : public UEvent
|
||||||
@@ -1097,12 +1110,59 @@ int RTABMapApp::Render()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ARCore and AREngine capture should be done in opengl thread!
|
// ARCore and AREngine capture should be done in opengl thread!
|
||||||
|
const float* uvsTransformed = 0;
|
||||||
|
glm::mat4 arProjectionMatrix(0);
|
||||||
|
glm::mat4 arViewMatrix(0);
|
||||||
|
rtabmap::Mesh occlusionMesh;
|
||||||
if((cameraDriver_ == 1 || cameraDriver_ == 2) && camera_!=0)
|
if((cameraDriver_ == 1 || cameraDriver_ == 2) && camera_!=0)
|
||||||
{
|
{
|
||||||
boost::mutex::scoped_lock lock(cameraMutex_);
|
boost::mutex::scoped_lock lock(cameraMutex_);
|
||||||
if(camera_!=0)
|
if(camera_!=0)
|
||||||
{
|
{
|
||||||
|
#ifdef RTABMAP_ARCORE
|
||||||
|
if(cameraDriver_ == 1)
|
||||||
|
{
|
||||||
|
((rtabmap::CameraARCore*)camera_)->updateOcclusionImage(!visualizingMesh_ && main_scene_.GetCameraType() == tango_gl::GestureCamera::kFirstPerson);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
camera_->spinOnce();
|
camera_->spinOnce();
|
||||||
|
|
||||||
|
#ifdef RTABMAP_ARCORE
|
||||||
|
if(cameraDriver_ == 1)
|
||||||
|
{
|
||||||
|
if(main_scene_.background_renderer_ == 0)
|
||||||
|
{
|
||||||
|
main_scene_.background_renderer_ = new BackgroundRenderer();
|
||||||
|
main_scene_.background_renderer_->InitializeGlContent(((rtabmap::CameraARCore*)camera_)->getTextureId());
|
||||||
|
}
|
||||||
|
if(((rtabmap::CameraARCore*)camera_)->uvsInitialized())
|
||||||
|
{
|
||||||
|
uvsTransformed = ((rtabmap::CameraARCore*)camera_)->uvsTransformed();
|
||||||
|
((rtabmap::CameraARCore*)camera_)->getVPMatrices(arViewMatrix, arProjectionMatrix);
|
||||||
|
}
|
||||||
|
if(!visualizingMesh_ && main_scene_.GetCameraType() == tango_gl::GestureCamera::kFirstPerson)
|
||||||
|
{
|
||||||
|
rtabmap::CameraModel occlusionModel;
|
||||||
|
cv::Mat occlusionImage = ((rtabmap::CameraARCore*)camera_)->getOcclusionImage(&occlusionModel);
|
||||||
|
|
||||||
|
if(occlusionModel.isValidForProjection())
|
||||||
|
{
|
||||||
|
pcl::IndicesPtr indices(new std::vector<int>);
|
||||||
|
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud = rtabmap::util3d::cloudFromDepth(occlusionImage, occlusionModel, 1, 0, 0, indices.get());
|
||||||
|
cloud = rtabmap::util3d::transformPointCloud(cloud, rtabmap::opengl_world_T_rtabmap_world*occlusionModel.localTransform());
|
||||||
|
occlusionMesh.cloud.reset(new pcl::PointCloud<pcl::PointXYZRGB>());
|
||||||
|
pcl::copyPointCloud(*cloud, *occlusionMesh.cloud);
|
||||||
|
occlusionMesh.indices = indices;
|
||||||
|
occlusionMesh.polygons = rtabmap::util3d::organizedFastMesh(cloud, 1.0*M_PI/180.0, false, meshTrianglePix_);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UERROR("invalid occlusionModel: %f %f %f %f %dx%d", occlusionModel.fx(), occlusionModel.fy(), occlusionModel.cx(), occlusionModel.cy(), occlusionModel.imageWidth(), occlusionModel.imageHeight());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1788,7 +1848,7 @@ int RTABMapApp::Render()
|
|||||||
|
|
||||||
fpsTime.restart();
|
fpsTime.restart();
|
||||||
main_scene_.setFrustumVisible(camera_!=0);
|
main_scene_.setFrustumVisible(camera_!=0);
|
||||||
lastDrawnCloudsCount_ = main_scene_.Render();
|
lastDrawnCloudsCount_ = main_scene_.Render(uvsTransformed, arViewMatrix, arProjectionMatrix, occlusionMesh);
|
||||||
if(renderingTime_ < fpsTime.elapsed())
|
if(renderingTime_ < fpsTime.elapsed())
|
||||||
{
|
{
|
||||||
renderingTime_ = fpsTime.elapsed();
|
renderingTime_ = fpsTime.elapsed();
|
||||||
@@ -2074,6 +2134,14 @@ void RTABMapApp::setSmoothing(bool enabled)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RTABMapApp::setDepthFromMotion(bool enabled)
|
||||||
|
{
|
||||||
|
if(depthFromMotion_ != enabled)
|
||||||
|
{
|
||||||
|
depthFromMotion_ = enabled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void RTABMapApp::setAppendMode(bool enabled)
|
void RTABMapApp::setAppendMode(bool enabled)
|
||||||
{
|
{
|
||||||
if(appendMode_ != enabled)
|
if(appendMode_ != enabled)
|
||||||
@@ -2391,12 +2459,13 @@ bool RTABMapApp::exportMesh(
|
|||||||
gains[1] = jter->second.gains[1];
|
gains[1] = jter->second.gains[1];
|
||||||
gains[2] = jter->second.gains[2];
|
gains[2] = jter->second.gains[2];
|
||||||
|
|
||||||
rtabmap::SensorData data = rtabmap_->getMemory()->getNodeData(iter->first, false);
|
rtabmap::SensorData data = rtabmap_->getMemory()->getNodeData(iter->first, true, false, false, false);
|
||||||
data.uncompressData(0, &depth);
|
data.uncompressData(0, &depth);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
rtabmap::SensorData data = rtabmap_->getMemory()->getNodeData(iter->first, true);
|
rtabmap::SensorData data = rtabmap_->getMemory()->getNodeData(iter->first, true, false, false, false);
|
||||||
|
data.uncompressData();
|
||||||
if(!data.imageRaw().empty() && !data.depthRaw().empty() && data.cameraModels().size() == 1)
|
if(!data.imageRaw().empty() && !data.depthRaw().empty() && data.cameraModels().size() == 1)
|
||||||
{
|
{
|
||||||
cloud = rtabmap::util3d::cloudRGBFromSensorData(data, meshDecimation_, maxCloudDepth_, minCloudDepth_, indices.get());
|
cloud = rtabmap::util3d::cloudRGBFromSensorData(data, meshDecimation_, maxCloudDepth_, minCloudDepth_, indices.get());
|
||||||
@@ -2661,7 +2730,8 @@ bool RTABMapApp::exportMesh(
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
rtabmap::SensorData data = rtabmap_->getMemory()->getNodeData(iter->first, true);
|
rtabmap::SensorData data = rtabmap_->getMemory()->getNodeData(iter->first, true, false, false, false);
|
||||||
|
data.uncompressData();
|
||||||
if(!data.imageRaw().empty() && !data.depthRaw().empty() && data.cameraModels().size() == 1)
|
if(!data.imageRaw().empty() && !data.depthRaw().empty() && data.cameraModels().size() == 1)
|
||||||
{
|
{
|
||||||
cloud = rtabmap::util3d::cloudRGBFromSensorData(data, meshDecimation_, maxCloudDepth_, minCloudDepth_);
|
cloud = rtabmap::util3d::cloudRGBFromSensorData(data, meshDecimation_, maxCloudDepth_, minCloudDepth_);
|
||||||
@@ -2894,7 +2964,8 @@ bool RTABMapApp::exportMesh(
|
|||||||
gains[1] = jter->second.gains[1];
|
gains[1] = jter->second.gains[1];
|
||||||
gains[2] = jter->second.gains[2];
|
gains[2] = jter->second.gains[2];
|
||||||
}
|
}
|
||||||
rtabmap::SensorData data = rtabmap_->getMemory()->getNodeData(iter->first, true);
|
rtabmap::SensorData data = rtabmap_->getMemory()->getNodeData(iter->first, true, false, false, false);
|
||||||
|
data.uncompressData();
|
||||||
if(!data.imageRaw().empty() && !data.depthRaw().empty())
|
if(!data.imageRaw().empty() && !data.depthRaw().empty())
|
||||||
{
|
{
|
||||||
// full resolution
|
// full resolution
|
||||||
@@ -2913,7 +2984,8 @@ bool RTABMapApp::exportMesh(
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
rtabmap::SensorData data = rtabmap_->getMemory()->getNodeData(iter->first, true);
|
rtabmap::SensorData data = rtabmap_->getMemory()->getNodeData(iter->first, true, false, false, false);
|
||||||
|
data.uncompressData();
|
||||||
if(!data.imageRaw().empty() && !data.depthRaw().empty())
|
if(!data.imageRaw().empty() && !data.depthRaw().empty())
|
||||||
{
|
{
|
||||||
cloud = rtabmap::util3d::cloudRGBFromSensorData(data, meshDecimation_, maxCloudDepth_, minCloudDepth_, indices.get());
|
cloud = rtabmap::util3d::cloudRGBFromSensorData(data, meshDecimation_, maxCloudDepth_, minCloudDepth_, indices.get());
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <pcl/pcl_base.h>
|
#include <pcl/pcl_base.h>
|
||||||
#include <pcl/TextureMesh.h>
|
#include <pcl/TextureMesh.h>
|
||||||
|
|
||||||
|
|
||||||
// RTABMapApp handles the application lifecycle and resources.
|
// RTABMapApp handles the application lifecycle and resources.
|
||||||
class RTABMapApp : public UEventsHandler {
|
class RTABMapApp : public UEventsHandler {
|
||||||
public:
|
public:
|
||||||
@@ -109,6 +110,7 @@ class RTABMapApp : public UEventsHandler {
|
|||||||
void setCameraColor(bool enabled);
|
void setCameraColor(bool enabled);
|
||||||
void setFullResolution(bool enabled);
|
void setFullResolution(bool enabled);
|
||||||
void setSmoothing(bool enabled);
|
void setSmoothing(bool enabled);
|
||||||
|
void setDepthFromMotion(bool enabled);
|
||||||
void setAppendMode(bool enabled);
|
void setAppendMode(bool enabled);
|
||||||
void setDataRecorderMode(bool enabled);
|
void setDataRecorderMode(bool enabled);
|
||||||
void setMaxCloudDepth(float value);
|
void setMaxCloudDepth(float value);
|
||||||
@@ -182,6 +184,7 @@ class RTABMapApp : public UEventsHandler {
|
|||||||
bool trajectoryMode_;
|
bool trajectoryMode_;
|
||||||
bool rawScanSaved_;
|
bool rawScanSaved_;
|
||||||
bool smoothing_;
|
bool smoothing_;
|
||||||
|
bool depthFromMotion_;
|
||||||
bool cameraColor_;
|
bool cameraColor_;
|
||||||
bool fullResolution_;
|
bool fullResolution_;
|
||||||
bool appendMode_;
|
bool appendMode_;
|
||||||
|
|||||||
@@ -0,0 +1,92 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018 Google Inc. 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// This modules handles drawing the passthrough camera image into the OpenGL
|
||||||
|
// scene.
|
||||||
|
|
||||||
|
#include "background_renderer.h"
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
const std::string kVertexShader =
|
||||||
|
"attribute vec4 a_Position;\n"
|
||||||
|
"attribute vec2 a_TexCoord;\n"
|
||||||
|
|
||||||
|
"varying vec2 v_TexCoord;\n"
|
||||||
|
|
||||||
|
"void main() {\n"
|
||||||
|
" gl_Position = a_Position;\n"
|
||||||
|
" v_TexCoord = a_TexCoord;\n"
|
||||||
|
"}\n";
|
||||||
|
|
||||||
|
const std::string kFragmentShader =
|
||||||
|
"#extension GL_OES_EGL_image_external : require\n"
|
||||||
|
|
||||||
|
"precision mediump float;\n"
|
||||||
|
"varying vec2 v_TexCoord;\n"
|
||||||
|
"uniform samplerExternalOES sTexture;\n"
|
||||||
|
|
||||||
|
"void main() {\n"
|
||||||
|
" vec4 sample = texture2D(sTexture, v_TexCoord);\n"
|
||||||
|
" float grey = 0.21 * sample.r + 0.71 * sample.g + 0.07 * sample.b;\n"
|
||||||
|
" gl_FragColor = vec4(grey, grey, grey, 0.5);\n"
|
||||||
|
"}\n";
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
void BackgroundRenderer::InitializeGlContent(GLuint textureId)
|
||||||
|
{
|
||||||
|
texture_id_ = textureId;
|
||||||
|
|
||||||
|
shader_program_ = tango_gl::util::CreateProgram(kVertexShader.c_str(), kFragmentShader.c_str());
|
||||||
|
if (!shader_program_) {
|
||||||
|
LOGE("Could not create program.");
|
||||||
|
}
|
||||||
|
glUseProgram(shader_program_);
|
||||||
|
attribute_vertices_ = glGetAttribLocation(shader_program_, "a_Position");
|
||||||
|
attribute_uvs_ = glGetAttribLocation(shader_program_, "a_TexCoord");
|
||||||
|
glUseProgram(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BackgroundRenderer::Draw(const float * transformed_uvs) {
|
||||||
|
static_assert(std::extent<decltype(BackgroundRenderer_kVertices)>::value == kNumVertices * 2, "Incorrect kVertices length");
|
||||||
|
|
||||||
|
glUseProgram(shader_program_);
|
||||||
|
glDepthMask(GL_FALSE);
|
||||||
|
glEnable (GL_BLEND);
|
||||||
|
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture_id_);
|
||||||
|
|
||||||
|
glVertexAttribPointer(attribute_vertices_, 2, GL_FLOAT, GL_FALSE, 0, BackgroundRenderer_kVertices);
|
||||||
|
glVertexAttribPointer(attribute_uvs_, 2, GL_FLOAT, GL_FALSE, 0, transformed_uvs);
|
||||||
|
|
||||||
|
glEnableVertexAttribArray(attribute_vertices_);
|
||||||
|
glEnableVertexAttribArray(attribute_uvs_);
|
||||||
|
|
||||||
|
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||||
|
|
||||||
|
glDisableVertexAttribArray(attribute_vertices_);
|
||||||
|
glDisableVertexAttribArray(attribute_uvs_);
|
||||||
|
|
||||||
|
glUseProgram(0);
|
||||||
|
glDepthMask(GL_TRUE);
|
||||||
|
glDisable (GL_BLEND);
|
||||||
|
tango_gl::util::CheckGlError("BackgroundRenderer::Draw() error");
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018 Google Inc. 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef C_ARCORE_AUGMENTED_IMAGE_BACKGROUND_RENDERER_H_
|
||||||
|
#define C_ARCORE_AUGMENTED_IMAGE_BACKGROUND_RENDERER_H_
|
||||||
|
|
||||||
|
#include <GLES2/gl2.h>
|
||||||
|
#include <GLES2/gl2ext.h>
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
static const GLfloat BackgroundRenderer_kVertices[] = {
|
||||||
|
-1.0f, -1.0f, +1.0f, -1.0f, -1.0f, +1.0f, +1.0f, +1.0f,
|
||||||
|
};
|
||||||
|
|
||||||
|
// This class renders the passthrough camera image into the OpenGL frame.
|
||||||
|
class BackgroundRenderer {
|
||||||
|
public:
|
||||||
|
// Positions of the quad vertices in clip space (X, Y).
|
||||||
|
|
||||||
|
static constexpr int kNumVertices = 4;
|
||||||
|
|
||||||
|
public:
|
||||||
|
BackgroundRenderer() = default;
|
||||||
|
~BackgroundRenderer() = default;
|
||||||
|
|
||||||
|
// Sets up OpenGL state. Must be called on the OpenGL thread and before any
|
||||||
|
// other methods below.
|
||||||
|
void InitializeGlContent(GLuint textureId);
|
||||||
|
|
||||||
|
// Draws the background image. This methods must be called for every ArFrame
|
||||||
|
// returned by ArSession_update() to catch display geometry change events.
|
||||||
|
void Draw(const float * transformed_uvs);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
GLuint shader_program_;
|
||||||
|
GLuint texture_id_;
|
||||||
|
|
||||||
|
GLuint attribute_vertices_;
|
||||||
|
GLuint attribute_uvs_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // C_ARCORE_AUGMENTED_IMAGE_BACKGROUND_RENDERER_H_
|
||||||
@@ -512,6 +512,19 @@ Java_com_introlab_rtabmap_RTABMapLib_setSmoothing(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
JNIEXPORT void JNICALL
|
JNIEXPORT void JNICALL
|
||||||
|
Java_com_introlab_rtabmap_RTABMapLib_setDepthFromMotion(
|
||||||
|
JNIEnv*, jclass, jlong native_application, bool enabled)
|
||||||
|
{
|
||||||
|
if(native_application)
|
||||||
|
{
|
||||||
|
return native(native_application)->setDepthFromMotion(enabled);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UERROR("native_application is null!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
JNIEXPORT void JNICALL
|
||||||
Java_com_introlab_rtabmap_RTABMapLib_setCameraColor(
|
Java_com_introlab_rtabmap_RTABMapLib_setCameraColor(
|
||||||
JNIEnv*, jclass, jlong native_application, bool enabled)
|
JNIEnv*, jclass, jlong native_application, bool enabled)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ const std::string kGraphFragmentShader =
|
|||||||
|
|
||||||
|
|
||||||
Scene::Scene() :
|
Scene::Scene() :
|
||||||
|
background_renderer_(0),
|
||||||
gesture_camera_(0),
|
gesture_camera_(0),
|
||||||
axis_(0),
|
axis_(0),
|
||||||
frustum_(0),
|
frustum_(0),
|
||||||
@@ -160,6 +161,8 @@ void Scene::DeleteResources() {
|
|||||||
delete trace_;
|
delete trace_;
|
||||||
delete grid_;
|
delete grid_;
|
||||||
delete box_;
|
delete box_;
|
||||||
|
delete background_renderer_;
|
||||||
|
background_renderer_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
PointCloudDrawable::releaseShaderPrograms();
|
PointCloudDrawable::releaseShaderPrograms();
|
||||||
@@ -364,7 +367,7 @@ bool intersectFrustumAABB(
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Should only be called in OpenGL thread!
|
//Should only be called in OpenGL thread!
|
||||||
int Scene::Render() {
|
int Scene::Render(const float * uvsTransformed, glm::mat4 arViewMatrix, glm::mat4 arProjectionMatrix, const rtabmap::Mesh & occlusionMesh) {
|
||||||
UASSERT(gesture_camera_ != 0);
|
UASSERT(gesture_camera_ != 0);
|
||||||
|
|
||||||
if(currentPose_ == 0)
|
if(currentPose_ == 0)
|
||||||
@@ -395,6 +398,17 @@ int Scene::Render() {
|
|||||||
glm::mat4 projectionMatrix = gesture_camera_->GetProjectionMatrix();
|
glm::mat4 projectionMatrix = gesture_camera_->GetProjectionMatrix();
|
||||||
glm::mat4 viewMatrix = gesture_camera_->GetViewMatrix();
|
glm::mat4 viewMatrix = gesture_camera_->GetViewMatrix();
|
||||||
|
|
||||||
|
bool renderBackgroundCamera =
|
||||||
|
background_renderer_ &&
|
||||||
|
gesture_camera_->GetCameraType() == tango_gl::GestureCamera::kFirstPerson &&
|
||||||
|
!rtabmap::glmToTransform(arProjectionMatrix).isNull() &&
|
||||||
|
uvsTransformed;
|
||||||
|
if(renderBackgroundCamera)
|
||||||
|
{
|
||||||
|
projectionMatrix = arProjectionMatrix;
|
||||||
|
viewMatrix = arViewMatrix;
|
||||||
|
}
|
||||||
|
|
||||||
rtabmap::Transform openglCamera = GetOpenGLCameraPose();//*rtabmap::Transform(0.0f, 0.0f, 3.0f, 0.0f, 0.0f, 0.0f);
|
rtabmap::Transform openglCamera = GetOpenGLCameraPose();//*rtabmap::Transform(0.0f, 0.0f, 3.0f, 0.0f, 0.0f, 0.0f);
|
||||||
// transform in same coordinate as frustum filtering
|
// transform in same coordinate as frustum filtering
|
||||||
openglCamera *= rtabmap::Transform(
|
openglCamera *= rtabmap::Transform(
|
||||||
@@ -444,7 +458,7 @@ int Scene::Render() {
|
|||||||
|
|
||||||
UTimer timer;
|
UTimer timer;
|
||||||
|
|
||||||
bool onlineBlending = blending_ && gesture_camera_->GetCameraType()!=tango_gl::GestureCamera::kTopOrtho && mapRendering_ && meshRendering_ && cloudsToDraw.size()>1;
|
bool onlineBlending = (renderBackgroundCamera && occlusionMesh.cloud.get() && occlusionMesh.cloud->size()) || (blending_ && gesture_camera_->GetCameraType()!=tango_gl::GestureCamera::kTopOrtho && mapRendering_ && meshRendering_ && cloudsToDraw.size()>1);
|
||||||
if(onlineBlending && fboId_)
|
if(onlineBlending && fboId_)
|
||||||
{
|
{
|
||||||
// set the rendering destination to FBO
|
// set the rendering destination to FBO
|
||||||
@@ -454,11 +468,19 @@ int Scene::Render() {
|
|||||||
glClearColor(1, 1, 1, 1);
|
glClearColor(1, 1, 1, 1);
|
||||||
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
|
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
// Draw scene
|
if(renderBackgroundCamera)
|
||||||
for(std::vector<PointCloudDrawable*>::const_iterator iter=cloudsToDraw.begin(); iter!=cloudsToDraw.end(); ++iter)
|
|
||||||
{
|
{
|
||||||
// set large distance to cam to use low res polygons for fast processing
|
PointCloudDrawable drawable(occlusionMesh);
|
||||||
(*iter)->Render(projectionMatrix, viewMatrix, meshRendering_, pointSize_, false, false, 999.0f);
|
drawable.Render(projectionMatrix, viewMatrix, true, pointSize_, false, false, 999.0f);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Draw scene
|
||||||
|
for(std::vector<PointCloudDrawable*>::const_iterator iter=cloudsToDraw.begin(); iter!=cloudsToDraw.end(); ++iter)
|
||||||
|
{
|
||||||
|
// set large distance to cam to use low res polygons for fast processing
|
||||||
|
(*iter)->Render(projectionMatrix, viewMatrix, meshRendering_, pointSize_, false, false, 999.0f);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// back to normal window-system-provided framebuffer
|
// back to normal window-system-provided framebuffer
|
||||||
@@ -495,6 +517,15 @@ int Scene::Render() {
|
|||||||
glClearColor(r_, g_, b_, 1.0f);
|
glClearColor(r_, g_, b_, 1.0f);
|
||||||
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
|
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
|
if(renderBackgroundCamera)
|
||||||
|
{
|
||||||
|
background_renderer_->Draw(uvsTransformed);
|
||||||
|
|
||||||
|
//To debug occlusion image:
|
||||||
|
//PointCloudDrawable drawable(occlusionMesh);
|
||||||
|
//drawable.Render(projectionMatrix, viewMatrix, true, pointSize_, false, false, 999.0f);
|
||||||
|
}
|
||||||
|
|
||||||
if(!currentPose_->isNull())
|
if(!currentPose_->isNull())
|
||||||
{
|
{
|
||||||
if (frustumVisible_ && gesture_camera_->GetCameraType() != tango_gl::GestureCamera::kFirstPerson)
|
if (frustumVisible_ && gesture_camera_->GetCameraType() != tango_gl::GestureCamera::kFirstPerson)
|
||||||
@@ -523,7 +554,7 @@ int Scene::Render() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(gridVisible_)
|
if(gridVisible_ && !renderBackgroundCamera)
|
||||||
{
|
{
|
||||||
grid_->Render(projectionMatrix, viewMatrix);
|
grid_->Render(projectionMatrix, viewMatrix);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,6 +38,7 @@
|
|||||||
#include <point_cloud_drawable.h>
|
#include <point_cloud_drawable.h>
|
||||||
#include <graph_drawable.h>
|
#include <graph_drawable.h>
|
||||||
#include <bounding_box_drawable.h>
|
#include <bounding_box_drawable.h>
|
||||||
|
#include <background_renderer.h>
|
||||||
|
|
||||||
#include <pcl/point_cloud.h>
|
#include <pcl/point_cloud.h>
|
||||||
#include <pcl/point_types.h>
|
#include <pcl/point_types.h>
|
||||||
@@ -71,13 +72,14 @@ class Scene {
|
|||||||
// frame's timestamp.
|
// frame's timestamp.
|
||||||
// @param: point_cloud_vertices, point cloud's vertices of the current point
|
// @param: point_cloud_vertices, point cloud's vertices of the current point
|
||||||
// frame.
|
// frame.
|
||||||
int Render();
|
int Render(const float * uvsTransformed = 0, glm::mat4 arViewMatrix = glm::mat4(0), glm::mat4 arProjectionMatrix=glm::mat4(0), const rtabmap::Mesh & occlusionMesh=rtabmap::Mesh());
|
||||||
|
|
||||||
// Set render camera's viewing angle, first person, third person or top down.
|
// Set render camera's viewing angle, first person, third person or top down.
|
||||||
//
|
//
|
||||||
// @param: camera_type, camera type includes first person, third person and
|
// @param: camera_type, camera type includes first person, third person and
|
||||||
// top down
|
// top down
|
||||||
void SetCameraType(tango_gl::GestureCamera::CameraType camera_type);
|
void SetCameraType(tango_gl::GestureCamera::CameraType camera_type);
|
||||||
|
tango_gl::GestureCamera::CameraType GetCameraType() const {return gesture_camera_->GetCameraType();}
|
||||||
|
|
||||||
void SetCameraPose(const rtabmap::Transform & pose); // opengl camera
|
void SetCameraPose(const rtabmap::Transform & pose); // opengl camera
|
||||||
rtabmap::Transform GetCameraPose() const {return currentPose_!=0?*currentPose_:rtabmap::Transform();}
|
rtabmap::Transform GetCameraPose() const {return currentPose_!=0?*currentPose_:rtabmap::Transform();}
|
||||||
@@ -152,6 +154,8 @@ class Scene {
|
|||||||
bool isLighting() const {return lighting_;}
|
bool isLighting() const {return lighting_;}
|
||||||
bool isBackfaceCulling() const {return backfaceCulling_;}
|
bool isBackfaceCulling() const {return backfaceCulling_;}
|
||||||
|
|
||||||
|
BackgroundRenderer * background_renderer_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Camera object that allows user to use touch input to interact with.
|
// Camera object that allows user to use touch input to interact with.
|
||||||
tango_gl::GestureCamera* gesture_camera_;
|
tango_gl::GestureCamera* gesture_camera_;
|
||||||
|
|||||||
@@ -199,8 +199,8 @@ void GestureCamera::SetCameraType(CameraType camera_index) {
|
|||||||
SetRotation(glm::quat(1.0f, 0.0f, 0.0f, 0.0f));
|
SetRotation(glm::quat(1.0f, 0.0f, 0.0f, 0.0f));
|
||||||
cam_cur_dist_ = kThirdPersonFollow?kThirdPersonFollowCameraDist:kThirdPersonCameraDist;
|
cam_cur_dist_ = kThirdPersonFollow?kThirdPersonFollowCameraDist:kThirdPersonCameraDist;
|
||||||
anchor_offset_ = glm::vec3(0.0f,0.0f,0.0f);
|
anchor_offset_ = glm::vec3(0.0f,0.0f,0.0f);
|
||||||
cam_cur_angle_.x = -M_PI / 6.0f;
|
cam_cur_angle_.x = -M_PI / 12.0f;
|
||||||
cam_cur_angle_.y = kThirdPersonFollow?0:M_PI / 4.0f;
|
cam_cur_angle_.y = kThirdPersonFollow?0:M_PI / 2.0f;
|
||||||
cam_cur_target_rot_ = glm::quat(1,0,0,0);
|
cam_cur_target_rot_ = glm::quat(1,0,0,0);
|
||||||
StartCameraToCurrentTransform();
|
StartCameraToCurrentTransform();
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -252,7 +252,7 @@ inline ScreenRotation GetAndroidRotationFromColorCameraToDisplay(
|
|||||||
// @param display: integer value of display orientation, values available
|
// @param display: integer value of display orientation, values available
|
||||||
// are 0, 1, 2 ,3. Followed by Android display orientation standard:
|
// are 0, 1, 2 ,3. Followed by Android display orientation standard:
|
||||||
// https://developer.android.com/reference/android/view/Display.html#getRotation()
|
// https://developer.android.com/reference/android/view/Display.html#getRotation()
|
||||||
// @param color_camera: integer value of color camera oreintation, values
|
// @param color_camera: integer value of color camera orientation, values
|
||||||
// available are 0, 90, 180, 270. Followed by Android camera orientation
|
// available are 0, 90, 180, 270. Followed by Android camera orientation
|
||||||
// standard:
|
// standard:
|
||||||
// https://developer.android.com/reference/android/hardware/Camera.CameraInfo.html#orientation
|
// https://developer.android.com/reference/android/hardware/Camera.CameraInfo.html#orientation
|
||||||
|
|||||||
@@ -163,6 +163,7 @@
|
|||||||
android:layout_height="100dp"
|
android:layout_height="100dp"
|
||||||
android:layout_alignLeft="@+id/button_library"
|
android:layout_alignLeft="@+id/button_library"
|
||||||
android:layout_below="@+id/button_library"
|
android:layout_below="@+id/button_library"
|
||||||
|
android:layout_marginTop="20dp"
|
||||||
android:text="@string/new_scan" />
|
android:text="@string/new_scan" />
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
android:entries="@array/pref_camera_driver_keys"
|
android:entries="@array/pref_camera_driver_keys"
|
||||||
android:entryValues="@array/pref_camera_driver_values"
|
android:entryValues="@array/pref_camera_driver_values"
|
||||||
android:defaultValue="@string/pref_default_camera_driver"/>
|
android:defaultValue="@string/pref_default_camera_driver"/>
|
||||||
|
|
||||||
<PreferenceCategory
|
<PreferenceCategory
|
||||||
android:title="@string/pref_title_rendering">
|
android:title="@string/pref_title_rendering">
|
||||||
<ListPreference
|
<ListPreference
|
||||||
@@ -97,6 +97,11 @@
|
|||||||
android:title="@string/pref_title_resolution"
|
android:title="@string/pref_title_resolution"
|
||||||
android:summary="@string/pref_summary_resolution"
|
android:summary="@string/pref_summary_resolution"
|
||||||
android:defaultValue="@string/pref_default_resolution"/>
|
android:defaultValue="@string/pref_default_resolution"/>
|
||||||
|
<com.introlab.rtabmap.CustomSwitchPreference
|
||||||
|
android:key="@string/pref_key_depth_from_motion"
|
||||||
|
android:title="@string/pref_title_depth_from_motion"
|
||||||
|
android:summary="@string/pref_summary_depth_from_motion"
|
||||||
|
android:defaultValue="@string/pref_default_depth_from_motion"/>
|
||||||
<com.introlab.rtabmap.CustomSwitchPreference
|
<com.introlab.rtabmap.CustomSwitchPreference
|
||||||
android:key="@string/pref_key_smoothing"
|
android:key="@string/pref_key_smoothing"
|
||||||
android:title="@string/pref_title_smoothing"
|
android:title="@string/pref_title_smoothing"
|
||||||
|
|||||||
@@ -81,6 +81,8 @@
|
|||||||
|
|
||||||
<string name="pref_key_camera_driver">pref_key_camera_driver</string>
|
<string name="pref_key_camera_driver">pref_key_camera_driver</string>
|
||||||
<string name="pref_default_camera_driver">0</string>
|
<string name="pref_default_camera_driver">0</string>
|
||||||
|
<string name="pref_key_depth_from_motion">pref_key_depth_from_motion</string>
|
||||||
|
<string name="pref_default_depth_from_motion">false</string>
|
||||||
<string name="pref_key_update_rate">pref_key_update_rate</string>
|
<string name="pref_key_update_rate">pref_key_update_rate</string>
|
||||||
<string name="pref_default_update_rate">1</string>
|
<string name="pref_default_update_rate">1</string>
|
||||||
<string name="pref_key_max_speed">pref_key_max_speed</string>
|
<string name="pref_key_max_speed">pref_key_max_speed</string>
|
||||||
@@ -323,6 +325,8 @@
|
|||||||
<string name="pref_title_mapping_database">Database</string>
|
<string name="pref_title_mapping_database">Database</string>
|
||||||
<string name="pref_title_camera_driver">Camera Driver</string>
|
<string name="pref_title_camera_driver">Camera Driver</string>
|
||||||
<string name="pref_summary_camera_driver">AR sdk use for capturing 6DoF poses and images. A TOF camera is required to record a 3D model.</string>
|
<string name="pref_summary_camera_driver">AR sdk use for capturing 6DoF poses and images. A TOF camera is required to record a 3D model.</string>
|
||||||
|
<string name="pref_title_depth_from_motion">Depth From Motion</string>
|
||||||
|
<string name="pref_summary_depth_from_motion">Use ARCore\'s depth API to compute depth image from motion. If the phone has a TOF camera and is supported by ARCore, results should be better. Currently supported only with ARCore NDK driver.</string>
|
||||||
<string name="pref_title_append">Append Mode</string>
|
<string name="pref_title_append">Append Mode</string>
|
||||||
<string name="pref_summary_append">When resuming mapping, wait for a relocalization on the current map before starting a new map.</string>
|
<string name="pref_summary_append">When resuming mapping, wait for a relocalization on the current map before starting a new map.</string>
|
||||||
<string name="pref_title_resolution">HD Mode</string>
|
<string name="pref_title_resolution">HD Mode</string>
|
||||||
|
|||||||
@@ -1,588 +0,0 @@
|
|||||||
package com.introlab.rtabmap;
|
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.nio.FloatBuffer;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.EnumSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
|
||||||
|
|
||||||
import com.google.ar.core.Camera;
|
|
||||||
import com.google.ar.core.CameraIntrinsics;
|
|
||||||
import com.google.ar.core.Config;
|
|
||||||
import com.google.ar.core.Frame;
|
|
||||||
import com.google.ar.core.ImageMetadata;
|
|
||||||
import com.google.ar.core.PointCloud;
|
|
||||||
import com.google.ar.core.Pose;
|
|
||||||
import com.google.ar.core.Session;
|
|
||||||
import com.google.ar.core.SharedCamera;
|
|
||||||
import com.google.ar.core.TrackingState;
|
|
||||||
import com.google.ar.core.exceptions.CameraNotAvailableException;
|
|
||||||
import com.google.ar.core.exceptions.NotYetAvailableException;
|
|
||||||
import com.google.ar.core.exceptions.UnavailableException;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.graphics.ImageFormat;
|
|
||||||
import android.hardware.camera2.CameraAccessException;
|
|
||||||
import android.hardware.camera2.CameraCaptureSession;
|
|
||||||
import android.hardware.camera2.CameraCharacteristics;
|
|
||||||
import android.hardware.camera2.CameraDevice;
|
|
||||||
import android.hardware.camera2.CameraManager;
|
|
||||||
import android.hardware.camera2.CaptureFailure;
|
|
||||||
import android.hardware.camera2.CaptureRequest;
|
|
||||||
import android.hardware.camera2.TotalCaptureResult;
|
|
||||||
import android.media.Image;
|
|
||||||
import android.opengl.GLES20;
|
|
||||||
import android.opengl.GLSurfaceView;
|
|
||||||
import android.os.Handler;
|
|
||||||
import android.os.HandlerThread;
|
|
||||||
import android.support.annotation.NonNull;
|
|
||||||
import android.util.Log;
|
|
||||||
import android.view.Surface;
|
|
||||||
|
|
||||||
public class ARCoreSharedCamera {
|
|
||||||
|
|
||||||
public static final String TAG = ARCoreSharedCamera.class.getSimpleName();
|
|
||||||
|
|
||||||
|
|
||||||
private static RTABMapActivity mActivity;
|
|
||||||
public ARCoreSharedCamera(RTABMapActivity c) {
|
|
||||||
mActivity = c;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Depth TOF Image.
|
|
||||||
// Use 240 * 180 for now, hardcoded for Huawei P30 Pro
|
|
||||||
private static final int DEPTH_WIDTH = 240;
|
|
||||||
private static final int DEPTH_HEIGHT = 180;
|
|
||||||
|
|
||||||
// GL Surface used to draw camera preview image.
|
|
||||||
public GLSurfaceView surfaceView;
|
|
||||||
|
|
||||||
// ARCore session that supports camera sharing.
|
|
||||||
private Session sharedSession;
|
|
||||||
|
|
||||||
// Camera capture session. Used by both non-AR and AR modes.
|
|
||||||
private CameraCaptureSession captureSession;
|
|
||||||
|
|
||||||
// Reference to the camera system service.
|
|
||||||
private CameraManager cameraManager;
|
|
||||||
|
|
||||||
// Camera device. Used by both non-AR and AR modes.
|
|
||||||
private CameraDevice cameraDevice;
|
|
||||||
|
|
||||||
// Looper handler thread.
|
|
||||||
private HandlerThread backgroundThread;
|
|
||||||
// Looper handler.
|
|
||||||
private Handler backgroundHandler;
|
|
||||||
|
|
||||||
// ARCore shared camera instance, obtained from ARCore session that supports sharing.
|
|
||||||
private SharedCamera sharedCamera;
|
|
||||||
|
|
||||||
// Camera ID for the camera used by ARCore.
|
|
||||||
private String cameraId;
|
|
||||||
|
|
||||||
private AtomicBoolean mReady = new AtomicBoolean(false);
|
|
||||||
|
|
||||||
// Camera preview capture request builder
|
|
||||||
private CaptureRequest.Builder previewCaptureRequestBuilder;
|
|
||||||
|
|
||||||
private int cameraTextureId = -1;
|
|
||||||
|
|
||||||
// Image reader that continuously processes CPU images.
|
|
||||||
public TOF_ImageReader mTOFImageReader = new TOF_ImageReader();
|
|
||||||
private boolean mTOFAvailable = false;
|
|
||||||
|
|
||||||
public boolean isDepthSupported() {return mTOFAvailable;}
|
|
||||||
|
|
||||||
// Camera device state callback.
|
|
||||||
private final CameraDevice.StateCallback cameraDeviceCallback =
|
|
||||||
new CameraDevice.StateCallback() {
|
|
||||||
@Override
|
|
||||||
public void onOpened(@NonNull CameraDevice cameraDevice) {
|
|
||||||
Log.d(TAG, "Camera device ID " + cameraDevice.getId() + " opened.");
|
|
||||||
ARCoreSharedCamera.this.cameraDevice = cameraDevice;
|
|
||||||
createCameraPreviewSession();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onClosed(@NonNull CameraDevice cameraDevice) {
|
|
||||||
Log.d(TAG, "Camera device ID " + cameraDevice.getId() + " closed.");
|
|
||||||
ARCoreSharedCamera.this.cameraDevice = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDisconnected(@NonNull CameraDevice cameraDevice) {
|
|
||||||
Log.w(TAG, "Camera device ID " + cameraDevice.getId() + " disconnected.");
|
|
||||||
cameraDevice.close();
|
|
||||||
ARCoreSharedCamera.this.cameraDevice = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onError(@NonNull CameraDevice cameraDevice, int error) {
|
|
||||||
Log.e(TAG, "Camera device ID " + cameraDevice.getId() + " error " + error);
|
|
||||||
cameraDevice.close();
|
|
||||||
ARCoreSharedCamera.this.cameraDevice = null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Repeating camera capture session state callback.
|
|
||||||
CameraCaptureSession.StateCallback cameraCaptureCallback =
|
|
||||||
new CameraCaptureSession.StateCallback() {
|
|
||||||
|
|
||||||
// Called when the camera capture session is first configured after the app
|
|
||||||
// is initialized, and again each time the activity is resumed.
|
|
||||||
@Override
|
|
||||||
public void onConfigured(@NonNull CameraCaptureSession session) {
|
|
||||||
Log.d(TAG, "Camera capture session configured.");
|
|
||||||
captureSession = session;
|
|
||||||
setRepeatingCaptureRequest();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onSurfacePrepared(
|
|
||||||
@NonNull CameraCaptureSession session, @NonNull Surface surface) {
|
|
||||||
Log.d(TAG, "Camera capture surface prepared.");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onReady(@NonNull CameraCaptureSession session) {
|
|
||||||
Log.d(TAG, "Camera capture session ready.");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onActive(@NonNull CameraCaptureSession session) {
|
|
||||||
Log.d(TAG, "Camera capture session active.");
|
|
||||||
resumeARCore();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onClosed(@NonNull CameraCaptureSession session) {
|
|
||||||
Log.d(TAG, "Camera capture session closed.");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onConfigureFailed(@NonNull CameraCaptureSession session) {
|
|
||||||
Log.e(TAG, "Failed to configure camera capture session.");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Repeating camera capture session capture callback.
|
|
||||||
private final CameraCaptureSession.CaptureCallback captureSessionCallback =
|
|
||||||
new CameraCaptureSession.CaptureCallback() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCaptureCompleted(
|
|
||||||
@NonNull CameraCaptureSession session,
|
|
||||||
@NonNull CaptureRequest request,
|
|
||||||
@NonNull TotalCaptureResult result) {
|
|
||||||
Log.i(TAG, "onCaptureCompleted");
|
|
||||||
}
|
|
||||||
|
|
||||||
//@Override // android 23
|
|
||||||
public void onCaptureBufferLost(
|
|
||||||
@NonNull CameraCaptureSession session,
|
|
||||||
@NonNull CaptureRequest request,
|
|
||||||
@NonNull Surface target,
|
|
||||||
long frameNumber) {
|
|
||||||
Log.e(TAG, "onCaptureBufferLost: " + frameNumber);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCaptureFailed(
|
|
||||||
@NonNull CameraCaptureSession session,
|
|
||||||
@NonNull CaptureRequest request,
|
|
||||||
@NonNull CaptureFailure failure) {
|
|
||||||
Log.e(TAG, "onCaptureFailed: " + failure.getFrameNumber() + " " + failure.getReason());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCaptureSequenceAborted(
|
|
||||||
@NonNull CameraCaptureSession session, int sequenceId) {
|
|
||||||
Log.e(TAG, "onCaptureSequenceAborted: " + sequenceId + " " + session);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private void resumeARCore() {
|
|
||||||
// Ensure that session is valid before triggering ARCore resume. Handles the case where the user
|
|
||||||
// manually uninstalls ARCore while the app is paused and then resumes.
|
|
||||||
if (sharedSession == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
Log.i(TAG, "Resume ARCore.");
|
|
||||||
// Resume ARCore.
|
|
||||||
sharedSession.resume();
|
|
||||||
// Set capture session callback while in AR mode.
|
|
||||||
sharedCamera.setCaptureCallback(captureSessionCallback, backgroundHandler);
|
|
||||||
} catch (CameraNotAvailableException e) {
|
|
||||||
Log.e(TAG, "Failed to resume ARCore session", e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Called when starting non-AR mode or switching to non-AR mode.
|
|
||||||
// Also called when app starts in AR mode, or resumes in AR mode.
|
|
||||||
private void setRepeatingCaptureRequest() {
|
|
||||||
try {
|
|
||||||
captureSession.setRepeatingRequest(
|
|
||||||
previewCaptureRequestBuilder.build(), captureSessionCallback, backgroundHandler);
|
|
||||||
} catch (CameraAccessException e) {
|
|
||||||
Log.e(TAG, "Failed to set repeating request", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void createCameraPreviewSession() {
|
|
||||||
Log.e(TAG, "createCameraPreviewSession: " + "starting camera preview session.");
|
|
||||||
try {
|
|
||||||
// Note that isGlAttached will be set to true in AR mode in onDrawFrame().
|
|
||||||
sharedSession.setCameraTextureName(cameraTextureId);
|
|
||||||
|
|
||||||
// Create an ARCore compatible capture request using `TEMPLATE_RECORD`.
|
|
||||||
previewCaptureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
|
|
||||||
|
|
||||||
// Build surfaces list, starting with ARCore provided surfaces.
|
|
||||||
List<Surface> surfaceList = sharedCamera.getArCoreSurfaces();
|
|
||||||
Log.e(TAG, " createCameraPreviewSession: " + "surfaceList: sharedCamera.getArCoreSurfaces(): " + surfaceList.size());
|
|
||||||
|
|
||||||
// Add a CPU image reader surface. On devices that don't support CPU image access, the image
|
|
||||||
// may arrive significantly later, or not arrive at all.
|
|
||||||
if (mTOFAvailable) surfaceList.add(mTOFImageReader.imageReader.getSurface());
|
|
||||||
// Surface list should now contain three surfacemReadymReadys:
|
|
||||||
// 0. sharedCamera.getSurfaceTexture()
|
|
||||||
// 1. …
|
|
||||||
// 2. depthImageReader.getSurface()
|
|
||||||
|
|
||||||
// Add ARCore surfaces and CPU image surface targets.
|
|
||||||
for (Surface surface : surfaceList) {
|
|
||||||
previewCaptureRequestBuilder.addTarget(surface);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wrap our callback in a shared camera callback.
|
|
||||||
CameraCaptureSession.StateCallback wrappedCallback = sharedCamera.createARSessionStateCallback(cameraCaptureCallback, backgroundHandler);
|
|
||||||
|
|
||||||
// Create camera capture session for camera preview using ARCore wrapped callback.
|
|
||||||
cameraDevice.createCaptureSession(surfaceList, wrappedCallback, backgroundHandler);
|
|
||||||
|
|
||||||
mReady.set(true);
|
|
||||||
} catch (CameraAccessException e) {
|
|
||||||
Log.e(TAG, "CameraAccessException", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start background handler thread, used to run callbacks without blocking UI thread.
|
|
||||||
private void startBackgroundThread() {
|
|
||||||
backgroundThread = new HandlerThread("sharedCameraBackground");
|
|
||||||
backgroundThread.start();
|
|
||||||
backgroundHandler = new Handler(backgroundThread.getLooper());
|
|
||||||
mTOFImageReader.startBackgroundThread();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stop background handler thread.
|
|
||||||
private void stopBackgroundThread() {
|
|
||||||
if (backgroundThread != null) {
|
|
||||||
backgroundThread.quitSafely();
|
|
||||||
try {
|
|
||||||
backgroundThread.join();
|
|
||||||
backgroundThread = null;
|
|
||||||
backgroundHandler = null;
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
Log.e(TAG, "Interrupted while trying to join background handler thread", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mTOFImageReader.stopBackgroundThread();
|
|
||||||
}
|
|
||||||
|
|
||||||
private long mPreviousTime = 0;
|
|
||||||
|
|
||||||
// Perform various checks, then open camera device and create CPU image reader.
|
|
||||||
public boolean openCamera() {
|
|
||||||
|
|
||||||
close();
|
|
||||||
|
|
||||||
startBackgroundThread();
|
|
||||||
|
|
||||||
mPreviousTime = System.currentTimeMillis();
|
|
||||||
|
|
||||||
if(cameraTextureId == -1)
|
|
||||||
{
|
|
||||||
int[] textures = new int[1];
|
|
||||||
GLES20.glGenTextures(1, textures, 0);
|
|
||||||
cameraTextureId = textures[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
Log.v(TAG + " opencamera: ", "Perform various checks, then open camera device and create CPU image reader.");
|
|
||||||
// Don't open camera if already opened.
|
|
||||||
if (cameraDevice != null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sharedSession == null) {
|
|
||||||
try {
|
|
||||||
// Create ARCore session that supports camera sharing.
|
|
||||||
sharedSession = new Session(mActivity, EnumSet.of(Session.Feature.SHARED_CAMERA));
|
|
||||||
} catch (UnavailableException e) {
|
|
||||||
Log.e(TAG, "Failed to create ARCore session that supports camera sharing", e);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enable auto focus mode while ARCore is running.
|
|
||||||
Config config = sharedSession.getConfig();
|
|
||||||
config.setFocusMode(Config.FocusMode.FIXED);
|
|
||||||
config.setUpdateMode(Config.UpdateMode.LATEST_CAMERA_IMAGE);
|
|
||||||
config.setPlaneFindingMode(Config.PlaneFindingMode.DISABLED);
|
|
||||||
config.setLightEstimationMode(Config.LightEstimationMode.DISABLED);
|
|
||||||
//config.setCloudAnchorMode(Config.CloudAnchorMode.ENABLED);
|
|
||||||
sharedSession.configure(config);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Store the ARCore shared camera reference.
|
|
||||||
sharedCamera = sharedSession.getSharedCamera();
|
|
||||||
// Store the ID of the camera used by ARCore.
|
|
||||||
cameraId = sharedSession.getCameraConfig().getCameraId();
|
|
||||||
initCamera(mActivity, cameraId, 1);
|
|
||||||
ArrayList<String> resolutions;
|
|
||||||
|
|
||||||
mTOFAvailable = false;
|
|
||||||
|
|
||||||
resolutions = getResolutions(mActivity, cameraId, ImageFormat.DEPTH16);
|
|
||||||
if (resolutions != null) {
|
|
||||||
for( String temp : resolutions) {
|
|
||||||
Log.e(TAG + "DEPTH16 resolution: ", temp);
|
|
||||||
};
|
|
||||||
if (resolutions.size()>0) mTOFAvailable = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Color CPU Image.
|
|
||||||
// Use the currently configured CPU image size.
|
|
||||||
//Size desiredCPUImageSize = sharedSession.getCameraConfig().getImageSize();
|
|
||||||
|
|
||||||
if (mTOFAvailable) mTOFImageReader.createImageReader(DEPTH_WIDTH, DEPTH_HEIGHT);
|
|
||||||
|
|
||||||
// When ARCore is running, make sure it also updates our CPU image surface.
|
|
||||||
if (mTOFAvailable) {
|
|
||||||
sharedCamera.setAppSurfaces(this.cameraId, Arrays.asList(mTOFImageReader.imageReader.getSurface()));
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
|
|
||||||
// Wrap our callback in a shared camera callback.
|
|
||||||
CameraDevice.StateCallback wrappedCallback = sharedCamera.createARDeviceStateCallback(cameraDeviceCallback, backgroundHandler);
|
|
||||||
|
|
||||||
// Store a reference to the camera system service.
|
|
||||||
cameraManager = (CameraManager) mActivity.getSystemService(Context.CAMERA_SERVICE);
|
|
||||||
|
|
||||||
// Get the characteristics for the ARCore camera.
|
|
||||||
//CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(this.cameraId);
|
|
||||||
|
|
||||||
// Open the camera device using the ARCore wrapped callback.
|
|
||||||
cameraManager.openCamera(cameraId, wrappedCallback, backgroundHandler);
|
|
||||||
|
|
||||||
} catch (CameraAccessException e) {
|
|
||||||
Log.e(TAG, "Failed to open camera", e);
|
|
||||||
return false;
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
Log.e(TAG, "Failed to open camera", e);
|
|
||||||
return false;
|
|
||||||
} catch (SecurityException e) {
|
|
||||||
Log.e(TAG, "Failed to open camera", e);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Log.i(TAG, " opencamera: TOF_available: " + mTOFAvailable);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Close the camera device.
|
|
||||||
public void close() {
|
|
||||||
|
|
||||||
if (sharedSession != null) {
|
|
||||||
sharedSession.pause();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (captureSession != null) {
|
|
||||||
captureSession.close();
|
|
||||||
captureSession = null;
|
|
||||||
}
|
|
||||||
if (cameraDevice != null) {
|
|
||||||
cameraDevice.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mTOFImageReader.imageReader != null) {
|
|
||||||
mTOFImageReader.imageReader.close();
|
|
||||||
mTOFImageReader.imageReader = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(cameraTextureId>=0)
|
|
||||||
{
|
|
||||||
GLES20.glDeleteTextures(1, new int[] {cameraTextureId}, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
stopBackgroundThread();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************** ONDRAWFRAME ARCORE ************************************************************* */
|
|
||||||
|
|
||||||
// Draw frame when in AR mode. Called on the GL thread.
|
|
||||||
public void updateGL() throws CameraNotAvailableException {
|
|
||||||
|
|
||||||
if(!mReady.get())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mTOFAvailable && mTOFImageReader.frameCount == 0) return;
|
|
||||||
|
|
||||||
// Perform ARCore per-frame update.
|
|
||||||
Frame frame = null;
|
|
||||||
try {
|
|
||||||
frame = sharedSession.update();
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Camera camera = null;
|
|
||||||
if (frame != null) {
|
|
||||||
camera = frame.getCamera();
|
|
||||||
}else
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (camera == null) return;
|
|
||||||
// If not tracking, don't draw 3D objects.
|
|
||||||
if (camera.getTrackingState() == TrackingState.PAUSED) return;
|
|
||||||
|
|
||||||
if (frame.getTimestamp() != 0) {
|
|
||||||
|
|
||||||
Pose pose = camera.getPose();
|
|
||||||
if(!RTABMapActivity.DISABLE_LOG) Log.d(TAG, String.format("pose=%f %f %f q=%f %f %f %f", pose.tx(), pose.ty(), pose.tz(), pose.qx(), pose.qy(), pose.qz(), pose.qw()));
|
|
||||||
RTABMapLib.postCameraPoseEvent(RTABMapActivity.nativeApplication, pose.tx(), pose.ty(), pose.tz(), pose.qx(), pose.qy(), pose.qz(), pose.qw());
|
|
||||||
|
|
||||||
int rateMs = 100; // send images at most 10 Hz
|
|
||||||
if(System. currentTimeMillis() - mPreviousTime < rateMs)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
mPreviousTime = System. currentTimeMillis();
|
|
||||||
|
|
||||||
CameraIntrinsics intrinsics = camera.getImageIntrinsics();
|
|
||||||
try{
|
|
||||||
Image image = frame.acquireCameraImage();
|
|
||||||
PointCloud cloud = frame.acquirePointCloud();
|
|
||||||
FloatBuffer points = cloud.getPoints();
|
|
||||||
|
|
||||||
if (image.getFormat() != ImageFormat.YUV_420_888) {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"Expected image in YUV_420_888 format, got format " + image.getFormat());
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!RTABMapActivity.DISABLE_LOG)
|
|
||||||
{
|
|
||||||
for(int i =0;i<image.getPlanes().length;++i)
|
|
||||||
{
|
|
||||||
Log.d(TAG, String.format("Plane[%d] pixel stride = %d, row stride = %d", i, image.getPlanes()[i].getPixelStride(), image.getPlanes()[i].getRowStride()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
float[] fl = intrinsics.getFocalLength();
|
|
||||||
float[] pp = intrinsics.getPrincipalPoint();
|
|
||||||
if(!RTABMapActivity.DISABLE_LOG) Log.d(TAG, String.format("fx=%f fy=%f cx=%f cy=%f", fl[0], fl[1], pp[0], pp[1]));
|
|
||||||
|
|
||||||
ByteBuffer y = image.getPlanes()[0].getBuffer().asReadOnlyBuffer();
|
|
||||||
ByteBuffer u = image.getPlanes()[1].getBuffer().asReadOnlyBuffer();
|
|
||||||
ByteBuffer v = image.getPlanes()[2].getBuffer().asReadOnlyBuffer();
|
|
||||||
|
|
||||||
double stamp = (double)image.getTimestamp()/10e8;
|
|
||||||
if(!RTABMapActivity.DISABLE_LOG) Log.d(TAG, String.format("RGB %dx%d len=%dbytes format=%d =%f",
|
|
||||||
image.getWidth(), image.getHeight(), y.limit(), image.getFormat(), stamp));
|
|
||||||
|
|
||||||
if(mTOFAvailable)
|
|
||||||
{
|
|
||||||
if(!RTABMapActivity.DISABLE_LOG) Log.d(TAG, String.format("Depth %dx%d len=%dbytes format=%d stamp=%f",
|
|
||||||
mTOFImageReader.WIDTH, mTOFImageReader.HEIGHT, mTOFImageReader.depth16_raw.limit(), ImageFormat.DEPTH16, (double)mTOFImageReader.timestamp/10e9));
|
|
||||||
|
|
||||||
RTABMapLib.postOdometryEvent(
|
|
||||||
RTABMapActivity.nativeApplication,
|
|
||||||
pose.tx(), pose.ty(), pose.tz(), pose.qx(), pose.qy(), pose.qz(), pose.qw(),
|
|
||||||
fl[0], fl[1], pp[0], pp[1], stamp,
|
|
||||||
y, u, v, y.limit(), image.getWidth(), image.getHeight(), image.getFormat(),
|
|
||||||
mTOFImageReader.depth16_raw, mTOFImageReader.depth16_raw.limit(), mTOFImageReader.WIDTH, mTOFImageReader.HEIGHT, ImageFormat.DEPTH16,
|
|
||||||
points, points.limit()/4);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ByteBuffer bb = ByteBuffer.allocate(0);
|
|
||||||
RTABMapLib.postOdometryEvent(
|
|
||||||
RTABMapActivity.nativeApplication,
|
|
||||||
pose.tx(), pose.ty(), pose.tz(), pose.qx(), pose.qy(), pose.qz(), pose.qw(),
|
|
||||||
fl[0], fl[1], pp[0], pp[1], stamp,
|
|
||||||
y, u, v, y.limit(), image.getWidth(), image.getHeight(), image.getFormat(),
|
|
||||||
bb, 0, 0, 0, ImageFormat.DEPTH16,
|
|
||||||
points, points.limit()/4);
|
|
||||||
}
|
|
||||||
|
|
||||||
image.close();
|
|
||||||
cloud.close();
|
|
||||||
|
|
||||||
} catch (NotYetAvailableException e) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************************************* */
|
|
||||||
/*************************************************** End ************************************************************* */
|
|
||||||
/********************************************************************************************************************* */
|
|
||||||
|
|
||||||
|
|
||||||
public ArrayList<String> getResolutions (Context context, String cameraId,int imageFormat){
|
|
||||||
Log.v(TAG + "getResolutions:", " cameraId:" + cameraId + " imageFormat: " + imageFormat);
|
|
||||||
|
|
||||||
ArrayList<String> output = new ArrayList<String>();
|
|
||||||
try {
|
|
||||||
CameraManager manager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
|
|
||||||
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
|
|
||||||
|
|
||||||
for (android.util.Size s : characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP).getOutputSizes(imageFormat)) {
|
|
||||||
output.add(s.getWidth() + "x" + s.getHeight());
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void initCamera (Context context, String cameraId,int index){
|
|
||||||
boolean ok = false;
|
|
||||||
try {
|
|
||||||
int current = 0;
|
|
||||||
CameraManager manager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
|
|
||||||
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
|
|
||||||
for (android.util.Size s : characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP).getOutputSizes(ImageFormat.DEPTH16)) {
|
|
||||||
ok = true;
|
|
||||||
if (current == index)
|
|
||||||
break;
|
|
||||||
else ;
|
|
||||||
current++;
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
if (!ok) {
|
|
||||||
Log.e(TAG + " initCamera", "Depth sensor not found!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -90,9 +90,9 @@ import android.widget.SeekBar.OnSeekBarChangeListener;
|
|||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
import android.widget.ToggleButton;
|
import android.widget.ToggleButton;
|
||||||
|
|
||||||
import com.google.ar.core.ArCoreApk;
|
//import com.google.ar.core.ArCoreApk;
|
||||||
import com.google.atap.tangoservice.Tango;
|
import com.google.atap.tangoservice.Tango;
|
||||||
import com.huawei.hiar.AREnginesApk;
|
//import com.huawei.hiar.AREnginesApk;
|
||||||
|
|
||||||
|
|
||||||
// The main activity of the application. This activity shows debug information
|
// The main activity of the application. This activity shows debug information
|
||||||
@@ -254,7 +254,7 @@ public class RTABMapActivity extends FragmentActivity implements OnClickListener
|
|||||||
|
|
||||||
GestureDetector mGesDetect = null;
|
GestureDetector mGesDetect = null;
|
||||||
|
|
||||||
ARCoreSharedCamera mArCoreCamera = null;
|
//ARCoreSharedCamera mArCoreCamera = null;
|
||||||
int mCameraDriver = 0;
|
int mCameraDriver = 0;
|
||||||
|
|
||||||
//Tango Service connection.
|
//Tango Service connection.
|
||||||
@@ -586,8 +586,8 @@ public class RTABMapActivity extends FragmentActivity implements OnClickListener
|
|||||||
String cameraDriverStr = sharedPref.getString(getString(R.string.pref_key_camera_driver), getString(R.string.pref_default_camera_driver));
|
String cameraDriverStr = sharedPref.getString(getString(R.string.pref_key_camera_driver), getString(R.string.pref_default_camera_driver));
|
||||||
mCameraDriver = Integer.parseInt(cameraDriverStr);
|
mCameraDriver = Integer.parseInt(cameraDriverStr);
|
||||||
|
|
||||||
isArCoreAvailable();
|
//isArCoreAvailable();
|
||||||
isArEngineAvailable();
|
//isArEngineAvailable();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Should be called only if read/write permissions are granted!
|
// Should be called only if read/write permissions are granted!
|
||||||
@@ -613,7 +613,7 @@ public class RTABMapActivity extends FragmentActivity implements OnClickListener
|
|||||||
Log.i(TAG, String.format("updateCameraDriverSettings() mCameraDriver=%d RTABMapLib.isBuiltWith(%d)=%d", mCameraDriver, mCameraDriver, RTABMapLib.isBuiltWith(nativeApplication, mCameraDriver)?1:0));
|
Log.i(TAG, String.format("updateCameraDriverSettings() mCameraDriver=%d RTABMapLib.isBuiltWith(%d)=%d", mCameraDriver, mCameraDriver, RTABMapLib.isBuiltWith(nativeApplication, mCameraDriver)?1:0));
|
||||||
|
|
||||||
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
|
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
|
||||||
|
/*
|
||||||
if(mCameraDriver == 0 && (!CheckTangoCoreVersion(MIN_TANGO_CORE_VERSION) || !RTABMapLib.isBuiltWith(nativeApplication, 0)))
|
if(mCameraDriver == 0 && (!CheckTangoCoreVersion(MIN_TANGO_CORE_VERSION) || !RTABMapLib.isBuiltWith(nativeApplication, 0)))
|
||||||
{
|
{
|
||||||
if(mIsAREngineAvailable && RTABMapLib.isBuiltWith(nativeApplication, 2))
|
if(mIsAREngineAvailable && RTABMapLib.isBuiltWith(nativeApplication, 2))
|
||||||
@@ -659,9 +659,9 @@ public class RTABMapActivity extends FragmentActivity implements OnClickListener
|
|||||||
editor.putString(getString(R.string.pref_key_camera_driver), "3");
|
editor.putString(getString(R.string.pref_key_camera_driver), "3");
|
||||||
editor.commit();
|
editor.commit();
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
private void isArCoreAvailable() {
|
private void isArCoreAvailable() {
|
||||||
ArCoreApk.Availability availability = ArCoreApk.getInstance().checkAvailability(this);
|
ArCoreApk.Availability availability = ArCoreApk.getInstance().checkAvailability(this);
|
||||||
if (availability.isTransient()) {
|
if (availability.isTransient()) {
|
||||||
@@ -713,7 +713,7 @@ public class RTABMapActivity extends FragmentActivity implements OnClickListener
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void onDestroy() {
|
public void onDestroy() {
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
@@ -992,6 +992,7 @@ public class RTABMapActivity extends FragmentActivity implements OnClickListener
|
|||||||
RTABMapLib.setRawScanSaved(nativeApplication, sharedPref.getBoolean(getString(R.string.pref_key_raw_scan_saved), Boolean.parseBoolean(getString(R.string.pref_default_raw_scan_saved))));
|
RTABMapLib.setRawScanSaved(nativeApplication, sharedPref.getBoolean(getString(R.string.pref_key_raw_scan_saved), Boolean.parseBoolean(getString(R.string.pref_default_raw_scan_saved))));
|
||||||
RTABMapLib.setFullResolution(nativeApplication, sharedPref.getBoolean(getString(R.string.pref_key_resolution), Boolean.parseBoolean(getString(R.string.pref_default_resolution))));
|
RTABMapLib.setFullResolution(nativeApplication, sharedPref.getBoolean(getString(R.string.pref_key_resolution), Boolean.parseBoolean(getString(R.string.pref_default_resolution))));
|
||||||
RTABMapLib.setSmoothing(nativeApplication, sharedPref.getBoolean(getString(R.string.pref_key_smoothing), Boolean.parseBoolean(getString(R.string.pref_default_smoothing))));
|
RTABMapLib.setSmoothing(nativeApplication, sharedPref.getBoolean(getString(R.string.pref_key_smoothing), Boolean.parseBoolean(getString(R.string.pref_default_smoothing))));
|
||||||
|
RTABMapLib.setDepthFromMotion(nativeApplication, sharedPref.getBoolean(getString(R.string.pref_key_depth_from_motion), Boolean.parseBoolean(getString(R.string.pref_default_depth_from_motion))));
|
||||||
RTABMapLib.setCameraColor(nativeApplication, !sharedPref.getBoolean(getString(R.string.pref_key_fisheye), Boolean.parseBoolean(getString(R.string.pref_default_fisheye))));
|
RTABMapLib.setCameraColor(nativeApplication, !sharedPref.getBoolean(getString(R.string.pref_key_fisheye), Boolean.parseBoolean(getString(R.string.pref_default_fisheye))));
|
||||||
RTABMapLib.setAppendMode(nativeApplication, sharedPref.getBoolean(getString(R.string.pref_key_append), Boolean.parseBoolean(getString(R.string.pref_default_append))));
|
RTABMapLib.setAppendMode(nativeApplication, sharedPref.getBoolean(getString(R.string.pref_key_append), Boolean.parseBoolean(getString(R.string.pref_default_append))));
|
||||||
RTABMapLib.setMappingParameter(nativeApplication, "Rtabmap/DetectionRate", mUpdateRate);
|
RTABMapLib.setMappingParameter(nativeApplication, "Rtabmap/DetectionRate", mUpdateRate);
|
||||||
@@ -1162,6 +1163,7 @@ public class RTABMapActivity extends FragmentActivity implements OnClickListener
|
|||||||
|
|
||||||
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
|
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
|
||||||
String cameraDriverStr = sharedPref.getString(getString(R.string.pref_key_camera_driver), getString(R.string.pref_default_camera_driver));
|
String cameraDriverStr = sharedPref.getString(getString(R.string.pref_key_camera_driver), getString(R.string.pref_default_camera_driver));
|
||||||
|
final boolean depthFromMotion = sharedPref.getBoolean(getString(R.string.pref_key_depth_from_motion), Boolean.parseBoolean(getString(R.string.pref_default_depth_from_motion)));
|
||||||
mCameraDriver = Integer.parseInt(cameraDriverStr);
|
mCameraDriver = Integer.parseInt(cameraDriverStr);
|
||||||
|
|
||||||
if(!DISABLE_LOG) Log.i(TAG, String.format("startCamera() driver=%d", mCameraDriver));
|
if(!DISABLE_LOG) Log.i(TAG, String.format("startCamera() driver=%d", mCameraDriver));
|
||||||
@@ -1197,7 +1199,7 @@ public class RTABMapActivity extends FragmentActivity implements OnClickListener
|
|||||||
mToast.makeText(this, "Current camera driver selected is Tango, but Tango service binding failed. Abort scanning...", mToast.LENGTH_LONG).show();
|
mToast.makeText(this, "Current camera driver selected is Tango, but Tango service binding failed. Abort scanning...", mToast.LENGTH_LONG).show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}/*
|
||||||
else if(mCameraDriver == 1 || mCameraDriver == 2 || mCameraDriver == 3)
|
else if(mCameraDriver == 1 || mCameraDriver == 2 || mCameraDriver == 3)
|
||||||
{
|
{
|
||||||
if((mCameraDriver == 1 || mCameraDriver == 3) && !mIsARCoreAvailable)
|
if((mCameraDriver == 1 || mCameraDriver == 3) && !mIsARCoreAvailable)
|
||||||
@@ -1218,7 +1220,8 @@ public class RTABMapActivity extends FragmentActivity implements OnClickListener
|
|||||||
}
|
}
|
||||||
Thread bindThread = new Thread(new Runnable() {
|
Thread bindThread = new Thread(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
if(mCameraDriver==1)
|
|
||||||
|
if(mCameraDriver==1 && !depthFromMotion)
|
||||||
{
|
{
|
||||||
RTABMapLib.setMeshRendering(
|
RTABMapLib.setMeshRendering(
|
||||||
nativeApplication,
|
nativeApplication,
|
||||||
@@ -1263,9 +1266,9 @@ public class RTABMapActivity extends FragmentActivity implements OnClickListener
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if((mState==State.STATE_IDLE || mState==State.STATE_WELCOME) && mCameraDriver == 1)
|
if((mState==State.STATE_IDLE || mState==State.STATE_WELCOME) && mCameraDriver == 1 && !depthFromMotion)
|
||||||
{
|
{
|
||||||
mToast.makeText(getApplicationContext(), "Currently ARCore NDK driver doesn't support depth, only poses and RGB images can be recorded.", mToast.LENGTH_LONG).show();
|
mToast.makeText(getApplicationContext(), "Currently ARCore NDK driver doesn't support depth, only poses, RGB images and 3d features can be recorded.", mToast.LENGTH_LONG).show();
|
||||||
}
|
}
|
||||||
updateState(mState==State.STATE_VISUALIZING?State.STATE_VISUALIZING_CAMERA:State.STATE_CAMERA);
|
updateState(mState==State.STATE_VISUALIZING?State.STATE_VISUALIZING_CAMERA:State.STATE_CAMERA);
|
||||||
if(mState==State.STATE_VISUALIZING_CAMERA && mItemLocalizationMode.isChecked())
|
if(mState==State.STATE_VISUALIZING_CAMERA && mItemLocalizationMode.isChecked())
|
||||||
@@ -1278,7 +1281,7 @@ public class RTABMapActivity extends FragmentActivity implements OnClickListener
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
bindThread.start();
|
bindThread.start();
|
||||||
}
|
}*/
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mToast.makeText(this, "Supported camera driver not found! Cannot start a new scan.", mToast.LENGTH_LONG).show();
|
mToast.makeText(this, "Supported camera driver not found! Cannot start a new scan.", mToast.LENGTH_LONG).show();
|
||||||
@@ -2271,14 +2274,14 @@ public class RTABMapActivity extends FragmentActivity implements OnClickListener
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mArCoreCamera != null)
|
/* if(mArCoreCamera != null)
|
||||||
{
|
{
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
mRenderer.setCamera(null);
|
mRenderer.setCamera(null);
|
||||||
mArCoreCamera.close();
|
mArCoreCamera.close();
|
||||||
mArCoreCamera = null;
|
mArCoreCamera = null;
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
Thread stopThread = new Thread(new Runnable() {
|
Thread stopThread = new Thread(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
@@ -2311,6 +2314,15 @@ public class RTABMapActivity extends FragmentActivity implements OnClickListener
|
|||||||
|
|
||||||
updateState(State.STATE_IDLE);
|
updateState(State.STATE_IDLE);
|
||||||
|
|
||||||
|
/*if(mArCoreCamera != null)
|
||||||
|
{
|
||||||
|
synchronized (this) {
|
||||||
|
mRenderer.setCamera(null);
|
||||||
|
mArCoreCamera.close();
|
||||||
|
mArCoreCamera = null;
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
Thread stopThread = new Thread(new Runnable() {
|
Thread stopThread = new Thread(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
if(!DISABLE_LOG) Log.i(TAG, String.format("setPausedMapping()"));
|
if(!DISABLE_LOG) Log.i(TAG, String.format("setPausedMapping()"));
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ public class RTABMapLib
|
|||||||
public static native void setRawScanSaved(long nativeApplication, boolean enabled);
|
public static native void setRawScanSaved(long nativeApplication, boolean enabled);
|
||||||
public static native void setFullResolution(long nativeApplication, boolean enabled);
|
public static native void setFullResolution(long nativeApplication, boolean enabled);
|
||||||
public static native void setSmoothing(long nativeApplication, boolean enabled);
|
public static native void setSmoothing(long nativeApplication, boolean enabled);
|
||||||
|
public static native void setDepthFromMotion(long nativeApplication, boolean enabled);
|
||||||
public static native void setCameraColor(long nativeApplication, boolean enabled);
|
public static native void setCameraColor(long nativeApplication, boolean enabled);
|
||||||
public static native void setAppendMode(long nativeApplication, boolean enabled);
|
public static native void setAppendMode(long nativeApplication, boolean enabled);
|
||||||
public static native void setDataRecorderMode(long nativeApplication, boolean enabled);
|
public static native void setDataRecorderMode(long nativeApplication, boolean enabled);
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ public class Renderer implements GLSurfaceView.Renderer {
|
|||||||
private float mSurfaceHeight = 0.0f;
|
private float mSurfaceHeight = 0.0f;
|
||||||
private float mTextColor = 1.0f;
|
private float mTextColor = 1.0f;
|
||||||
private int mOffset = 0;
|
private int mOffset = 0;
|
||||||
private ARCoreSharedCamera mCamera = null;
|
//private ARCoreSharedCamera mCamera = null;
|
||||||
|
|
||||||
private Vector<TextObject> mTexts;
|
private Vector<TextObject> mTexts;
|
||||||
|
|
||||||
@@ -73,10 +73,10 @@ public class Renderer implements GLSurfaceView.Renderer {
|
|||||||
mOffset = offset;
|
mOffset = offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCamera(ARCoreSharedCamera camera)
|
//public void setCamera(ARCoreSharedCamera camera)
|
||||||
{
|
//{
|
||||||
mCamera = camera;
|
// mCamera = camera;
|
||||||
}
|
//}
|
||||||
|
|
||||||
// Render loop of the Gl context.
|
// Render loop of the Gl context.
|
||||||
public void onDrawFrame(GL10 useGLES20instead) {
|
public void onDrawFrame(GL10 useGLES20instead) {
|
||||||
@@ -86,10 +86,10 @@ public class Renderer implements GLSurfaceView.Renderer {
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if(mCamera!=null)
|
// if(mCamera!=null)
|
||||||
{
|
// {
|
||||||
mCamera.updateGL();
|
// mCamera.updateGL();
|
||||||
}
|
// }
|
||||||
|
|
||||||
final int value = RTABMapLib.render(mActivity.nativeApplication);
|
final int value = RTABMapLib.render(mActivity.nativeApplication);
|
||||||
|
|
||||||
|
|||||||
@@ -361,7 +361,7 @@ public class SettingsActivity extends PreferenceActivity implements OnSharedPref
|
|||||||
ed.commit(); //save it.
|
ed.commit(); //save it.
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] results) {
|
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] results) {
|
||||||
|
|
||||||
switch (requestCode) {
|
switch (requestCode) {
|
||||||
|
|||||||
@@ -1,87 +0,0 @@
|
|||||||
package com.introlab.rtabmap;
|
|
||||||
|
|
||||||
|
|
||||||
import android.graphics.ImageFormat;
|
|
||||||
import android.media.Image;
|
|
||||||
import android.media.ImageReader;
|
|
||||||
import android.os.Handler;
|
|
||||||
import android.os.HandlerThread;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
|
|
||||||
public class TOF_ImageReader implements ImageReader.OnImageAvailableListener {
|
|
||||||
|
|
||||||
public int WIDTH;
|
|
||||||
public int HEIGHT;
|
|
||||||
public ImageReader imageReader;
|
|
||||||
public int frameCount = 0;
|
|
||||||
public long timestamp;
|
|
||||||
|
|
||||||
// Looper handler thread.
|
|
||||||
private HandlerThread backgroundThread;
|
|
||||||
// Looper handler.
|
|
||||||
private Handler backgroundHandler;
|
|
||||||
|
|
||||||
public ByteBuffer depth16_raw;
|
|
||||||
|
|
||||||
TOF_ImageReader(){
|
|
||||||
}
|
|
||||||
|
|
||||||
public void createImageReader(int width, int height){
|
|
||||||
this.WIDTH = width;
|
|
||||||
this.HEIGHT = height;
|
|
||||||
this.imageReader =
|
|
||||||
ImageReader.newInstance(
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
ImageFormat.DEPTH16,
|
|
||||||
2);
|
|
||||||
this.imageReader.setOnImageAvailableListener(this, this.backgroundHandler);
|
|
||||||
}
|
|
||||||
|
|
||||||
// CPU image reader callback.
|
|
||||||
@Override
|
|
||||||
public void onImageAvailable(ImageReader imageReader) {
|
|
||||||
Image image = imageReader.acquireLatestImage();
|
|
||||||
if (image == null) {
|
|
||||||
Log.w("RTABMapActivity", "onImageAvailable: Skipping null image.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
if(image.getFormat() == ImageFormat.DEPTH16){
|
|
||||||
this.timestamp = image.getTimestamp();
|
|
||||||
depth16_raw = image.getPlanes()[0].getBuffer().asReadOnlyBuffer();
|
|
||||||
// copy raw undecoded DEPTH16 format depth data to NativeBuffer
|
|
||||||
frameCount++;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
Log.w("RTABMapActivity", "onImageAvailable: depth image not in DEPTH16 format, skipping image");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
image.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start background handler thread, used to run callbacks without blocking UI thread.
|
|
||||||
public void startBackgroundThread() {
|
|
||||||
this.backgroundThread = new HandlerThread("DepthDecoderThread");
|
|
||||||
this.backgroundThread.start();
|
|
||||||
this.backgroundHandler = new Handler(backgroundThread.getLooper());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stop background handler thread.
|
|
||||||
public void stopBackgroundThread() {
|
|
||||||
if (this.backgroundThread != null) {
|
|
||||||
this.backgroundThread.quitSafely();
|
|
||||||
try {
|
|
||||||
this.backgroundThread.join();
|
|
||||||
this.backgroundThread = null;
|
|
||||||
this.backgroundHandler = null;
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
Log.e("RTABMapActivity", "Interrupted while trying to join depth background handler thread", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
+29
-17
@@ -137,6 +137,16 @@ IF(BUILD_AS_BUNDLE AND (APPLE OR WIN32))
|
|||||||
DESTINATION ${openni2_dest_dir}
|
DESTINATION ${openni2_dest_dir}
|
||||||
COMPONENT runtime)
|
COMPONENT runtime)
|
||||||
ENDIF(OpenNI2_FOUND)
|
ENDIF(OpenNI2_FOUND)
|
||||||
|
|
||||||
|
IF(k4a_FOUND)
|
||||||
|
# Install needed depthengine_2_0.dll
|
||||||
|
IF(WIN32)
|
||||||
|
file(TO_CMAKE_PATH "$ENV{K4A_ROOT_DIR}" ENV_K4A_ROOT_DIR)
|
||||||
|
INSTALL(FILES "${ENV_K4A_ROOT_DIR}/tools/depthengine_2_0.dll"
|
||||||
|
DESTINATION ${plugin_dest_dir}
|
||||||
|
COMPONENT runtime)
|
||||||
|
ENDIF(WIN32)
|
||||||
|
ENDIF(k4a_FOUND)
|
||||||
|
|
||||||
# Install needed Qt plugins by copying directories from the qt installation
|
# Install needed Qt plugins by copying directories from the qt installation
|
||||||
# One can cull what gets copied by using 'REGEX "..." EXCLUDE'
|
# One can cull what gets copied by using 'REGEX "..." EXCLUDE'
|
||||||
@@ -156,26 +166,28 @@ IF(BUILD_AS_BUNDLE AND (APPLE OR WIN32))
|
|||||||
list(GET loc_list 1 plugin_type)
|
list(GET loc_list 1 plugin_type)
|
||||||
IF(NOT plugin_root)
|
IF(NOT plugin_root)
|
||||||
get_filename_component(plugin_root ${plugin_dir} DIRECTORY)
|
get_filename_component(plugin_root ${plugin_dir} DIRECTORY)
|
||||||
ENDIF(NOT plugin_root)
|
ENDIF(NOT plugin_root)
|
||||||
#MESSAGE(STATUS "Qt5 plugin \"${plugin_loc}\" installed in \"${plugin_dest_dir}/plugins${plugin_type}\"")
|
#MESSAGE(STATUS "Qt5 plugin \"${plugin_loc}\" installed in \"${plugin_dest_dir}/plugins${plugin_type}\"")
|
||||||
INSTALL(FILES ${plugin_loc}
|
INSTALL(FILES ${plugin_loc}
|
||||||
DESTINATION ${plugin_dest_dir}/plugins${plugin_type}
|
DESTINATION ${plugin_dest_dir}/plugins${plugin_type}
|
||||||
COMPONENT runtime)
|
COMPONENT runtime)
|
||||||
endforeach()
|
endforeach()
|
||||||
IF(WIN32)
|
IF(NOT Qt5Widgets_VERSION VERSION_LESS 5.10.0)
|
||||||
IF(NOT Qt5Widgets_VERSION VERSION_LESS 5.10.0)
|
IF(WIN32)
|
||||||
SET(plugin_loc "${plugin_root}/styles/qwindowsvistastyle.dll")
|
SET(plugin_loc "${plugin_root}/styles/qwindowsvistastyle.dll")
|
||||||
IF(EXISTS ${plugin_loc})
|
ELSEIF(APPLE)
|
||||||
get_filename_component(plugin_dir ${plugin_loc} DIRECTORY)
|
SET(plugin_loc "${plugin_root}/styles/libqmacstyle.dylib")
|
||||||
string(REPLACE "plugins" ";" loc_list ${plugin_dir})
|
ENDIF()
|
||||||
list(GET loc_list 1 plugin_type)
|
IF(EXISTS ${plugin_loc})
|
||||||
INSTALL(FILES ${plugin_loc}
|
get_filename_component(plugin_dir ${plugin_loc} DIRECTORY)
|
||||||
DESTINATION ${plugin_dest_dir}/plugins${plugin_type}
|
string(REPLACE "plugins" ";" loc_list ${plugin_dir})
|
||||||
COMPONENT runtime)
|
list(GET loc_list 1 plugin_type)
|
||||||
#MESSAGE(STATUS "Qt5 plugin \"${plugin_loc}\" installed in \"${plugin_dest_dir}/plugins${plugin_type}\"")
|
INSTALL(FILES ${plugin_loc}
|
||||||
ENDIF(EXISTS ${plugin_loc})
|
DESTINATION ${plugin_dest_dir}/plugins${plugin_type}
|
||||||
ENDIF(NOT Qt5Widgets_VERSION VERSION_LESS 5.10.0)
|
COMPONENT runtime)
|
||||||
ENDIF(WIN32)
|
#MESSAGE(STATUS "Qt5 plugin \"${plugin_loc}\" installed in \"${plugin_dest_dir}/plugins${plugin_type}\"")
|
||||||
|
ENDIF(EXISTS ${plugin_loc})
|
||||||
|
ENDIF(NOT Qt5Widgets_VERSION VERSION_LESS 5.10.0)
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
# install a qt.conf file
|
# install a qt.conf file
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ public:
|
|||||||
virtual ~Camera();
|
virtual ~Camera();
|
||||||
SensorData takeImage(CameraInfo * info = 0);
|
SensorData takeImage(CameraInfo * info = 0);
|
||||||
|
|
||||||
|
bool initFromFile(const std::string & calibrationPath);
|
||||||
virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = "") = 0;
|
virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = "") = 0;
|
||||||
virtual bool isCalibrated() const = 0;
|
virtual bool isCalibrated() const = 0;
|
||||||
virtual std::string getSerial() const = 0;
|
virtual std::string getSerial() const = 0;
|
||||||
@@ -73,7 +74,7 @@ protected:
|
|||||||
*
|
*
|
||||||
* @param imageRate : image/second , 0 for fast as the camera can
|
* @param imageRate : image/second , 0 for fast as the camera can
|
||||||
*/
|
*/
|
||||||
Camera(float imageRate = 0, const Transform & localTransform = Transform::getIdentity());
|
Camera(float imageRate = 0, const Transform & localTransform = CameraModel::opticalRotation());
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* returned rgb and depth images should be already rectified if calibration was loaded
|
* returned rgb and depth images should be already rectified if calibration was loaded
|
||||||
|
|||||||
@@ -37,6 +37,13 @@ namespace rtabmap {
|
|||||||
|
|
||||||
class RTABMAP_EXP CameraModel
|
class RTABMAP_EXP CameraModel
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Optical rotation used to transform image coordinate frame (x->right, y->down, z->forward)
|
||||||
|
* to robot coordinate frame (x->forward, y->left, z->up).
|
||||||
|
*/
|
||||||
|
static Transform opticalRotation() {return Transform(0,0,1,0, -1,0,0,0, 0,-1,0,0);}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CameraModel();
|
CameraModel();
|
||||||
// K is the camera intrinsic 3x3 CV_64FC1
|
// K is the camera intrinsic 3x3 CV_64FC1
|
||||||
@@ -50,7 +57,7 @@ public:
|
|||||||
const cv::Mat & D,
|
const cv::Mat & D,
|
||||||
const cv::Mat & R,
|
const cv::Mat & R,
|
||||||
const cv::Mat & P,
|
const cv::Mat & P,
|
||||||
const Transform & localTransform = Transform::getIdentity());
|
const Transform & localTransform = opticalRotation());
|
||||||
|
|
||||||
// minimal
|
// minimal
|
||||||
CameraModel(
|
CameraModel(
|
||||||
@@ -58,7 +65,7 @@ public:
|
|||||||
double fy,
|
double fy,
|
||||||
double cx,
|
double cx,
|
||||||
double cy,
|
double cy,
|
||||||
const Transform & localTransform = Transform::getIdentity(),
|
const Transform & localTransform = opticalRotation(),
|
||||||
double Tx = 0.0f,
|
double Tx = 0.0f,
|
||||||
const cv::Size & imageSize = cv::Size(0,0));
|
const cv::Size & imageSize = cv::Size(0,0));
|
||||||
// minimal to be saved
|
// minimal to be saved
|
||||||
@@ -68,7 +75,7 @@ public:
|
|||||||
double fy,
|
double fy,
|
||||||
double cx,
|
double cx,
|
||||||
double cy,
|
double cy,
|
||||||
const Transform & localTransform = Transform::getIdentity(),
|
const Transform & localTransform = opticalRotation(),
|
||||||
double Tx = 0.0f,
|
double Tx = 0.0f,
|
||||||
const cv::Size & imageSize = cv::Size(0,0));
|
const cv::Size & imageSize = cv::Size(0,0));
|
||||||
|
|
||||||
@@ -113,6 +120,12 @@ public:
|
|||||||
int imageWidth() const {return imageSize_.width;}
|
int imageWidth() const {return imageSize_.width;}
|
||||||
int imageHeight() const {return imageSize_.height;}
|
int imageHeight() const {return imageSize_.height;}
|
||||||
|
|
||||||
|
double fovX() const; // in radians
|
||||||
|
double fovY() const; // in radians
|
||||||
|
double horizontalFOV() const; // in degrees
|
||||||
|
double verticalFOV() const; // in degrees
|
||||||
|
|
||||||
|
bool load(const std::string & filePath);
|
||||||
bool load(const std::string & directory, const std::string & cameraName);
|
bool load(const std::string & directory, const std::string & cameraName);
|
||||||
bool save(const std::string & directory) const;
|
bool save(const std::string & directory) const;
|
||||||
std::vector<unsigned char> serialize() const;
|
std::vector<unsigned char> serialize() const;
|
||||||
@@ -122,9 +135,6 @@ public:
|
|||||||
CameraModel scaled(double scale) const;
|
CameraModel scaled(double scale) const;
|
||||||
CameraModel roi(const cv::Rect & roi) const;
|
CameraModel roi(const cv::Rect & roi) const;
|
||||||
|
|
||||||
double horizontalFOV() const; // in degrees
|
|
||||||
double verticalFOV() const; // in degrees
|
|
||||||
|
|
||||||
// For depth images, your should use cv::INTER_NEAREST
|
// For depth images, your should use cv::INTER_NEAREST
|
||||||
cv::Mat rectifyImage(const cv::Mat & raw, int interpolation = cv::INTER_LINEAR) const;
|
cv::Mat rectifyImage(const cv::Mat & raw, int interpolation = cv::INTER_LINEAR) const;
|
||||||
cv::Mat rectifyDepth(const cv::Mat & raw) const;
|
cv::Mat rectifyDepth(const cv::Mat & raw) const;
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ public:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
void addInfoAfterRun(int stMemSize, int lastSignAdded, int processMemUsed, int databaseMemUsed, int dictionarySize, const ParametersMap & parameters) const;
|
void addInfoAfterRun(int stMemSize, int lastSignAdded, int processMemUsed, int databaseMemUsed, int dictionarySize, const ParametersMap & parameters) const;
|
||||||
void addStatistics(const Statistics & statistics) const;
|
void addStatistics(const Statistics & statistics, bool saveWmState) const;
|
||||||
void savePreviewImage(const cv::Mat & image) const;
|
void savePreviewImage(const cv::Mat & image) const;
|
||||||
cv::Mat loadPreviewImage() const;
|
cv::Mat loadPreviewImage() const;
|
||||||
void saveOptimizedPoses(const std::map<int, Transform> & optimizedPoses, const Transform & lastlocalizationPose) const;
|
void saveOptimizedPoses(const std::map<int, Transform> & optimizedPoses, const Transform & lastlocalizationPose) const;
|
||||||
@@ -238,7 +238,7 @@ protected:
|
|||||||
int nodeId,
|
int nodeId,
|
||||||
const LaserScan & scan) const = 0;
|
const LaserScan & scan) const = 0;
|
||||||
|
|
||||||
virtual void addStatisticsQuery(const Statistics & statistics) const = 0;
|
virtual void addStatisticsQuery(const Statistics & statistics, bool saveWmState) const = 0;
|
||||||
virtual void savePreviewImageQuery(const cv::Mat & image) const = 0;
|
virtual void savePreviewImageQuery(const cv::Mat & image) const = 0;
|
||||||
virtual cv::Mat loadPreviewImageQuery() const = 0;
|
virtual cv::Mat loadPreviewImageQuery() const = 0;
|
||||||
virtual void saveOptimizedPosesQuery(const std::map<int, Transform> & optimizedPoses, const Transform & lastlocalizationPose) const = 0;
|
virtual void saveOptimizedPosesQuery(const std::map<int, Transform> & optimizedPoses, const Transform & lastlocalizationPose) const = 0;
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ protected:
|
|||||||
int nodeId,
|
int nodeId,
|
||||||
const LaserScan & scan) const;
|
const LaserScan & scan) const;
|
||||||
|
|
||||||
virtual void addStatisticsQuery(const Statistics & statistics) const;
|
virtual void addStatisticsQuery(const Statistics & statistics, bool saveWmState) const;
|
||||||
virtual void savePreviewImageQuery(const cv::Mat & image) const;
|
virtual void savePreviewImageQuery(const cv::Mat & image) const;
|
||||||
virtual cv::Mat loadPreviewImageQuery() const;
|
virtual cv::Mat loadPreviewImageQuery() const;
|
||||||
virtual void saveOptimizedPosesQuery(const std::map<int, Transform> & optimizedPoses, const Transform & lastlocalizationPose) const;
|
virtual void saveOptimizedPosesQuery(const std::map<int, Transform> & optimizedPoses, const Transform & lastlocalizationPose) const;
|
||||||
@@ -160,6 +160,7 @@ private:
|
|||||||
std::string queryStepLink() const;
|
std::string queryStepLink() const;
|
||||||
std::string queryStepWordsChanged() const;
|
std::string queryStepWordsChanged() const;
|
||||||
std::string queryStepKeypoint() const;
|
std::string queryStepKeypoint() const;
|
||||||
|
std::string queryStepGlobalDescriptor() const;
|
||||||
std::string queryStepOccupancyGridUpdate() const;
|
std::string queryStepOccupancyGridUpdate() const;
|
||||||
void stepNode(sqlite3_stmt * ppStmt, const Signature * s) const;
|
void stepNode(sqlite3_stmt * ppStmt, const Signature * s) const;
|
||||||
void stepImage(sqlite3_stmt * ppStmt, int id, const cv::Mat & imageBytes) const;
|
void stepImage(sqlite3_stmt * ppStmt, int id, const cv::Mat & imageBytes) const;
|
||||||
@@ -169,7 +170,8 @@ private:
|
|||||||
void stepSensorData(sqlite3_stmt * ppStmt, const SensorData & sensorData) const;
|
void stepSensorData(sqlite3_stmt * ppStmt, const SensorData & sensorData) const;
|
||||||
void stepLink(sqlite3_stmt * ppStmt, const Link & link) const;
|
void stepLink(sqlite3_stmt * ppStmt, const Link & link) const;
|
||||||
void stepWordsChanged(sqlite3_stmt * ppStmt, int signatureId, int oldWordId, int newWordId) const;
|
void stepWordsChanged(sqlite3_stmt * ppStmt, int signatureId, int oldWordId, int newWordId) const;
|
||||||
void stepKeypoint(sqlite3_stmt * ppStmt, int signatureId, int wordId, const cv::KeyPoint & kp, const cv::Point3f & pt, const cv::Mat & descriptor) const;
|
void stepKeypoint(sqlite3_stmt * ppStmt, int nodeID, int wordId, const cv::KeyPoint & kp, const cv::Point3f & pt, const cv::Mat & descriptor) const;
|
||||||
|
void stepGlobalDescriptor(sqlite3_stmt * ppStmt, int nodeId, const GlobalDescriptor & descriptor) const;
|
||||||
void stepOccupancyGridUpdate(sqlite3_stmt * ppStmt,
|
void stepOccupancyGridUpdate(sqlite3_stmt * ppStmt,
|
||||||
int nodeId,
|
int nodeId,
|
||||||
const cv::Mat & ground,
|
const cv::Mat & ground,
|
||||||
|
|||||||
@@ -75,8 +75,8 @@ public:
|
|||||||
static cv::Mat findFFromWords(
|
static cv::Mat findFFromWords(
|
||||||
const std::list<std::pair<int, std::pair<cv::KeyPoint, cv::KeyPoint> > > & pairs, // id, kpt1, kpt2
|
const std::list<std::pair<int, std::pair<cv::KeyPoint, cv::KeyPoint> > > & pairs, // id, kpt1, kpt2
|
||||||
std::vector<uchar> & status,
|
std::vector<uchar> & status,
|
||||||
double ransacParam1 = 3.0,
|
double ransacReprojThreshold = 3.0,
|
||||||
double ransacParam2 = 0.99);
|
double ransacConfidence = 0.99);
|
||||||
|
|
||||||
// assume a canonical camera (without K)
|
// assume a canonical camera (without K)
|
||||||
static void findRTFromP(
|
static void findRTFromP(
|
||||||
|
|||||||
@@ -62,7 +62,9 @@ namespace cv{
|
|||||||
namespace xfeatures2d {
|
namespace xfeatures2d {
|
||||||
class FREAK;
|
class FREAK;
|
||||||
class BriefDescriptorExtractor;
|
class BriefDescriptorExtractor;
|
||||||
|
#if CV_MAJOR_VERSION < 3 || (CV_MAJOR_VERSION == 4 && CV_MINOR_VERSION <= 3) || (CV_MAJOR_VERSION == 3 && (CV_MINOR_VERSION < 4 || (CV_MINOR_VERSION==4 && CV_SUBMINOR_VERSION<11)))
|
||||||
class SIFT;
|
class SIFT;
|
||||||
|
#endif
|
||||||
class SURF;
|
class SURF;
|
||||||
}
|
}
|
||||||
namespace cuda {
|
namespace cuda {
|
||||||
@@ -71,7 +73,11 @@ class ORB;
|
|||||||
class SURF_CUDA;
|
class SURF_CUDA;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#if CV_MAJOR_VERSION < 3 || (CV_MAJOR_VERSION == 4 && CV_MINOR_VERSION <= 3) || (CV_MAJOR_VERSION == 3 && (CV_MINOR_VERSION < 4 || (CV_MINOR_VERSION==4 && CV_SUBMINOR_VERSION<11)))
|
||||||
typedef cv::xfeatures2d::SIFT CV_SIFT;
|
typedef cv::xfeatures2d::SIFT CV_SIFT;
|
||||||
|
#else
|
||||||
|
typedef cv::SIFT CV_SIFT; // SIFT is back in features2d since 4.4.0 / 3.4.11
|
||||||
|
#endif
|
||||||
typedef cv::xfeatures2d::SURF CV_SURF;
|
typedef cv::xfeatures2d::SURF CV_SURF;
|
||||||
typedef cv::FastFeatureDetector CV_FAST;
|
typedef cv::FastFeatureDetector CV_FAST;
|
||||||
typedef cv::xfeatures2d::FREAK CV_FREAK;
|
typedef cv::xfeatures2d::FREAK CV_FREAK;
|
||||||
@@ -110,6 +116,37 @@ public:
|
|||||||
kFeatureKaze=9, //new 0.13.2
|
kFeatureKaze=9, //new 0.13.2
|
||||||
kFeatureOrbOctree=10, //new 0.19.2
|
kFeatureOrbOctree=10, //new 0.19.2
|
||||||
kFeatureSuperPointTorch=11}; //new 0.19.7
|
kFeatureSuperPointTorch=11}; //new 0.19.7
|
||||||
|
static std::string typeName(Type type)
|
||||||
|
{
|
||||||
|
switch(type){
|
||||||
|
case kFeatureSurf:
|
||||||
|
return "SURF";
|
||||||
|
case kFeatureSift:
|
||||||
|
return "SIFT";
|
||||||
|
case kFeatureOrb:
|
||||||
|
return "ORB";
|
||||||
|
case kFeatureFastFreak:
|
||||||
|
return "FAST+FREAK";
|
||||||
|
case kFeatureFastBrief:
|
||||||
|
return "FAST+BRIEF";
|
||||||
|
case kFeatureGfttFreak:
|
||||||
|
return "GFTT+Freak";
|
||||||
|
case kFeatureGfttBrief:
|
||||||
|
return "GFTT+Brief";
|
||||||
|
case kFeatureBrisk:
|
||||||
|
return "BRISK";
|
||||||
|
case kFeatureGfttOrb:
|
||||||
|
return "GFTT+ORB";
|
||||||
|
case kFeatureKaze:
|
||||||
|
return "KAZE";
|
||||||
|
case kFeatureOrbOctree:
|
||||||
|
return "ORB-OCTREE";
|
||||||
|
case kFeatureSuperPointTorch:
|
||||||
|
return "SUPERPOINT";
|
||||||
|
default:
|
||||||
|
return "Unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static Feature2D * create(const ParametersMap & parameters = ParametersMap());
|
static Feature2D * create(const ParametersMap & parameters = ParametersMap());
|
||||||
static Feature2D * create(Feature2D::Type type, const ParametersMap & parameters = ParametersMap()); // for convenience
|
static Feature2D * create(Feature2D::Type type, const ParametersMap & parameters = ParametersMap()); // for convenience
|
||||||
@@ -146,6 +183,7 @@ public:
|
|||||||
static void limitKeypoints(std::vector<cv::KeyPoint> & keypoints, cv::Mat & descriptors, int maxKeypoints);
|
static void limitKeypoints(std::vector<cv::KeyPoint> & keypoints, cv::Mat & descriptors, int maxKeypoints);
|
||||||
static void limitKeypoints(std::vector<cv::KeyPoint> & keypoints, std::vector<cv::Point3f> & keypoints3D, cv::Mat & descriptors, int maxKeypoints);
|
static void limitKeypoints(std::vector<cv::KeyPoint> & keypoints, std::vector<cv::Point3f> & keypoints3D, cv::Mat & descriptors, int maxKeypoints);
|
||||||
static void limitKeypoints(const std::vector<cv::KeyPoint> & keypoints, std::vector<bool> & inliers, int maxKeypoints);
|
static void limitKeypoints(const std::vector<cv::KeyPoint> & keypoints, std::vector<bool> & inliers, int maxKeypoints);
|
||||||
|
static void limitKeypoints(const std::vector<cv::KeyPoint> & keypoints, std::vector<bool> & inliers, int maxKeypoints, const cv::Size & imageSize, int gridRows, int gridCols);
|
||||||
|
|
||||||
static cv::Rect computeRoi(const cv::Mat & image, const std::string & roiRatios);
|
static cv::Rect computeRoi(const cv::Mat & image, const std::string & roiRatios);
|
||||||
static cv::Rect computeRoi(const cv::Mat & image, const std::vector<float> & roiRatios);
|
static cv::Rect computeRoi(const cv::Mat & image, const std::vector<float> & roiRatios);
|
||||||
@@ -153,6 +191,8 @@ public:
|
|||||||
int getMaxFeatures() const {return maxFeatures_;}
|
int getMaxFeatures() const {return maxFeatures_;}
|
||||||
float getMinDepth() const {return _minDepth;}
|
float getMinDepth() const {return _minDepth;}
|
||||||
float getMaxDepth() const {return _maxDepth;}
|
float getMaxDepth() const {return _maxDepth;}
|
||||||
|
int getGridRows() const {return gridRows_;}
|
||||||
|
int getGridCols() const {return gridCols_;}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual ~Feature2D();
|
virtual ~Feature2D();
|
||||||
@@ -239,6 +279,7 @@ private:
|
|||||||
double contrastThreshold_;
|
double contrastThreshold_;
|
||||||
double edgeThreshold_;
|
double edgeThreshold_;
|
||||||
double sigma_;
|
double sigma_;
|
||||||
|
bool rootSIFT_;
|
||||||
|
|
||||||
cv::Ptr<CV_SIFT> _sift;
|
cv::Ptr<CV_SIFT> _sift;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2010-2020, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
* Neither the name of the Universite de Sherbrooke nor the
|
||||||
|
names of its contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <opencv2/core/core.hpp>
|
||||||
|
|
||||||
|
namespace rtabmap
|
||||||
|
{
|
||||||
|
|
||||||
|
class GlobalDescriptor
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
GlobalDescriptor(int type, const cv::Mat & data, const cv::Mat & info = cv::Mat()) :
|
||||||
|
type_(type),
|
||||||
|
info_(info),
|
||||||
|
data_(data)
|
||||||
|
{}
|
||||||
|
GlobalDescriptor() :
|
||||||
|
type_(-1) // Not set
|
||||||
|
{}
|
||||||
|
virtual ~GlobalDescriptor() {}
|
||||||
|
|
||||||
|
int type() const {return type_;}
|
||||||
|
const cv::Mat info() const {return info_;}
|
||||||
|
const cv::Mat data() const {return data_;}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int type_;
|
||||||
|
cv::Mat info_;
|
||||||
|
cv::Mat data_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace rtabmap
|
||||||
@@ -93,7 +93,7 @@ public:
|
|||||||
std::set<int> reactivateSignatures(const std::list<int> & ids, unsigned int maxLoaded, double & timeDbAccess);
|
std::set<int> reactivateSignatures(const std::list<int> & ids, unsigned int maxLoaded, double & timeDbAccess);
|
||||||
|
|
||||||
int cleanup();
|
int cleanup();
|
||||||
void saveStatistics(const Statistics & statistics);
|
void saveStatistics(const Statistics & statistics, bool saveWMState);
|
||||||
void savePreviewImage(const cv::Mat & image) const;
|
void savePreviewImage(const cv::Mat & image) const;
|
||||||
cv::Mat loadPreviewImage() const;
|
cv::Mat loadPreviewImage() const;
|
||||||
void saveOptimizedPoses(const std::map<int, Transform> & optimizedPoses, const Transform & lastlocalizationPose) const;
|
void saveOptimizedPoses(const std::map<int, Transform> & optimizedPoses, const Transform & lastlocalizationPose) const;
|
||||||
@@ -197,16 +197,16 @@ public:
|
|||||||
EnvSensors & sensors,
|
EnvSensors & sensors,
|
||||||
bool lookInDatabase = false) const;
|
bool lookInDatabase = false) const;
|
||||||
cv::Mat getImageCompressed(int signatureId) const;
|
cv::Mat getImageCompressed(int signatureId) const;
|
||||||
SensorData getNodeData(int nodeId, bool uncompressedData = false) const;
|
SensorData getNodeData(int locationId, bool images, bool scan, bool userData, bool occupancyGrid) const;
|
||||||
void getNodeWords(int nodeId,
|
void getNodeWordsAndGlobalDescriptors(int nodeId,
|
||||||
std::multimap<int, cv::KeyPoint> & words,
|
std::multimap<int, cv::KeyPoint> & words,
|
||||||
std::multimap<int, cv::Point3f> & words3,
|
std::multimap<int, cv::Point3f> & words3,
|
||||||
std::multimap<int, cv::Mat> & wordsDescriptors);
|
std::multimap<int, cv::Mat> & wordsDescriptors,
|
||||||
|
std::vector<GlobalDescriptor> & globalDescriptors) const;
|
||||||
void getNodeCalibration(int nodeId,
|
void getNodeCalibration(int nodeId,
|
||||||
std::vector<CameraModel> & models,
|
std::vector<CameraModel> & models,
|
||||||
StereoCameraModel & stereoModel);
|
StereoCameraModel & stereoModel) const;
|
||||||
SensorData getSignatureDataConst(int locationId, bool images = true, bool scan = true, bool userData = true, bool occupancyGrid = true) const;
|
std::set<int> getAllSignatureIds(bool ignoreChildren = true) const;
|
||||||
std::set<int> getAllSignatureIds() const;
|
|
||||||
bool memoryChanged() const {return _memoryChanged;}
|
bool memoryChanged() const {return _memoryChanged;}
|
||||||
bool isIncremental() const {return _incrementalMemory;}
|
bool isIncremental() const {return _incrementalMemory;}
|
||||||
bool isLocalizationDataSaved() const {return _localizationDataSaved;}
|
bool isLocalizationDataSaved() const {return _localizationDataSaved;}
|
||||||
@@ -302,6 +302,7 @@ private:
|
|||||||
bool _badSignaturesIgnored;
|
bool _badSignaturesIgnored;
|
||||||
bool _mapLabelsAdded;
|
bool _mapLabelsAdded;
|
||||||
bool _depthAsMask;
|
bool _depthAsMask;
|
||||||
|
bool _stereoFromMotion;
|
||||||
int _imagePreDecimation;
|
int _imagePreDecimation;
|
||||||
int _imagePostDecimation;
|
int _imagePostDecimation;
|
||||||
bool _compressionParallelized;
|
bool _compressionParallelized;
|
||||||
|
|||||||
@@ -78,6 +78,9 @@ public:
|
|||||||
unsigned int framesProcessed() const {return framesProcessed_;}
|
unsigned int framesProcessed() const {return framesProcessed_;}
|
||||||
bool imagesAlreadyRectified() const {return _imagesAlreadyRectified;}
|
bool imagesAlreadyRectified() const {return _imagesAlreadyRectified;}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
const std::map<double, Transform> & imus() const {return imus_;}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual Transform computeTransform(SensorData & data, const Transform & guess = Transform(), OdometryInfo * info = 0) = 0;
|
virtual Transform computeTransform(SensorData & data, const Transform & guess = Transform(), OdometryInfo * info = 0) = 0;
|
||||||
|
|
||||||
@@ -90,7 +93,7 @@ private:
|
|||||||
bool _force3DoF;
|
bool _force3DoF;
|
||||||
bool _holonomic;
|
bool _holonomic;
|
||||||
bool guessFromMotion_;
|
bool guessFromMotion_;
|
||||||
bool guessSmoothingDelay_;
|
float guessSmoothingDelay_;
|
||||||
int _filteringStrategy;
|
int _filteringStrategy;
|
||||||
int _particleSize;
|
int _particleSize;
|
||||||
float _particleNoiseT;
|
float _particleNoiseT;
|
||||||
@@ -109,6 +112,7 @@ private:
|
|||||||
double previousStamp_;
|
double previousStamp_;
|
||||||
std::list<std::pair<std::vector<float>, double> > previousVelocities_;
|
std::list<std::pair<std::vector<float>, double> > previousVelocities_;
|
||||||
Transform velocityGuess_;
|
Transform velocityGuess_;
|
||||||
|
Transform imuLastTransform_;
|
||||||
Transform previousGroundTruthPose_;
|
Transform previousGroundTruthPose_;
|
||||||
float distanceTravelled_;
|
float distanceTravelled_;
|
||||||
unsigned int framesProcessed_;
|
unsigned int framesProcessed_;
|
||||||
@@ -116,6 +120,7 @@ private:
|
|||||||
std::vector<ParticleFilter *> particleFilters_;
|
std::vector<ParticleFilter *> particleFilters_;
|
||||||
cv::KalmanFilter kalmanFilter_;
|
cv::KalmanFilter kalmanFilter_;
|
||||||
StereoCameraModel stereoModel_;
|
StereoCameraModel stereoModel_;
|
||||||
|
std::map<double, Transform> imus_;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Odometry(const rtabmap::ParametersMap & parameters);
|
Odometry(const rtabmap::ParametersMap & parameters);
|
||||||
|
|||||||
@@ -56,6 +56,8 @@ public:
|
|||||||
interval(0),
|
interval(0),
|
||||||
distanceTravelled(0.0f),
|
distanceTravelled(0.0f),
|
||||||
memoryUsage(0),
|
memoryUsage(0),
|
||||||
|
gravityRollError(0.0),
|
||||||
|
gravityPitchError(0.0),
|
||||||
type(0)
|
type(0)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@@ -84,6 +86,8 @@ public:
|
|||||||
output.guessVelocity = guessVelocity;
|
output.guessVelocity = guessVelocity;
|
||||||
output.distanceTravelled = distanceTravelled;
|
output.distanceTravelled = distanceTravelled;
|
||||||
output.memoryUsage = memoryUsage;
|
output.memoryUsage = memoryUsage;
|
||||||
|
output.gravityRollError = gravityRollError;
|
||||||
|
output.gravityPitchError = gravityPitchError;
|
||||||
output.type = type;
|
output.type = type;
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
@@ -110,6 +114,8 @@ public:
|
|||||||
Transform guessVelocity;
|
Transform guessVelocity;
|
||||||
float distanceTravelled;
|
float distanceTravelled;
|
||||||
int memoryUsage; //MB
|
int memoryUsage; //MB
|
||||||
|
double gravityRollError;
|
||||||
|
double gravityPitchError;
|
||||||
|
|
||||||
int type;
|
int type;
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "rtabmap/core/RtabmapExp.h" // DLL export/import defines
|
#include "rtabmap/core/RtabmapExp.h" // DLL export/import defines
|
||||||
#include "rtabmap/core/Version.h" // DLL export/import defines
|
#include "rtabmap/core/Version.h" // DLL export/import defines
|
||||||
#include <rtabmap/utilite/UConversion.h>
|
#include <rtabmap/utilite/UConversion.h>
|
||||||
|
#include <opencv2/core/version.hpp>
|
||||||
|
#include <opencv2/opencv_modules.hpp>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
@@ -217,6 +219,7 @@ class RTABMAP_EXP Parameters
|
|||||||
RTABMAP_PARAM(Mem, BadSignaturesIgnored, bool, false, "Bad signatures are ignored.");
|
RTABMAP_PARAM(Mem, BadSignaturesIgnored, bool, false, "Bad signatures are ignored.");
|
||||||
RTABMAP_PARAM(Mem, InitWMWithAllNodes, bool, false, "Initialize the Working Memory with all nodes in Long-Term Memory. When false, it is initialized with nodes of the previous session.");
|
RTABMAP_PARAM(Mem, InitWMWithAllNodes, bool, false, "Initialize the Working Memory with all nodes in Long-Term Memory. When false, it is initialized with nodes of the previous session.");
|
||||||
RTABMAP_PARAM(Mem, DepthAsMask, bool, true, "Use depth image as mask when extracting features for vocabulary.");
|
RTABMAP_PARAM(Mem, DepthAsMask, bool, true, "Use depth image as mask when extracting features for vocabulary.");
|
||||||
|
RTABMAP_PARAM(Mem, StereoFromMotion, bool, false, uFormat("Triangulate features without depth using stereo from motion (odometry). It would be ignored if %s is true and the feature detector used supports masking.", kMemDepthAsMask().c_str()));
|
||||||
RTABMAP_PARAM(Mem, ImagePreDecimation, int, 1, "Image decimation (>=1) before features extraction.");
|
RTABMAP_PARAM(Mem, ImagePreDecimation, int, 1, "Image decimation (>=1) before features extraction.");
|
||||||
RTABMAP_PARAM(Mem, ImagePostDecimation, int, 1, "Image decimation (>=1) of saved data in created signatures (after features extraction). Decimation is done from the original image.");
|
RTABMAP_PARAM(Mem, ImagePostDecimation, int, 1, "Image decimation (>=1) of saved data in created signatures (after features extraction). Decimation is done from the original image.");
|
||||||
RTABMAP_PARAM(Mem, CompressionParallelized, bool, true, "Compression of sensor data is multi-threaded.");
|
RTABMAP_PARAM(Mem, CompressionParallelized, bool, true, "Compression of sensor data is multi-threaded.");
|
||||||
@@ -238,13 +241,9 @@ class RTABMAP_EXP Parameters
|
|||||||
RTABMAP_PARAM(Kp, MaxFeatures, int, 500, "Maximum features extracted from the images (0 means not bounded, <0 means no extraction).");
|
RTABMAP_PARAM(Kp, MaxFeatures, int, 500, "Maximum features extracted from the images (0 means not bounded, <0 means no extraction).");
|
||||||
RTABMAP_PARAM(Kp, BadSignRatio, float, 0.5, "Bad signature ratio (less than Ratio x AverageWordsPerImage = bad).");
|
RTABMAP_PARAM(Kp, BadSignRatio, float, 0.5, "Bad signature ratio (less than Ratio x AverageWordsPerImage = bad).");
|
||||||
RTABMAP_PARAM(Kp, NndrRatio, float, 0.8, "NNDR ratio (A matching pair is detected, if its distance is closer than X times the distance of the second nearest neighbor.)");
|
RTABMAP_PARAM(Kp, NndrRatio, float, 0.8, "NNDR ratio (A matching pair is detected, if its distance is closer than X times the distance of the second nearest neighbor.)");
|
||||||
#ifndef RTABMAP_NONFREE
|
#if CV_MAJOR_VERSION > 2 && !defined(HAVE_OPENCV_XFEATURES2D)
|
||||||
#ifdef RTABMAP_OPENCV3
|
// OpenCV>2 without xFeatures2D module doesn't have BRIEF
|
||||||
// OpenCV 3 without xFeatures2D module doesn't have BRIEF
|
|
||||||
RTABMAP_PARAM(Kp, DetectorStrategy, int, 8, "0=SURF 1=SIFT 2=ORB 3=FAST/FREAK 4=FAST/BRIEF 5=GFTT/FREAK 6=GFTT/BRIEF 7=BRISK 8=GFTT/ORB 9=KAZE 10=ORB-OCTREE 11=SuperPoint Torch.");
|
RTABMAP_PARAM(Kp, DetectorStrategy, int, 8, "0=SURF 1=SIFT 2=ORB 3=FAST/FREAK 4=FAST/BRIEF 5=GFTT/FREAK 6=GFTT/BRIEF 7=BRISK 8=GFTT/ORB 9=KAZE 10=ORB-OCTREE 11=SuperPoint Torch.");
|
||||||
#else
|
|
||||||
RTABMAP_PARAM(Kp, DetectorStrategy, int, 6, "0=SURF 1=SIFT 2=ORB 3=FAST/FREAK 4=FAST/BRIEF 5=GFTT/FREAK 6=GFTT/BRIEF 7=BRISK 8=GFTT/ORB 9=KAZE 10=ORB-OCTREE 11=SuperPoint Torch.");
|
|
||||||
#endif
|
|
||||||
#else
|
#else
|
||||||
RTABMAP_PARAM(Kp, DetectorStrategy, int, 6, "0=SURF 1=SIFT 2=ORB 3=FAST/FREAK 4=FAST/BRIEF 5=GFTT/FREAK 6=GFTT/BRIEF 7=BRISK 8=GFTT/ORB 9=KAZE 10=ORB-OCTREE 11=SuperPoint Torch.");
|
RTABMAP_PARAM(Kp, DetectorStrategy, int, 6, "0=SURF 1=SIFT 2=ORB 3=FAST/FREAK 4=FAST/BRIEF 5=GFTT/FREAK 6=GFTT/BRIEF 7=BRISK 8=GFTT/ORB 9=KAZE 10=ORB-OCTREE 11=SuperPoint Torch.");
|
||||||
#endif
|
#endif
|
||||||
@@ -280,6 +279,7 @@ class RTABMAP_EXP Parameters
|
|||||||
RTABMAP_PARAM(SIFT, ContrastThreshold, double, 0.04, "The contrast threshold used to filter out weak features in semi-uniform (low-contrast) regions. The larger the threshold, the less features are produced by the detector.");
|
RTABMAP_PARAM(SIFT, ContrastThreshold, double, 0.04, "The contrast threshold used to filter out weak features in semi-uniform (low-contrast) regions. The larger the threshold, the less features are produced by the detector.");
|
||||||
RTABMAP_PARAM(SIFT, EdgeThreshold, double, 10, "The threshold used to filter out edge-like features. Note that the its meaning is different from the contrastThreshold, i.e. the larger the edgeThreshold, the less features are filtered out (more features are retained).");
|
RTABMAP_PARAM(SIFT, EdgeThreshold, double, 10, "The threshold used to filter out edge-like features. Note that the its meaning is different from the contrastThreshold, i.e. the larger the edgeThreshold, the less features are filtered out (more features are retained).");
|
||||||
RTABMAP_PARAM(SIFT, Sigma, double, 1.6, "The sigma of the Gaussian applied to the input image at the octave #0. If your image is captured with a weak camera with soft lenses, you might want to reduce the number.");
|
RTABMAP_PARAM(SIFT, Sigma, double, 1.6, "The sigma of the Gaussian applied to the input image at the octave #0. If your image is captured with a weak camera with soft lenses, you might want to reduce the number.");
|
||||||
|
RTABMAP_PARAM(SIFT, RootSIFT, bool, false, "Apply RootSIFT normalization of the descriptors.");
|
||||||
|
|
||||||
RTABMAP_PARAM(BRIEF, Bytes, int, 32, "Bytes is a length of descriptor in bytes. It can be equal 16, 32 or 64 bytes.");
|
RTABMAP_PARAM(BRIEF, Bytes, int, 32, "Bytes is a length of descriptor in bytes. It can be equal 16, 32 or 64 bytes.");
|
||||||
|
|
||||||
@@ -324,11 +324,11 @@ class RTABMAP_EXP Parameters
|
|||||||
RTABMAP_PARAM(KAZE, NOctaveLayers, int, 4, "Default number of sublevels per scale level.");
|
RTABMAP_PARAM(KAZE, NOctaveLayers, int, 4, "Default number of sublevels per scale level.");
|
||||||
RTABMAP_PARAM(KAZE, Diffusivity, int, 1, "Diffusivity type: 0=DIFF_PM_G1, 1=DIFF_PM_G2, 2=DIFF_WEICKERT or 3=DIFF_CHARBONNIER.");
|
RTABMAP_PARAM(KAZE, Diffusivity, int, 1, "Diffusivity type: 0=DIFF_PM_G1, 1=DIFF_PM_G2, 2=DIFF_WEICKERT or 3=DIFF_CHARBONNIER.");
|
||||||
|
|
||||||
RTABMAP_PARAM_STR(SPTorch, ModelPath, "", "[Required] Path to pre-trained weights Torch file of SuperPoint (*.pt).");
|
RTABMAP_PARAM_STR(SuperPoint, ModelPath, "", "[Required] Path to pre-trained weights Torch file of SuperPoint (*.pt).");
|
||||||
RTABMAP_PARAM(SPTorch, Threshold, float, 0.200, "Detector response threshold to accept keypoint.");
|
RTABMAP_PARAM(SuperPoint, Threshold, float, 0.010, "Detector response threshold to accept keypoint.");
|
||||||
RTABMAP_PARAM(SPTorch, NMS, bool, true, "If true, non-maximum suppression is applied to detected keypoints.");
|
RTABMAP_PARAM(SuperPoint, NMS, bool, true, "If true, non-maximum suppression is applied to detected keypoints.");
|
||||||
RTABMAP_PARAM(SPTorch, MinDistance, int, 4, uFormat("[%s=true] Minimum distance (pixels) between keypoints.", kSPTorchNMS().c_str()));
|
RTABMAP_PARAM(SuperPoint, NMSRadius, int, 4, uFormat("[%s=true] Minimum distance (pixels) between keypoints.", kSuperPointNMS().c_str()));
|
||||||
RTABMAP_PARAM(SPTorch, Cuda, bool, false, "Use Cuda device for Torch, otherwise CPU device is used by default.");
|
RTABMAP_PARAM(SuperPoint, Cuda, bool, true, "Use Cuda device for Torch, otherwise CPU device is used by default.");
|
||||||
|
|
||||||
// BayesFilter
|
// BayesFilter
|
||||||
RTABMAP_PARAM(Bayes, VirtualPlacePriorThr, float, 0.9, "Virtual place prior");
|
RTABMAP_PARAM(Bayes, VirtualPlacePriorThr, float, 0.9, "Virtual place prior");
|
||||||
@@ -378,6 +378,7 @@ class RTABMAP_EXP Parameters
|
|||||||
RTABMAP_PARAM(RGBD, ProximityPathMaxNeighbors, int, 0, "Maximum neighbor nodes compared on each path. Set to 0 to disable merging the laser scans.");
|
RTABMAP_PARAM(RGBD, ProximityPathMaxNeighbors, int, 0, "Maximum neighbor nodes compared on each path. Set to 0 to disable merging the laser scans.");
|
||||||
RTABMAP_PARAM(RGBD, ProximityPathRawPosesUsed, bool, true, "When comparing to a local path, merge the scan using the odometry poses (with neighbor link optimizations) instead of the ones in the optimized local graph.");
|
RTABMAP_PARAM(RGBD, ProximityPathRawPosesUsed, bool, true, "When comparing to a local path, merge the scan using the odometry poses (with neighbor link optimizations) instead of the ones in the optimized local graph.");
|
||||||
RTABMAP_PARAM(RGBD, ProximityAngle, float, 45, "Maximum angle (degrees) for visual proximity detection.");
|
RTABMAP_PARAM(RGBD, ProximityAngle, float, 45, "Maximum angle (degrees) for visual proximity detection.");
|
||||||
|
RTABMAP_PARAM(RGBD, ProximityOdomGuess, bool, false, "Use odometry as motion guess for visual proximity detection.");
|
||||||
|
|
||||||
// Graph optimization
|
// Graph optimization
|
||||||
#ifdef RTABMAP_GTSAM
|
#ifdef RTABMAP_GTSAM
|
||||||
@@ -577,19 +578,15 @@ class RTABMAP_EXP Parameters
|
|||||||
RTABMAP_PARAM(Vis, PnPRefineIterations, int, 1, uFormat("[%s = 1] Refine iterations. Set to 0 if \"%s\" is also used.", kVisEstimationType().c_str(), kVisBundleAdjustment().c_str()));
|
RTABMAP_PARAM(Vis, PnPRefineIterations, int, 1, uFormat("[%s = 1] Refine iterations. Set to 0 if \"%s\" is also used.", kVisEstimationType().c_str(), kVisBundleAdjustment().c_str()));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
RTABMAP_PARAM(Vis, EpipolarGeometryVar, float, 0.02, uFormat("[%s = 2] Epipolar geometry maximum variance to accept the transformation.", kVisEstimationType().c_str()));
|
RTABMAP_PARAM(Vis, EpipolarGeometryVar, float, 0.1, uFormat("[%s = 2] Epipolar geometry maximum variance to accept the transformation.", kVisEstimationType().c_str()));
|
||||||
RTABMAP_PARAM(Vis, MinInliers, int, 20, "Minimum feature correspondences to compute/accept the transformation.");
|
RTABMAP_PARAM(Vis, MinInliers, int, 20, "Minimum feature correspondences to compute/accept the transformation.");
|
||||||
RTABMAP_PARAM(Vis, MeanInliersDistance, float, 0.0, "Maximum distance (m) of the mean distance of inliers from the camera to accept the transformation. 0 means disabled.");
|
RTABMAP_PARAM(Vis, MeanInliersDistance, float, 0.0, "Maximum distance (m) of the mean distance of inliers from the camera to accept the transformation. 0 means disabled.");
|
||||||
RTABMAP_PARAM(Vis, MinInliersDistribution, float, 0.0, "Minimum distribution value of the inliers in the image to accept the transformation. The distribution is the second eigen value of the PCA (Principal Component Analysis) on the keypoints of the normalized image [-0.5, 0.5]. The value would be between 0 and 0.5. 0 means disabled.");
|
RTABMAP_PARAM(Vis, MinInliersDistribution, float, 0.0, "Minimum distribution value of the inliers in the image to accept the transformation. The distribution is the second eigen value of the PCA (Principal Component Analysis) on the keypoints of the normalized image [-0.5, 0.5]. The value would be between 0 and 0.5. 0 means disabled.");
|
||||||
|
|
||||||
RTABMAP_PARAM(Vis, Iterations, int, 300, "Maximum iterations to compute the transform.");
|
RTABMAP_PARAM(Vis, Iterations, int, 300, "Maximum iterations to compute the transform.");
|
||||||
#ifndef RTABMAP_NONFREE
|
#if CV_MAJOR_VERSION > 2 && !defined(HAVE_OPENCV_XFEATURES2D)
|
||||||
#ifdef RTABMAP_OPENCV3
|
// OpenCV>2 without xFeatures2D module doesn't have BRIEF
|
||||||
// OpenCV 3 without xFeatures2D module doesn't have BRIEF
|
|
||||||
RTABMAP_PARAM(Vis, FeatureType, int, 8, "0=SURF 1=SIFT 2=ORB 3=FAST/FREAK 4=FAST/BRIEF 5=GFTT/FREAK 6=GFTT/BRIEF 7=BRISK 8=GFTT/ORB 9=KAZE 10=ORB-OCTREE 11=SuperPoint Torch.");
|
RTABMAP_PARAM(Vis, FeatureType, int, 8, "0=SURF 1=SIFT 2=ORB 3=FAST/FREAK 4=FAST/BRIEF 5=GFTT/FREAK 6=GFTT/BRIEF 7=BRISK 8=GFTT/ORB 9=KAZE 10=ORB-OCTREE 11=SuperPoint Torch.");
|
||||||
#else
|
|
||||||
RTABMAP_PARAM(Vis, FeatureType, int, 6, "0=SURF 1=SIFT 2=ORB 3=FAST/FREAK 4=FAST/BRIEF 5=GFTT/FREAK 6=GFTT/BRIEF 7=BRISK 8=GFTT/ORB 9=KAZE 10=ORB-OCTREE 11=SuperPoint Torch.");
|
|
||||||
#endif
|
|
||||||
#else
|
#else
|
||||||
RTABMAP_PARAM(Vis, FeatureType, int, 6, "0=SURF 1=SIFT 2=ORB 3=FAST/FREAK 4=FAST/BRIEF 5=GFTT/FREAK 6=GFTT/BRIEF 7=BRISK 8=GFTT/ORB 9=KAZE 10=ORB-OCTREE 11=SuperPoint Torch.");
|
RTABMAP_PARAM(Vis, FeatureType, int, 6, "0=SURF 1=SIFT 2=ORB 3=FAST/FREAK 4=FAST/BRIEF 5=GFTT/FREAK 6=GFTT/BRIEF 7=BRISK 8=GFTT/ORB 9=KAZE 10=ORB-OCTREE 11=SuperPoint Torch.");
|
||||||
#endif
|
#endif
|
||||||
@@ -604,9 +601,8 @@ class RTABMAP_EXP Parameters
|
|||||||
RTABMAP_PARAM(Vis, GridRows, int, 1, uFormat("Number of rows of the grid used to extract uniformly \"%s / grid cells\" features from each cell.", kVisMaxFeatures().c_str()));
|
RTABMAP_PARAM(Vis, GridRows, int, 1, uFormat("Number of rows of the grid used to extract uniformly \"%s / grid cells\" features from each cell.", kVisMaxFeatures().c_str()));
|
||||||
RTABMAP_PARAM(Vis, GridCols, int, 1, uFormat("Number of columns of the grid used to extract uniformly \"%s / grid cells\" features from each cell.", kVisMaxFeatures().c_str()));
|
RTABMAP_PARAM(Vis, GridCols, int, 1, uFormat("Number of columns of the grid used to extract uniformly \"%s / grid cells\" features from each cell.", kVisMaxFeatures().c_str()));
|
||||||
RTABMAP_PARAM(Vis, CorType, int, 0, "Correspondences computation approach: 0=Features Matching, 1=Optical Flow");
|
RTABMAP_PARAM(Vis, CorType, int, 0, "Correspondences computation approach: 0=Features Matching, 1=Optical Flow");
|
||||||
RTABMAP_PARAM(Vis, CorNNType, int, 1, uFormat("[%s=0] kNNFlannNaive=0, kNNFlannKdTree=1, kNNFlannLSH=2, kNNBruteForce=3, kNNBruteForceGPU=4. Used for features matching approach.", kVisCorType().c_str()));
|
RTABMAP_PARAM(Vis, CorNNType, int, 1, uFormat("[%s=0] kNNFlannNaive=0, kNNFlannKdTree=1, kNNFlannLSH=2, kNNBruteForce=3, kNNBruteForceGPU=4, BruteForceCrossCheck=5, SuperGlue=6, GMS=7. Used for features matching approach.", kVisCorType().c_str()));
|
||||||
RTABMAP_PARAM(Vis, CorNNDR, float, 0.6, uFormat("[%s=0] NNDR: nearest neighbor distance ratio. Used for knn features matching approach.", kVisCorType().c_str()));
|
RTABMAP_PARAM(Vis, CorNNDR, float, 0.6, uFormat("[%s=0] NNDR: nearest neighbor distance ratio. Used for knn features matching approach.", kVisCorType().c_str()));
|
||||||
RTABMAP_PARAM(Vis, CorCrossCheck, bool, false, uFormat("[%s=0] If true, brute force crosscheck matching is done instead of knn matching approach (%s).", kVisCorType().c_str(), kVisCorNNDR().c_str()));
|
|
||||||
RTABMAP_PARAM(Vis, CorGuessWinSize, int, 20, uFormat("[%s=0] Matching window size (pixels) around projected points when a guess transform is provided to find correspondences. 0 means disabled.", kVisCorType().c_str()));
|
RTABMAP_PARAM(Vis, CorGuessWinSize, int, 20, uFormat("[%s=0] Matching window size (pixels) around projected points when a guess transform is provided to find correspondences. 0 means disabled.", kVisCorType().c_str()));
|
||||||
RTABMAP_PARAM(Vis, CorGuessMatchToProjection, bool, false, uFormat("[%s=0] Match frame's corners to source's projected points (when guess transform is provided) instead of projected points to frame's corners.", kVisCorType().c_str()));
|
RTABMAP_PARAM(Vis, CorGuessMatchToProjection, bool, false, uFormat("[%s=0] Match frame's corners to source's projected points (when guess transform is provided) instead of projected points to frame's corners.", kVisCorType().c_str()));
|
||||||
RTABMAP_PARAM(Vis, CorFlowWinSize, int, 16, uFormat("[%s=1] See cv::calcOpticalFlowPyrLK(). Used for optical flow approach.", kVisCorType().c_str()));
|
RTABMAP_PARAM(Vis, CorFlowWinSize, int, 16, uFormat("[%s=1] See cv::calcOpticalFlowPyrLK(). Used for optical flow approach.", kVisCorType().c_str()));
|
||||||
@@ -619,6 +615,17 @@ class RTABMAP_EXP Parameters
|
|||||||
RTABMAP_PARAM(Vis, BundleAdjustment, int, 0, "Optimization with bundle adjustment: 0=disabled, 1=g2o, 2=cvsba, 3=Ceres.");
|
RTABMAP_PARAM(Vis, BundleAdjustment, int, 0, "Optimization with bundle adjustment: 0=disabled, 1=g2o, 2=cvsba, 3=Ceres.");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Features matching approaches
|
||||||
|
RTABMAP_PARAM_STR(PyMatcher, Path, "", "Path to python script file (see available ones in rtabmap/corelib/src/pymatcher/*). See the header to see where the script should be copied.");
|
||||||
|
RTABMAP_PARAM(PyMatcher, Iterations, int, 20, "Sinkhorn iterations. Used by SuperGlue.");
|
||||||
|
RTABMAP_PARAM(PyMatcher, Threshold, float, 0.2, "Used by SuperGlue.");
|
||||||
|
RTABMAP_PARAM(PyMatcher, Cuda, bool, true, "Used by SuperGlue.");
|
||||||
|
RTABMAP_PARAM_STR(PyMatcher, Model, "indoor", "For SuperGlue, set only \"indoor\" or \"outdoor\". For OANet, set path to one of the pth file (e.g., \"OANet/model/gl3d/sift-4000/model_best.pth\").");
|
||||||
|
|
||||||
|
RTABMAP_PARAM(GMS, WithRotation, bool, false, "Take rotation transformation into account.");
|
||||||
|
RTABMAP_PARAM(GMS, WithScale, bool, false, "Take scale transformation into account.");
|
||||||
|
RTABMAP_PARAM(GMS, ThresholdFactor, double, 6.0, "The higher, the less matches.");
|
||||||
|
|
||||||
// ICP registration parameters
|
// ICP registration parameters
|
||||||
RTABMAP_PARAM(Icp, MaxTranslation, float, 0.2, "Maximum ICP translation correction accepted (m).");
|
RTABMAP_PARAM(Icp, MaxTranslation, float, 0.2, "Maximum ICP translation correction accepted (m).");
|
||||||
RTABMAP_PARAM(Icp, MaxRotation, float, 0.78, "Maximum ICP rotation correction accepted (rad).");
|
RTABMAP_PARAM(Icp, MaxRotation, float, 0.78, "Maximum ICP rotation correction accepted (rad).");
|
||||||
|
|||||||
@@ -37,6 +37,10 @@ namespace rtabmap {
|
|||||||
|
|
||||||
class Feature2D;
|
class Feature2D;
|
||||||
|
|
||||||
|
#ifdef RTABMAP_PYMATCHER
|
||||||
|
class PyMatcher;
|
||||||
|
#endif
|
||||||
|
|
||||||
// Visual registration
|
// Visual registration
|
||||||
class RTABMAP_EXP RegistrationVis : public Registration
|
class RTABMAP_EXP RegistrationVis : public Registration
|
||||||
{
|
{
|
||||||
@@ -50,6 +54,11 @@ public:
|
|||||||
float getInlierDistance() const {return _inlierDistance;}
|
float getInlierDistance() const {return _inlierDistance;}
|
||||||
int getIterations() const {return _iterations;}
|
int getIterations() const {return _iterations;}
|
||||||
int getMinInliers() const {return _minInliers;}
|
int getMinInliers() const {return _minInliers;}
|
||||||
|
int getNNType() const {return _nnType;}
|
||||||
|
float getNNDR() const {return _nndr;}
|
||||||
|
int getEstimationType() const {return _estimationType;}
|
||||||
|
|
||||||
|
const Feature2D * getDetector() const {return _detectorFrom;}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual Transform computeTransformationImpl(
|
virtual Transform computeTransformationImpl(
|
||||||
@@ -78,8 +87,11 @@ private:
|
|||||||
int _flowIterations;
|
int _flowIterations;
|
||||||
float _flowEps;
|
float _flowEps;
|
||||||
int _flowMaxLevel;
|
int _flowMaxLevel;
|
||||||
bool _bfCrossCheck;
|
|
||||||
float _nndr;
|
float _nndr;
|
||||||
|
int _nnType;
|
||||||
|
bool _gmsWithRotation;
|
||||||
|
bool _gmsWithScale;
|
||||||
|
double _gmsThresholdFactor;
|
||||||
int _guessWinSize;
|
int _guessWinSize;
|
||||||
bool _guessMatchToProjection;
|
bool _guessMatchToProjection;
|
||||||
int _bundleAdjustment;
|
int _bundleAdjustment;
|
||||||
@@ -92,6 +104,10 @@ private:
|
|||||||
|
|
||||||
Feature2D * _detectorFrom;
|
Feature2D * _detectorFrom;
|
||||||
Feature2D * _detectorTo;
|
Feature2D * _detectorTo;
|
||||||
|
|
||||||
|
#ifdef RTABMAP_PYMATCHER
|
||||||
|
PyMatcher * _pyMatcher;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -86,8 +86,32 @@ public:
|
|||||||
const cv::Mat & image,
|
const cv::Mat & image,
|
||||||
int id=0, const std::map<std::string, float> & externalStats = std::map<std::string, float>());
|
int id=0, const std::map<std::string, float> & externalStats = std::map<std::string, float>());
|
||||||
|
|
||||||
void init(const ParametersMap & parameters, const std::string & databasePath = "");
|
/**
|
||||||
void init(const std::string & configFile = "", const std::string & databasePath = "");
|
* Initialize Rtabmap with parameters and a database
|
||||||
|
* @param parameters Parameters overriding default parameters and database parameters
|
||||||
|
* (@see loadDatabaseParameters)
|
||||||
|
* @param databasePath The database input/output path. If not set, an
|
||||||
|
* empty database is used in RAM. If set and the file doesn't exist,
|
||||||
|
* it will be created empty. If the database exists, nodes and
|
||||||
|
* vocabulary will be loaded in working memory.
|
||||||
|
* @param loadDatabaseParameters If an existing database is used (@see databasePath),
|
||||||
|
* the parameters inside are loaded and set to current
|
||||||
|
* Rtabmap instance.
|
||||||
|
*/
|
||||||
|
void init(const ParametersMap & parameters, const std::string & databasePath = "", bool loadDatabaseParameters = false);
|
||||||
|
/**
|
||||||
|
* Initialize Rtabmap with parameters from a configuration file and a database
|
||||||
|
* @param configFile Configuration file (*.ini) overriding default parameters and database parameters
|
||||||
|
* (@see loadDatabaseParameters)
|
||||||
|
* @param databasePath The database input/output path. If not set, an
|
||||||
|
* empty database is used in RAM. If set and the file doesn't exist,
|
||||||
|
* it will be created empty. If the database exists, nodes and
|
||||||
|
* vocabulary will be loaded in working memory.
|
||||||
|
* @param loadDatabaseParameters If an existing database is used (@see databasePath),
|
||||||
|
* the parameters inside are loaded and set to current
|
||||||
|
* Rtabmap instance.
|
||||||
|
*/
|
||||||
|
void init(const std::string & configFile = "", const std::string & databasePath = "", bool loadDatabaseParameters = false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Close rtabmap. This will delete rtabmap object if set.
|
* Close rtabmap. This will delete rtabmap object if set.
|
||||||
@@ -156,16 +180,24 @@ public:
|
|||||||
void rejectLastLoopClosure();
|
void rejectLastLoopClosure();
|
||||||
void deleteLastLocation();
|
void deleteLastLocation();
|
||||||
void setOptimizedPoses(const std::map<int, Transform> & poses);
|
void setOptimizedPoses(const std::map<int, Transform> & poses);
|
||||||
void get3DMap(std::map<int, Signature> & signatures,
|
Signature getSignatureCopy(int id, bool images, bool scan, bool userData, bool occupancyGrid, bool withWords, bool withGlobalDescriptors) const;
|
||||||
std::map<int, Transform> & poses,
|
RTABMAP_DEPRECATED(
|
||||||
std::multimap<int, Link> & constraints,
|
void get3DMap(std::map<int, Signature> & signatures,
|
||||||
bool optimized,
|
std::map<int, Transform> & poses,
|
||||||
bool global) const;
|
std::multimap<int, Link> & constraints,
|
||||||
|
bool optimized,
|
||||||
|
bool global) const, "Use getGraph() instead with withImages=true, withScan=true, withUserData=true and withGrid=true.");
|
||||||
void getGraph(std::map<int, Transform> & poses,
|
void getGraph(std::map<int, Transform> & poses,
|
||||||
std::multimap<int, Link> & constraints,
|
std::multimap<int, Link> & constraints,
|
||||||
bool optimized,
|
bool optimized,
|
||||||
bool global,
|
bool global,
|
||||||
std::map<int, Signature> * signatures = 0);
|
std::map<int, Signature> * signatures = 0,
|
||||||
|
bool withImages = false,
|
||||||
|
bool withScan = false,
|
||||||
|
bool withUserData = false,
|
||||||
|
bool withGrid = false,
|
||||||
|
bool withWords = true,
|
||||||
|
bool withGlobalDescriptors = true) const;
|
||||||
int detectMoreLoopClosures(
|
int detectMoreLoopClosures(
|
||||||
float clusterRadius = 0.5f,
|
float clusterRadius = 0.5f,
|
||||||
float clusterAngle = M_PI/6.0f,
|
float clusterAngle = M_PI/6.0f,
|
||||||
@@ -257,6 +289,7 @@ private:
|
|||||||
float _proximityFilteringRadius;
|
float _proximityFilteringRadius;
|
||||||
bool _proximityRawPosesUsed;
|
bool _proximityRawPosesUsed;
|
||||||
float _proximityAngle;
|
float _proximityAngle;
|
||||||
|
bool _proximityOdomGuess;
|
||||||
std::string _databasePath;
|
std::string _databasePath;
|
||||||
bool _optimizeFromGraphEnd;
|
bool _optimizeFromGraphEnd;
|
||||||
float _optimizationMaxError;
|
float _optimizationMaxError;
|
||||||
@@ -277,6 +310,7 @@ private:
|
|||||||
double _lastProcessTime;
|
double _lastProcessTime;
|
||||||
bool _someNodesHaveBeenTransferred;
|
bool _someNodesHaveBeenTransferred;
|
||||||
float _distanceTravelled;
|
float _distanceTravelled;
|
||||||
|
bool _optimizeFromGraphEndChanged;
|
||||||
|
|
||||||
// Abstract classes containing all loop closure
|
// Abstract classes containing all loop closure
|
||||||
// strategies for a type of signature or configuration.
|
// strategies for a type of signature or configuration.
|
||||||
@@ -306,6 +340,8 @@ private:
|
|||||||
bool _currentSessionHasGPS;
|
bool _currentSessionHasGPS;
|
||||||
std::map<int, Transform> _odomCachePoses; // used in localization mode to reject loop closures
|
std::map<int, Transform> _odomCachePoses; // used in localization mode to reject loop closures
|
||||||
std::multimap<int, Link> _odomCacheConstraints; // used in localization mode to reject loop closures
|
std::multimap<int, Link> _odomCacheConstraints; // used in localization mode to reject loop closures
|
||||||
|
std::map<int, Transform> _odomCacheAddLink; // used in localization mode when adding external link
|
||||||
|
std::vector<float> _odomCorrectionAcc;
|
||||||
|
|
||||||
// Planning stuff
|
// Planning stuff
|
||||||
int _pathStatus;
|
int _pathStatus;
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <rtabmap/core/GPS.h>
|
#include <rtabmap/core/GPS.h>
|
||||||
#include <rtabmap/core/EnvSensor.h>
|
#include <rtabmap/core/EnvSensor.h>
|
||||||
#include <rtabmap/core/Landmark.h>
|
#include <rtabmap/core/Landmark.h>
|
||||||
|
#include <rtabmap/core/GlobalDescriptor.h>
|
||||||
|
|
||||||
namespace rtabmap
|
namespace rtabmap
|
||||||
{
|
{
|
||||||
@@ -249,6 +250,11 @@ public:
|
|||||||
const std::vector<cv::Point3f> & keypoints3D() const {return _keypoints3D;}
|
const std::vector<cv::Point3f> & keypoints3D() const {return _keypoints3D;}
|
||||||
const cv::Mat & descriptors() const {return _descriptors;}
|
const cv::Mat & descriptors() const {return _descriptors;}
|
||||||
|
|
||||||
|
void addGlobalDescriptor(const GlobalDescriptor & descriptor) {_globalDescriptors.push_back(descriptor);}
|
||||||
|
void setGlobalDescriptors(const std::vector<GlobalDescriptor> & descriptors) {_globalDescriptors = descriptors;}
|
||||||
|
void clearGlobalDescriptors() {_globalDescriptors.clear();}
|
||||||
|
const std::vector<GlobalDescriptor> & globalDescriptors() const {return _globalDescriptors;}
|
||||||
|
|
||||||
void setGroundTruth(const Transform & pose) {groundTruth_ = pose;}
|
void setGroundTruth(const Transform & pose) {groundTruth_ = pose;}
|
||||||
const Transform & groundTruth() const {return groundTruth_;}
|
const Transform & groundTruth() const {return groundTruth_;}
|
||||||
|
|
||||||
@@ -323,6 +329,9 @@ private:
|
|||||||
std::vector<cv::Point3f> _keypoints3D;
|
std::vector<cv::Point3f> _keypoints3D;
|
||||||
cv::Mat _descriptors;
|
cv::Mat _descriptors;
|
||||||
|
|
||||||
|
// global descriptors
|
||||||
|
std::vector<GlobalDescriptor> _globalDescriptors;
|
||||||
|
|
||||||
Transform groundTruth_;
|
Transform groundTruth_;
|
||||||
|
|
||||||
Transform globalPose_;
|
Transform globalPose_;
|
||||||
|
|||||||
@@ -52,14 +52,18 @@ namespace rtabmap {
|
|||||||
|
|
||||||
class RTABMAP_EXP Statistics
|
class RTABMAP_EXP Statistics
|
||||||
{
|
{
|
||||||
|
RTABMAP_STATS(Loop, Id,); // Combined loop or proximity detection
|
||||||
RTABMAP_STATS(Loop, RejectedHypothesis,);
|
RTABMAP_STATS(Loop, RejectedHypothesis,);
|
||||||
RTABMAP_STATS(Loop, Accepted_hypothesis_id,);
|
RTABMAP_STATS(Loop, Accepted_hypothesis_id,);
|
||||||
|
RTABMAP_STATS(Loop, Suppressed_hypothesis_id,);
|
||||||
RTABMAP_STATS(Loop, Highest_hypothesis_id,);
|
RTABMAP_STATS(Loop, Highest_hypothesis_id,);
|
||||||
RTABMAP_STATS(Loop, Highest_hypothesis_value,);
|
RTABMAP_STATS(Loop, Highest_hypothesis_value,);
|
||||||
RTABMAP_STATS(Loop, Vp_hypothesis,);
|
RTABMAP_STATS(Loop, Vp_hypothesis,);
|
||||||
RTABMAP_STATS(Loop, Reactivate_id,);
|
RTABMAP_STATS(Loop, Reactivate_id,);
|
||||||
RTABMAP_STATS(Loop, Hypothesis_ratio,);
|
RTABMAP_STATS(Loop, Hypothesis_ratio,);
|
||||||
RTABMAP_STATS(Loop, Hypothesis_reactivated,);
|
RTABMAP_STATS(Loop, Hypothesis_reactivated,);
|
||||||
|
RTABMAP_STATS(Loop, Map_id,);
|
||||||
|
RTABMAP_STATS(Loop, Visual_words,);
|
||||||
RTABMAP_STATS(Loop, Visual_inliers,);
|
RTABMAP_STATS(Loop, Visual_inliers,);
|
||||||
RTABMAP_STATS(Loop, Visual_matches,);
|
RTABMAP_STATS(Loop, Visual_matches,);
|
||||||
RTABMAP_STATS(Loop, Last_id,);
|
RTABMAP_STATS(Loop, Last_id,);
|
||||||
@@ -73,13 +77,40 @@ class RTABMAP_EXP Statistics
|
|||||||
RTABMAP_STATS(Loop, Landmark_detected_node_ref,);
|
RTABMAP_STATS(Loop, Landmark_detected_node_ref,);
|
||||||
RTABMAP_STATS(Loop, Visual_inliers_mean_dist,m);
|
RTABMAP_STATS(Loop, Visual_inliers_mean_dist,m);
|
||||||
RTABMAP_STATS(Loop, Visual_inliers_distribution,);
|
RTABMAP_STATS(Loop, Visual_inliers_distribution,);
|
||||||
RTABMAP_STATS(Loop, Map_correction_norm, m);
|
//Odom correction
|
||||||
RTABMAP_STATS(Loop, Map_correction_x, m);
|
RTABMAP_STATS(Loop, Odom_correction_norm, m);
|
||||||
RTABMAP_STATS(Loop, Map_correction_y, m);
|
RTABMAP_STATS(Loop, Odom_correction_angle, deg);
|
||||||
RTABMAP_STATS(Loop, Map_correction_z, m);
|
RTABMAP_STATS(Loop, Odom_correction_x, m);
|
||||||
RTABMAP_STATS(Loop, Map_correction_roll, deg);
|
RTABMAP_STATS(Loop, Odom_correction_y, m);
|
||||||
RTABMAP_STATS(Loop, Map_correction_pitch, deg);
|
RTABMAP_STATS(Loop, Odom_correction_z, m);
|
||||||
RTABMAP_STATS(Loop, Map_correction_yaw, deg);
|
RTABMAP_STATS(Loop, Odom_correction_roll, deg);
|
||||||
|
RTABMAP_STATS(Loop, Odom_correction_pitch, deg);
|
||||||
|
RTABMAP_STATS(Loop, Odom_correction_yaw, deg);
|
||||||
|
//Odom correction
|
||||||
|
RTABMAP_STATS(Loop, Odom_correction_acc_norm, m);
|
||||||
|
RTABMAP_STATS(Loop, Odom_correction_acc_angle, deg);
|
||||||
|
RTABMAP_STATS(Loop, Odom_correction_acc_x, m);
|
||||||
|
RTABMAP_STATS(Loop, Odom_correction_acc_y, m);
|
||||||
|
RTABMAP_STATS(Loop, Odom_correction_acc_z, m);
|
||||||
|
RTABMAP_STATS(Loop, Odom_correction_acc_roll, deg);
|
||||||
|
RTABMAP_STATS(Loop, Odom_correction_acc_pitch, deg);
|
||||||
|
RTABMAP_STATS(Loop, Odom_correction_acc_yaw, deg);
|
||||||
|
// Map to Odom
|
||||||
|
RTABMAP_STATS(Loop, MapToOdom_norm, m);
|
||||||
|
RTABMAP_STATS(Loop, MapToOdom_angle, deg);
|
||||||
|
RTABMAP_STATS(Loop, MapToOdom_x, m);
|
||||||
|
RTABMAP_STATS(Loop, MapToOdom_y, m);
|
||||||
|
RTABMAP_STATS(Loop, MapToOdom_z, m);
|
||||||
|
RTABMAP_STATS(Loop, MapToOdom_roll, deg);
|
||||||
|
RTABMAP_STATS(Loop, MapToOdom_pitch, deg);
|
||||||
|
RTABMAP_STATS(Loop, MapToOdom_yaw, deg);
|
||||||
|
// Map to Base
|
||||||
|
RTABMAP_STATS(Loop, MapToBase_x, m);
|
||||||
|
RTABMAP_STATS(Loop, MapToBase_y, m);
|
||||||
|
RTABMAP_STATS(Loop, MapToBase_z, m);
|
||||||
|
RTABMAP_STATS(Loop, MapToBase_roll, deg);
|
||||||
|
RTABMAP_STATS(Loop, MapToBase_pitch, deg);
|
||||||
|
RTABMAP_STATS(Loop, MapToBase_yaw, deg);
|
||||||
|
|
||||||
RTABMAP_STATS(Proximity, Time_detections,);
|
RTABMAP_STATS(Proximity, Time_detections,);
|
||||||
RTABMAP_STATS(Proximity, Space_last_detection_id,);
|
RTABMAP_STATS(Proximity, Space_last_detection_id,);
|
||||||
@@ -159,6 +190,7 @@ class RTABMAP_EXP Statistics
|
|||||||
RTABMAP_STATS(TimingMem, Markers_detection, ms);
|
RTABMAP_STATS(TimingMem, Markers_detection, ms);
|
||||||
|
|
||||||
RTABMAP_STATS(Keypoint, Dictionary_size, words);
|
RTABMAP_STATS(Keypoint, Dictionary_size, words);
|
||||||
|
RTABMAP_STATS(Keypoint, Current_frame, words);
|
||||||
RTABMAP_STATS(Keypoint, Indexed_words, words);
|
RTABMAP_STATS(Keypoint, Indexed_words, words);
|
||||||
RTABMAP_STATS(Keypoint, Index_memory_usage, KB);
|
RTABMAP_STATS(Keypoint, Index_memory_usage, KB);
|
||||||
|
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ public:
|
|||||||
const cv::Size & imageSize2,
|
const cv::Size & imageSize2,
|
||||||
const cv::Mat & K2, const cv::Mat & D2, const cv::Mat & R2, const cv::Mat & P2,
|
const cv::Mat & K2, const cv::Mat & D2, const cv::Mat & R2, const cv::Mat & P2,
|
||||||
const cv::Mat & R, const cv::Mat & T, const cv::Mat & E, const cv::Mat & F,
|
const cv::Mat & R, const cv::Mat & T, const cv::Mat & E, const cv::Mat & F,
|
||||||
const Transform & localTransform = Transform::getIdentity());
|
const Transform & localTransform = Transform(0,0,1,0, -1,0,0,0, 0,-1,0,0));
|
||||||
|
|
||||||
// if R and T are not null, left and right camera models should be valid to be rectified.
|
// if R and T are not null, left and right camera models should be valid to be rectified.
|
||||||
StereoCameraModel(
|
StereoCameraModel(
|
||||||
@@ -68,7 +68,7 @@ public:
|
|||||||
double cx,
|
double cx,
|
||||||
double cy,
|
double cy,
|
||||||
double baseline,
|
double baseline,
|
||||||
const Transform & localTransform = Transform::getIdentity(),
|
const Transform & localTransform = Transform(0,0,1,0, -1,0,0,0, 0,-1,0,0),
|
||||||
const cv::Size & imageSize = cv::Size(0,0));
|
const cv::Size & imageSize = cv::Size(0,0));
|
||||||
//minimal to be saved
|
//minimal to be saved
|
||||||
StereoCameraModel(
|
StereoCameraModel(
|
||||||
@@ -78,7 +78,7 @@ public:
|
|||||||
double cx,
|
double cx,
|
||||||
double cy,
|
double cy,
|
||||||
double baseline,
|
double baseline,
|
||||||
const Transform & localTransform = Transform::getIdentity(),
|
const Transform & localTransform = Transform(0,0,1,0, -1,0,0,0, 0,-1,0,0),
|
||||||
const cv::Size & imageSize = cv::Size(0,0));
|
const cv::Size & imageSize = cv::Size(0,0));
|
||||||
virtual ~StereoCameraModel() {}
|
virtual ~StereoCameraModel() {}
|
||||||
|
|
||||||
|
|||||||
@@ -140,6 +140,15 @@ public:
|
|||||||
static Transform fromEigen3f(const Eigen::Isometry3f & matrix);
|
static Transform fromEigen3f(const Eigen::Isometry3f & matrix);
|
||||||
static Transform fromEigen3d(const Eigen::Isometry3d & matrix);
|
static Transform fromEigen3d(const Eigen::Isometry3d & matrix);
|
||||||
|
|
||||||
|
static Transform opengl_T_rtabmap() {return Transform(
|
||||||
|
0.0f, -1.0f, 0.0f, 0.0f,
|
||||||
|
0.0f, 0.0f, 1.0f, 0.0f,
|
||||||
|
-1.0f, 0.0f, 0.0f, 0.0f);}
|
||||||
|
static Transform rtabmap_T_opengl() {return Transform(
|
||||||
|
0.0f, 0.0f,-1.0f, 0.0f,
|
||||||
|
-1.0f, 0.0f, 0.0f, 0.0f,
|
||||||
|
0.0f, 1.0f, 0.0f, 0.0f);}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Format (3 values): x y z
|
* Format (3 values): x y z
|
||||||
* Format (6 values): x y z roll pitch yaw
|
* Format (6 values): x y z roll pitch yaw
|
||||||
|
|||||||
@@ -55,6 +55,23 @@ public:
|
|||||||
kNNUndef};
|
kNNUndef};
|
||||||
static const int ID_START;
|
static const int ID_START;
|
||||||
static const int ID_INVALID;
|
static const int ID_INVALID;
|
||||||
|
static std::string nnStrategyName(NNStrategy strategy)
|
||||||
|
{
|
||||||
|
switch(strategy) {
|
||||||
|
case kNNFlannNaive:
|
||||||
|
return "FLANN NAIVE";
|
||||||
|
case kNNFlannKdTree:
|
||||||
|
return "FLANN KD-TREE";
|
||||||
|
case kNNFlannLSH:
|
||||||
|
return "FLANN LSH";
|
||||||
|
case kNNBruteForce:
|
||||||
|
return "BRUTE FORCE";
|
||||||
|
case kNNBruteForceGPU:
|
||||||
|
return "BRUTE FORCE GPU";
|
||||||
|
default:
|
||||||
|
return "Unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
VWDictionary(const ParametersMap & parameters = ParametersMap());
|
VWDictionary(const ParametersMap & parameters = ParametersMap());
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ public:
|
|||||||
CameraFreenect(int deviceId= 0,
|
CameraFreenect(int deviceId= 0,
|
||||||
Type type = kTypeColorDepth,
|
Type type = kTypeColorDepth,
|
||||||
float imageRate=0.0f,
|
float imageRate=0.0f,
|
||||||
const Transform & localTransform = Transform::getIdentity());
|
const Transform & localTransform = CameraModel::opticalRotation());
|
||||||
virtual ~CameraFreenect();
|
virtual ~CameraFreenect();
|
||||||
|
|
||||||
virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = "");
|
virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = "");
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ public:
|
|||||||
CameraFreenect2(int deviceId= 0,
|
CameraFreenect2(int deviceId= 0,
|
||||||
Type type = kTypeDepth2ColorSD,
|
Type type = kTypeDepth2ColorSD,
|
||||||
float imageRate=0.0f,
|
float imageRate=0.0f,
|
||||||
const Transform & localTransform = Transform::getIdentity(),
|
const Transform & localTransform = CameraModel::opticalRotation(),
|
||||||
float minDepth = 0.3f,
|
float minDepth = 0.3f,
|
||||||
float maxDepth = 12.0f,
|
float maxDepth = 12.0f,
|
||||||
bool bilateralFiltering = true,
|
bool bilateralFiltering = true,
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ public:
|
|||||||
CameraImages(
|
CameraImages(
|
||||||
const std::string & path,
|
const std::string & path,
|
||||||
float imageRate = 0,
|
float imageRate = 0,
|
||||||
const Transform & localTransform = Transform::getIdentity());
|
const Transform & localTransform = CameraModel::opticalRotation());
|
||||||
virtual ~CameraImages();
|
virtual ~CameraImages();
|
||||||
|
|
||||||
virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = "");
|
virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = "");
|
||||||
|
|||||||
@@ -34,6 +34,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "rtabmap/core/Version.h"
|
#include "rtabmap/core/Version.h"
|
||||||
#include "rtabmap/utilite/UTimer.h"
|
#include "rtabmap/utilite/UTimer.h"
|
||||||
|
|
||||||
|
#ifdef RTABMAP_K4A
|
||||||
|
#include <k4a/k4atypes.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace rtabmap
|
namespace rtabmap
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -46,10 +50,10 @@ public:
|
|||||||
public:
|
public:
|
||||||
CameraK4A(int deviceId = 0,
|
CameraK4A(int deviceId = 0,
|
||||||
float imageRate = 0.0f,
|
float imageRate = 0.0f,
|
||||||
const Transform & localTransform = Transform::getIdentity());
|
const Transform & localTransform = CameraModel::opticalRotation());
|
||||||
CameraK4A(const std::string & fileName,
|
CameraK4A(const std::string & fileName,
|
||||||
float imageRate = 0.0f,
|
float imageRate = 0.0f,
|
||||||
const Transform & localTransform = Transform::getIdentity());
|
const Transform & localTransform = CameraModel::opticalRotation());
|
||||||
virtual ~CameraK4A();
|
virtual ~CameraK4A();
|
||||||
|
|
||||||
virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = "");
|
virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = "");
|
||||||
@@ -57,6 +61,7 @@ public:
|
|||||||
virtual std::string getSerial() const;
|
virtual std::string getSerial() const;
|
||||||
|
|
||||||
void setIRDepthFormat(bool enabled);
|
void setIRDepthFormat(bool enabled);
|
||||||
|
void setPreferences(int rgb_resolution, int framerate, int depth_resolution);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual SensorData captureImage(CameraInfo * info = 0);
|
virtual SensorData captureImage(CameraInfo * info = 0);
|
||||||
@@ -67,14 +72,25 @@ private:
|
|||||||
private:
|
private:
|
||||||
|
|
||||||
#ifdef RTABMAP_K4A
|
#ifdef RTABMAP_K4A
|
||||||
|
k4a_device_t device_;
|
||||||
|
k4a_device_configuration_t config_;
|
||||||
|
k4a_calibration_t calibration_;
|
||||||
|
k4a_transformation_t transformation_;
|
||||||
|
k4a_capture_t capture_;
|
||||||
|
std::string serial_number_;
|
||||||
|
|
||||||
void* playbackHandle_;
|
void* playbackHandle_;
|
||||||
void* transformationHandle_;
|
void* transformationHandle_;
|
||||||
CameraModel model_;
|
CameraModel model_;
|
||||||
int deviceId_;
|
int deviceId_;
|
||||||
std::string fileName_;
|
std::string fileName_;
|
||||||
|
int rgb_resolution_;
|
||||||
|
int framerate_;
|
||||||
|
int depth_resolution_;
|
||||||
bool ir_;
|
bool ir_;
|
||||||
double previousStamp_;
|
double previousStamp_;
|
||||||
UTimer timer_;
|
UTimer timer_;
|
||||||
|
Transform imuLocalTransform_;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ public:
|
|||||||
CameraK4W2(int deviceId = 0, // not used
|
CameraK4W2(int deviceId = 0, // not used
|
||||||
Type type = kTypeDepth2ColorSD,
|
Type type = kTypeDepth2ColorSD,
|
||||||
float imageRate = 0.0f,
|
float imageRate = 0.0f,
|
||||||
const Transform & localTransform = Transform::getIdentity());
|
const Transform & localTransform = CameraModel::opticalRotation());
|
||||||
virtual ~CameraK4W2();
|
virtual ~CameraK4W2();
|
||||||
|
|
||||||
virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = "");
|
virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = "");
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ public:
|
|||||||
static bool available();
|
static bool available();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CameraMyntEye(const std::string & device = "", bool apiRectification = false, bool apiDepth = false, float imageRate = 0, const Transform & localTransform = Transform::getIdentity());
|
CameraMyntEye(const std::string & device = "", bool apiRectification = false, bool apiDepth = false, float imageRate = 0, const Transform & localTransform = CameraModel::opticalRotation());
|
||||||
virtual ~CameraMyntEye();
|
virtual ~CameraMyntEye();
|
||||||
|
|
||||||
virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = "");
|
virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = "");
|
||||||
@@ -61,6 +61,9 @@ public:
|
|||||||
virtual bool odomProvided() const { return false; }
|
virtual bool odomProvided() const { return false; }
|
||||||
|
|
||||||
void publishInterIMU(bool enabled);
|
void publishInterIMU(bool enabled);
|
||||||
|
void setAutoExposure();
|
||||||
|
void setManualExposure(int gain=24, int brightness=120, int constrast=116);
|
||||||
|
void setIrControl(int value);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
@@ -80,6 +83,11 @@ private:
|
|||||||
std::string deviceName_;
|
std::string deviceName_;
|
||||||
bool apiRectification_;
|
bool apiRectification_;
|
||||||
bool apiDepth_;
|
bool apiDepth_;
|
||||||
|
bool autoExposure_;
|
||||||
|
int gain_;
|
||||||
|
int brightness_;
|
||||||
|
int contrast_;
|
||||||
|
int irControl_;
|
||||||
USemaphore dataReady_;
|
USemaphore dataReady_;
|
||||||
UMutex dataMutex_;
|
UMutex dataMutex_;
|
||||||
cv::Mat leftFrameBuffer_;
|
cv::Mat leftFrameBuffer_;
|
||||||
@@ -94,7 +102,7 @@ private:
|
|||||||
|
|
||||||
double softTimeBegin_;
|
double softTimeBegin_;
|
||||||
std::uint64_t hardTimeBegin_;
|
std::uint64_t hardTimeBegin_;
|
||||||
std::uint64_t unitHardTime;
|
std::uint64_t unitHardTime_;
|
||||||
std::vector<std::uint64_t> lastHardTimes_;
|
std::vector<std::uint64_t> lastHardTimes_;
|
||||||
std::vector<std::uint64_t> acc_;
|
std::vector<std::uint64_t> acc_;
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ public:
|
|||||||
CameraOpenNI2(const std::string & deviceId = "",
|
CameraOpenNI2(const std::string & deviceId = "",
|
||||||
Type type = kTypeColorDepth,
|
Type type = kTypeColorDepth,
|
||||||
float imageRate = 0,
|
float imageRate = 0,
|
||||||
const Transform & localTransform = Transform::getIdentity());
|
const Transform & localTransform = CameraModel::opticalRotation());
|
||||||
virtual ~CameraOpenNI2();
|
virtual ~CameraOpenNI2();
|
||||||
|
|
||||||
virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = "");
|
virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = "");
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ public:
|
|||||||
public:
|
public:
|
||||||
CameraOpenNICV(bool asus = false,
|
CameraOpenNICV(bool asus = false,
|
||||||
float imageRate = 0,
|
float imageRate = 0,
|
||||||
const Transform & localTransform = Transform::getIdentity());
|
const Transform & localTransform = CameraModel::opticalRotation());
|
||||||
virtual ~CameraOpenNICV();
|
virtual ~CameraOpenNICV();
|
||||||
|
|
||||||
virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = "");
|
virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = "");
|
||||||
|
|||||||
@@ -66,13 +66,20 @@ public:
|
|||||||
// default local transform z in, x right, y down));
|
// default local transform z in, x right, y down));
|
||||||
CameraOpenni(const std::string & deviceId="",
|
CameraOpenni(const std::string & deviceId="",
|
||||||
float imageRate = 0,
|
float imageRate = 0,
|
||||||
const Transform & localTransform = Transform::getIdentity());
|
const Transform & localTransform = CameraModel::opticalRotation());
|
||||||
virtual ~CameraOpenni();
|
virtual ~CameraOpenni();
|
||||||
#ifdef RTABMAP_OPENNI
|
#ifdef RTABMAP_OPENNI
|
||||||
|
#if PCL_VERSION_COMPARE(>=, 1, 10, 0)
|
||||||
|
void image_cb (
|
||||||
|
const std::shared_ptr<openni_wrapper::Image>& rgb,
|
||||||
|
const std::shared_ptr<openni_wrapper::DepthImage>& depth,
|
||||||
|
float constant);
|
||||||
|
#else
|
||||||
void image_cb (
|
void image_cb (
|
||||||
const boost::shared_ptr<openni_wrapper::Image>& rgb,
|
const boost::shared_ptr<openni_wrapper::Image>& rgb,
|
||||||
const boost::shared_ptr<openni_wrapper::DepthImage>& depth,
|
const boost::shared_ptr<openni_wrapper::DepthImage>& depth,
|
||||||
float constant);
|
float constant);
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = "");
|
virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = "");
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ public:
|
|||||||
const std::string & pathDepthImages,
|
const std::string & pathDepthImages,
|
||||||
float depthScaleFactor = 1.0f,
|
float depthScaleFactor = 1.0f,
|
||||||
float imageRate=0.0f,
|
float imageRate=0.0f,
|
||||||
const Transform & localTransform = Transform::getIdentity());
|
const Transform & localTransform = CameraModel::opticalRotation());
|
||||||
virtual ~CameraRGBDImages();
|
virtual ~CameraRGBDImages();
|
||||||
|
|
||||||
virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = "");
|
virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = "");
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ public:
|
|||||||
int presetDepth = 0, // 0=best quality, 1=largest image, 2=highest framerate
|
int presetDepth = 0, // 0=best quality, 1=largest image, 2=highest framerate
|
||||||
bool computeOdometry = false,
|
bool computeOdometry = false,
|
||||||
float imageRate = 0,
|
float imageRate = 0,
|
||||||
const Transform & localTransform = Transform::getIdentity());
|
const Transform & localTransform = CameraModel::opticalRotation());
|
||||||
virtual ~CameraRealSense();
|
virtual ~CameraRealSense();
|
||||||
|
|
||||||
void setDepthScaledToRGBSize(bool enabled);
|
void setDepthScaledToRGBSize(bool enabled);
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ public:
|
|||||||
CameraRealSense2(
|
CameraRealSense2(
|
||||||
const std::string & deviceId = "",
|
const std::string & deviceId = "",
|
||||||
float imageRate = 0,
|
float imageRate = 0,
|
||||||
const Transform & localTransform = Transform::getIdentity());
|
const Transform & localTransform = CameraModel::opticalRotation());
|
||||||
virtual ~CameraRealSense2();
|
virtual ~CameraRealSense2();
|
||||||
|
|
||||||
virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = "");
|
virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = "");
|
||||||
@@ -134,6 +134,7 @@ private:
|
|||||||
bool dualMode_;
|
bool dualMode_;
|
||||||
Transform dualExtrinsics_;
|
Transform dualExtrinsics_;
|
||||||
std::string jsonConfig_;
|
std::string jsonConfig_;
|
||||||
|
bool closing_;
|
||||||
|
|
||||||
static Transform realsense2PoseRotation_;
|
static Transform realsense2PoseRotation_;
|
||||||
static Transform realsense2PoseRotationInv_;
|
static Transform realsense2PoseRotationInv_;
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ public:
|
|||||||
static bool available();
|
static bool available();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CameraStereoDC1394( float imageRate=0.0f, const Transform & localTransform = Transform::getIdentity());
|
CameraStereoDC1394( float imageRate=0.0f, const Transform & localTransform = CameraModel::opticalRotation());
|
||||||
virtual ~CameraStereoDC1394();
|
virtual ~CameraStereoDC1394();
|
||||||
|
|
||||||
virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = "");
|
virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = "");
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ public:
|
|||||||
static bool available();
|
static bool available();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CameraStereoFlyCapture2( float imageRate=0.0f, const Transform & localTransform = Transform::getIdentity());
|
CameraStereoFlyCapture2( float imageRate=0.0f, const Transform & localTransform = CameraModel::opticalRotation());
|
||||||
virtual ~CameraStereoFlyCapture2();
|
virtual ~CameraStereoFlyCapture2();
|
||||||
|
|
||||||
virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = "");
|
virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = "");
|
||||||
|
|||||||
@@ -49,12 +49,12 @@ public:
|
|||||||
const std::string & pathRightImages,
|
const std::string & pathRightImages,
|
||||||
bool rectifyImages = false,
|
bool rectifyImages = false,
|
||||||
float imageRate=0.0f,
|
float imageRate=0.0f,
|
||||||
const Transform & localTransform = Transform::getIdentity());
|
const Transform & localTransform = CameraModel::opticalRotation());
|
||||||
CameraStereoImages(
|
CameraStereoImages(
|
||||||
const std::string & pathLeftRightImages,
|
const std::string & pathLeftRightImages,
|
||||||
bool rectifyImages = false,
|
bool rectifyImages = false,
|
||||||
float imageRate=0.0f,
|
float imageRate=0.0f,
|
||||||
const Transform & localTransform = Transform::getIdentity());
|
const Transform & localTransform = CameraModel::opticalRotation());
|
||||||
virtual ~CameraStereoImages();
|
virtual ~CameraStereoImages();
|
||||||
|
|
||||||
virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = "");
|
virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = "");
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ public:
|
|||||||
int device,
|
int device,
|
||||||
bool rectifyImages = false,
|
bool rectifyImages = false,
|
||||||
float imageRate = 0.0f,
|
float imageRate = 0.0f,
|
||||||
const Transform & localTransform = Transform::getIdentity());
|
const Transform & localTransform = CameraModel::opticalRotation());
|
||||||
|
|
||||||
virtual ~CameraStereoTara();
|
virtual ~CameraStereoTara();
|
||||||
|
|
||||||
|
|||||||
@@ -46,24 +46,24 @@ public:
|
|||||||
const std::string & pathSideBySide,
|
const std::string & pathSideBySide,
|
||||||
bool rectifyImages = false,
|
bool rectifyImages = false,
|
||||||
float imageRate=0.0f,
|
float imageRate=0.0f,
|
||||||
const Transform & localTransform = Transform::getIdentity());
|
const Transform & localTransform = CameraModel::opticalRotation());
|
||||||
CameraStereoVideo(
|
CameraStereoVideo(
|
||||||
const std::string & pathLeft,
|
const std::string & pathLeft,
|
||||||
const std::string & pathRight,
|
const std::string & pathRight,
|
||||||
bool rectifyImages = false,
|
bool rectifyImages = false,
|
||||||
float imageRate=0.0f,
|
float imageRate=0.0f,
|
||||||
const Transform & localTransform = Transform::getIdentity());
|
const Transform & localTransform = CameraModel::opticalRotation());
|
||||||
CameraStereoVideo(
|
CameraStereoVideo(
|
||||||
int device,
|
int device,
|
||||||
bool rectifyImages = false,
|
bool rectifyImages = false,
|
||||||
float imageRate = 0.0f,
|
float imageRate = 0.0f,
|
||||||
const Transform & localTransform = Transform::getIdentity());
|
const Transform & localTransform = CameraModel::opticalRotation());
|
||||||
CameraStereoVideo(
|
CameraStereoVideo(
|
||||||
int deviceLeft,
|
int deviceLeft,
|
||||||
int deviceRight,
|
int deviceRight,
|
||||||
bool rectifyImages = false,
|
bool rectifyImages = false,
|
||||||
float imageRate = 0.0f,
|
float imageRate = 0.0f,
|
||||||
const Transform & localTransform = Transform::getIdentity());
|
const Transform & localTransform = CameraModel::opticalRotation());
|
||||||
virtual ~CameraStereoVideo();
|
virtual ~CameraStereoVideo();
|
||||||
|
|
||||||
virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = "");
|
virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = "");
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ public:
|
|||||||
int confidenceThr = 100,
|
int confidenceThr = 100,
|
||||||
bool computeOdometry = false,
|
bool computeOdometry = false,
|
||||||
float imageRate=0.0f,
|
float imageRate=0.0f,
|
||||||
const Transform & localTransform = Transform::getIdentity(),
|
const Transform & localTransform = CameraModel::opticalRotation(),
|
||||||
bool selfCalibration = true,
|
bool selfCalibration = true,
|
||||||
bool odomForce3DoF = false,
|
bool odomForce3DoF = false,
|
||||||
int texturenessConfidenceThr = 90); // introduced with ZED SDK 3
|
int texturenessConfidenceThr = 90); // introduced with ZED SDK 3
|
||||||
@@ -68,7 +68,7 @@ public:
|
|||||||
int confidenceThr = 100,
|
int confidenceThr = 100,
|
||||||
bool computeOdometry = false,
|
bool computeOdometry = false,
|
||||||
float imageRate=0.0f,
|
float imageRate=0.0f,
|
||||||
const Transform & localTransform = Transform::getIdentity(),
|
const Transform & localTransform = CameraModel::opticalRotation(),
|
||||||
bool selfCalibration = true,
|
bool selfCalibration = true,
|
||||||
bool odomForce3DoF = false,
|
bool odomForce3DoF = false,
|
||||||
int texturenessConfidenceThr = 90); // introduced with ZED SDK 3
|
int texturenessConfidenceThr = 90); // introduced with ZED SDK 3
|
||||||
|
|||||||
@@ -45,11 +45,11 @@ public:
|
|||||||
CameraVideo(int usbDevice = 0,
|
CameraVideo(int usbDevice = 0,
|
||||||
bool rectifyImages = false,
|
bool rectifyImages = false,
|
||||||
float imageRate = 0,
|
float imageRate = 0,
|
||||||
const Transform & localTransform = Transform::getIdentity());
|
const Transform & localTransform = CameraModel::opticalRotation());
|
||||||
CameraVideo(const std::string & filePath,
|
CameraVideo(const std::string & filePath,
|
||||||
bool rectifyImages = false,
|
bool rectifyImages = false,
|
||||||
float imageRate = 0,
|
float imageRate = 0,
|
||||||
const Transform & localTransform = Transform::getIdentity());
|
const Transform & localTransform = CameraModel::opticalRotation());
|
||||||
virtual ~CameraVideo();
|
virtual ~CameraVideo();
|
||||||
|
|
||||||
virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = "");
|
virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = "");
|
||||||
|
|||||||
@@ -97,11 +97,28 @@ void segmentObstaclesFromGround(
|
|||||||
// cluster all surfaces for which the centroid is in the Z-range of the bigger surface
|
// cluster all surfaces for which the centroid is in the Z-range of the bigger surface
|
||||||
if(clusteredFlatSurfaces.size())
|
if(clusteredFlatSurfaces.size())
|
||||||
{
|
{
|
||||||
ground = clusteredFlatSurfaces.at(biggestFlatSurfaceIndex);
|
|
||||||
Eigen::Vector4f min,max;
|
Eigen::Vector4f min,max;
|
||||||
pcl::getMinMax3D(*cloud, *clusteredFlatSurfaces.at(biggestFlatSurfaceIndex), min, max);
|
if(maxGroundHeight != 0.0f)
|
||||||
|
{
|
||||||
|
// Search for biggest surface under max ground height
|
||||||
|
size_t points = 0;
|
||||||
|
for(size_t i=0;i<clusteredFlatSurfaces.size();++i)
|
||||||
|
{
|
||||||
|
pcl::getMinMax3D(*cloud, *clusteredFlatSurfaces.at(i), min, max);
|
||||||
|
if(min[2]<maxGroundHeight && clusteredFlatSurfaces.size() > points)
|
||||||
|
{
|
||||||
|
points = clusteredFlatSurfaces.at(i)->size();
|
||||||
|
biggestFlatSurfaceIndex = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pcl::getMinMax3D(*cloud, *clusteredFlatSurfaces.at(biggestFlatSurfaceIndex), min, max);
|
||||||
|
}
|
||||||
|
ground = clusteredFlatSurfaces.at(biggestFlatSurfaceIndex);
|
||||||
|
|
||||||
if(maxGroundHeight == 0.0f || min[2] < maxGroundHeight)
|
if(!ground->empty() && (maxGroundHeight == 0.0f || min[2] < maxGroundHeight))
|
||||||
{
|
{
|
||||||
for(unsigned int i=0; i<clusteredFlatSurfaces.size(); ++i)
|
for(unsigned int i=0; i<clusteredFlatSurfaces.size(); ++i)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -79,7 +79,6 @@ private:
|
|||||||
Signature * lastFrame_;
|
Signature * lastFrame_;
|
||||||
int lastFrameOldestNewId_;
|
int lastFrameOldestNewId_;
|
||||||
std::vector<std::pair<pcl::PointCloud<pcl::PointNormal>::Ptr, pcl::IndicesPtr> > scansBuffer_;
|
std::vector<std::pair<pcl::PointCloud<pcl::PointNormal>::Ptr, pcl::IndicesPtr> > scansBuffer_;
|
||||||
std::map<double, Transform> imus_;
|
|
||||||
bool initGravity_;
|
bool initGravity_;
|
||||||
|
|
||||||
std::map<int, std::map<int, FeatureBA> > bundleWordReferences_; //<WordId, <FrameId, pt2D+depth>>
|
std::map<int, std::map<int, FeatureBA> > bundleWordReferences_; //<WordId, <FrameId, pt2D+depth>>
|
||||||
|
|||||||
@@ -29,11 +29,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#define ODOMETRYMONO_H_
|
#define ODOMETRYMONO_H_
|
||||||
|
|
||||||
#include <rtabmap/core/Odometry.h>
|
#include <rtabmap/core/Odometry.h>
|
||||||
|
#include <rtabmap/core/Link.h>
|
||||||
|
|
||||||
namespace rtabmap {
|
namespace rtabmap {
|
||||||
|
|
||||||
class Memory;
|
class Memory;
|
||||||
class Stereo;
|
class Feature2D;
|
||||||
|
|
||||||
class RTABMAP_EXP OdometryMono : public Odometry
|
class RTABMAP_EXP OdometryMono : public Odometry
|
||||||
{
|
{
|
||||||
@@ -41,6 +42,7 @@ public:
|
|||||||
OdometryMono(const rtabmap::ParametersMap & parameters = rtabmap::ParametersMap());
|
OdometryMono(const rtabmap::ParametersMap & parameters = rtabmap::ParametersMap());
|
||||||
virtual ~OdometryMono();
|
virtual ~OdometryMono();
|
||||||
virtual void reset(const Transform & initialPose);
|
virtual void reset(const Transform & initialPose);
|
||||||
|
virtual Odometry::Type getType() {return kTypeUndef;}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual Transform computeTransform(SensorData & data, const Transform & guess = Transform(), OdometryInfo * info = 0);
|
virtual Transform computeTransform(SensorData & data, const Transform & guess = Transform(), OdometryInfo * info = 0);
|
||||||
@@ -56,7 +58,7 @@ private:
|
|||||||
int pnpFlags_;
|
int pnpFlags_;
|
||||||
int pnpRefineIterations_;
|
int pnpRefineIterations_;
|
||||||
|
|
||||||
Stereo * stereo_;
|
Feature2D * feature2D_;
|
||||||
|
|
||||||
Memory * memory_;
|
Memory * memory_;
|
||||||
int localHistoryMaxSize_;
|
int localHistoryMaxSize_;
|
||||||
@@ -66,12 +68,14 @@ private:
|
|||||||
float fundMatrixReprojError_;
|
float fundMatrixReprojError_;
|
||||||
float fundMatrixConfidence_;
|
float fundMatrixConfidence_;
|
||||||
|
|
||||||
cv::Mat refDepthOrRight_;
|
std::map<int, cv::Point2f> firstFrameGuessCorners_;
|
||||||
std::map<int, cv::Point2f> cornersMap_;
|
|
||||||
std::map<int, cv::Point3f> localMap_;
|
std::map<int, cv::Point3f> localMap_;
|
||||||
std::map<int, std::map<int, cv::Point3f> > keyFrameWords3D_;
|
std::map<int, std::map<int, cv::Point3f> > keyFrameWords3D_;
|
||||||
std::map<int, Transform> keyFramePoses_;
|
std::map<int, Transform> keyFramePoses_;
|
||||||
|
std::multimap<int, Link> keyFrameLinks_;
|
||||||
|
std::map<int, CameraModel> keyFrameModels_;
|
||||||
float maxVariance_;
|
float maxVariance_;
|
||||||
|
float keyFrameThr_;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,10 +37,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <opencv2/calib3d/calib3d_c.h>
|
#include <opencv2/calib3d/calib3d_c.h>
|
||||||
|
|
||||||
#if CV_MAJOR_VERSION >= 4
|
#if CV_MAJOR_VERSION >= 4
|
||||||
|
|
||||||
#if CV_MINOR_VERSION >= 3
|
|
||||||
#include <opencv2/core/core_c.h>
|
#include <opencv2/core/core_c.h>
|
||||||
#endif
|
|
||||||
|
|
||||||
// Opencv4 doesn't expose those functions below anymore, we should recopy all of them!
|
// Opencv4 doesn't expose those functions below anymore, we should recopy all of them!
|
||||||
int cvRodrigues2( const CvMat* src, CvMat* dst, CvMat* jacobian CV_DEFAULT(0))
|
int cvRodrigues2( const CvMat* src, CvMat* dst, CvMat* jacobian CV_DEFAULT(0))
|
||||||
@@ -1192,8 +1189,8 @@ void stereoRectifyFisheye( cv::InputArray _cameraMatrix1, cv::InputArray _distCo
|
|||||||
cv::Mat cameraMatrix1 = _cameraMatrix1.getMat(), cameraMatrix2 = _cameraMatrix2.getMat();
|
cv::Mat cameraMatrix1 = _cameraMatrix1.getMat(), cameraMatrix2 = _cameraMatrix2.getMat();
|
||||||
cv::Mat distCoeffs1 = _distCoeffs1.getMat(), distCoeffs2 = _distCoeffs2.getMat();
|
cv::Mat distCoeffs1 = _distCoeffs1.getMat(), distCoeffs2 = _distCoeffs2.getMat();
|
||||||
cv::Mat Rmat = _Rmat.getMat(), Tmat = _Tmat.getMat();
|
cv::Mat Rmat = _Rmat.getMat(), Tmat = _Tmat.getMat();
|
||||||
|
|
||||||
#if CV_MAJOR_VERSION > 3 or (CV_MAJOR_VERSION >= 3 and (CV_MINOR_VERSION>4 or CV_MINOR_VERSION>=4 and CV_SUBMINOR_VERSION>=4))
|
#if CV_MAJOR_VERSION > 3 || (CV_MAJOR_VERSION >= 3 && (CV_MINOR_VERSION>4 || (CV_MINOR_VERSION>=4 && CV_SUBMINOR_VERSION>=4)))
|
||||||
CvMat c_cameraMatrix1 = cvMat(cameraMatrix1);
|
CvMat c_cameraMatrix1 = cvMat(cameraMatrix1);
|
||||||
CvMat c_cameraMatrix2 = cvMat(cameraMatrix2);
|
CvMat c_cameraMatrix2 = cvMat(cameraMatrix2);
|
||||||
CvMat c_distCoeffs1 = cvMat(distCoeffs1);
|
CvMat c_distCoeffs1 = cvMat(distCoeffs1);
|
||||||
@@ -1213,7 +1210,7 @@ void stereoRectifyFisheye( cv::InputArray _cameraMatrix1, cv::InputArray _distCo
|
|||||||
_Pmat1.create(3, 4, rtype);
|
_Pmat1.create(3, 4, rtype);
|
||||||
_Pmat2.create(3, 4, rtype);
|
_Pmat2.create(3, 4, rtype);
|
||||||
cv::Mat R1 = _Rmat1.getMat(), R2 = _Rmat2.getMat(), P1 = _Pmat1.getMat(), P2 = _Pmat2.getMat(), Q;
|
cv::Mat R1 = _Rmat1.getMat(), R2 = _Rmat2.getMat(), P1 = _Pmat1.getMat(), P2 = _Pmat2.getMat(), Q;
|
||||||
#if CV_MAJOR_VERSION > 3 or (CV_MAJOR_VERSION >= 3 and (CV_MINOR_VERSION>4 or CV_MINOR_VERSION>=4 and CV_SUBMINOR_VERSION>=4))
|
#if CV_MAJOR_VERSION > 3 || (CV_MAJOR_VERSION >= 3 && (CV_MINOR_VERSION>4 || (CV_MINOR_VERSION>=4 && CV_SUBMINOR_VERSION>=4)))
|
||||||
CvMat c_R1 = cvMat(R1), c_R2 = cvMat(R2), c_P1 = cvMat(P1), c_P2 = cvMat(P2);
|
CvMat c_R1 = cvMat(R1), c_R2 = cvMat(R2), c_P1 = cvMat(P1), c_P2 = cvMat(P2);
|
||||||
#else
|
#else
|
||||||
CvMat c_R1 = CvMat(R1), c_R2 = CvMat(R2), c_P1 = CvMat(P1), c_P2 = CvMat(P2);
|
CvMat c_R1 = CvMat(R1), c_R2 = CvMat(R2), c_P1 = CvMat(P1), c_P2 = CvMat(P2);
|
||||||
@@ -1223,7 +1220,7 @@ void stereoRectifyFisheye( cv::InputArray _cameraMatrix1, cv::InputArray _distCo
|
|||||||
if( _Qmat.needed() )
|
if( _Qmat.needed() )
|
||||||
{
|
{
|
||||||
_Qmat.create(4, 4, rtype);
|
_Qmat.create(4, 4, rtype);
|
||||||
#if CV_MAJOR_VERSION > 3 or (CV_MAJOR_VERSION >= 3 and (CV_MINOR_VERSION>4 or CV_MINOR_VERSION>=4 and CV_SUBMINOR_VERSION>=4))
|
#if CV_MAJOR_VERSION > 3 || (CV_MAJOR_VERSION >= 3 && (CV_MINOR_VERSION>4 || (CV_MINOR_VERSION>=4 && CV_SUBMINOR_VERSION>=4)))
|
||||||
p_Q = &(c_Q = cvMat(Q = _Qmat.getMat()));
|
p_Q = &(c_Q = cvMat(Q = _Qmat.getMat()));
|
||||||
#else
|
#else
|
||||||
p_Q = &(c_Q = CvMat(Q = _Qmat.getMat()));
|
p_Q = &(c_Q = CvMat(Q = _Qmat.getMat()));
|
||||||
@@ -1233,7 +1230,7 @@ void stereoRectifyFisheye( cv::InputArray _cameraMatrix1, cv::InputArray _distCo
|
|||||||
CvMat *p_distCoeffs1 = distCoeffs1.empty() ? NULL : &c_distCoeffs1;
|
CvMat *p_distCoeffs1 = distCoeffs1.empty() ? NULL : &c_distCoeffs1;
|
||||||
CvMat *p_distCoeffs2 = distCoeffs2.empty() ? NULL : &c_distCoeffs2;
|
CvMat *p_distCoeffs2 = distCoeffs2.empty() ? NULL : &c_distCoeffs2;
|
||||||
cvStereoRectifyFisheye( &c_cameraMatrix1, &c_cameraMatrix2, p_distCoeffs1, p_distCoeffs2,
|
cvStereoRectifyFisheye( &c_cameraMatrix1, &c_cameraMatrix2, p_distCoeffs1, p_distCoeffs2,
|
||||||
#if CV_MAJOR_VERSION > 3 or (CV_MAJOR_VERSION >= 3 and (CV_MINOR_VERSION>4 or CV_MINOR_VERSION>=4 and CV_SUBMINOR_VERSION>=4))
|
#if CV_MAJOR_VERSION > 3 || (CV_MAJOR_VERSION >= 3 && (CV_MINOR_VERSION>4 || (CV_MINOR_VERSION>=4 && CV_SUBMINOR_VERSION>=4)))
|
||||||
cvSize(imageSize), &c_R, &c_T, &c_R1, &c_R2, &c_P1, &c_P2, p_Q, flags, alpha,
|
cvSize(imageSize), &c_R, &c_T, &c_R1, &c_R2, &c_P1, &c_P2, p_Q, flags, alpha,
|
||||||
cvSize(newImageSize));
|
cvSize(newImageSize));
|
||||||
#else
|
#else
|
||||||
|
|||||||
@@ -78,14 +78,11 @@ std::map<int, cv::Point3f> RTABMAP_EXP generateWords3DMono(
|
|||||||
const std::map<int, cv::KeyPoint> & previousKpts,
|
const std::map<int, cv::KeyPoint> & previousKpts,
|
||||||
const CameraModel & cameraModel,
|
const CameraModel & cameraModel,
|
||||||
Transform & cameraTransform,
|
Transform & cameraTransform,
|
||||||
int pnpIterations = 100,
|
float ransacReprojThreshold = 3.0f,
|
||||||
float pnpReprojError = 8.0f,
|
float ransacConfidence = 0.99f,
|
||||||
int pnpFlags = 0, // cv::SOLVEPNP_ITERATIVE
|
|
||||||
int pnpRefineIterations = 1,
|
|
||||||
float ransacParam1 = 3.0f,
|
|
||||||
float ransacParam2 = 0.99f,
|
|
||||||
const std::map<int, cv::Point3f> & refGuess3D = std::map<int, cv::Point3f>(),
|
const std::map<int, cv::Point3f> & refGuess3D = std::map<int, cv::Point3f>(),
|
||||||
double * variance = 0);
|
double * variance = 0,
|
||||||
|
std::vector<int> * matchesOut = 0);
|
||||||
|
|
||||||
std::multimap<int, cv::KeyPoint> RTABMAP_EXP aggregate(
|
std::multimap<int, cv::KeyPoint> RTABMAP_EXP aggregate(
|
||||||
const std::list<int> & wordIds,
|
const std::list<int> & wordIds,
|
||||||
|
|||||||
@@ -117,6 +117,8 @@ SET(SRC_FILES
|
|||||||
clams/slam_calibrator.cpp
|
clams/slam_calibrator.cpp
|
||||||
|
|
||||||
opencv/ORBextractor.cc
|
opencv/ORBextractor.cc
|
||||||
|
opencv/solvepnp.cpp
|
||||||
|
opencv/five-point.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
IF(OpenCV_VERSION_MAJOR EQUAL 2)
|
IF(OpenCV_VERSION_MAJOR EQUAL 2)
|
||||||
@@ -125,10 +127,6 @@ SET(SRC_FILES
|
|||||||
opencv/Orb.cpp
|
opencv/Orb.cpp
|
||||||
)
|
)
|
||||||
ENDIF(OpenCV_VERSION_MAJOR EQUAL 2)
|
ENDIF(OpenCV_VERSION_MAJOR EQUAL 2)
|
||||||
SET(SRC_FILES
|
|
||||||
${SRC_FILES}
|
|
||||||
opencv/solvepnp.cpp
|
|
||||||
)
|
|
||||||
|
|
||||||
# to get includes in visual studio
|
# to get includes in visual studio
|
||||||
IF(MSVC)
|
IF(MSVC)
|
||||||
@@ -190,6 +188,24 @@ IF(TORCH_FOUND)
|
|||||||
)
|
)
|
||||||
ENDIF(TORCH_FOUND)
|
ENDIF(TORCH_FOUND)
|
||||||
|
|
||||||
|
IF(Python3_FOUND)
|
||||||
|
SET(LIBRARIES
|
||||||
|
${LIBRARIES}
|
||||||
|
Python3::Python
|
||||||
|
)
|
||||||
|
SET(SRC_FILES
|
||||||
|
${SRC_FILES}
|
||||||
|
pymatcher/PyMatcher.cpp
|
||||||
|
)
|
||||||
|
SET(INCLUDE_DIRS
|
||||||
|
${TORCH_INCLUDE_DIRS}
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/pymatcher
|
||||||
|
${INCLUDE_DIRS}
|
||||||
|
)
|
||||||
|
ENDIF(Python3_FOUND)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
IF(Freenect_FOUND)
|
IF(Freenect_FOUND)
|
||||||
IF(Freenect_DASH_INCLUDES)
|
IF(Freenect_DASH_INCLUDES)
|
||||||
ADD_DEFINITIONS("-DFREENECT_DASH_INCLUDES")
|
ADD_DEFINITIONS("-DFREENECT_DASH_INCLUDES")
|
||||||
@@ -277,6 +293,11 @@ IF(realsense2_FOUND)
|
|||||||
${LIBRARIES}
|
${LIBRARIES}
|
||||||
${RealSense2_LIBRARIES}
|
${RealSense2_LIBRARIES}
|
||||||
)
|
)
|
||||||
|
ELSEIF(APPLE)
|
||||||
|
SET(LIBRARIES
|
||||||
|
${LIBRARIES}
|
||||||
|
${realsense2_LIBRARIES}
|
||||||
|
)
|
||||||
ELSE()
|
ELSE()
|
||||||
SET(LIBRARIES
|
SET(LIBRARIES
|
||||||
${LIBRARIES}
|
${LIBRARIES}
|
||||||
|
|||||||
@@ -64,6 +64,11 @@ void Camera::resetTimer()
|
|||||||
_frameRateTimer->start();
|
_frameRateTimer->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Camera::initFromFile(const std::string & calibrationPath)
|
||||||
|
{
|
||||||
|
return init(UDirectory::getDir(calibrationPath), uSplit(UFile::getName(calibrationPath), '.').front());
|
||||||
|
}
|
||||||
|
|
||||||
SensorData Camera::takeImage(CameraInfo * info)
|
SensorData Camera::takeImage(CameraInfo * info)
|
||||||
{
|
{
|
||||||
bool warnFrameRateTooHigh = false;
|
bool warnFrameRateTooHigh = false;
|
||||||
|
|||||||
+19
-13
@@ -37,7 +37,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
namespace rtabmap {
|
namespace rtabmap {
|
||||||
|
|
||||||
CameraModel::CameraModel()
|
CameraModel::CameraModel() :
|
||||||
|
localTransform_(0,0,1,0, -1,0,0,0, 0,-1,0,0)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -210,7 +211,7 @@ void CameraModel::setImageSize(const cv::Size & size)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CameraModel::load(const std::string & directory, const std::string & cameraName)
|
bool CameraModel::load(const std::string & filePath)
|
||||||
{
|
{
|
||||||
K_ = cv::Mat();
|
K_ = cv::Mat();
|
||||||
D_ = cv::Mat();
|
D_ = cv::Mat();
|
||||||
@@ -221,7 +222,6 @@ bool CameraModel::load(const std::string & directory, const std::string & camera
|
|||||||
name_.clear();
|
name_.clear();
|
||||||
imageSize_ = cv::Size();
|
imageSize_ = cv::Size();
|
||||||
|
|
||||||
std::string filePath = directory+"/"+cameraName+".yaml";
|
|
||||||
if(UFile::exists(filePath))
|
if(UFile::exists(filePath))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -360,6 +360,11 @@ bool CameraModel::load(const std::string & directory, const std::string & camera
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CameraModel::load(const std::string & directory, const std::string & cameraName)
|
||||||
|
{
|
||||||
|
return load(directory+"/"+cameraName+".yaml");
|
||||||
|
}
|
||||||
|
|
||||||
bool CameraModel::save(const std::string & directory) const
|
bool CameraModel::save(const std::string & directory) const
|
||||||
{
|
{
|
||||||
std::string filePath = directory+"/"+name_+".yaml";
|
std::string filePath = directory+"/"+name_+".yaml";
|
||||||
@@ -635,22 +640,23 @@ CameraModel CameraModel::roi(const cv::Rect & roi) const
|
|||||||
return roiModel;
|
return roiModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double CameraModel::fovX() const
|
||||||
|
{
|
||||||
|
return imageSize_.width>0 && fx()>0?2.0*atan(imageSize_.width/(fx()*2.0)):0.0;
|
||||||
|
}
|
||||||
|
double CameraModel::fovY() const
|
||||||
|
{
|
||||||
|
return imageSize_.height>0 && fy()>0?2.0*atan(imageSize_.height/(fy()*2.0)):0.0;
|
||||||
|
}
|
||||||
|
|
||||||
double CameraModel::horizontalFOV() const
|
double CameraModel::horizontalFOV() const
|
||||||
{
|
{
|
||||||
if(imageWidth() > 0 && fx() > 0.0)
|
return fovX()*180.0/CV_PI;
|
||||||
{
|
|
||||||
return atan((double(imageWidth())/2.0)/fx())*2.0*180.0/CV_PI;
|
|
||||||
}
|
|
||||||
return 0.0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
double CameraModel::verticalFOV() const
|
double CameraModel::verticalFOV() const
|
||||||
{
|
{
|
||||||
if(imageHeight() > 0 && fy() > 0.0)
|
return fovY()*180.0/CV_PI;
|
||||||
{
|
|
||||||
return atan((double(imageHeight())/2.0)/fy())*2.0*180.0/CV_PI;
|
|
||||||
}
|
|
||||||
return 0.0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cv::Mat CameraModel::rectifyImage(const cv::Mat & raw, int interpolation) const
|
cv::Mat CameraModel::rectifyImage(const cv::Mat & raw, int interpolation) const
|
||||||
|
|||||||
@@ -74,7 +74,6 @@ CameraThread::CameraThread(Camera * camera, const ParametersMap & parameters) :
|
|||||||
|
|
||||||
CameraThread::~CameraThread()
|
CameraThread::~CameraThread()
|
||||||
{
|
{
|
||||||
UDEBUG("");
|
|
||||||
join(true);
|
join(true);
|
||||||
delete _camera;
|
delete _camera;
|
||||||
delete _distortionModel;
|
delete _distortionModel;
|
||||||
@@ -139,7 +138,6 @@ void CameraThread::mainLoopBegin()
|
|||||||
void CameraThread::mainLoop()
|
void CameraThread::mainLoop()
|
||||||
{
|
{
|
||||||
UTimer totalTime;
|
UTimer totalTime;
|
||||||
UDEBUG("");
|
|
||||||
CameraInfo info;
|
CameraInfo info;
|
||||||
SensorData data = _camera->takeImage(&info);
|
SensorData data = _camera->takeImage(&info);
|
||||||
|
|
||||||
@@ -161,7 +159,6 @@ void CameraThread::mainLoop()
|
|||||||
|
|
||||||
void CameraThread::mainLoopKill()
|
void CameraThread::mainLoopKill()
|
||||||
{
|
{
|
||||||
UDEBUG("");
|
|
||||||
if(dynamic_cast<CameraFreenect2*>(_camera) != 0)
|
if(dynamic_cast<CameraFreenect2*>(_camera) != 0)
|
||||||
{
|
{
|
||||||
int i=20;
|
int i=20;
|
||||||
|
|||||||
@@ -683,13 +683,29 @@ void DBDriver::getNodeData(
|
|||||||
if(uContains(_trashSignatures, signatureId))
|
if(uContains(_trashSignatures, signatureId))
|
||||||
{
|
{
|
||||||
const Signature * s = _trashSignatures.at(signatureId);
|
const Signature * s = _trashSignatures.at(signatureId);
|
||||||
if(!s->sensorData().imageCompressed().empty() ||
|
if((!s->isSaved() ||
|
||||||
!s->sensorData().laserScanCompressed().isEmpty() ||
|
((!images || !s->sensorData().imageCompressed().empty()) &&
|
||||||
!s->sensorData().userDataCompressed().empty() ||
|
(!scan || !s->sensorData().laserScanCompressed().isEmpty()) &&
|
||||||
s->sensorData().gridCellSize() != 0.0f ||
|
(!userData || !s->sensorData().userDataCompressed().empty()) &&
|
||||||
!s->isSaved())
|
(!occupancyGrid || s->sensorData().gridCellSize() != 0.0f))))
|
||||||
{
|
{
|
||||||
data = (SensorData)s->sensorData();
|
data = (SensorData)s->sensorData();
|
||||||
|
if(!images)
|
||||||
|
{
|
||||||
|
data.setRGBDImage(cv::Mat(), cv::Mat(), std::vector<CameraModel>());
|
||||||
|
}
|
||||||
|
if(!scan)
|
||||||
|
{
|
||||||
|
data.setLaserScan(LaserScan());
|
||||||
|
}
|
||||||
|
if(!userData)
|
||||||
|
{
|
||||||
|
data.setUserData(cv::Mat());
|
||||||
|
}
|
||||||
|
if(!occupancyGrid)
|
||||||
|
{
|
||||||
|
data.setOccupancyGrid(cv::Mat(), cv::Mat(), cv::Mat(), 0, cv::Point3f());
|
||||||
|
}
|
||||||
found = true;
|
found = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1140,10 +1156,10 @@ void DBDriver::addInfoAfterRun(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DBDriver::addStatistics(const Statistics & statistics) const
|
void DBDriver::addStatistics(const Statistics & statistics, bool saveWmState) const
|
||||||
{
|
{
|
||||||
_dbSafeAccessMutex.lock();
|
_dbSafeAccessMutex.lock();
|
||||||
addStatisticsQuery(statistics);
|
addStatisticsQuery(statistics, saveWmState);
|
||||||
_dbSafeAccessMutex.unlock();
|
_dbSafeAccessMutex.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -842,22 +842,22 @@ long DBDriverSqlite3::getFeaturesMemoryUsedQuery() const
|
|||||||
std::string query;
|
std::string query;
|
||||||
if(uStrNumCmp(_version, "0.13.0") >= 0)
|
if(uStrNumCmp(_version, "0.13.0") >= 0)
|
||||||
{
|
{
|
||||||
query = "SELECT sum(length(word_id) + length(pos_x) + length(pos_y) + length(size) + length(dir) + length(response) + length(octave) + length(depth_x) + length(depth_y) + length(depth_z) + length(descriptor_size) + length(descriptor)) "
|
query = "SELECT sum(length(node_id) + length(word_id) + length(pos_x) + length(pos_y) + length(size) + length(dir) + length(response) + length(octave) + length(depth_x) + length(depth_y) + length(depth_z) + length(descriptor_size) + length(descriptor)) "
|
||||||
"FROM Feature";
|
"FROM Feature";
|
||||||
}
|
}
|
||||||
else if(uStrNumCmp(_version, "0.12.0") >= 0)
|
else if(uStrNumCmp(_version, "0.12.0") >= 0)
|
||||||
{
|
{
|
||||||
query = "SELECT sum(length(word_id) + length(pos_x) + length(pos_y) + length(size) + length(dir) + length(response) + length(octave) + length(depth_x) + length(depth_y) + length(depth_z) + length(descriptor_size) + length(descriptor)) "
|
query = "SELECT sum(length(node_id) + length(word_id) + length(pos_x) + length(pos_y) + length(size) + length(dir) + length(response) + length(octave) + length(depth_x) + length(depth_y) + length(depth_z) + length(descriptor_size) + length(descriptor)) "
|
||||||
"FROM Map_Node_Word";
|
"FROM Map_Node_Word";
|
||||||
}
|
}
|
||||||
else if(uStrNumCmp(_version, "0.11.2") >= 0)
|
else if(uStrNumCmp(_version, "0.11.2") >= 0)
|
||||||
{
|
{
|
||||||
query = "SELECT sum(length(word_id) + length(pos_x) + length(pos_y) + length(size) + length(dir) + length(response) + length(depth_x) + length(depth_y) + length(depth_z) + length(descriptor_size) + length(descriptor)) "
|
query = "SELECT sum(length(node_id) + length(word_id) + length(pos_x) + length(pos_y) + length(size) + length(dir) + length(response) + length(depth_x) + length(depth_y) + length(depth_z) + length(descriptor_size) + length(descriptor)) "
|
||||||
"FROM Map_Node_Word";
|
"FROM Map_Node_Word";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
query = "SELECT sum(length(word_id) + length(pos_x) + length(pos_y) + length(size) + length(dir) + length(response) + length(depth_x) + length(depth_y) + length(depth_z)) "
|
query = "SELECT sum(length(node_id) + length(word_id) + length(pos_x) + length(pos_y) + length(size) + length(dir) + length(response) + length(depth_x) + length(depth_y) + length(depth_z)) "
|
||||||
"FROM Map_Node_Word";
|
"FROM Map_Node_Word";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3384,6 +3384,74 @@ void DBDriverSqlite3::loadSignaturesQuery(const std::list<int> & ids, std::list<
|
|||||||
|
|
||||||
ULOGGER_DEBUG("Time load %d calibrations=%fs", (int)nodes.size(), timer.ticks());
|
ULOGGER_DEBUG("Time load %d calibrations=%fs", (int)nodes.size(), timer.ticks());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// load global descriptors
|
||||||
|
if(nodes.size() && uStrNumCmp(_version, "0.20.0") >= 0)
|
||||||
|
{
|
||||||
|
std::stringstream query3;
|
||||||
|
query3 << "SELECT type, info, data "
|
||||||
|
"FROM GlobalDescriptor "
|
||||||
|
"WHERE node_id = ? ";
|
||||||
|
|
||||||
|
rc = sqlite3_prepare_v2(_ppDb, query3.str().c_str(), -1, &ppStmt, 0);
|
||||||
|
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
|
||||||
|
|
||||||
|
for(std::list<Signature*>::const_iterator iter=nodes.begin(); iter!=nodes.end(); ++iter)
|
||||||
|
{
|
||||||
|
// bind id
|
||||||
|
rc = sqlite3_bind_int(ppStmt, 1, (*iter)->id());
|
||||||
|
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
|
||||||
|
|
||||||
|
std::vector<GlobalDescriptor> globalDescriptors;
|
||||||
|
|
||||||
|
rc = sqlite3_step(ppStmt);
|
||||||
|
while(rc == SQLITE_ROW)
|
||||||
|
{
|
||||||
|
int index=0;
|
||||||
|
const void * data = 0;
|
||||||
|
int dataSize = 0;
|
||||||
|
int type = -1;
|
||||||
|
cv::Mat info;
|
||||||
|
cv::Mat dataMat;
|
||||||
|
|
||||||
|
type = sqlite3_column_int(ppStmt, index++);
|
||||||
|
data = sqlite3_column_blob(ppStmt, index);
|
||||||
|
dataSize = sqlite3_column_bytes(ppStmt, index++);
|
||||||
|
if(dataSize && data)
|
||||||
|
{
|
||||||
|
info = rtabmap::uncompressData(cv::Mat(1, dataSize, CV_8UC1, (void *)data).clone());
|
||||||
|
}
|
||||||
|
data = sqlite3_column_blob(ppStmt, index);
|
||||||
|
dataSize = sqlite3_column_bytes(ppStmt, index++);
|
||||||
|
if(dataSize && data)
|
||||||
|
{
|
||||||
|
dataMat = rtabmap::uncompressData(cv::Mat(1, dataSize, CV_8UC1, (void *)data).clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
UASSERT(!dataMat.empty());
|
||||||
|
globalDescriptors.push_back(GlobalDescriptor(type, dataMat, info));
|
||||||
|
|
||||||
|
rc = sqlite3_step(ppStmt);
|
||||||
|
}
|
||||||
|
UASSERT_MSG(rc == SQLITE_DONE, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
|
||||||
|
|
||||||
|
if(!globalDescriptors.empty())
|
||||||
|
{
|
||||||
|
(*iter)->sensorData().setGlobalDescriptors(globalDescriptors);
|
||||||
|
ULOGGER_DEBUG("Add %d global descriptors to node %d", (int)globalDescriptors.size(), (*iter)->id());
|
||||||
|
}
|
||||||
|
|
||||||
|
//reset
|
||||||
|
rc = sqlite3_reset(ppStmt);
|
||||||
|
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
|
||||||
|
}
|
||||||
|
// Finalize (delete) the statement
|
||||||
|
rc = sqlite3_finalize(ppStmt);
|
||||||
|
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
|
||||||
|
|
||||||
|
ULOGGER_DEBUG("Time load %d global descriptors=%fs", (int)nodes.size(), timer.ticks());
|
||||||
|
}
|
||||||
|
|
||||||
if(ids.size() != loaded)
|
if(ids.size() != loaded)
|
||||||
{
|
{
|
||||||
UERROR("Some signatures not found in database");
|
UERROR("Some signatures not found in database");
|
||||||
@@ -3658,7 +3726,7 @@ void DBDriverSqlite3::loadLinksQuery(
|
|||||||
query << "SELECT to_id, type, transform FROM Link ";
|
query << "SELECT to_id, type, transform FROM Link ";
|
||||||
}
|
}
|
||||||
query << "WHERE from_id = " << signatureId;
|
query << "WHERE from_id = " << signatureId;
|
||||||
if(typeIn != Link::kUndef)
|
if(typeIn < Link::kEnd)
|
||||||
{
|
{
|
||||||
if(uStrNumCmp(_version, "0.7.4") >= 0)
|
if(uStrNumCmp(_version, "0.7.4") >= 0)
|
||||||
{
|
{
|
||||||
@@ -4235,6 +4303,27 @@ void DBDriverSqlite3::saveQuery(const std::list<Signature *> & signatures)
|
|||||||
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
|
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
|
||||||
UDEBUG("Time=%fs", timer.ticks());
|
UDEBUG("Time=%fs", timer.ticks());
|
||||||
|
|
||||||
|
if(uStrNumCmp(_version, "0.20.0") >= 0)
|
||||||
|
{
|
||||||
|
// Global descriptor table
|
||||||
|
std::string query = queryStepGlobalDescriptor();
|
||||||
|
rc = sqlite3_prepare_v2(_ppDb, query.c_str(), -1, &ppStmt, 0);
|
||||||
|
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
|
||||||
|
|
||||||
|
for(std::list<Signature *>::const_iterator i=signatures.begin(); i!=signatures.end(); ++i)
|
||||||
|
{
|
||||||
|
for(size_t d=0; d<(*i)->sensorData().globalDescriptors().size(); ++d)
|
||||||
|
{
|
||||||
|
stepGlobalDescriptor(ppStmt, (*i)->id(), (*i)->sensorData().globalDescriptors()[d]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Finalize (delete) the statement
|
||||||
|
rc = sqlite3_finalize(ppStmt);
|
||||||
|
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
|
||||||
|
|
||||||
|
UDEBUG("Time=%fs", timer.ticks());
|
||||||
|
}
|
||||||
|
|
||||||
if(uStrNumCmp(_version, "0.10.0") >= 0)
|
if(uStrNumCmp(_version, "0.10.0") >= 0)
|
||||||
{
|
{
|
||||||
// Add SensorData
|
// Add SensorData
|
||||||
@@ -4519,7 +4608,7 @@ void DBDriverSqlite3::updateLaserScanQuery(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DBDriverSqlite3::addStatisticsQuery(const Statistics & statistics) const
|
void DBDriverSqlite3::addStatisticsQuery(const Statistics & statistics, bool saveWmState) const
|
||||||
{
|
{
|
||||||
UDEBUG("Ref ID = %d", statistics.refImageId());
|
UDEBUG("Ref ID = %d", statistics.refImageId());
|
||||||
if(_ppDb)
|
if(_ppDb)
|
||||||
@@ -4570,7 +4659,7 @@ void DBDriverSqlite3::addStatisticsQuery(const Statistics & statistics) const
|
|||||||
cv::Mat compressedWmState;
|
cv::Mat compressedWmState;
|
||||||
if(uStrNumCmp(this->getDatabaseVersion(), "0.16.2") >= 0)
|
if(uStrNumCmp(this->getDatabaseVersion(), "0.16.2") >= 0)
|
||||||
{
|
{
|
||||||
if(!statistics.wmState().empty())
|
if(saveWmState && !statistics.wmState().empty())
|
||||||
{
|
{
|
||||||
compressedWmState = compressData2(cv::Mat(1, statistics.wmState().size(), CV_32SC1, (void *)statistics.wmState().data()));
|
compressedWmState = compressData2(cv::Mat(1, statistics.wmState().size(), CV_32SC1, (void *)statistics.wmState().data()));
|
||||||
rc = sqlite3_bind_blob(ppStmt, index++, compressedWmState.data, compressedWmState.cols, SQLITE_STATIC);
|
rc = sqlite3_bind_blob(ppStmt, index++, compressedWmState.data, compressedWmState.cols, SQLITE_STATIC);
|
||||||
@@ -6364,6 +6453,61 @@ void DBDriverSqlite3::stepKeypoint(sqlite3_stmt * ppStmt,
|
|||||||
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
|
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string DBDriverSqlite3::queryStepGlobalDescriptor() const
|
||||||
|
{
|
||||||
|
UASSERT(uStrNumCmp(_version, "0.20.0") >= 0);
|
||||||
|
return "INSERT INTO GlobalDescriptor(node_id, type, info, data) VALUES(?,?,?,?);";
|
||||||
|
}
|
||||||
|
void DBDriverSqlite3::stepGlobalDescriptor(sqlite3_stmt * ppStmt,
|
||||||
|
int nodeId,
|
||||||
|
const GlobalDescriptor & descriptor) const
|
||||||
|
{
|
||||||
|
if(!ppStmt)
|
||||||
|
{
|
||||||
|
UFATAL("");
|
||||||
|
}
|
||||||
|
int rc = SQLITE_OK;
|
||||||
|
int index = 1;
|
||||||
|
|
||||||
|
//node_if
|
||||||
|
rc = sqlite3_bind_int(ppStmt, index++, nodeId);
|
||||||
|
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
|
||||||
|
|
||||||
|
//type
|
||||||
|
rc = sqlite3_bind_int(ppStmt, index++, nodeId);
|
||||||
|
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
|
||||||
|
|
||||||
|
//info
|
||||||
|
std::vector<unsigned char> infoBytes = rtabmap::compressData(descriptor.info());
|
||||||
|
if(infoBytes.empty())
|
||||||
|
{
|
||||||
|
rc = sqlite3_bind_null(ppStmt, index++);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rc = sqlite3_bind_blob(ppStmt, index++, infoBytes.data(), infoBytes.size(), SQLITE_STATIC);
|
||||||
|
}
|
||||||
|
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
|
||||||
|
|
||||||
|
//data
|
||||||
|
std::vector<unsigned char> dataBytes = rtabmap::compressData(descriptor.data());
|
||||||
|
if(infoBytes.empty())
|
||||||
|
{
|
||||||
|
rc = sqlite3_bind_null(ppStmt, index++);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rc = sqlite3_bind_blob(ppStmt, index++, dataBytes.data(), dataBytes.size(), SQLITE_STATIC);
|
||||||
|
}
|
||||||
|
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
|
||||||
|
|
||||||
|
rc=sqlite3_step(ppStmt);
|
||||||
|
UASSERT_MSG(rc == SQLITE_DONE, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
|
||||||
|
|
||||||
|
rc = sqlite3_reset(ppStmt);
|
||||||
|
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
|
||||||
|
}
|
||||||
|
|
||||||
std::string DBDriverSqlite3::queryStepOccupancyGridUpdate() const
|
std::string DBDriverSqlite3::queryStepOccupancyGridUpdate() const
|
||||||
{
|
{
|
||||||
UASSERT(uStrNumCmp(_version, "0.11.10") >= 0);
|
UASSERT(uStrNumCmp(_version, "0.11.10") >= 0);
|
||||||
|
|||||||
@@ -292,8 +292,8 @@ cv::Mat EpipolarGeometry::findPFromE(const cv::Mat & E,
|
|||||||
cv::Mat EpipolarGeometry::findFFromWords(
|
cv::Mat EpipolarGeometry::findFFromWords(
|
||||||
const std::list<std::pair<int, std::pair<cv::KeyPoint, cv::KeyPoint> > > & pairs, // id, kpt1, kpt2
|
const std::list<std::pair<int, std::pair<cv::KeyPoint, cv::KeyPoint> > > & pairs, // id, kpt1, kpt2
|
||||||
std::vector<uchar> & status,
|
std::vector<uchar> & status,
|
||||||
double ransacParam1,
|
double ransacReprojThreshold,
|
||||||
double ransacParam2)
|
double ransacConfidence)
|
||||||
{
|
{
|
||||||
|
|
||||||
status = std::vector<uchar>(pairs.size(), 0);
|
status = std::vector<uchar>(pairs.size(), 0);
|
||||||
@@ -329,8 +329,8 @@ cv::Mat EpipolarGeometry::findFFromWords(
|
|||||||
points2,
|
points2,
|
||||||
status,
|
status,
|
||||||
cv::FM_RANSAC,
|
cv::FM_RANSAC,
|
||||||
ransacParam1,
|
ransacReprojThreshold,
|
||||||
ransacParam2);
|
ransacConfidence);
|
||||||
|
|
||||||
ULOGGER_DEBUG("Find fundamental matrix (OpenCV) time = %fs", timer.ticks());
|
ULOGGER_DEBUG("Find fundamental matrix (OpenCV) time = %fs", timer.ticks());
|
||||||
|
|
||||||
|
|||||||
+104
-27
@@ -44,7 +44,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "opencv/ORBextractor.h"
|
#include "opencv/ORBextractor.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef RTABMAP_SP_TORCH
|
#ifdef RTABMAP_SUPERPOINT_TORCH
|
||||||
#include "superpoint_torch/SuperPoint.h"
|
#include "superpoint_torch/SuperPoint.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -339,7 +339,7 @@ void Feature2D::limitKeypoints(const std::vector<cv::KeyPoint> & keypoints, std:
|
|||||||
if(maxKeypoints > 0 && (int)keypoints.size() > maxKeypoints)
|
if(maxKeypoints > 0 && (int)keypoints.size() > maxKeypoints)
|
||||||
{
|
{
|
||||||
UTimer timer;
|
UTimer timer;
|
||||||
ULOGGER_DEBUG("too much words (%d), removing words with the hessian threshold", keypoints.size());
|
ULOGGER_DEBUG("too much words (%d), removing words with the hessian threshold", (int)keypoints.size());
|
||||||
// Remove words under the new hessian threshold
|
// Remove words under the new hessian threshold
|
||||||
|
|
||||||
// Sort words by hessian
|
// Sort words by hessian
|
||||||
@@ -365,10 +365,50 @@ void Feature2D::limitKeypoints(const std::vector<cv::KeyPoint> & keypoints, std:
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
ULOGGER_DEBUG("keeping all %d keypoints", (int)keypoints.size());
|
||||||
inliers.resize(keypoints.size(), true);
|
inliers.resize(keypoints.size(), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Feature2D::limitKeypoints(const std::vector<cv::KeyPoint> & keypoints, std::vector<bool> & inliers, int maxKeypoints, const cv::Size & imageSize, int gridRows, int gridCols)
|
||||||
|
{
|
||||||
|
if(maxKeypoints <= 0 || (int)keypoints.size() <= maxKeypoints)
|
||||||
|
{
|
||||||
|
inliers.resize(keypoints.size(), true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
UASSERT(gridCols>=1 && gridRows >=1);
|
||||||
|
UASSERT(imageSize.height>gridRows && imageSize.width>gridCols);
|
||||||
|
int rowSize = imageSize.height / gridRows;
|
||||||
|
int colSize = imageSize.width / gridCols;
|
||||||
|
int maxKeypointsPerCell = maxKeypoints / (gridRows * gridCols);
|
||||||
|
std::vector<std::vector<cv::KeyPoint> > keypointsPerCell(gridRows * gridCols);
|
||||||
|
std::vector<std::vector<int> > indexesPerCell(gridRows * gridCols);
|
||||||
|
for(size_t i=0; i<keypoints.size(); ++i)
|
||||||
|
{
|
||||||
|
int cellRow = int(keypoints[i].pt.y)/rowSize;
|
||||||
|
int cellCol = int(keypoints[i].pt.x)/colSize;
|
||||||
|
UASSERT(cellRow >=0 && cellRow < gridRows);
|
||||||
|
UASSERT(cellCol >=0 && cellCol < gridCols);
|
||||||
|
|
||||||
|
keypointsPerCell[cellRow*gridCols + cellCol].push_back(keypoints[i]);
|
||||||
|
indexesPerCell[cellRow*gridCols + cellCol].push_back(i);
|
||||||
|
}
|
||||||
|
inliers.resize(keypoints.size(), false);
|
||||||
|
for(size_t i=0; i<keypointsPerCell.size(); ++i)
|
||||||
|
{
|
||||||
|
std::vector<bool> inliersCell;
|
||||||
|
limitKeypoints(keypointsPerCell[i], inliersCell, maxKeypointsPerCell);
|
||||||
|
for(size_t j=0; j<inliersCell.size(); ++j)
|
||||||
|
{
|
||||||
|
if(inliersCell[j])
|
||||||
|
{
|
||||||
|
inliers.at(indexesPerCell[i][j]) = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cv::Rect Feature2D::computeRoi(const cv::Mat & image, const std::string & roiRatios)
|
cv::Rect Feature2D::computeRoi(const cv::Mat & image, const std::string & roiRatios)
|
||||||
{
|
{
|
||||||
return util2d::computeRoi(image, roiRatios);
|
return util2d::computeRoi(image, roiRatios);
|
||||||
@@ -414,10 +454,6 @@ void Feature2D::parseParameters(const ParametersMap & parameters)
|
|||||||
Parameters::parse(parameters, Parameters::kKpGridCols(), gridCols_);
|
Parameters::parse(parameters, Parameters::kKpGridCols(), gridCols_);
|
||||||
|
|
||||||
UASSERT(gridRows_ >= 1 && gridCols_>=1);
|
UASSERT(gridRows_ >= 1 && gridCols_>=1);
|
||||||
if(maxFeatures_ > 0)
|
|
||||||
{
|
|
||||||
maxFeatures_ = maxFeatures_ / (gridRows_ * gridCols_);
|
|
||||||
}
|
|
||||||
|
|
||||||
// convert ROI from string to vector
|
// convert ROI from string to vector
|
||||||
ParametersMap::const_iterator iter;
|
ParametersMap::const_iterator iter;
|
||||||
@@ -472,6 +508,8 @@ Feature2D * Feature2D::create(const ParametersMap & parameters)
|
|||||||
}
|
}
|
||||||
Feature2D * Feature2D::create(Feature2D::Type type, const ParametersMap & parameters)
|
Feature2D * Feature2D::create(Feature2D::Type type, const ParametersMap & parameters)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
#if CV_MAJOR_VERSION < 3 || (CV_MAJOR_VERSION == 4 && CV_MINOR_VERSION <= 3) || (CV_MAJOR_VERSION == 3 && (CV_MINOR_VERSION < 4 || (CV_MINOR_VERSION==4 && CV_SUBMINOR_VERSION<11)))
|
||||||
#ifndef RTABMAP_NONFREE
|
#ifndef RTABMAP_NONFREE
|
||||||
if(type == Feature2D::kFeatureSurf || type == Feature2D::kFeatureSift)
|
if(type == Feature2D::kFeatureSurf || type == Feature2D::kFeatureSift)
|
||||||
{
|
{
|
||||||
@@ -494,6 +532,18 @@ Feature2D * Feature2D::create(Feature2D::Type type, const ParametersMap & parame
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#else // >= 4.4.0 >= 3.4.11
|
||||||
|
|
||||||
|
#ifndef RTABMAP_NONFREE
|
||||||
|
if(type == Feature2D::kFeatureSurf)
|
||||||
|
{
|
||||||
|
UWARN("SURF features cannot be used because OpenCV was not built with nonfree module. SIFT is used instead.");
|
||||||
|
type = Feature2D::kFeatureSift;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // >= 4.4.0 >= 3.4.11
|
||||||
|
|
||||||
#if CV_MAJOR_VERSION < 3
|
#if CV_MAJOR_VERSION < 3
|
||||||
if(type == Feature2D::kFeatureKaze)
|
if(type == Feature2D::kFeatureKaze)
|
||||||
{
|
{
|
||||||
@@ -515,7 +565,7 @@ Feature2D * Feature2D::create(Feature2D::Type type, const ParametersMap & parame
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef RTABMAP_SP_TORCH
|
#ifndef RTABMAP_SUPERPOINT_TORCH
|
||||||
if(type == Feature2D::kFeatureSuperPointTorch)
|
if(type == Feature2D::kFeatureSuperPointTorch)
|
||||||
{
|
{
|
||||||
UWARN("SupertPoint Torch feature cannot be used as RTAB-Map is not built with the option enabled. GFTT/ORB is used instead.");
|
UWARN("SupertPoint Torch feature cannot be used as RTAB-Map is not built with the option enabled. GFTT/ORB is used instead.");
|
||||||
@@ -559,7 +609,7 @@ Feature2D * Feature2D::create(Feature2D::Type type, const ParametersMap & parame
|
|||||||
case Feature2D::kFeatureOrbOctree:
|
case Feature2D::kFeatureOrbOctree:
|
||||||
feature2D = new ORBOctree(parameters);
|
feature2D = new ORBOctree(parameters);
|
||||||
break;
|
break;
|
||||||
#ifdef RTABMAP_SP_TORCH
|
#ifdef RTABMAP_SUPERPOINT_TORCH
|
||||||
case Feature2D::kFeatureSuperPointTorch:
|
case Feature2D::kFeatureSuperPointTorch:
|
||||||
feature2D = new SuperPointTorch(parameters);
|
feature2D = new SuperPointTorch(parameters);
|
||||||
break;
|
break;
|
||||||
@@ -639,6 +689,7 @@ std::vector<cv::KeyPoint> Feature2D::generateKeypoints(const cv::Mat & image, co
|
|||||||
// Get keypoints
|
// Get keypoints
|
||||||
int rowSize = globalRoi.height / gridRows_;
|
int rowSize = globalRoi.height / gridRows_;
|
||||||
int colSize = globalRoi.width / gridCols_;
|
int colSize = globalRoi.width / gridCols_;
|
||||||
|
int maxFeatures = maxFeatures_ / (gridRows_ * gridCols_);
|
||||||
for (int i = 0; i<gridRows_; ++i)
|
for (int i = 0; i<gridRows_; ++i)
|
||||||
{
|
{
|
||||||
for (int j = 0; j<gridCols_; ++j)
|
for (int j = 0; j<gridCols_; ++j)
|
||||||
@@ -646,7 +697,7 @@ std::vector<cv::KeyPoint> Feature2D::generateKeypoints(const cv::Mat & image, co
|
|||||||
cv::Rect roi(globalRoi.x + j*colSize, globalRoi.y + i*rowSize, colSize, rowSize);
|
cv::Rect roi(globalRoi.x + j*colSize, globalRoi.y + i*rowSize, colSize, rowSize);
|
||||||
std::vector<cv::KeyPoint> sub_keypoints;
|
std::vector<cv::KeyPoint> sub_keypoints;
|
||||||
sub_keypoints = this->generateKeypointsImpl(image, roi, mask);
|
sub_keypoints = this->generateKeypointsImpl(image, roi, mask);
|
||||||
limitKeypoints(sub_keypoints, maxFeatures_);
|
limitKeypoints(sub_keypoints, maxFeatures);
|
||||||
if(roi.x || roi.y)
|
if(roi.x || roi.y)
|
||||||
{
|
{
|
||||||
// Adjust keypoint position to raw image
|
// Adjust keypoint position to raw image
|
||||||
@@ -659,7 +710,8 @@ std::vector<cv::KeyPoint> Feature2D::generateKeypoints(const cv::Mat & image, co
|
|||||||
keypoints.insert( keypoints.end(), sub_keypoints.begin(), sub_keypoints.end() );
|
keypoints.insert( keypoints.end(), sub_keypoints.begin(), sub_keypoints.end() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
UDEBUG("Keypoints extraction time = %f s, keypoints extracted = %d (mask empty=%d)", timer.ticks(), keypoints.size(), mask.empty()?1:0);
|
UDEBUG("Keypoints extraction time = %f s, keypoints extracted = %d (grid=%dx%d, mask empty=%d)",
|
||||||
|
timer.ticks(), keypoints.size(), gridCols_, gridRows_, mask.empty()?1:0);
|
||||||
|
|
||||||
if(keypoints.size() && _subPixWinSize > 0 && _subPixIterations > 0)
|
if(keypoints.size() && _subPixWinSize > 0 && _subPixIterations > 0)
|
||||||
{
|
{
|
||||||
@@ -891,7 +943,8 @@ SIFT::SIFT(const ParametersMap & parameters) :
|
|||||||
nOctaveLayers_(Parameters::defaultSIFTNOctaveLayers()),
|
nOctaveLayers_(Parameters::defaultSIFTNOctaveLayers()),
|
||||||
contrastThreshold_(Parameters::defaultSIFTContrastThreshold()),
|
contrastThreshold_(Parameters::defaultSIFTContrastThreshold()),
|
||||||
edgeThreshold_(Parameters::defaultSIFTEdgeThreshold()),
|
edgeThreshold_(Parameters::defaultSIFTEdgeThreshold()),
|
||||||
sigma_(Parameters::defaultSIFTSigma())
|
sigma_(Parameters::defaultSIFTSigma()),
|
||||||
|
rootSIFT_(Parameters::defaultSIFTRootSIFT())
|
||||||
{
|
{
|
||||||
parseParameters(parameters);
|
parseParameters(parameters);
|
||||||
}
|
}
|
||||||
@@ -908,7 +961,9 @@ void SIFT::parseParameters(const ParametersMap & parameters)
|
|||||||
Parameters::parse(parameters, Parameters::kSIFTEdgeThreshold(), edgeThreshold_);
|
Parameters::parse(parameters, Parameters::kSIFTEdgeThreshold(), edgeThreshold_);
|
||||||
Parameters::parse(parameters, Parameters::kSIFTNOctaveLayers(), nOctaveLayers_);
|
Parameters::parse(parameters, Parameters::kSIFTNOctaveLayers(), nOctaveLayers_);
|
||||||
Parameters::parse(parameters, Parameters::kSIFTSigma(), sigma_);
|
Parameters::parse(parameters, Parameters::kSIFTSigma(), sigma_);
|
||||||
|
Parameters::parse(parameters, Parameters::kSIFTRootSIFT(), rootSIFT_);
|
||||||
|
|
||||||
|
#if CV_MAJOR_VERSION < 3 || (CV_MAJOR_VERSION == 4 && CV_MINOR_VERSION <= 3) || (CV_MAJOR_VERSION == 3 && (CV_MINOR_VERSION < 4 || (CV_MINOR_VERSION==4 && CV_SUBMINOR_VERSION<11)))
|
||||||
#ifdef RTABMAP_NONFREE
|
#ifdef RTABMAP_NONFREE
|
||||||
#if CV_MAJOR_VERSION < 3
|
#if CV_MAJOR_VERSION < 3
|
||||||
_sift = cv::Ptr<CV_SIFT>(new CV_SIFT(this->getMaxFeatures(), nOctaveLayers_, contrastThreshold_, edgeThreshold_, sigma_));
|
_sift = cv::Ptr<CV_SIFT>(new CV_SIFT(this->getMaxFeatures(), nOctaveLayers_, contrastThreshold_, edgeThreshold_, sigma_));
|
||||||
@@ -918,13 +973,16 @@ void SIFT::parseParameters(const ParametersMap & parameters)
|
|||||||
#else
|
#else
|
||||||
UWARN("RTAB-Map is not built with OpenCV nonfree module so SIFT cannot be used!");
|
UWARN("RTAB-Map is not built with OpenCV nonfree module so SIFT cannot be used!");
|
||||||
#endif
|
#endif
|
||||||
|
#else
|
||||||
|
_sift = CV_SIFT::create(this->getMaxFeatures(), nOctaveLayers_, contrastThreshold_, edgeThreshold_, sigma_);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<cv::KeyPoint> SIFT::generateKeypointsImpl(const cv::Mat & image, const cv::Rect & roi, const cv::Mat & mask)
|
std::vector<cv::KeyPoint> SIFT::generateKeypointsImpl(const cv::Mat & image, const cv::Rect & roi, const cv::Mat & mask)
|
||||||
{
|
{
|
||||||
UASSERT(!image.empty() && image.channels() == 1 && image.depth() == CV_8U);
|
UASSERT(!image.empty() && image.channels() == 1 && image.depth() == CV_8U);
|
||||||
std::vector<cv::KeyPoint> keypoints;
|
std::vector<cv::KeyPoint> keypoints;
|
||||||
#ifdef RTABMAP_NONFREE
|
#if defined(RTABMAP_NONFREE) || CV_MAJOR_VERSION > 4 || (CV_MAJOR_VERSION == 4 && CV_MINOR_VERSION >= 3)
|
||||||
cv::Mat imgRoi(image, roi);
|
cv::Mat imgRoi(image, roi);
|
||||||
cv::Mat maskRoi;
|
cv::Mat maskRoi;
|
||||||
if(!mask.empty())
|
if(!mask.empty())
|
||||||
@@ -942,8 +1000,25 @@ cv::Mat SIFT::generateDescriptorsImpl(const cv::Mat & image, std::vector<cv::Key
|
|||||||
{
|
{
|
||||||
UASSERT(!image.empty() && image.channels() == 1 && image.depth() == CV_8U);
|
UASSERT(!image.empty() && image.channels() == 1 && image.depth() == CV_8U);
|
||||||
cv::Mat descriptors;
|
cv::Mat descriptors;
|
||||||
#ifdef RTABMAP_NONFREE
|
#if defined(RTABMAP_NONFREE) || CV_MAJOR_VERSION > 4 || (CV_MAJOR_VERSION == 4 && CV_MINOR_VERSION >= 3)
|
||||||
_sift->compute(image, keypoints, descriptors);
|
_sift->compute(image, keypoints, descriptors);
|
||||||
|
|
||||||
|
if( rootSIFT_ && !descriptors.empty())
|
||||||
|
{
|
||||||
|
UDEBUG("Performing RootSIFT...");
|
||||||
|
// see http://www.pyimagesearch.com/2015/04/13/implementing-rootsift-in-python-and-opencv/
|
||||||
|
// apply the Hellinger kernel by first L1-normalizing and taking the
|
||||||
|
// square-root
|
||||||
|
for(int i=0; i<descriptors.rows; ++i)
|
||||||
|
{
|
||||||
|
// By taking the L1 norm, followed by the square-root, we have
|
||||||
|
// already L2 normalized the feature vector and further normalization
|
||||||
|
// is not needed.
|
||||||
|
descriptors.row(i) = descriptors.row(i) / cv::sum(descriptors.row(i))[0];
|
||||||
|
cv::sqrt(descriptors.row(i), descriptors.row(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
UWARN("RTAB-Map is not built with OpenCV nonfree module so SIFT cannot be used!");
|
UWARN("RTAB-Map is not built with OpenCV nonfree module so SIFT cannot be used!");
|
||||||
#endif
|
#endif
|
||||||
@@ -1866,11 +1941,11 @@ cv::Mat ORBOctree::generateDescriptorsImpl(const cv::Mat & image, std::vector<cv
|
|||||||
//SuperPointTorch
|
//SuperPointTorch
|
||||||
//////////////////////////
|
//////////////////////////
|
||||||
SuperPointTorch::SuperPointTorch(const ParametersMap & parameters) :
|
SuperPointTorch::SuperPointTorch(const ParametersMap & parameters) :
|
||||||
path_(Parameters::defaultSPTorchModelPath()),
|
path_(Parameters::defaultSuperPointModelPath()),
|
||||||
threshold_(Parameters::defaultSPTorchThreshold()),
|
threshold_(Parameters::defaultSuperPointThreshold()),
|
||||||
nms_(Parameters::defaultSPTorchNMS()),
|
nms_(Parameters::defaultSuperPointNMS()),
|
||||||
minDistance_(Parameters::defaultSPTorchMinDistance()),
|
minDistance_(Parameters::defaultSuperPointNMSRadius()),
|
||||||
cuda_(Parameters::defaultSPTorchCuda())
|
cuda_(Parameters::defaultSuperPointCuda())
|
||||||
{
|
{
|
||||||
parseParameters(parameters);
|
parseParameters(parameters);
|
||||||
}
|
}
|
||||||
@@ -1884,14 +1959,16 @@ void SuperPointTorch::parseParameters(const ParametersMap & parameters)
|
|||||||
Feature2D::parseParameters(parameters);
|
Feature2D::parseParameters(parameters);
|
||||||
|
|
||||||
std::string previousPath = path_;
|
std::string previousPath = path_;
|
||||||
|
#ifdef RTABMAP_SUPERPOINT_TORCH
|
||||||
bool previousCuda = cuda_;
|
bool previousCuda = cuda_;
|
||||||
Parameters::parse(parameters, Parameters::kSPTorchModelPath(), path_);
|
#endif
|
||||||
Parameters::parse(parameters, Parameters::kSPTorchThreshold(), threshold_);
|
Parameters::parse(parameters, Parameters::kSuperPointModelPath(), path_);
|
||||||
Parameters::parse(parameters, Parameters::kSPTorchNMS(), nms_);
|
Parameters::parse(parameters, Parameters::kSuperPointThreshold(), threshold_);
|
||||||
Parameters::parse(parameters, Parameters::kSPTorchMinDistance(), minDistance_);
|
Parameters::parse(parameters, Parameters::kSuperPointNMS(), nms_);
|
||||||
Parameters::parse(parameters, Parameters::kSPTorchCuda(), cuda_);
|
Parameters::parse(parameters, Parameters::kSuperPointNMSRadius(), minDistance_);
|
||||||
|
Parameters::parse(parameters, Parameters::kSuperPointCuda(), cuda_);
|
||||||
|
|
||||||
#ifdef RTABMAP_SP_TORCH
|
#ifdef RTABMAP_SUPERPOINT_TORCH
|
||||||
if(superPoint_.get() == 0 || path_.compare(previousPath) != 0 || previousCuda != cuda_)
|
if(superPoint_.get() == 0 || path_.compare(previousPath) != 0 || previousCuda != cuda_)
|
||||||
{
|
{
|
||||||
superPoint_ = cv::Ptr<SPDetector>(new SPDetector(path_, threshold_, nms_, minDistance_, cuda_));
|
superPoint_ = cv::Ptr<SPDetector>(new SPDetector(path_, threshold_, nms_, minDistance_, cuda_));
|
||||||
@@ -1909,10 +1986,10 @@ void SuperPointTorch::parseParameters(const ParametersMap & parameters)
|
|||||||
|
|
||||||
std::vector<cv::KeyPoint> SuperPointTorch::generateKeypointsImpl(const cv::Mat & image, const cv::Rect & roi, const cv::Mat & mask)
|
std::vector<cv::KeyPoint> SuperPointTorch::generateKeypointsImpl(const cv::Mat & image, const cv::Rect & roi, const cv::Mat & mask)
|
||||||
{
|
{
|
||||||
#ifdef RTABMAP_SP_TORCH
|
#ifdef RTABMAP_SUPERPOINT_TORCH
|
||||||
UASSERT(!image.empty() && image.channels() == 1 && image.depth() == CV_8U);
|
UASSERT(!image.empty() && image.channels() == 1 && image.depth() == CV_8U);
|
||||||
UASSERT_MSG(roi.x==0 && roi.y ==0, "Not supporting ROI");
|
UASSERT_MSG(roi.x==0 && roi.y ==0, "Not supporting ROI");
|
||||||
return superPoint_->detect(image);
|
return superPoint_->detect(image, mask);
|
||||||
#else
|
#else
|
||||||
UWARN("RTAB-Map is not built with SuperPoint Torch support so SuperPoint Torch feature cannot be used!");
|
UWARN("RTAB-Map is not built with SuperPoint Torch support so SuperPoint Torch feature cannot be used!");
|
||||||
return std::vector<cv::KeyPoint>();
|
return std::vector<cv::KeyPoint>();
|
||||||
@@ -1921,7 +1998,7 @@ std::vector<cv::KeyPoint> SuperPointTorch::generateKeypointsImpl(const cv::Mat &
|
|||||||
|
|
||||||
cv::Mat SuperPointTorch::generateDescriptorsImpl(const cv::Mat & image, std::vector<cv::KeyPoint> & keypoints) const
|
cv::Mat SuperPointTorch::generateDescriptorsImpl(const cv::Mat & image, std::vector<cv::KeyPoint> & keypoints) const
|
||||||
{
|
{
|
||||||
#ifdef RTABMAP_SP_TORCH
|
#ifdef RTABMAP_SUPERPOINT_TORCH
|
||||||
UASSERT(!image.empty() && image.channels() == 1 && image.depth() == CV_8U);
|
UASSERT(!image.empty() && image.channels() == 1 && image.depth() == CV_8U);
|
||||||
return superPoint_->compute(keypoints);
|
return superPoint_->compute(keypoints);
|
||||||
#else
|
#else
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <pcl/search/kdtree.h>
|
#include <pcl/search/kdtree.h>
|
||||||
#include <pcl/common/eigen.h>
|
#include <pcl/common/eigen.h>
|
||||||
#include <pcl/common/common.h>
|
#include <pcl/common/common.h>
|
||||||
|
#include <pcl/common/point_tests.h>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|||||||
+203
-90
@@ -90,6 +90,7 @@ Memory::Memory(const ParametersMap & parameters) :
|
|||||||
_badSignaturesIgnored(Parameters::defaultMemBadSignaturesIgnored()),
|
_badSignaturesIgnored(Parameters::defaultMemBadSignaturesIgnored()),
|
||||||
_mapLabelsAdded(Parameters::defaultMemMapLabelsAdded()),
|
_mapLabelsAdded(Parameters::defaultMemMapLabelsAdded()),
|
||||||
_depthAsMask(Parameters::defaultMemDepthAsMask()),
|
_depthAsMask(Parameters::defaultMemDepthAsMask()),
|
||||||
|
_stereoFromMotion(Parameters::defaultMemStereoFromMotion()),
|
||||||
_imagePreDecimation(Parameters::defaultMemImagePreDecimation()),
|
_imagePreDecimation(Parameters::defaultMemImagePreDecimation()),
|
||||||
_imagePostDecimation(Parameters::defaultMemImagePostDecimation()),
|
_imagePostDecimation(Parameters::defaultMemImagePostDecimation()),
|
||||||
_compressionParallelized(Parameters::defaultMemCompressionParallelized()),
|
_compressionParallelized(Parameters::defaultMemCompressionParallelized()),
|
||||||
@@ -552,6 +553,7 @@ void Memory::parseParameters(const ParametersMap & parameters)
|
|||||||
Parameters::parse(params, Parameters::kMemTransferSortingByWeightId(), _transferSortingByWeightId);
|
Parameters::parse(params, Parameters::kMemTransferSortingByWeightId(), _transferSortingByWeightId);
|
||||||
Parameters::parse(params, Parameters::kMemSTMSize(), _maxStMemSize);
|
Parameters::parse(params, Parameters::kMemSTMSize(), _maxStMemSize);
|
||||||
Parameters::parse(params, Parameters::kMemDepthAsMask(), _depthAsMask);
|
Parameters::parse(params, Parameters::kMemDepthAsMask(), _depthAsMask);
|
||||||
|
Parameters::parse(params, Parameters::kMemStereoFromMotion(), _stereoFromMotion);
|
||||||
Parameters::parse(params, Parameters::kMemImagePreDecimation(), _imagePreDecimation);
|
Parameters::parse(params, Parameters::kMemImagePreDecimation(), _imagePreDecimation);
|
||||||
Parameters::parse(params, Parameters::kMemImagePostDecimation(), _imagePostDecimation);
|
Parameters::parse(params, Parameters::kMemImagePostDecimation(), _imagePostDecimation);
|
||||||
Parameters::parse(params, Parameters::kMemCompressionParallelized(), _compressionParallelized);
|
Parameters::parse(params, Parameters::kMemCompressionParallelized(), _compressionParallelized);
|
||||||
@@ -1080,27 +1082,32 @@ void Memory::moveSignatureToWMFromSTM(int id, int * reducedTo)
|
|||||||
{
|
{
|
||||||
for(std::multimap<int, Link>::const_iterator iter=links.begin(); iter!=links.end(); ++iter)
|
for(std::multimap<int, Link>::const_iterator iter=links.begin(); iter!=links.end(); ++iter)
|
||||||
{
|
{
|
||||||
merge = true;
|
|
||||||
Signature * sTo = this->_getSignature(iter->first);
|
Signature * sTo = this->_getSignature(iter->first);
|
||||||
UASSERT(sTo!=0);
|
if(sTo->id()!=s->id()) // Not Prior/Gravity links...
|
||||||
sTo->removeLink(s->id());
|
|
||||||
if(iter->second.type() != Link::kNeighbor &&
|
|
||||||
iter->second.type() != Link::kNeighborMerged &&
|
|
||||||
iter->second.type() != Link::kUndef)
|
|
||||||
{
|
{
|
||||||
// link to all neighbors
|
UASSERT_MSG(sTo!=0, uFormat("id=%d", iter->first).c_str());
|
||||||
for(std::map<int, Link>::iterator jter=neighbors.begin(); jter!=neighbors.end(); ++jter)
|
sTo->removeLink(s->id());
|
||||||
|
if(iter->second.type() != Link::kNeighbor &&
|
||||||
|
iter->second.type() != Link::kNeighborMerged &&
|
||||||
|
iter->second.type() != Link::kUndef)
|
||||||
{
|
{
|
||||||
if(!sTo->hasLink(jter->second.to()))
|
// link to all neighbors
|
||||||
|
for(std::map<int, Link>::iterator jter=neighbors.begin(); jter!=neighbors.end(); ++jter)
|
||||||
{
|
{
|
||||||
Link l = iter->second.inverse().merge(
|
if(!sTo->hasLink(jter->second.to()))
|
||||||
jter->second,
|
{
|
||||||
iter->second.userDataCompressed().empty() && iter->second.type() != Link::kVirtualClosure?Link::kNeighborMerged:iter->second.type());
|
UDEBUG("Merging link %d->%d (type=%d) to link %d->%d (type %d)",
|
||||||
sTo->addLink(l);
|
iter->second.from(), iter->second.to(), iter->second.type(),
|
||||||
Signature * sB = this->_getSignature(l.to());
|
jter->second.from(), jter->second.to(), jter->second.type());
|
||||||
UASSERT(sB!=0);
|
Link l = iter->second.inverse().merge(
|
||||||
UASSERT(!sB->hasLink(l.to()));
|
jter->second,
|
||||||
sB->addLink(l.inverse());
|
iter->second.userDataCompressed().empty() && iter->second.type() != Link::kVirtualClosure?Link::kNeighborMerged:iter->second.type());
|
||||||
|
sTo->addLink(l);
|
||||||
|
Signature * sB = this->_getSignature(l.to());
|
||||||
|
UASSERT(sB!=0);
|
||||||
|
UASSERT_MSG(!sB->hasLink(l.from()), uFormat("%d->%d", sB->id(), l.to()).c_str());
|
||||||
|
sB->addLink(l.inverse());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1347,7 +1354,10 @@ std::map<int, int> Memory::getNeighborsId(
|
|||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
UASSERT(maxGraphDepth >= 0);
|
UASSERT(maxGraphDepth >= 0);
|
||||||
//UDEBUG("signatureId=%d, neighborsMargin=%d", signatureId, margin);
|
//DEBUG("signatureId=%d maxGraphDepth=%d maxCheckedInDatabase=%d incrementMarginOnLoop=%d "
|
||||||
|
// "ignoreLoopIds=%d ignoreIntermediateNodes=%d ignoreLocalSpaceLoopIds=%d",
|
||||||
|
// signatureId, maxGraphDepth, maxCheckedInDatabase, incrementMarginOnLoop?1:0,
|
||||||
|
// ignoreLoopIds?1:0, ignoreIntermediateNodes?1:0, ignoreLocalSpaceLoopIds?1:0);
|
||||||
if(dbAccessTime)
|
if(dbAccessTime)
|
||||||
{
|
{
|
||||||
*dbAccessTime = 0;
|
*dbAccessTime = 0;
|
||||||
@@ -1405,6 +1415,10 @@ std::map<int, int> Memory::getNeighborsId(
|
|||||||
|
|
||||||
UTimer timer;
|
UTimer timer;
|
||||||
_dbDriver->loadLinks(*jter, tmpLinks, ignoreLoopIds?Link::kAllWithoutLandmarks:Link::kAllWithLandmarks);
|
_dbDriver->loadLinks(*jter, tmpLinks, ignoreLoopIds?Link::kAllWithoutLandmarks:Link::kAllWithLandmarks);
|
||||||
|
if(tmpLinks.empty())
|
||||||
|
{
|
||||||
|
UWARN("No links loaded for %d?!", *jter);
|
||||||
|
}
|
||||||
if(!ignoreLoopIds)
|
if(!ignoreLoopIds)
|
||||||
{
|
{
|
||||||
for(std::multimap<int, Link>::iterator kter=tmpLinks.begin(); kter!=tmpLinks.end();)
|
for(std::multimap<int, Link>::iterator kter=tmpLinks.begin(); kter!=tmpLinks.end();)
|
||||||
@@ -1414,6 +1428,11 @@ std::map<int, int> Memory::getNeighborsId(
|
|||||||
tmpLandmarks.insert(*kter);
|
tmpLandmarks.insert(*kter);
|
||||||
tmpLinks.erase(kter++);
|
tmpLinks.erase(kter++);
|
||||||
}
|
}
|
||||||
|
else if(kter->second.from() == kter->second.to())
|
||||||
|
{
|
||||||
|
// ignore self-referring links
|
||||||
|
tmpLinks.erase(kter++);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
++kter;
|
++kter;
|
||||||
@@ -1429,7 +1448,8 @@ std::map<int, int> Memory::getNeighborsId(
|
|||||||
// links
|
// links
|
||||||
for(std::multimap<int, Link>::const_iterator iter=links->begin(); iter!=links->end(); ++iter)
|
for(std::multimap<int, Link>::const_iterator iter=links->begin(); iter!=links->end(); ++iter)
|
||||||
{
|
{
|
||||||
if( !uContains(ids, iter->first) && ignoredIds.find(iter->first) == ignoredIds.end())
|
if(!uContains(ids, iter->first) &&
|
||||||
|
ignoredIds.find(iter->first) == ignoredIds.end())
|
||||||
{
|
{
|
||||||
UASSERT(iter->second.type() != Link::kUndef);
|
UASSERT(iter->second.type() != Link::kUndef);
|
||||||
if(iter->second.type() == Link::kNeighbor ||
|
if(iter->second.type() == Link::kNeighbor ||
|
||||||
@@ -1631,12 +1651,12 @@ double Memory::getDbSavingTime() const
|
|||||||
return _dbDriver?_dbDriver->getEmptyTrashesTime():0;
|
return _dbDriver?_dbDriver->getEmptyTrashesTime():0;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::set<int> Memory::getAllSignatureIds() const
|
std::set<int> Memory::getAllSignatureIds(bool ignoreChildren) const
|
||||||
{
|
{
|
||||||
std::set<int> ids;
|
std::set<int> ids;
|
||||||
if(_dbDriver)
|
if(_dbDriver)
|
||||||
{
|
{
|
||||||
_dbDriver->getAllNodeIds(ids);
|
_dbDriver->getAllNodeIds(ids, ignoreChildren);
|
||||||
}
|
}
|
||||||
for(std::map<int, Signature*>::const_iterator iter = _signatures.begin(); iter!=_signatures.end(); ++iter)
|
for(std::map<int, Signature*>::const_iterator iter = _signatures.begin(); iter!=_signatures.end(); ++iter)
|
||||||
{
|
{
|
||||||
@@ -2003,11 +2023,11 @@ int Memory::cleanup()
|
|||||||
return signatureRemoved;
|
return signatureRemoved;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Memory::saveStatistics(const Statistics & statistics)
|
void Memory::saveStatistics(const Statistics & statistics, bool saveWmState)
|
||||||
{
|
{
|
||||||
if(_dbDriver)
|
if(_dbDriver)
|
||||||
{
|
{
|
||||||
_dbDriver->addStatistics(statistics);
|
_dbDriver->addStatistics(statistics, saveWmState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2698,13 +2718,13 @@ Transform Memory::computeTransform(
|
|||||||
(_registrationPipeline->isScanRequired() && fromS.sensorData().imageCompressed().empty() && fromS.sensorData().laserScanCompressed().isEmpty()) ||
|
(_registrationPipeline->isScanRequired() && fromS.sensorData().imageCompressed().empty() && fromS.sensorData().laserScanCompressed().isEmpty()) ||
|
||||||
(_registrationPipeline->isUserDataRequired() && fromS.sensorData().imageCompressed().empty() && fromS.sensorData().userDataCompressed().empty()))
|
(_registrationPipeline->isUserDataRequired() && fromS.sensorData().imageCompressed().empty() && fromS.sensorData().userDataCompressed().empty()))
|
||||||
{
|
{
|
||||||
fromS.sensorData() = getNodeData(fromS.id());
|
fromS.sensorData() = getNodeData(fromS.id(), true, true, true, true);
|
||||||
}
|
}
|
||||||
if(((_reextractLoopClosureFeatures && _registrationPipeline->isImageRequired()) && toS.sensorData().imageCompressed().empty()) ||
|
if(((_reextractLoopClosureFeatures && _registrationPipeline->isImageRequired()) && toS.sensorData().imageCompressed().empty()) ||
|
||||||
(_registrationPipeline->isScanRequired() && toS.sensorData().imageCompressed().empty() && toS.sensorData().laserScanCompressed().isEmpty()) ||
|
(_registrationPipeline->isScanRequired() && toS.sensorData().imageCompressed().empty() && toS.sensorData().laserScanCompressed().isEmpty()) ||
|
||||||
(_registrationPipeline->isUserDataRequired() && toS.sensorData().imageCompressed().empty() && toS.sensorData().userDataCompressed().empty()))
|
(_registrationPipeline->isUserDataRequired() && toS.sensorData().imageCompressed().empty() && toS.sensorData().userDataCompressed().empty()))
|
||||||
{
|
{
|
||||||
toS.sensorData() = getNodeData(toS.id());
|
toS.sensorData() = getNodeData(toS.id(), true, true, true, true);
|
||||||
}
|
}
|
||||||
// uncompress only what we need
|
// uncompress only what we need
|
||||||
cv::Mat imgBuf, depthBuf, userBuf;
|
cv::Mat imgBuf, depthBuf, userBuf;
|
||||||
@@ -3066,6 +3086,8 @@ Transform Memory::computeIcpTransformMulti(
|
|||||||
pcl::PointCloud<pcl::PointNormal>::Ptr assembledToNormalClouds(new pcl::PointCloud<pcl::PointNormal>);
|
pcl::PointCloud<pcl::PointNormal>::Ptr assembledToNormalClouds(new pcl::PointCloud<pcl::PointNormal>);
|
||||||
pcl::PointCloud<pcl::PointXYZI>::Ptr assembledToIClouds(new pcl::PointCloud<pcl::PointXYZI>);
|
pcl::PointCloud<pcl::PointXYZI>::Ptr assembledToIClouds(new pcl::PointCloud<pcl::PointXYZI>);
|
||||||
pcl::PointCloud<pcl::PointXYZINormal>::Ptr assembledToNormalIClouds(new pcl::PointCloud<pcl::PointXYZINormal>);
|
pcl::PointCloud<pcl::PointXYZINormal>::Ptr assembledToNormalIClouds(new pcl::PointCloud<pcl::PointXYZINormal>);
|
||||||
|
pcl::PointCloud<pcl::PointXYZRGB>::Ptr assembledToRGBClouds(new pcl::PointCloud<pcl::PointXYZRGB>);
|
||||||
|
pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr assembledToNormalRGBClouds(new pcl::PointCloud<pcl::PointXYZRGBNormal>);
|
||||||
UDEBUG("maxPoints from(%d) = %d", fromId, maxPoints);
|
UDEBUG("maxPoints from(%d) = %d", fromId, maxPoints);
|
||||||
for(std::map<int, Transform>::const_iterator iter = poses.begin(); iter!=poses.end(); ++iter)
|
for(std::map<int, Transform>::const_iterator iter = poses.begin(); iter!=poses.end(); ++iter)
|
||||||
{
|
{
|
||||||
@@ -3091,6 +3113,19 @@ Transform Memory::computeIcpTransformMulti(
|
|||||||
toPoseInv * iter->second * scan.localTransform());
|
toPoseInv * iter->second * scan.localTransform());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if(scan.hasRGB())
|
||||||
|
{
|
||||||
|
if(scan.hasNormals())
|
||||||
|
{
|
||||||
|
*assembledToNormalRGBClouds += *util3d::laserScanToPointCloudRGBNormal(scan,
|
||||||
|
toPoseInv * iter->second * scan.localTransform());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*assembledToRGBClouds += *util3d::laserScanToPointCloudRGB(scan,
|
||||||
|
toPoseInv * iter->second * scan.localTransform());
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(scan.hasNormals())
|
if(scan.hasNormals())
|
||||||
@@ -3140,6 +3175,28 @@ Transform Memory::computeIcpTransformMulti(
|
|||||||
{
|
{
|
||||||
assembledScan = fromScan.is2d()?util3d::laserScan2dFromPointCloud(*assembledToIClouds):util3d::laserScanFromPointCloud(*assembledToIClouds);
|
assembledScan = fromScan.is2d()?util3d::laserScan2dFromPointCloud(*assembledToIClouds):util3d::laserScanFromPointCloud(*assembledToIClouds);
|
||||||
}
|
}
|
||||||
|
else if(assembledToNormalRGBClouds->size())
|
||||||
|
{
|
||||||
|
if(fromScan.is2d())
|
||||||
|
{
|
||||||
|
UERROR("Cannot handle 2d scan with RGB format.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assembledScan = util3d::laserScanFromPointCloud(*assembledToNormalRGBClouds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(assembledToRGBClouds->size())
|
||||||
|
{
|
||||||
|
if(fromScan.is2d())
|
||||||
|
{
|
||||||
|
UERROR("Cannot handle 2d scan with RGB format.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assembledScan = util3d::laserScanFromPointCloud(*assembledToRGBClouds);
|
||||||
|
}
|
||||||
|
}
|
||||||
UDEBUG("assembledScan=%d points", assembledScan.cols);
|
UDEBUG("assembledScan=%d points", assembledScan.cols);
|
||||||
|
|
||||||
// scans are in base frame but for 2d scans, set the height so that correspondences matching works
|
// scans are in base frame but for 2d scans, set the height so that correspondences matching works
|
||||||
@@ -3815,33 +3872,49 @@ cv::Mat Memory::getImageCompressed(int signatureId) const
|
|||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
SensorData Memory::getNodeData(int nodeId, bool uncompressedData) const
|
SensorData Memory::getNodeData(int locationId, bool images, bool scan, bool userData, bool occupancyGrid) const
|
||||||
{
|
{
|
||||||
//UDEBUG("nodeId=%d", nodeId);
|
//UDEBUG("");
|
||||||
SensorData r;
|
SensorData r;
|
||||||
Signature * s = this->_getSignature(nodeId);
|
const Signature * s = this->getSignature(locationId);
|
||||||
if(s && !s->sensorData().imageCompressed().empty())
|
if(s && (!s->isSaved() ||
|
||||||
|
((!images || !s->sensorData().imageCompressed().empty()) &&
|
||||||
|
(!scan || !s->sensorData().laserScanCompressed().isEmpty()) &&
|
||||||
|
(!userData || !s->sensorData().userDataCompressed().empty()) &&
|
||||||
|
(!occupancyGrid || s->sensorData().gridCellSize() != 0.0f))))
|
||||||
{
|
{
|
||||||
r = s->sensorData();
|
r = s->sensorData();
|
||||||
|
if(!images)
|
||||||
|
{
|
||||||
|
r.setRGBDImage(cv::Mat(), cv::Mat(), std::vector<CameraModel>());
|
||||||
|
}
|
||||||
|
if(!scan)
|
||||||
|
{
|
||||||
|
r.setLaserScan(LaserScan());
|
||||||
|
}
|
||||||
|
if(!userData)
|
||||||
|
{
|
||||||
|
r.setUserData(cv::Mat());
|
||||||
|
}
|
||||||
|
if(!occupancyGrid)
|
||||||
|
{
|
||||||
|
r.setOccupancyGrid(cv::Mat(), cv::Mat(), cv::Mat(), 0, cv::Point3f());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if(_dbDriver)
|
else if(_dbDriver)
|
||||||
{
|
{
|
||||||
// load from database
|
// load from database
|
||||||
_dbDriver->getNodeData(nodeId, r);
|
_dbDriver->getNodeData(locationId, r, images, scan, userData, occupancyGrid);
|
||||||
}
|
|
||||||
|
|
||||||
if(uncompressedData)
|
|
||||||
{
|
|
||||||
r.uncompressData();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Memory::getNodeWords(int nodeId,
|
void Memory::getNodeWordsAndGlobalDescriptors(int nodeId,
|
||||||
std::multimap<int, cv::KeyPoint> & words,
|
std::multimap<int, cv::KeyPoint> & words,
|
||||||
std::multimap<int, cv::Point3f> & words3,
|
std::multimap<int, cv::Point3f> & words3,
|
||||||
std::multimap<int, cv::Mat> & wordsDescriptors)
|
std::multimap<int, cv::Mat> & wordsDescriptors,
|
||||||
|
std::vector<GlobalDescriptor> & globalDescriptors) const
|
||||||
{
|
{
|
||||||
//UDEBUG("nodeId=%d", nodeId);
|
//UDEBUG("nodeId=%d", nodeId);
|
||||||
Signature * s = this->_getSignature(nodeId);
|
Signature * s = this->_getSignature(nodeId);
|
||||||
@@ -3850,6 +3923,7 @@ void Memory::getNodeWords(int nodeId,
|
|||||||
words = s->getWords();
|
words = s->getWords();
|
||||||
words3 = s->getWords3();
|
words3 = s->getWords3();
|
||||||
wordsDescriptors = s->getWordsDescriptors();
|
wordsDescriptors = s->getWordsDescriptors();
|
||||||
|
globalDescriptors = s->sensorData().globalDescriptors();
|
||||||
}
|
}
|
||||||
else if(_dbDriver)
|
else if(_dbDriver)
|
||||||
{
|
{
|
||||||
@@ -3864,6 +3938,7 @@ void Memory::getNodeWords(int nodeId,
|
|||||||
words = signatures.front()->getWords();
|
words = signatures.front()->getWords();
|
||||||
words3 = signatures.front()->getWords3();
|
words3 = signatures.front()->getWords3();
|
||||||
wordsDescriptors = signatures.front()->getWordsDescriptors();
|
wordsDescriptors = signatures.front()->getWordsDescriptors();
|
||||||
|
globalDescriptors = signatures.front()->sensorData().globalDescriptors();
|
||||||
if(loadedFromTrash.size())
|
if(loadedFromTrash.size())
|
||||||
{
|
{
|
||||||
//put back
|
//put back
|
||||||
@@ -3879,7 +3954,7 @@ void Memory::getNodeWords(int nodeId,
|
|||||||
|
|
||||||
void Memory::getNodeCalibration(int nodeId,
|
void Memory::getNodeCalibration(int nodeId,
|
||||||
std::vector<CameraModel> & models,
|
std::vector<CameraModel> & models,
|
||||||
StereoCameraModel & stereoModel)
|
StereoCameraModel & stereoModel) const
|
||||||
{
|
{
|
||||||
//UDEBUG("nodeId=%d", nodeId);
|
//UDEBUG("nodeId=%d", nodeId);
|
||||||
Signature * s = this->_getSignature(nodeId);
|
Signature * s = this->_getSignature(nodeId);
|
||||||
@@ -3895,28 +3970,6 @@ void Memory::getNodeCalibration(int nodeId,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SensorData Memory::getSignatureDataConst(int locationId,
|
|
||||||
bool images, bool scan, bool userData, bool occupancyGrid) const
|
|
||||||
{
|
|
||||||
//UDEBUG("");
|
|
||||||
SensorData r;
|
|
||||||
const Signature * s = this->getSignature(locationId);
|
|
||||||
if(s && (!s->sensorData().imageCompressed().empty() ||
|
|
||||||
!s->sensorData().laserScanCompressed().isEmpty() ||
|
|
||||||
!s->sensorData().userDataCompressed().empty() ||
|
|
||||||
s->sensorData().gridCellSize() != 0.0f))
|
|
||||||
{
|
|
||||||
r = s->sensorData();
|
|
||||||
}
|
|
||||||
else if(_dbDriver)
|
|
||||||
{
|
|
||||||
// load from database
|
|
||||||
_dbDriver->getNodeData(locationId, r, images, scan, userData, occupancyGrid);
|
|
||||||
}
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Memory::generateGraph(const std::string & fileName, const std::set<int> & ids)
|
void Memory::generateGraph(const std::string & fileName, const std::set<int> & ids)
|
||||||
{
|
{
|
||||||
if(!_dbDriver)
|
if(!_dbDriver)
|
||||||
@@ -4244,29 +4297,48 @@ Signature * Memory::createSignature(const SensorData & inputData, const Transfor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int oldMaxFeatures = _feature2D->getMaxFeatures();
|
bool useProvided3dPoints = false;
|
||||||
UDEBUG("rawDescriptorsKept=%d, pose=%d, maxFeatures=%d, visMaxFeatures=%d", _rawDescriptorsKept?1:0, pose.isNull()?0:1, _feature2D->getMaxFeatures(), _visMaxFeatures);
|
if(_useOdometryFeatures && !data.keypoints().empty())
|
||||||
ParametersMap tmpMaxFeatureParameter;
|
|
||||||
if(_rawDescriptorsKept&&!pose.isNull()&&_feature2D->getMaxFeatures()>0&&_feature2D->getMaxFeatures()<_visMaxFeatures)
|
|
||||||
{
|
{
|
||||||
// The total extracted features should match the number of features used for transformation estimation
|
UDEBUG("Using provided keypoints (%d)", (int)data.keypoints().size());
|
||||||
UDEBUG("Changing temporary max features from %d to %d", _feature2D->getMaxFeatures(), _visMaxFeatures);
|
keypoints = data.keypoints();
|
||||||
tmpMaxFeatureParameter.insert(ParametersPair(Parameters::kKpMaxFeatures(), uNumber2Str(_visMaxFeatures)));
|
|
||||||
_feature2D->parseParameters(tmpMaxFeatureParameter);
|
// In case we provided corresponding 3D features
|
||||||
|
if(keypoints.size() == data.keypoints3D().size())
|
||||||
|
{
|
||||||
|
for(size_t i=0; i<keypoints.size(); ++i)
|
||||||
|
{
|
||||||
|
keypoints[i].class_id = i;
|
||||||
|
}
|
||||||
|
useProvided3dPoints = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
keypoints = _feature2D->generateKeypoints(
|
|
||||||
imageMono,
|
|
||||||
depthMask);
|
|
||||||
|
|
||||||
if(tmpMaxFeatureParameter.size())
|
|
||||||
{
|
{
|
||||||
tmpMaxFeatureParameter.at(Parameters::kKpMaxFeatures()) = uNumber2Str(oldMaxFeatures);
|
int oldMaxFeatures = _feature2D->getMaxFeatures();
|
||||||
_feature2D->parseParameters(tmpMaxFeatureParameter); // reset back
|
UDEBUG("rawDescriptorsKept=%d, pose=%d, maxFeatures=%d, visMaxFeatures=%d", _rawDescriptorsKept?1:0, pose.isNull()?0:1, _feature2D->getMaxFeatures(), _visMaxFeatures);
|
||||||
|
ParametersMap tmpMaxFeatureParameter;
|
||||||
|
if(_rawDescriptorsKept&&!pose.isNull()&&_feature2D->getMaxFeatures()>0&&_feature2D->getMaxFeatures()<_visMaxFeatures)
|
||||||
|
{
|
||||||
|
// The total extracted features should match the number of features used for transformation estimation
|
||||||
|
UDEBUG("Changing temporary max features from %d to %d", _feature2D->getMaxFeatures(), _visMaxFeatures);
|
||||||
|
tmpMaxFeatureParameter.insert(ParametersPair(Parameters::kKpMaxFeatures(), uNumber2Str(_visMaxFeatures)));
|
||||||
|
_feature2D->parseParameters(tmpMaxFeatureParameter);
|
||||||
|
}
|
||||||
|
|
||||||
|
keypoints = _feature2D->generateKeypoints(
|
||||||
|
imageMono,
|
||||||
|
depthMask);
|
||||||
|
|
||||||
|
if(tmpMaxFeatureParameter.size())
|
||||||
|
{
|
||||||
|
tmpMaxFeatureParameter.at(Parameters::kKpMaxFeatures()) = uNumber2Str(oldMaxFeatures);
|
||||||
|
_feature2D->parseParameters(tmpMaxFeatureParameter); // reset back
|
||||||
|
}
|
||||||
|
t = timer.ticks();
|
||||||
|
if(stats) stats->addStatistic(Statistics::kTimingMemKeypoints_detection(), t*1000.0f);
|
||||||
|
UDEBUG("time keypoints (%d) = %fs", (int)keypoints.size(), t);
|
||||||
}
|
}
|
||||||
t = timer.ticks();
|
|
||||||
if(stats) stats->addStatistic(Statistics::kTimingMemKeypoints_detection(), t*1000.0f);
|
|
||||||
UDEBUG("time keypoints (%d) = %fs", (int)keypoints.size(), t);
|
|
||||||
|
|
||||||
descriptors = _feature2D->generateDescriptors(imageMono, keypoints);
|
descriptors = _feature2D->generateDescriptors(imageMono, keypoints);
|
||||||
t = timer.ticks();
|
t = timer.ticks();
|
||||||
@@ -4398,7 +4470,22 @@ Signature * Memory::createSignature(const SensorData & inputData, const Transfor
|
|||||||
UDEBUG("time rectification = %fs", t);
|
UDEBUG("time rectification = %fs", t);
|
||||||
}
|
}
|
||||||
|
|
||||||
if((!decimatedData.depthRaw().empty() && decimatedData.cameraModels().size() && decimatedData.cameraModels()[0].isValidForProjection()) ||
|
if(useProvided3dPoints && keypoints.size() != data.keypoints3D().size())
|
||||||
|
{
|
||||||
|
UDEBUG("Using provided 3d points (%d->%d)", (int)data.keypoints3D().size(), (int)keypoints.size());
|
||||||
|
keypoints3D.resize(keypoints.size());
|
||||||
|
for(size_t i=0; i<keypoints.size(); ++i)
|
||||||
|
{
|
||||||
|
UASSERT(keypoints[i].class_id < (int)data.keypoints3D().size());
|
||||||
|
keypoints3D[i] = data.keypoints3D()[keypoints[i].class_id];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(keypoints.size() == data.keypoints3D().size())
|
||||||
|
{
|
||||||
|
UDEBUG("Using provided 3d points (%d)", (int)data.keypoints3D().size());
|
||||||
|
keypoints3D = data.keypoints3D();
|
||||||
|
}
|
||||||
|
else if((!decimatedData.depthRaw().empty() && decimatedData.cameraModels().size() && decimatedData.cameraModels()[0].isValidForProjection()) ||
|
||||||
(!decimatedData.rightRaw().empty() && decimatedData.stereoCameraModel().isValidForProjection()))
|
(!decimatedData.rightRaw().empty() && decimatedData.stereoCameraModel().isValidForProjection()))
|
||||||
{
|
{
|
||||||
keypoints3D = _feature2D->generateKeypoints3D(decimatedData, keypoints);
|
keypoints3D = _feature2D->generateKeypoints3D(decimatedData, keypoints);
|
||||||
@@ -4514,10 +4601,26 @@ Signature * Memory::createSignature(const SensorData & inputData, const Transfor
|
|||||||
if(_feature2D->getMaxFeatures()>0 && descriptors.rows > _feature2D->getMaxFeatures())
|
if(_feature2D->getMaxFeatures()>0 && descriptors.rows > _feature2D->getMaxFeatures())
|
||||||
{
|
{
|
||||||
UASSERT((int)keypoints.size() == descriptors.rows);
|
UASSERT((int)keypoints.size() == descriptors.rows);
|
||||||
Feature2D::limitKeypoints(keypoints, inliers, _feature2D->getMaxFeatures());
|
int inliersCount = 0;
|
||||||
|
if(_feature2D->getGridRows() > 1 || _feature2D->getGridCols() > 1)
|
||||||
|
{
|
||||||
|
Feature2D::limitKeypoints(keypoints, inliers, _feature2D->getMaxFeatures(), decimatedData.imageRaw().size(), _feature2D->getGridRows(), _feature2D->getGridCols());
|
||||||
|
for(size_t i=0; i<inliers.size(); ++i)
|
||||||
|
{
|
||||||
|
if(inliers[i])
|
||||||
|
{
|
||||||
|
++inliersCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Feature2D::limitKeypoints(keypoints, inliers, _feature2D->getMaxFeatures());
|
||||||
|
inliersCount = _feature2D->getMaxFeatures();
|
||||||
|
}
|
||||||
|
|
||||||
descriptorsForQuantization = cv::Mat(_feature2D->getMaxFeatures(), descriptors.cols, descriptors.type());
|
descriptorsForQuantization = cv::Mat(inliersCount, descriptors.cols, descriptors.type());
|
||||||
quantizedToRawIndices.resize(_feature2D->getMaxFeatures());
|
quantizedToRawIndices.resize(inliersCount);
|
||||||
unsigned int oi=0;
|
unsigned int oi=0;
|
||||||
UASSERT((int)inliers.size() == descriptors.rows);
|
UASSERT((int)inliers.size() == descriptors.rows);
|
||||||
for(int k=0; k < descriptors.rows; ++k)
|
for(int k=0; k < descriptors.rows; ++k)
|
||||||
@@ -4537,7 +4640,9 @@ Signature * Memory::createSignature(const SensorData & inputData, const Transfor
|
|||||||
++oi;
|
++oi;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
UASSERT((int)oi == _feature2D->getMaxFeatures());
|
UASSERT_MSG((int)oi == inliersCount,
|
||||||
|
uFormat("oi=%d inliersCount=%d (maxFeatures=%d, grid=%dx%d)",
|
||||||
|
oi, inliersCount, _feature2D->getMaxFeatures(), _feature2D->getGridCols(), _feature2D->getGridRows()).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Quantization to vocabulary
|
// Quantization to vocabulary
|
||||||
@@ -4577,6 +4682,7 @@ Signature * Memory::createSignature(const SensorData & inputData, const Transfor
|
|||||||
std::multimap<int, cv::KeyPoint> words;
|
std::multimap<int, cv::KeyPoint> words;
|
||||||
std::multimap<int, cv::Point3f> words3D;
|
std::multimap<int, cv::Point3f> words3D;
|
||||||
std::multimap<int, cv::Mat> wordsDescriptors;
|
std::multimap<int, cv::Mat> wordsDescriptors;
|
||||||
|
int words3DValid = 0;
|
||||||
if(wordIds.size() > 0)
|
if(wordIds.size() > 0)
|
||||||
{
|
{
|
||||||
UASSERT(wordIds.size() == keypoints.size());
|
UASSERT(wordIds.size() == keypoints.size());
|
||||||
@@ -4600,6 +4706,10 @@ Signature * Memory::createSignature(const SensorData & inputData, const Transfor
|
|||||||
if(keypoints3D.size())
|
if(keypoints3D.size())
|
||||||
{
|
{
|
||||||
words3D.insert(std::pair<int, cv::Point3f>(*iter, keypoints3D.at(i)));
|
words3D.insert(std::pair<int, cv::Point3f>(*iter, keypoints3D.at(i)));
|
||||||
|
if(util3d::isFinite(keypoints3D.at(i)))
|
||||||
|
{
|
||||||
|
++words3DValid;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if(_rawDescriptorsKept)
|
if(_rawDescriptorsKept)
|
||||||
{
|
{
|
||||||
@@ -4703,16 +4813,17 @@ Signature * Memory::createSignature(const SensorData & inputData, const Transfor
|
|||||||
UDEBUG("time post-decimation = %fs", t);
|
UDEBUG("time post-decimation = %fs", t);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool triangulateWordsWithoutDepth = !_depthAsMask;
|
if(_stereoFromMotion &&
|
||||||
if(!pose.isNull() &&
|
!pose.isNull() &&
|
||||||
cameraModels.size() == 1 &&
|
cameraModels.size() == 1 &&
|
||||||
words.size() &&
|
words.size() &&
|
||||||
(words3D.size() == 0 || (triangulateWordsWithoutDepth && words.size() == words3D.size())) &&
|
(words3D.size() == 0 || (words.size() == words3D.size() && words3DValid!=(int)words3D.size())) &&
|
||||||
_registrationPipeline->isImageRequired() &&
|
_registrationPipeline->isImageRequired() &&
|
||||||
_signatures.size() &&
|
_signatures.size() &&
|
||||||
_signatures.rbegin()->second->mapId() == _idMapCount) // same map
|
_signatures.rbegin()->second->mapId() == _idMapCount) // same map
|
||||||
{
|
{
|
||||||
UDEBUG("Generate 3D words using odometry");
|
UDEBUG("Generate 3D words using odometry (%s=true and words3DValid=%d/%d)",
|
||||||
|
Parameters::kMemStereoFromMotion().c_str(), words3DValid, (int)words3D.size());
|
||||||
Signature * previousS = _signatures.rbegin()->second;
|
Signature * previousS = _signatures.rbegin()->second;
|
||||||
if(previousS->getWords().size() > 8 && words.size() > 8 && !previousS->getPose().isNull())
|
if(previousS->getWords().size() > 8 && words.size() > 8 && !previousS->getPose().isNull())
|
||||||
{
|
{
|
||||||
@@ -4735,7 +4846,9 @@ Signature * Memory::createSignature(const SensorData & inputData, const Transfor
|
|||||||
cpCurrent.setWords(std::multimap<int, cv::KeyPoint>(uniqueWords.begin(), uniqueWords.end()));
|
cpCurrent.setWords(std::multimap<int, cv::KeyPoint>(uniqueWords.begin(), uniqueWords.end()));
|
||||||
cpCurrent.setWordsDescriptors(std::multimap<int, cv::Mat>(uniqueWordsDescriptors.begin(), uniqueWordsDescriptors.end()));
|
cpCurrent.setWordsDescriptors(std::multimap<int, cv::Mat>(uniqueWordsDescriptors.begin(), uniqueWordsDescriptors.end()));
|
||||||
|
|
||||||
|
// The following is used only to re-estimate the correspondences, the returned transform is ignored
|
||||||
Transform tmpt;
|
Transform tmpt;
|
||||||
|
RegistrationVis reg(parameters_);
|
||||||
if(_registrationPipeline->isScanRequired())
|
if(_registrationPipeline->isScanRequired())
|
||||||
{
|
{
|
||||||
// If icp is used, remove it to just do visual registration
|
// If icp is used, remove it to just do visual registration
|
||||||
@@ -4746,10 +4859,9 @@ Signature * Memory::createSignature(const SensorData & inputData, const Transfor
|
|||||||
{
|
{
|
||||||
tmpt = _registrationPipeline->computeTransformationMod(cpCurrent, cpPrevious, cameraTransform);
|
tmpt = _registrationPipeline->computeTransformationMod(cpCurrent, cpPrevious, cameraTransform);
|
||||||
}
|
}
|
||||||
|
|
||||||
UDEBUG("t=%s", tmpt.prettyPrint().c_str());
|
UDEBUG("t=%s", tmpt.prettyPrint().c_str());
|
||||||
|
|
||||||
// compute 3D words by epipolar geometry with the previous signature
|
// compute 3D words by epipolar geometry with the previous signature using odometry motion
|
||||||
std::map<int, cv::Point3f> inliers = util3d::generateWords3DMono(
|
std::map<int, cv::Point3f> inliers = util3d::generateWords3DMono(
|
||||||
uMultimapToMapUnique(cpCurrent.getWords()),
|
uMultimapToMapUnique(cpCurrent.getWords()),
|
||||||
uMultimapToMapUnique(cpPrevious.getWords()),
|
uMultimapToMapUnique(cpPrevious.getWords()),
|
||||||
@@ -5060,6 +5172,7 @@ Signature * Memory::createSignature(const SensorData & inputData, const Transfor
|
|||||||
s->sensorData().setGroundTruth(data.groundTruth());
|
s->sensorData().setGroundTruth(data.groundTruth());
|
||||||
s->sensorData().setGPS(data.gps());
|
s->sensorData().setGPS(data.gps());
|
||||||
s->sensorData().setEnvSensors(data.envSensors());
|
s->sensorData().setEnvSensors(data.envSensors());
|
||||||
|
s->sensorData().setGlobalDescriptors(data.globalDescriptors());
|
||||||
|
|
||||||
t = timer.ticks();
|
t = timer.ticks();
|
||||||
if(stats) stats->addStatistic(Statistics::kTimingMemCompressing_data(), t*1000.0f);
|
if(stats) stats->addStatistic(Statistics::kTimingMemCompressing_data(), t*1000.0f);
|
||||||
|
|||||||
+72
-43
@@ -186,7 +186,6 @@ Odometry::~Odometry()
|
|||||||
{
|
{
|
||||||
delete particleFilters_[i];
|
delete particleFilters_[i];
|
||||||
}
|
}
|
||||||
particleFilters_.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Odometry::reset(const Transform & initialPose)
|
void Odometry::reset(const Transform & initialPose)
|
||||||
@@ -199,6 +198,8 @@ void Odometry::reset(const Transform & initialPose)
|
|||||||
previousStamp_ = 0;
|
previousStamp_ = 0;
|
||||||
distanceTravelled_ = 0;
|
distanceTravelled_ = 0;
|
||||||
framesProcessed_ = 0;
|
framesProcessed_ = 0;
|
||||||
|
imuLastTransform_.setNull();
|
||||||
|
imus_.clear();
|
||||||
if(_force3DoF || particleFilters_.size())
|
if(_force3DoF || particleFilters_.size())
|
||||||
{
|
{
|
||||||
float x,y,z, roll,pitch,yaw;
|
float x,y,z, roll,pitch,yaw;
|
||||||
@@ -382,6 +383,21 @@ Transform Odometry::process(SensorData & data, const Transform & guessIn, Odomet
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// cache imu data
|
||||||
|
if(!data.imu().empty())
|
||||||
|
{
|
||||||
|
if(!(data.imu().orientation()[0] == 0.0 && data.imu().orientation()[1] == 0.0 && data.imu().orientation()[2] == 0.0))
|
||||||
|
{
|
||||||
|
Transform orientation(0,0,0, data.imu().orientation()[0], data.imu().orientation()[1], data.imu().orientation()[2], data.imu().orientation()[3]);
|
||||||
|
// orientation includes roll and pitch but not yaw in local transform
|
||||||
|
imus_.insert(std::make_pair(data.stamp(), Transform(0,0,data.imu().localTransform().theta()) * orientation*data.imu().localTransform().inverse()));
|
||||||
|
if(imus_.size() > 1000)
|
||||||
|
{
|
||||||
|
imus_.erase(imus_.begin());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// KITTI datasets start with stamp=0
|
// KITTI datasets start with stamp=0
|
||||||
double dt = previousStamp_>0.0f || (previousStamp_==0.0f && framesProcessed()==1)?data.stamp() - previousStamp_:0.0;
|
double dt = previousStamp_>0.0f || (previousStamp_==0.0f && framesProcessed()==1)?data.stamp() - previousStamp_:0.0;
|
||||||
Transform guess = dt>0.0 && guessFromMotion_ && !velocityGuess_.isNull()?Transform::getIdentity():Transform();
|
Transform guess = dt>0.0 && guessFromMotion_ && !velocityGuess_.isNull()?Transform::getIdentity():Transform();
|
||||||
@@ -423,10 +439,24 @@ Transform Odometry::process(SensorData & data, const Transform & guessIn, Odomet
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Transform imuCurrentTransform;
|
||||||
if(!guessIn.isNull())
|
if(!guessIn.isNull())
|
||||||
{
|
{
|
||||||
guess = guessIn;
|
guess = guessIn;
|
||||||
}
|
}
|
||||||
|
else if(!data.imu().empty() && !imus_.empty())
|
||||||
|
{
|
||||||
|
// replace orientation guess with IMU (if available)
|
||||||
|
imuCurrentTransform = Transform::getTransform(imus_, data.stamp());
|
||||||
|
if(!imuCurrentTransform.isNull() && !imuLastTransform_.isNull())
|
||||||
|
{
|
||||||
|
Transform orientation = imuLastTransform_.inverse() * imuCurrentTransform;
|
||||||
|
guess = Transform(
|
||||||
|
orientation.r11(), orientation.r12(), orientation.r13(), guess.x(),
|
||||||
|
orientation.r21(), orientation.r22(), orientation.r23(), guess.y(),
|
||||||
|
orientation.r31(), orientation.r32(), orientation.r33(), guess.z());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
UTimer time;
|
UTimer time;
|
||||||
Transform t;
|
Transform t;
|
||||||
@@ -562,50 +592,58 @@ Transform Odometry::process(SensorData & data, const Transform & guessIn, Odomet
|
|||||||
updateKalmanFilter(vx,vy,vz,vroll,vpitch,vyaw);
|
updateKalmanFilter(vx,vy,vz,vroll,vpitch,vyaw);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(particleFilters_.size())
|
else
|
||||||
{
|
{
|
||||||
// Particle filtering
|
if(particleFilters_.size())
|
||||||
UASSERT(particleFilters_.size()==6);
|
|
||||||
if(velocityGuess_.isNull())
|
|
||||||
{
|
{
|
||||||
particleFilters_[0]->init(vx);
|
// Particle filtering
|
||||||
particleFilters_[1]->init(vy);
|
UASSERT(particleFilters_.size()==6);
|
||||||
particleFilters_[2]->init(vz);
|
if(velocityGuess_.isNull())
|
||||||
particleFilters_[3]->init(vroll);
|
|
||||||
particleFilters_[4]->init(vpitch);
|
|
||||||
particleFilters_[5]->init(vyaw);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
vx = particleFilters_[0]->filter(vx);
|
|
||||||
vy = particleFilters_[1]->filter(vy);
|
|
||||||
vyaw = particleFilters_[5]->filter(vyaw);
|
|
||||||
|
|
||||||
if(!_holonomic)
|
|
||||||
{
|
{
|
||||||
// arc trajectory around ICR
|
particleFilters_[0]->init(vx);
|
||||||
float tmpY = vyaw!=0.0f ? vx / tan((CV_PI-vyaw)/2.0f) : 0.0f;
|
particleFilters_[1]->init(vy);
|
||||||
if(fabs(tmpY) < fabs(vy) || (tmpY<=0 && vy >=0) || (tmpY>=0 && vy<=0))
|
particleFilters_[2]->init(vz);
|
||||||
|
particleFilters_[3]->init(vroll);
|
||||||
|
particleFilters_[4]->init(vpitch);
|
||||||
|
particleFilters_[5]->init(vyaw);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vx = particleFilters_[0]->filter(vx);
|
||||||
|
vy = particleFilters_[1]->filter(vy);
|
||||||
|
vyaw = particleFilters_[5]->filter(vyaw);
|
||||||
|
|
||||||
|
if(!_holonomic)
|
||||||
{
|
{
|
||||||
vy = tmpY;
|
// arc trajectory around ICR
|
||||||
|
float tmpY = vyaw!=0.0f ? vx / tan((CV_PI-vyaw)/2.0f) : 0.0f;
|
||||||
|
if(fabs(tmpY) < fabs(vy) || (tmpY<=0 && vy >=0) || (tmpY>=0 && vy<=0))
|
||||||
|
{
|
||||||
|
vy = tmpY;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vyaw = (atan(vx/vy)*2.0f-CV_PI)*-1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
if(!_force3DoF)
|
||||||
{
|
{
|
||||||
vyaw = (atan(vx/vy)*2.0f-CV_PI)*-1;
|
vz = particleFilters_[2]->filter(vz);
|
||||||
|
vroll = particleFilters_[3]->filter(vroll);
|
||||||
|
vpitch = particleFilters_[4]->filter(vpitch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!_force3DoF)
|
if(info)
|
||||||
{
|
{
|
||||||
vz = particleFilters_[2]->filter(vz);
|
info->timeParticleFiltering = time.ticks();
|
||||||
vroll = particleFilters_[3]->filter(vroll);
|
|
||||||
vpitch = particleFilters_[4]->filter(vpitch);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if(!_holonomic)
|
||||||
if(info)
|
|
||||||
{
|
{
|
||||||
info->timeParticleFiltering = time.ticks();
|
// arc trajectory around ICR
|
||||||
|
vy = vyaw!=0.0f ? vx / tan((CV_PI-vyaw)/2.0f) : 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(_force3DoF)
|
if(_force3DoF)
|
||||||
@@ -615,17 +653,6 @@ Transform Odometry::process(SensorData & data, const Transform & guessIn, Odomet
|
|||||||
vpitch = 0.0f;
|
vpitch = 0.0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(!_holonomic)
|
|
||||||
{
|
|
||||||
// arc trajectory around ICR
|
|
||||||
vy = vyaw!=0.0f ? vx / tan((CV_PI-vyaw)/2.0f) : 0.0f;
|
|
||||||
if(_force3DoF)
|
|
||||||
{
|
|
||||||
vz = 0.0f;
|
|
||||||
vroll = 0.0f;
|
|
||||||
vpitch = 0.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(dt)
|
if(dt)
|
||||||
{
|
{
|
||||||
@@ -688,6 +715,8 @@ Transform Odometry::process(SensorData & data, const Transform & guessIn, Odomet
|
|||||||
}
|
}
|
||||||
++framesProcessed_;
|
++framesProcessed_;
|
||||||
|
|
||||||
|
imuLastTransform_ = imuCurrentTransform;
|
||||||
|
|
||||||
return _pose *= t; // update
|
return _pose *= t; // update
|
||||||
}
|
}
|
||||||
else if(_resetCurrentCount > 0)
|
else if(_resetCurrentCount > 0)
|
||||||
|
|||||||
@@ -489,6 +489,13 @@ std::map<int, Transform> Optimizer::optimizeBA(
|
|||||||
model.localTransform(),
|
model.localTransform(),
|
||||||
-signatures.at(iter->first).sensorData().stereoCameraModel().baseline()*model.fx());
|
-signatures.at(iter->first).sensorData().stereoCameraModel().baseline()*model.fx());
|
||||||
}
|
}
|
||||||
|
else if(signatures.at(iter->first).sensorData().cameraModels().size() > 1)
|
||||||
|
{
|
||||||
|
UERROR("Multi-cameras (%d) is not supported (id=%d).",
|
||||||
|
signatures.at(iter->first).sensorData().cameraModels().size(),
|
||||||
|
iter->first);
|
||||||
|
return std::map<int, Transform>();
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
UERROR("Missing calibration for node %d", iter->first);
|
UERROR("Missing calibration for node %d", iter->first);
|
||||||
|
|||||||
+38
-10
@@ -40,6 +40,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "SimpleIni.h"
|
#include "SimpleIni.h"
|
||||||
#include <opencv2/core/version.hpp>
|
#include <opencv2/core/version.hpp>
|
||||||
#include <pcl/pcl_config.h>
|
#include <pcl/pcl_config.h>
|
||||||
|
#include <opencv2/opencv_modules.hpp>
|
||||||
#ifndef DISABLE_VTK
|
#ifndef DISABLE_VTK
|
||||||
#include <vtkVersion.h>
|
#include <vtkVersion.h>
|
||||||
#endif
|
#endif
|
||||||
@@ -166,7 +167,7 @@ bool Parameters::isFeatureParameter(const std::string & parameter)
|
|||||||
group.compare("GFTT") == 0 ||
|
group.compare("GFTT") == 0 ||
|
||||||
group.compare("BRISK") == 0 ||
|
group.compare("BRISK") == 0 ||
|
||||||
group.compare("KAZE") == 0 ||
|
group.compare("KAZE") == 0 ||
|
||||||
group.compare("SPTorch") == 0;
|
group.compare("SuperPoint") == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
rtabmap::ParametersMap Parameters::getDefaultOdometryParameters(bool stereo, bool vis, bool icp)
|
rtabmap::ParametersMap Parameters::getDefaultOdometryParameters(bool stereo, bool vis, bool icp)
|
||||||
@@ -184,16 +185,9 @@ rtabmap::ParametersMap Parameters::getDefaultOdometryParameters(bool stereo, boo
|
|||||||
group.compare("Optimizer") == 0 ||
|
group.compare("Optimizer") == 0 ||
|
||||||
group.compare("g2o") == 0 ||
|
group.compare("g2o") == 0 ||
|
||||||
group.compare("GTSAM") == 0 ||
|
group.compare("GTSAM") == 0 ||
|
||||||
(vis && group.compare("Vis") == 0) ||
|
(vis && (group.compare("Vis") == 0 || group.compare("PyMatcher") == 0 || group.compare("GMS") == 0)) ||
|
||||||
iter->first.compare(kRtabmapPublishRAMUsage())==0)
|
iter->first.compare(kRtabmapPublishRAMUsage())==0)
|
||||||
{
|
{
|
||||||
if(stereo)
|
|
||||||
{
|
|
||||||
if(iter->first.compare(Parameters::kVisEstimationType()) == 0)
|
|
||||||
{
|
|
||||||
iter->second = "1"; // 3D->2D (PNP)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
odomParameters.insert(*iter);
|
odomParameters.insert(*iter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -238,6 +232,20 @@ const std::map<std::string, std::pair<bool, std::string> > & Parameters::getRemo
|
|||||||
{
|
{
|
||||||
// removed parameters
|
// removed parameters
|
||||||
|
|
||||||
|
// 0.20.
|
||||||
|
removedParameters_.insert(std::make_pair("SuperGlue/Path", std::make_pair(true, Parameters::kPyMatcherPath())));
|
||||||
|
removedParameters_.insert(std::make_pair("SuperGlue/Iterations", std::make_pair(true, Parameters::kPyMatcherIterations())));
|
||||||
|
removedParameters_.insert(std::make_pair("SuperGlue/MatchThreshold", std::make_pair(true, Parameters::kPyMatcherThreshold())));
|
||||||
|
removedParameters_.insert(std::make_pair("SuperGlue/Cuda", std::make_pair(true, Parameters::kPyMatcherCuda())));
|
||||||
|
removedParameters_.insert(std::make_pair("SuperGlue/Indoor", std::make_pair(false, Parameters::kPyMatcherModel())));
|
||||||
|
|
||||||
|
removedParameters_.insert(std::make_pair("Vis/CorCrossCheck", std::make_pair(false, Parameters::kVisCorNNType())));
|
||||||
|
removedParameters_.insert(std::make_pair("SPTorch/ModelPath", std::make_pair(true, Parameters::kSuperPointModelPath())));
|
||||||
|
removedParameters_.insert(std::make_pair("SPTorch/Threshold", std::make_pair(true, Parameters::kSuperPointThreshold())));
|
||||||
|
removedParameters_.insert(std::make_pair("SPTorch/NMS", std::make_pair(true, Parameters::kSuperPointNMS())));
|
||||||
|
removedParameters_.insert(std::make_pair("SPTorch/MinDistance", std::make_pair(true, Parameters::kSuperPointNMSRadius())));
|
||||||
|
removedParameters_.insert(std::make_pair("SPTorch/Cuda", std::make_pair(true, Parameters::kSuperPointCuda())));
|
||||||
|
|
||||||
// 0.19.4
|
// 0.19.4
|
||||||
removedParameters_.insert(std::make_pair("RGBD/MaxLocalizationDistance", std::make_pair(true, Parameters::kRGBDMaxLoopClosureDistance())));
|
removedParameters_.insert(std::make_pair("RGBD/MaxLocalizationDistance", std::make_pair(true, Parameters::kRGBDMaxLoopClosureDistance())));
|
||||||
|
|
||||||
@@ -595,6 +603,14 @@ ParametersMap Parameters::parseArguments(int argc, char * argv[], bool onlyParam
|
|||||||
#endif
|
#endif
|
||||||
str = "OpenCV:";
|
str = "OpenCV:";
|
||||||
std::cout << str << std::setw(spacing - str.size()) << CV_VERSION << std::endl;
|
std::cout << str << std::setw(spacing - str.size()) << CV_VERSION << std::endl;
|
||||||
|
#if CV_MAJOR_VERSION >= 3
|
||||||
|
str = "With OpenCV xfeatures2d:";
|
||||||
|
#ifdef HAVE_OPENCV_XFEATURES2D
|
||||||
|
std::cout << str << std::setw(spacing - str.size()) << "true" << std::endl;
|
||||||
|
#else
|
||||||
|
std::cout << str << std::setw(spacing - str.size()) << "false" << std::endl;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
str = "With OpenCV nonfree:";
|
str = "With OpenCV nonfree:";
|
||||||
#ifdef RTABMAP_NONFREE
|
#ifdef RTABMAP_NONFREE
|
||||||
std::cout << str << std::setw(spacing - str.size()) << "true" << std::endl;
|
std::cout << str << std::setw(spacing - str.size()) << "true" << std::endl;
|
||||||
@@ -608,7 +624,13 @@ ParametersMap Parameters::parseArguments(int argc, char * argv[], bool onlyParam
|
|||||||
std::cout << str << std::setw(spacing - str.size()) << "false" << std::endl;
|
std::cout << str << std::setw(spacing - str.size()) << "false" << std::endl;
|
||||||
#endif
|
#endif
|
||||||
str = "With SuperPoint Torch:";
|
str = "With SuperPoint Torch:";
|
||||||
#ifdef RTABMAP_SP_TORCH
|
#ifdef RTABMAP_SUPERPOINT_TORCH
|
||||||
|
std::cout << str << std::setw(spacing - str.size()) << "true" << std::endl;
|
||||||
|
#else
|
||||||
|
std::cout << str << std::setw(spacing - str.size()) << "false" << std::endl;
|
||||||
|
#endif
|
||||||
|
str = "With Python3:";
|
||||||
|
#ifdef RTABMAP_PYMATCHER
|
||||||
std::cout << str << std::setw(spacing - str.size()) << "true" << std::endl;
|
std::cout << str << std::setw(spacing - str.size()) << "true" << std::endl;
|
||||||
#else
|
#else
|
||||||
std::cout << str << std::setw(spacing - str.size()) << "false" << std::endl;
|
std::cout << str << std::setw(spacing - str.size()) << "false" << std::endl;
|
||||||
@@ -720,6 +742,12 @@ ParametersMap Parameters::parseArguments(int argc, char * argv[], bool onlyParam
|
|||||||
std::cout << str << std::setw(spacing - str.size()) << "true" << std::endl;
|
std::cout << str << std::setw(spacing - str.size()) << "true" << std::endl;
|
||||||
#else
|
#else
|
||||||
std::cout << str << std::setw(spacing - str.size()) << "false" << std::endl;
|
std::cout << str << std::setw(spacing - str.size()) << "false" << std::endl;
|
||||||
|
#endif
|
||||||
|
str = "With MYNT EYE S:";
|
||||||
|
#ifdef RTABMAP_MYNTEYE
|
||||||
|
std::cout << str << std::setw(spacing - str.size()) << "true" << std::endl;
|
||||||
|
#else
|
||||||
|
std::cout << str << std::setw(spacing - str.size()) << "false" << std::endl;
|
||||||
#endif
|
#endif
|
||||||
str = "With libpointmatcher:";
|
str = "With libpointmatcher:";
|
||||||
#ifdef RTABMAP_POINTMATCHER
|
#ifdef RTABMAP_POINTMATCHER
|
||||||
|
|||||||
+153
-23
@@ -44,8 +44,17 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <rtabmap/utilite/UMath.h>
|
#include <rtabmap/utilite/UMath.h>
|
||||||
#include <opencv2/core/core_c.h>
|
#include <opencv2/core/core_c.h>
|
||||||
|
|
||||||
|
#if defined(HAVE_OPENCV_XFEATURES2D) && (CV_MAJOR_VERSION > 3 || (CV_MAJOR_VERSION==3 && CV_MINOR_VERSION >=4 && CV_SUBMINOR_VERSION >= 1))
|
||||||
|
#include <opencv2/xfeatures2d.hpp> // For GMS matcher
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <rtflann/flann.hpp>
|
#include <rtflann/flann.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef RTABMAP_PYMATCHER
|
||||||
|
#include <pymatcher/PyMatcher.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace rtabmap {
|
namespace rtabmap {
|
||||||
|
|
||||||
RegistrationVis::RegistrationVis(const ParametersMap & parameters, Registration * child) :
|
RegistrationVis::RegistrationVis(const ParametersMap & parameters, Registration * child) :
|
||||||
@@ -66,7 +75,10 @@ RegistrationVis::RegistrationVis(const ParametersMap & parameters, Registration
|
|||||||
_flowEps(Parameters::defaultVisCorFlowEps()),
|
_flowEps(Parameters::defaultVisCorFlowEps()),
|
||||||
_flowMaxLevel(Parameters::defaultVisCorFlowMaxLevel()),
|
_flowMaxLevel(Parameters::defaultVisCorFlowMaxLevel()),
|
||||||
_nndr(Parameters::defaultVisCorNNDR()),
|
_nndr(Parameters::defaultVisCorNNDR()),
|
||||||
_bfCrossCheck(Parameters::defaultVisCorCrossCheck()),
|
_nnType(Parameters::defaultVisCorNNType()),
|
||||||
|
_gmsWithRotation(Parameters::defaultGMSWithRotation()),
|
||||||
|
_gmsWithScale(Parameters::defaultGMSWithScale()),
|
||||||
|
_gmsThresholdFactor(Parameters::defaultGMSThresholdFactor()),
|
||||||
_guessWinSize(Parameters::defaultVisCorGuessWinSize()),
|
_guessWinSize(Parameters::defaultVisCorGuessWinSize()),
|
||||||
_guessMatchToProjection(Parameters::defaultVisCorGuessMatchToProjection()),
|
_guessMatchToProjection(Parameters::defaultVisCorGuessMatchToProjection()),
|
||||||
_bundleAdjustment(Parameters::defaultVisBundleAdjustment()),
|
_bundleAdjustment(Parameters::defaultVisBundleAdjustment()),
|
||||||
@@ -75,6 +87,10 @@ RegistrationVis::RegistrationVis(const ParametersMap & parameters, Registration
|
|||||||
_maxInliersMeanDistance(Parameters::defaultVisMeanInliersDistance()),
|
_maxInliersMeanDistance(Parameters::defaultVisMeanInliersDistance()),
|
||||||
_detectorFrom(0),
|
_detectorFrom(0),
|
||||||
_detectorTo(0)
|
_detectorTo(0)
|
||||||
|
#ifdef RTABMAP_PYMATCHER
|
||||||
|
,
|
||||||
|
_pyMatcher(0)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
_featureParameters = Parameters::getDefaultParameters();
|
_featureParameters = Parameters::getDefaultParameters();
|
||||||
uInsert(_featureParameters, ParametersPair(Parameters::kKpNNStrategy(), _featureParameters.at(Parameters::kVisCorNNType())));
|
uInsert(_featureParameters, ParametersPair(Parameters::kKpNNStrategy(), _featureParameters.at(Parameters::kVisCorNNType())));
|
||||||
@@ -114,7 +130,10 @@ void RegistrationVis::parseParameters(const ParametersMap & parameters)
|
|||||||
Parameters::parse(parameters, Parameters::kVisCorFlowEps(), _flowEps);
|
Parameters::parse(parameters, Parameters::kVisCorFlowEps(), _flowEps);
|
||||||
Parameters::parse(parameters, Parameters::kVisCorFlowMaxLevel(), _flowMaxLevel);
|
Parameters::parse(parameters, Parameters::kVisCorFlowMaxLevel(), _flowMaxLevel);
|
||||||
Parameters::parse(parameters, Parameters::kVisCorNNDR(), _nndr);
|
Parameters::parse(parameters, Parameters::kVisCorNNDR(), _nndr);
|
||||||
Parameters::parse(parameters, Parameters::kVisCorCrossCheck(), _bfCrossCheck);
|
Parameters::parse(parameters, Parameters::kVisCorNNType(), _nnType);
|
||||||
|
Parameters::parse(parameters, Parameters::kGMSWithRotation(), _gmsWithRotation);
|
||||||
|
Parameters::parse(parameters, Parameters::kGMSWithScale(), _gmsWithScale);
|
||||||
|
Parameters::parse(parameters, Parameters::kGMSThresholdFactor(), _gmsThresholdFactor);
|
||||||
Parameters::parse(parameters, Parameters::kVisCorGuessWinSize(), _guessWinSize);
|
Parameters::parse(parameters, Parameters::kVisCorGuessWinSize(), _guessWinSize);
|
||||||
Parameters::parse(parameters, Parameters::kVisCorGuessMatchToProjection(), _guessMatchToProjection);
|
Parameters::parse(parameters, Parameters::kVisCorGuessMatchToProjection(), _guessMatchToProjection);
|
||||||
Parameters::parse(parameters, Parameters::kVisBundleAdjustment(), _bundleAdjustment);
|
Parameters::parse(parameters, Parameters::kVisBundleAdjustment(), _bundleAdjustment);
|
||||||
@@ -131,6 +150,48 @@ void RegistrationVis::parseParameters(const ParametersMap & parameters)
|
|||||||
UASSERT_MSG(_inlierDistance > 0.0f, uFormat("value=%f", _inlierDistance).c_str());
|
UASSERT_MSG(_inlierDistance > 0.0f, uFormat("value=%f", _inlierDistance).c_str());
|
||||||
UASSERT_MSG(_iterations > 0, uFormat("value=%d", _iterations).c_str());
|
UASSERT_MSG(_iterations > 0, uFormat("value=%d", _iterations).c_str());
|
||||||
|
|
||||||
|
if(_nnType == 6)
|
||||||
|
{
|
||||||
|
// verify that we have Python3 support
|
||||||
|
#ifndef RTABMAP_PYMATCHER
|
||||||
|
UWARN("%s is set to 6 but RTAB-Map is not built with Python3 support, using default %d.",
|
||||||
|
Parameters::kVisCorNNType().c_str(), Parameters::defaultVisCorNNType());
|
||||||
|
_nnType = Parameters::defaultVisCorNNType();
|
||||||
|
#else
|
||||||
|
int iterations = _pyMatcher?_pyMatcher->iterations():Parameters::defaultPyMatcherIterations();
|
||||||
|
float matchThr = _pyMatcher?_pyMatcher->matchThreshold():Parameters::defaultPyMatcherThreshold();
|
||||||
|
std::string path = _pyMatcher?_pyMatcher->path():Parameters::defaultPyMatcherPath();
|
||||||
|
bool cuda = _pyMatcher?_pyMatcher->cuda():Parameters::defaultPyMatcherCuda();
|
||||||
|
std::string model = _pyMatcher?_pyMatcher->model():Parameters::defaultPyMatcherModel();
|
||||||
|
Parameters::parse(parameters, Parameters::kPyMatcherIterations(), iterations);
|
||||||
|
Parameters::parse(parameters, Parameters::kPyMatcherThreshold(), matchThr);
|
||||||
|
Parameters::parse(parameters, Parameters::kPyMatcherPath(), path);
|
||||||
|
Parameters::parse(parameters, Parameters::kPyMatcherCuda(), cuda);
|
||||||
|
Parameters::parse(parameters, Parameters::kPyMatcherModel(), model);
|
||||||
|
if(path.empty())
|
||||||
|
{
|
||||||
|
UERROR("%s parameter should be set to use Python3 matching (%s=6), using default %d.",
|
||||||
|
Parameters::kPyMatcherPath().c_str(),
|
||||||
|
Parameters::kVisCorNNType().c_str(),
|
||||||
|
Parameters::defaultVisCorNNType());
|
||||||
|
_nnType = Parameters::defaultVisCorNNType();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
delete _pyMatcher;
|
||||||
|
_pyMatcher = new PyMatcher(path, matchThr, iterations, cuda, model);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#if !defined(HAVE_OPENCV_XFEATURES2D) || (CV_MAJOR_VERSION == 3 && (CV_MINOR_VERSION<4 || CV_MINOR_VERSION==4 && CV_SUBMINOR_VERSION<1))
|
||||||
|
else if(_nnType == 7)
|
||||||
|
{
|
||||||
|
UWARN("%s is set to 7 but RTAB-Map is not built with OpenCV's xfeatures2d support (OpenCV >= 3.4.1 also required), using default %d.",
|
||||||
|
Parameters::kVisCorNNType().c_str(), Parameters::defaultVisCorNNType());
|
||||||
|
_nnType = Parameters::defaultVisCorNNType();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// override feature parameters
|
// override feature parameters
|
||||||
for(ParametersMap::const_iterator iter=parameters.begin(); iter!=parameters.end(); ++iter)
|
for(ParametersMap::const_iterator iter=parameters.begin(); iter!=parameters.end(); ++iter)
|
||||||
{
|
{
|
||||||
@@ -143,7 +204,10 @@ void RegistrationVis::parseParameters(const ParametersMap & parameters)
|
|||||||
|
|
||||||
if(uContains(parameters, Parameters::kVisCorNNType()))
|
if(uContains(parameters, Parameters::kVisCorNNType()))
|
||||||
{
|
{
|
||||||
uInsert(_featureParameters, ParametersPair(Parameters::kKpNNStrategy(), parameters.at(Parameters::kVisCorNNType())));
|
if(_nnType<VWDictionary::kNNUndef)
|
||||||
|
{
|
||||||
|
uInsert(_featureParameters, ParametersPair(Parameters::kKpNNStrategy(), uNumber2Str(_nnType)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if(uContains(parameters, Parameters::kVisCorNNDR()))
|
if(uContains(parameters, Parameters::kVisCorNNDR()))
|
||||||
{
|
{
|
||||||
@@ -200,6 +264,9 @@ RegistrationVis::~RegistrationVis()
|
|||||||
{
|
{
|
||||||
delete _detectorFrom;
|
delete _detectorFrom;
|
||||||
delete _detectorTo;
|
delete _detectorTo;
|
||||||
|
#ifdef RTABMAP_PYMATCHER
|
||||||
|
delete _pyMatcher;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
Transform RegistrationVis::computeTransformationImpl(
|
Transform RegistrationVis::computeTransformationImpl(
|
||||||
@@ -222,7 +289,10 @@ Transform RegistrationVis::computeTransformationImpl(
|
|||||||
UDEBUG("%s=%f", Parameters::kVisCorFlowEps().c_str(), _flowEps);
|
UDEBUG("%s=%f", Parameters::kVisCorFlowEps().c_str(), _flowEps);
|
||||||
UDEBUG("%s=%d", Parameters::kVisCorFlowMaxLevel().c_str(), _flowMaxLevel);
|
UDEBUG("%s=%d", Parameters::kVisCorFlowMaxLevel().c_str(), _flowMaxLevel);
|
||||||
UDEBUG("%s=%f", Parameters::kVisCorNNDR().c_str(), _nndr);
|
UDEBUG("%s=%f", Parameters::kVisCorNNDR().c_str(), _nndr);
|
||||||
UDEBUG("%s=%d", Parameters::kVisCorCrossCheck().c_str(), _bfCrossCheck?1:0);
|
UDEBUG("%s=%d", Parameters::kVisCorNNType().c_str(), _nnType);
|
||||||
|
UDEBUG("%s=%d", Parameters::kVisCorGuessWinSize().c_str(), _guessWinSize);
|
||||||
|
UDEBUG("%s=%d", Parameters::kVisCorGuessMatchToProjection().c_str(), _guessMatchToProjection?1:0);
|
||||||
|
UDEBUG("Feature Detector = %d", (int)_detectorFrom->getType());
|
||||||
UDEBUG("guess=%s", guess.prettyPrint().c_str());
|
UDEBUG("guess=%s", guess.prettyPrint().c_str());
|
||||||
|
|
||||||
UDEBUG("Input(%d): from=%d words, %d 3D words, %d words descriptors, %d kpts, %d kpts3D, %d descriptors, image=%dx%d models=%d stereo=%d",
|
UDEBUG("Input(%d): from=%d words, %d 3D words, %d words descriptors, %d kpts, %d kpts3D, %d descriptors, image=%dx%d models=%d stereo=%d",
|
||||||
@@ -709,7 +779,8 @@ Transform RegistrationVis::computeTransformationImpl(
|
|||||||
// If guess is set, limit the search of matches using optical flow window size
|
// If guess is set, limit the search of matches using optical flow window size
|
||||||
bool guessSet = !guess.isIdentity() && !guess.isNull();
|
bool guessSet = !guess.isIdentity() && !guess.isNull();
|
||||||
if(guessSet && _guessWinSize > 0 && kptsFrom3D.size() &&
|
if(guessSet && _guessWinSize > 0 && kptsFrom3D.size() &&
|
||||||
isCalibrated) // needed for projection
|
isCalibrated && // needed for projection
|
||||||
|
_estimationType != 2) // To make sure we match all features for 2D->2D
|
||||||
{
|
{
|
||||||
UDEBUG("");
|
UDEBUG("");
|
||||||
UASSERT((int)kptsTo.size() == descriptorsTo.rows);
|
UASSERT((int)kptsTo.size() == descriptorsTo.rows);
|
||||||
@@ -807,9 +878,8 @@ Transform RegistrationVis::computeTransformationImpl(
|
|||||||
descriptorsIndices.resize(oi);
|
descriptorsIndices.resize(oi);
|
||||||
UASSERT(oi >=2);
|
UASSERT(oi >=2);
|
||||||
|
|
||||||
|
cv::BFMatcher matcher(descriptors.type()==CV_8U?cv::NORM_HAMMING:cv::NORM_L2SQR, _nnType == 5);
|
||||||
cv::BFMatcher matcher(descriptors.type()==CV_8U?cv::NORM_HAMMING:cv::NORM_L2SQR, _bfCrossCheck);
|
if(_nnType == 5) // bruteforce cross check
|
||||||
if(_bfCrossCheck)
|
|
||||||
{
|
{
|
||||||
std::vector<cv::DMatch> matches;
|
std::vector<cv::DMatch> matches;
|
||||||
matcher.match(descriptorsTo.row(i), cv::Mat(descriptors, cv::Range(0, oi)), matches);
|
matcher.match(descriptorsTo.row(i), cv::Mat(descriptors, cv::Range(0, oi)), matches);
|
||||||
@@ -818,7 +888,7 @@ Transform RegistrationVis::computeTransformationImpl(
|
|||||||
matchedIndex = descriptorsIndices.at(matches.at(0).trainIdx);
|
matchedIndex = descriptorsIndices.at(matches.at(0).trainIdx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else // bruteforce knn
|
||||||
{
|
{
|
||||||
std::vector<std::vector<cv::DMatch> > matches;
|
std::vector<std::vector<cv::DMatch> > matches;
|
||||||
matcher.knnMatch(descriptorsTo.row(i), cv::Mat(descriptors, cv::Range(0, oi)), matches, 2);
|
matcher.knnMatch(descriptorsTo.row(i), cv::Mat(descriptors, cv::Range(0, oi)), matches, 2);
|
||||||
@@ -829,7 +899,6 @@ Transform RegistrationVis::computeTransformationImpl(
|
|||||||
matchedIndex = descriptorsIndices.at(matches[0].at(0).trainIdx);
|
matchedIndex = descriptorsIndices.at(matches[0].at(0).trainIdx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else if(indices[i].size() == 1)
|
else if(indices[i].size() == 1)
|
||||||
{
|
{
|
||||||
@@ -957,8 +1026,8 @@ Transform RegistrationVis::computeTransformationImpl(
|
|||||||
bruteForceDescCopy += bruteForceTimer.ticks();
|
bruteForceDescCopy += bruteForceTimer.ticks();
|
||||||
UASSERT(oi >=2);
|
UASSERT(oi >=2);
|
||||||
|
|
||||||
cv::BFMatcher matcher(descriptors.type()==CV_8U?cv::NORM_HAMMING:cv::NORM_L2SQR, _bfCrossCheck);
|
cv::BFMatcher matcher(descriptors.type()==CV_8U?cv::NORM_HAMMING:cv::NORM_L2SQR, _nnType==5);
|
||||||
if(_bfCrossCheck)
|
if(_nnType==5) // bruteforce cross check
|
||||||
{
|
{
|
||||||
std::vector<cv::DMatch> matches;
|
std::vector<cv::DMatch> matches;
|
||||||
matcher.match(descriptorsFrom.row(matchedIndexFrom), cv::Mat(descriptors, cv::Range(0, oi)), matches);
|
matcher.match(descriptorsFrom.row(matchedIndexFrom), cv::Mat(descriptors, cv::Range(0, oi)), matches);
|
||||||
@@ -967,7 +1036,7 @@ Transform RegistrationVis::computeTransformationImpl(
|
|||||||
matchedIndexTo = descriptorsIndices.at(matches.at(0).trainIdx);
|
matchedIndexTo = descriptorsIndices.at(matches.at(0).trainIdx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else // bruteforce knn
|
||||||
{
|
{
|
||||||
std::vector<std::vector<cv::DMatch> > matches;
|
std::vector<std::vector<cv::DMatch> > matches;
|
||||||
matcher.knnMatch(descriptorsFrom.row(matchedIndexFrom), cv::Mat(descriptors, cv::Range(0, oi)), matches, 2);
|
matcher.knnMatch(descriptorsFrom.row(matchedIndexFrom), cv::Mat(descriptors, cv::Range(0, oi)), matches, 2);
|
||||||
@@ -1068,7 +1137,11 @@ Transform RegistrationVis::computeTransformationImpl(
|
|||||||
// match between all descriptors
|
// match between all descriptors
|
||||||
std::list<int> fromWordIds;
|
std::list<int> fromWordIds;
|
||||||
std::list<int> toWordIds;
|
std::list<int> toWordIds;
|
||||||
if(_bfCrossCheck)
|
#ifdef RTABMAP_PYMATCHER
|
||||||
|
if(_nnType == 5 || (_nnType == 6 && _pyMatcher) || _nnType==7)
|
||||||
|
#else
|
||||||
|
if(_nnType == 5 || _nnType == 7) // bruteforce cross check or GMS
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
std::vector<int> fromWordIdsV(descriptorsFrom.rows);
|
std::vector<int> fromWordIdsV(descriptorsFrom.rows);
|
||||||
for (int i = 0; i < descriptorsFrom.rows; ++i)
|
for (int i = 0; i < descriptorsFrom.rows; ++i)
|
||||||
@@ -1083,10 +1156,66 @@ Transform RegistrationVis::computeTransformationImpl(
|
|||||||
}
|
}
|
||||||
if(descriptorsTo.rows)
|
if(descriptorsTo.rows)
|
||||||
{
|
{
|
||||||
cv::BFMatcher matcher(descriptorsFrom.type()==CV_8U?cv::NORM_HAMMING:cv::NORM_L2SQR, true);
|
|
||||||
std::vector<int> toWordIdsV(descriptorsTo.rows, 0);
|
std::vector<int> toWordIdsV(descriptorsTo.rows, 0);
|
||||||
std::vector<cv::DMatch> matches;
|
std::vector<cv::DMatch> matches;
|
||||||
matcher.match(descriptorsTo, descriptorsFrom, matches);
|
#ifdef RTABMAP_PYMATCHER
|
||||||
|
if(_nnType == 6 && _pyMatcher &&
|
||||||
|
descriptorsTo.cols == descriptorsFrom.cols &&
|
||||||
|
descriptorsTo.rows == (int)kptsTo.size() &&
|
||||||
|
descriptorsTo.type() == CV_32F &&
|
||||||
|
descriptorsFrom.type() == CV_32F &&
|
||||||
|
descriptorsFrom.rows == (int)kptsFrom.size() &&
|
||||||
|
imageSize.width > 0 && imageSize.height > 0)
|
||||||
|
{
|
||||||
|
UDEBUG("Python matching");
|
||||||
|
matches = _pyMatcher->match(descriptorsTo, descriptorsFrom, kptsTo, kptsFrom, imageSize);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(_nnType == 6 && _pyMatcher)
|
||||||
|
{
|
||||||
|
UDEBUG("Invalid inputs for Python matching (desc type=%d, only float descriptors supported), doing bruteforce matching instead.", descriptorsFrom.type());
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
bool doCrossCheck = true;
|
||||||
|
#ifdef HAVE_OPENCV_XFEATURES2D
|
||||||
|
#if CV_MAJOR_VERSION > 3 || (CV_MAJOR_VERSION==3 && CV_MINOR_VERSION >=4 && CV_SUBMINOR_VERSION >= 1)
|
||||||
|
cv::Size imageSizeFrom;
|
||||||
|
if(_nnType == 7)
|
||||||
|
{
|
||||||
|
imageSizeFrom = imageFrom.size();
|
||||||
|
if(imageSizeFrom.height == 0 || imageSizeFrom.width == 0)
|
||||||
|
{
|
||||||
|
imageSizeFrom = fromSignature.sensorData().cameraModels().size() == 1?fromSignature.sensorData().cameraModels()[0].imageSize():fromSignature.sensorData().stereoCameraModel().left().imageSize();
|
||||||
|
}
|
||||||
|
if(imageSize.height > 0 && imageSize.width > 0 &&
|
||||||
|
imageSizeFrom.height > 0 && imageSizeFrom.width > 0)
|
||||||
|
{
|
||||||
|
doCrossCheck = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UDEBUG("Invalid inputs for GMS matching, image size should be set for both inputs, doing bruteforce matching instead.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
UDEBUG("BruteForce matching%s", _nnType!=7?" with crosscheck":" with GMS");
|
||||||
|
cv::BFMatcher matcher(descriptorsFrom.type()==CV_8U?cv::NORM_HAMMING:cv::NORM_L2SQR, doCrossCheck);
|
||||||
|
matcher.match(descriptorsTo, descriptorsFrom, matches);
|
||||||
|
|
||||||
|
#if defined(HAVE_OPENCV_XFEATURES2D) && (CV_MAJOR_VERSION > 3 || (CV_MAJOR_VERSION==3 && CV_MINOR_VERSION >=4 && CV_SUBMINOR_VERSION >= 1))
|
||||||
|
if(!doCrossCheck)
|
||||||
|
{
|
||||||
|
std::vector<cv::DMatch> matchesGMS;
|
||||||
|
cv::xfeatures2d::matchGMS(imageSize, imageSizeFrom, kptsTo, kptsFrom, matches, matchesGMS, _gmsWithRotation, _gmsWithScale, _gmsThresholdFactor);
|
||||||
|
matches = matchesGMS;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
for(size_t i=0; i<matches.size(); ++i)
|
for(size_t i=0; i<matches.size(); ++i)
|
||||||
{
|
{
|
||||||
toWordIdsV[matches[i].queryIdx] = fromWordIdsV[matches[i].trainIdx];
|
toWordIdsV[matches[i].queryIdx] = fromWordIdsV[matches[i].trainIdx];
|
||||||
@@ -1104,6 +1233,7 @@ Transform RegistrationVis::computeTransformationImpl(
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
UDEBUG("VWDictionary knn matching");
|
||||||
VWDictionary dictionary(_featureParameters);
|
VWDictionary dictionary(_featureParameters);
|
||||||
if(orignalWordsFromIds.empty())
|
if(orignalWordsFromIds.empty())
|
||||||
{
|
{
|
||||||
@@ -1241,21 +1371,20 @@ Transform RegistrationVis::computeTransformationImpl(
|
|||||||
// we only need the camera transform, send guess words3 for scale estimation
|
// we only need the camera transform, send guess words3 for scale estimation
|
||||||
Transform cameraTransform;
|
Transform cameraTransform;
|
||||||
double variance = 1.0f;
|
double variance = 1.0f;
|
||||||
|
std::vector<int> matchesV;
|
||||||
std::map<int, cv::Point3f> inliers3D = util3d::generateWords3DMono(
|
std::map<int, cv::Point3f> inliers3D = util3d::generateWords3DMono(
|
||||||
uMultimapToMapUnique(signatureA->getWords()),
|
uMultimapToMapUnique(signatureA->getWords()),
|
||||||
uMultimapToMapUnique(signatureB->getWords()),
|
uMultimapToMapUnique(signatureB->getWords()),
|
||||||
cameraModel,
|
cameraModel,
|
||||||
cameraTransform,
|
cameraTransform,
|
||||||
_iterations,
|
|
||||||
_PnPReprojError,
|
_PnPReprojError,
|
||||||
_PnPFlags, // cv::SOLVEPNP_ITERATIVE
|
|
||||||
_PnPRefineIterations,
|
|
||||||
1.0f,
|
|
||||||
0.99f,
|
0.99f,
|
||||||
uMultimapToMapUnique(signatureA->getWords3()), // for scale estimation
|
uMultimapToMapUnique(signatureA->getWords3()), // for scale estimation
|
||||||
&variance);
|
&variance,
|
||||||
|
&matchesV);
|
||||||
covariances[dir] *= variance;
|
covariances[dir] *= variance;
|
||||||
inliers[dir] = uKeys(inliers3D);
|
inliers[dir] = uKeys(inliers3D);
|
||||||
|
matches[dir] = matchesV;
|
||||||
|
|
||||||
if(!cameraTransform.isNull())
|
if(!cameraTransform.isNull())
|
||||||
{
|
{
|
||||||
@@ -1274,7 +1403,7 @@ Transform RegistrationVis::computeTransformationImpl(
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
msg = uFormat("Variance is too high! (max inlier distance=%f, variance=%f)", _epipolarGeometryVar, variance);
|
msg = uFormat("Variance is too high! (Max %s=%f, variance=%f)", Parameters::kVisEpipolarGeometryVar().c_str(), _epipolarGeometryVar, variance);
|
||||||
UINFO(msg.c_str());
|
UINFO(msg.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1752,7 +1881,7 @@ Transform RegistrationVis::computeTransformationImpl(
|
|||||||
}
|
}
|
||||||
else if(toSignature.sensorData().isValid())
|
else if(toSignature.sensorData().isValid())
|
||||||
{
|
{
|
||||||
UWARN("Missing correspondences for registration (%d->%d). fromWords = %d fromImageEmpty=%d toWords = %d toImageEmpty=%d",
|
msg = uFormat("Missing correspondences for registration (%d->%d). fromWords = %d fromImageEmpty=%d toWords = %d toImageEmpty=%d",
|
||||||
fromSignature.id(), toSignature.id(),
|
fromSignature.id(), toSignature.id(),
|
||||||
(int)fromSignature.getWords().size(), fromSignature.sensorData().imageRaw().empty()?1:0,
|
(int)fromSignature.getWords().size(), fromSignature.sensorData().imageRaw().empty()?1:0,
|
||||||
(int)toSignature.getWords().size(), toSignature.sensorData().imageRaw().empty()?1:0);
|
(int)toSignature.getWords().size(), toSignature.sensorData().imageRaw().empty()?1:0);
|
||||||
@@ -1763,6 +1892,7 @@ Transform RegistrationVis::computeTransformationImpl(
|
|||||||
info.rejectedMsg = msg;
|
info.rejectedMsg = msg;
|
||||||
info.covariance = covariance;
|
info.covariance = covariance;
|
||||||
|
|
||||||
|
UDEBUG("inliers=%d/%d", info.inliers, info.matches);
|
||||||
UDEBUG("transform=%s", transform.prettyPrint().c_str());
|
UDEBUG("transform=%s", transform.prettyPrint().c_str());
|
||||||
return transform;
|
return transform;
|
||||||
}
|
}
|
||||||
|
|||||||
+529
-385
File diff suppressed because it is too large
Load Diff
@@ -128,6 +128,7 @@ void RtabmapThread::close(bool databaseSaved, const std::string & ouputDatabaseP
|
|||||||
|
|
||||||
void RtabmapThread::publishMap(bool optimized, bool full, bool graphOnly) const
|
void RtabmapThread::publishMap(bool optimized, bool full, bool graphOnly) const
|
||||||
{
|
{
|
||||||
|
UDEBUG("optimized=%s, full=%s, graphOnly=%s", optimized?"true":"false", full?"true":"false", graphOnly?"true":"false");
|
||||||
if(_rtabmap)
|
if(_rtabmap)
|
||||||
{
|
{
|
||||||
std::map<int, Signature> signatures;
|
std::map<int, Signature> signatures;
|
||||||
@@ -138,23 +139,15 @@ void RtabmapThread::publishMap(bool optimized, bool full, bool graphOnly) const
|
|||||||
std::map<int, std::string> labels;
|
std::map<int, std::string> labels;
|
||||||
std::map<int, std::vector<unsigned char> > userDatas;
|
std::map<int, std::vector<unsigned char> > userDatas;
|
||||||
|
|
||||||
if(graphOnly)
|
_rtabmap->getGraph(poses,
|
||||||
{
|
constraints,
|
||||||
_rtabmap->getGraph(poses,
|
optimized,
|
||||||
constraints,
|
full,
|
||||||
optimized,
|
&signatures,
|
||||||
full,
|
!graphOnly,
|
||||||
&signatures);
|
!graphOnly,
|
||||||
}
|
!graphOnly,
|
||||||
else
|
!graphOnly);
|
||||||
{
|
|
||||||
_rtabmap->get3DMap(
|
|
||||||
signatures,
|
|
||||||
poses,
|
|
||||||
constraints,
|
|
||||||
optimized,
|
|
||||||
full);
|
|
||||||
}
|
|
||||||
|
|
||||||
this->post(new RtabmapEvent3DMap(
|
this->post(new RtabmapEvent3DMap(
|
||||||
signatures,
|
signatures,
|
||||||
@@ -217,7 +210,6 @@ void RtabmapThread::mainLoop()
|
|||||||
Parameters::parse(parameters, Parameters::kRtabmapImageBufferSize(), _dataBufferMaxSize);
|
Parameters::parse(parameters, Parameters::kRtabmapImageBufferSize(), _dataBufferMaxSize);
|
||||||
Parameters::parse(parameters, Parameters::kRtabmapDetectionRate(), _rate);
|
Parameters::parse(parameters, Parameters::kRtabmapDetectionRate(), _rate);
|
||||||
Parameters::parse(parameters, Parameters::kRtabmapCreateIntermediateNodes(), _createIntermediateNodes);
|
Parameters::parse(parameters, Parameters::kRtabmapCreateIntermediateNodes(), _createIntermediateNodes);
|
||||||
UASSERT(_dataBufferMaxSize >= 0);
|
|
||||||
UASSERT(_rate >= 0.0f);
|
UASSERT(_rate >= 0.0f);
|
||||||
_rtabmap->init(parameters, str);
|
_rtabmap->init(parameters, str);
|
||||||
break;
|
break;
|
||||||
@@ -225,7 +217,6 @@ void RtabmapThread::mainLoop()
|
|||||||
Parameters::parse(parameters, Parameters::kRtabmapImageBufferSize(), _dataBufferMaxSize);
|
Parameters::parse(parameters, Parameters::kRtabmapImageBufferSize(), _dataBufferMaxSize);
|
||||||
Parameters::parse(parameters, Parameters::kRtabmapDetectionRate(), _rate);
|
Parameters::parse(parameters, Parameters::kRtabmapDetectionRate(), _rate);
|
||||||
Parameters::parse(parameters, Parameters::kRtabmapCreateIntermediateNodes(), _createIntermediateNodes);
|
Parameters::parse(parameters, Parameters::kRtabmapCreateIntermediateNodes(), _createIntermediateNodes);
|
||||||
UASSERT(_dataBufferMaxSize >= 0);
|
|
||||||
UASSERT(_rate >= 0.0f);
|
UASSERT(_rate >= 0.0f);
|
||||||
_rtabmap->parseParameters(parameters);
|
_rtabmap->parseParameters(parameters);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -279,47 +279,50 @@ void VWDictionary::setFixedDictionary(const std::string & dictionaryPath)
|
|||||||
|
|
||||||
void VWDictionary::setNNStrategy(NNStrategy strategy)
|
void VWDictionary::setNNStrategy(NNStrategy strategy)
|
||||||
{
|
{
|
||||||
if(strategy!=kNNUndef)
|
|
||||||
{
|
|
||||||
#if CV_MAJOR_VERSION < 3
|
#if CV_MAJOR_VERSION < 3
|
||||||
#ifdef HAVE_OPENCV_GPU
|
#ifdef HAVE_OPENCV_GPU
|
||||||
if(strategy == kNNBruteForceGPU && !cv::gpu::getCudaEnabledDeviceCount())
|
if(strategy == kNNBruteForceGPU && !cv::gpu::getCudaEnabledDeviceCount())
|
||||||
{
|
{
|
||||||
UERROR("Nearest neighobr strategy \"kNNBruteForceGPU\" chosen but no CUDA devices found! Doing \"kNNBruteForce\" instead.");
|
UERROR("Nearest neighobr strategy \"kNNBruteForceGPU\" chosen but no CUDA devices found! Doing \"kNNBruteForce\" instead.");
|
||||||
strategy = kNNBruteForce;
|
strategy = kNNBruteForce;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if(strategy == kNNBruteForceGPU)
|
if(strategy == kNNBruteForceGPU)
|
||||||
{
|
{
|
||||||
UERROR("Nearest neighobr strategy \"kNNBruteForceGPU\" chosen but OpenCV is not built with GPU/cuda module! Doing \"kNNBruteForce\" instead.");
|
UERROR("Nearest neighobr strategy \"kNNBruteForceGPU\" chosen but OpenCV is not built with GPU/cuda module! Doing \"kNNBruteForce\" instead.");
|
||||||
strategy = kNNBruteForce;
|
strategy = kNNBruteForce;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
#ifdef HAVE_OPENCV_CUDAFEATURES2D
|
#ifdef HAVE_OPENCV_CUDAFEATURES2D
|
||||||
if(strategy == kNNBruteForceGPU && !cv::cuda::getCudaEnabledDeviceCount())
|
if(strategy == kNNBruteForceGPU && !cv::cuda::getCudaEnabledDeviceCount())
|
||||||
{
|
{
|
||||||
UERROR("Nearest neighobr strategy \"kNNBruteForceGPU\" chosen but no CUDA devices found! Doing \"kNNBruteForce\" instead.");
|
UERROR("Nearest neighobr strategy \"kNNBruteForceGPU\" chosen but no CUDA devices found! Doing \"kNNBruteForce\" instead.");
|
||||||
strategy = kNNBruteForce;
|
strategy = kNNBruteForce;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if(strategy == kNNBruteForceGPU)
|
if(strategy == kNNBruteForceGPU)
|
||||||
{
|
{
|
||||||
UERROR("Nearest neighobr strategy \"kNNBruteForceGPU\" chosen but OpenCV cudafeatures2d module is not found! Doing \"kNNBruteForce\" instead.");
|
UERROR("Nearest neighobr strategy \"kNNBruteForceGPU\" chosen but OpenCV cudafeatures2d module is not found! Doing \"kNNBruteForce\" instead.");
|
||||||
strategy = kNNBruteForce;
|
strategy = kNNBruteForce;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool update = _strategy != strategy;
|
if(strategy>=kNNUndef)
|
||||||
_strategy = strategy;
|
{
|
||||||
if(update)
|
UERROR("Nearest neighobr strategy \"%d\" chosen but this strategy cannot be used with a dictionary! Doing \"kNNBruteForce\" instead.");
|
||||||
{
|
strategy = kNNBruteForce;
|
||||||
_dataTree = cv::Mat();
|
}
|
||||||
_notIndexedWords = uKeysSet(_visualWords);
|
|
||||||
_removedIndexedWords.clear();
|
bool update = _strategy != strategy;
|
||||||
this->update();
|
_strategy = strategy;
|
||||||
}
|
if(update)
|
||||||
|
{
|
||||||
|
_dataTree = cv::Mat();
|
||||||
|
_notIndexedWords = uKeysSet(_visualWords);
|
||||||
|
_removedIndexedWords.clear();
|
||||||
|
this->update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -473,8 +473,10 @@ SensorData CameraFreenect::captureImage(CameraInfo * info)
|
|||||||
freenectDevice_->getAccelerometerValues(x,y,z);
|
freenectDevice_->getAccelerometerValues(x,y,z);
|
||||||
if(x != 0.0 && y != 0.0 && z != 0.0)
|
if(x != 0.0 && y != 0.0 && z != 0.0)
|
||||||
{
|
{
|
||||||
// frame of imu on kinect is x->right, y->down, z->backward
|
Transform opticalTransform(0,-1,0,0, 0,0,-1,0, 1,0,0,0);
|
||||||
data.setIMU(IMU(cv::Vec3d(0,0,0), cv::Mat(), cv::Vec3d(x, y, z), cv::Mat(), Transform(0,0,-1,0, -1,0,0,0, 0,-1,0,0)));
|
Transform base = this->getLocalTransform()*opticalTransform;
|
||||||
|
// frame of imu on kinect is x->left, y->up, z->forward
|
||||||
|
data.setIMU(IMU(cv::Vec3d(0,0,0), cv::Mat(), cv::Vec3d(x, y, z), cv::Mat(), base*Transform(0,0,1,0, 1,0,0,0, 0,1,0,0)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,12 +4,12 @@ All rights reserved.
|
|||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
modification, are permitted provided that the following conditions are met:
|
modification, are permitted provided that the following conditions are met:
|
||||||
* Redistributions of source code must retain the above copyright
|
* Redistributions of source code must retain the above copyright
|
||||||
notice, this list of conditions and the following disclaimer.
|
notice, this list of conditions and the following disclaimer.
|
||||||
* Redistributions in binary form must reproduce the above copyright
|
* Redistributions in binary form must reproduce the above copyright
|
||||||
notice, this list of conditions and the following disclaimer in the
|
notice, this list of conditions and the following disclaimer in the
|
||||||
documentation and/or other materials provided with the distribution.
|
documentation and/or other materials provided with the distribution.
|
||||||
* Neither the name of the Universite de Sherbrooke nor the
|
* Neither the name of the Universite de Sherbrooke nor the
|
||||||
names of its contributors may be used to endorse or promote products
|
names of its contributors may be used to endorse or promote products
|
||||||
derived from this software without specific prior written permission.
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
@@ -22,7 +22,7 @@ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|||||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <rtabmap/core/camera/CameraK4A.h>
|
#include <rtabmap/core/camera/CameraK4A.h>
|
||||||
#include <rtabmap/utilite/UTimer.h>
|
#include <rtabmap/utilite/UTimer.h>
|
||||||
@@ -49,33 +49,47 @@ bool CameraK4A::available()
|
|||||||
}
|
}
|
||||||
|
|
||||||
CameraK4A::CameraK4A(
|
CameraK4A::CameraK4A(
|
||||||
int deviceId,
|
int deviceId,
|
||||||
float imageRate,
|
float imageRate,
|
||||||
const Transform & localTransform) :
|
const Transform & localTransform) :
|
||||||
Camera(imageRate, localTransform)
|
Camera(imageRate, localTransform)
|
||||||
#ifdef RTABMAP_K4A
|
#ifdef RTABMAP_K4A
|
||||||
,playbackHandle_(NULL),
|
,
|
||||||
transformationHandle_(NULL),
|
device_(NULL),
|
||||||
deviceId_(deviceId),
|
config_(K4A_DEVICE_CONFIG_INIT_DISABLE_ALL),
|
||||||
ir_(false),
|
transformation_(NULL),
|
||||||
previousStamp_(0.0)
|
capture_(NULL),
|
||||||
|
playbackHandle_(NULL),
|
||||||
|
transformationHandle_(NULL),
|
||||||
|
deviceId_(deviceId),
|
||||||
|
rgb_resolution_(0),
|
||||||
|
framerate_(2),
|
||||||
|
depth_resolution_(2),
|
||||||
|
ir_(false),
|
||||||
|
previousStamp_(0.0)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
UERROR("CameraK4A: Live camera stream is not yet supported, only recorded mkv files are.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CameraK4A::CameraK4A(
|
CameraK4A::CameraK4A(
|
||||||
const std::string & fileName,
|
const std::string & fileName,
|
||||||
float imageRate,
|
float imageRate,
|
||||||
const Transform & localTransform) :
|
const Transform & localTransform) :
|
||||||
Camera(imageRate, localTransform)
|
Camera(imageRate, localTransform)
|
||||||
#ifdef RTABMAP_K4A
|
#ifdef RTABMAP_K4A
|
||||||
,playbackHandle_(NULL),
|
,
|
||||||
transformationHandle_(NULL),
|
device_(NULL),
|
||||||
deviceId_(-1),
|
transformation_(NULL),
|
||||||
fileName_(fileName),
|
capture_(NULL),
|
||||||
ir_(false),
|
playbackHandle_(NULL),
|
||||||
previousStamp_(0.0)
|
transformationHandle_(NULL),
|
||||||
|
deviceId_(-1),
|
||||||
|
fileName_(fileName),
|
||||||
|
rgb_resolution_(0),
|
||||||
|
framerate_(2),
|
||||||
|
depth_resolution_(2),
|
||||||
|
ir_(false),
|
||||||
|
previousStamp_(0.0)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -88,19 +102,48 @@ CameraK4A::~CameraK4A()
|
|||||||
void CameraK4A::close()
|
void CameraK4A::close()
|
||||||
{
|
{
|
||||||
#ifdef RTABMAP_K4A
|
#ifdef RTABMAP_K4A
|
||||||
if (playbackHandle_ != NULL)
|
if (!fileName_.empty())
|
||||||
{
|
{
|
||||||
k4a_playback_close((k4a_playback_t)playbackHandle_);
|
if (playbackHandle_ != NULL)
|
||||||
|
{
|
||||||
|
k4a_playback_close((k4a_playback_t)playbackHandle_);
|
||||||
|
playbackHandle_ = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (transformationHandle_ != NULL)
|
||||||
|
{
|
||||||
|
k4a_transformation_destroy((k4a_transformation_t)transformationHandle_);
|
||||||
|
transformationHandle_ = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (transformationHandle_ != NULL)
|
else
|
||||||
{
|
{
|
||||||
k4a_transformation_destroy((k4a_transformation_t)transformationHandle_);
|
if (device_ != NULL)
|
||||||
|
{
|
||||||
|
k4a_device_stop_imu(device_);
|
||||||
|
|
||||||
|
if (transformation_ != NULL)
|
||||||
|
{
|
||||||
|
k4a_transformation_destroy(transformation_);
|
||||||
|
transformation_ = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
k4a_device_stop_cameras(device_);
|
||||||
|
k4a_device_close(device_);
|
||||||
|
device_ = NULL;
|
||||||
|
config_ = K4A_DEVICE_CONFIG_INIT_DISABLE_ALL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/*
|
#endif
|
||||||
// Shut down the camera when finished with application logic
|
}
|
||||||
k4a_device_stop_cameras(device);
|
|
||||||
k4a_device_close(device);
|
void CameraK4A::setPreferences(int rgb_resolution, int framerate, int depth_resolution)
|
||||||
*/
|
{
|
||||||
|
#ifdef RTABMAP_K4A
|
||||||
|
rgb_resolution_ = rgb_resolution;
|
||||||
|
framerate_ = framerate;
|
||||||
|
depth_resolution_ = depth_resolution;
|
||||||
|
UINFO("setPreferences(): %i %i %i", rgb_resolution, framerate, depth_resolution);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,10 +158,10 @@ bool CameraK4A::init(const std::string & calibrationFolder, const std::string &
|
|||||||
{
|
{
|
||||||
#ifdef RTABMAP_K4A
|
#ifdef RTABMAP_K4A
|
||||||
|
|
||||||
close();
|
|
||||||
|
|
||||||
if (!fileName_.empty())
|
if (!fileName_.empty())
|
||||||
{
|
{
|
||||||
|
close();
|
||||||
|
|
||||||
if (k4a_playback_open(fileName_.c_str(), (k4a_playback_t*)&playbackHandle_) != K4A_RESULT_SUCCEEDED)
|
if (k4a_playback_open(fileName_.c_str(), (k4a_playback_t*)&playbackHandle_) != K4A_RESULT_SUCCEEDED)
|
||||||
{
|
{
|
||||||
UERROR("Failed to open recording \"%s\"", fileName_.c_str());
|
UERROR("Failed to open recording \"%s\"", fileName_.c_str());
|
||||||
@@ -138,29 +181,30 @@ bool CameraK4A::init(const std::string & calibrationFolder, const std::string &
|
|||||||
if (ir_)
|
if (ir_)
|
||||||
{
|
{
|
||||||
model_ = CameraModel(
|
model_ = CameraModel(
|
||||||
calibration.depth_camera_calibration.intrinsics.parameters.param.fx,
|
calibration.depth_camera_calibration.intrinsics.parameters.param.fx,
|
||||||
calibration.depth_camera_calibration.intrinsics.parameters.param.fy,
|
calibration.depth_camera_calibration.intrinsics.parameters.param.fy,
|
||||||
calibration.depth_camera_calibration.intrinsics.parameters.param.cx,
|
calibration.depth_camera_calibration.intrinsics.parameters.param.cx,
|
||||||
calibration.depth_camera_calibration.intrinsics.parameters.param.cy,
|
calibration.depth_camera_calibration.intrinsics.parameters.param.cy,
|
||||||
this->getLocalTransform(),
|
this->getLocalTransform(),
|
||||||
0,
|
0,
|
||||||
cv::Size(calibration.depth_camera_calibration.resolution_width, calibration.depth_camera_calibration.resolution_height));
|
cv::Size(calibration.depth_camera_calibration.resolution_width, calibration.depth_camera_calibration.resolution_height));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
model_ = CameraModel(
|
model_ = CameraModel(
|
||||||
calibration.color_camera_calibration.intrinsics.parameters.param.fx,
|
calibration.color_camera_calibration.intrinsics.parameters.param.fx,
|
||||||
calibration.color_camera_calibration.intrinsics.parameters.param.fy,
|
calibration.color_camera_calibration.intrinsics.parameters.param.fy,
|
||||||
calibration.color_camera_calibration.intrinsics.parameters.param.cx,
|
calibration.color_camera_calibration.intrinsics.parameters.param.cx,
|
||||||
calibration.color_camera_calibration.intrinsics.parameters.param.cy,
|
calibration.color_camera_calibration.intrinsics.parameters.param.cy,
|
||||||
this->getLocalTransform(),
|
this->getLocalTransform(),
|
||||||
0,
|
0,
|
||||||
cv::Size(calibration.color_camera_calibration.resolution_width, calibration.color_camera_calibration.resolution_height));
|
cv::Size(calibration.color_camera_calibration.resolution_width, calibration.color_camera_calibration.resolution_height));
|
||||||
|
|
||||||
transformationHandle_ = k4a_transformation_create(&calibration);
|
transformationHandle_ = k4a_transformation_create(&calibration);
|
||||||
}
|
}
|
||||||
|
|
||||||
k4a_record_configuration_t config;
|
k4a_record_configuration_t config;
|
||||||
|
|
||||||
if (k4a_playback_get_record_configuration((k4a_playback_t)playbackHandle_, &config))
|
if (k4a_playback_get_record_configuration((k4a_playback_t)playbackHandle_, &config))
|
||||||
{
|
{
|
||||||
UERROR("Failed to getting recording configuration");
|
UERROR("Failed to getting recording configuration");
|
||||||
@@ -170,19 +214,58 @@ bool CameraK4A::init(const std::string & calibrationFolder, const std::string &
|
|||||||
}
|
}
|
||||||
else if (deviceId_ >= 0)
|
else if (deviceId_ >= 0)
|
||||||
{
|
{
|
||||||
UERROR("CameraK4A: Live camera stream is not yet supported, only recorded mkv files are.");
|
if(device_!=NULL)
|
||||||
return false;
|
{
|
||||||
|
this->close();
|
||||||
|
}
|
||||||
|
|
||||||
/*uint32_t count = k4a_device_get_installed_count();
|
switch(rgb_resolution_)
|
||||||
if (count == 0)
|
{
|
||||||
|
case 0: config_.color_resolution = K4A_COLOR_RESOLUTION_720P; break;
|
||||||
|
case 1: config_.color_resolution = K4A_COLOR_RESOLUTION_1080P; break;
|
||||||
|
case 2: config_.color_resolution = K4A_COLOR_RESOLUTION_1440P; break;
|
||||||
|
case 3: config_.color_resolution = K4A_COLOR_RESOLUTION_1536P; break;
|
||||||
|
case 4: config_.color_resolution = K4A_COLOR_RESOLUTION_2160P; break;
|
||||||
|
case 5:
|
||||||
|
default: config_.color_resolution = K4A_COLOR_RESOLUTION_3072P; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(framerate_)
|
||||||
|
{
|
||||||
|
case 0: config_.camera_fps = K4A_FRAMES_PER_SECOND_5; break;
|
||||||
|
case 1: config_.camera_fps = K4A_FRAMES_PER_SECOND_15; break;
|
||||||
|
case 2:
|
||||||
|
default: config_.camera_fps = K4A_FRAMES_PER_SECOND_30; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(depth_resolution_)
|
||||||
|
{
|
||||||
|
case 0: config_.depth_mode = K4A_DEPTH_MODE_NFOV_2X2BINNED; break;
|
||||||
|
case 1: config_.depth_mode = K4A_DEPTH_MODE_NFOV_UNBINNED; break;
|
||||||
|
case 2: config_.depth_mode = K4A_DEPTH_MODE_WFOV_2X2BINNED; break;
|
||||||
|
case 3:
|
||||||
|
default: config_.depth_mode = K4A_DEPTH_MODE_WFOV_UNBINNED; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is fixed for now
|
||||||
|
config_.color_format = K4A_IMAGE_FORMAT_COLOR_BGRA32;
|
||||||
|
|
||||||
|
int device_count = k4a_device_get_installed_count();
|
||||||
|
|
||||||
|
if (device_count == 0)
|
||||||
{
|
{
|
||||||
UERROR("No k4a devices attached!");
|
UERROR("No k4a devices attached!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
else if(deviceId_ > device_count)
|
||||||
|
{
|
||||||
|
UERROR("Cannot select device %d, only %d devices detected.", deviceId_, device_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
UINFO("CameraK4A found %d k4a device(s) attached", device_count);
|
||||||
|
|
||||||
// Open the first plugged in Kinect device
|
// Open the first plugged in Kinect device
|
||||||
k4a_device_t device = NULL;
|
if (K4A_FAILED(k4a_device_open(deviceId_, &device_)))
|
||||||
if (K4A_FAILED(k4a_device_open(K4A_DEVICE_DEFAULT, &device)))
|
|
||||||
{
|
{
|
||||||
UERROR("Failed to open k4a device!");
|
UERROR("Failed to open k4a device!");
|
||||||
return false;
|
return false;
|
||||||
@@ -190,29 +273,97 @@ bool CameraK4A::init(const std::string & calibrationFolder, const std::string &
|
|||||||
|
|
||||||
// Get the size of the serial number
|
// Get the size of the serial number
|
||||||
size_t serial_size = 0;
|
size_t serial_size = 0;
|
||||||
k4a_device_get_serialnum(device, NULL, &serial_size);
|
k4a_device_get_serialnum(device_, NULL, &serial_size);
|
||||||
|
|
||||||
// Allocate memory for the serial, then acquire it
|
// Allocate memory for the serial, then acquire it
|
||||||
char *serial = (char*)(malloc(serial_size));
|
char *serial = (char*)(malloc(serial_size));
|
||||||
k4a_device_get_serialnum(device, serial, &serial_size);
|
k4a_device_get_serialnum(device_, serial, &serial_size);
|
||||||
UINFO("Opened device: %s", serial);
|
serial_number_.assign(serial, serial_size);
|
||||||
free(serial);
|
free(serial);
|
||||||
|
|
||||||
// Configure a stream of 4096x3072 BRGA color data at 15 frames per second
|
UINFO("Opened K4A device: %s", serial_number_.c_str());
|
||||||
k4a_device_configuration_t config = K4A_DEVICE_CONFIG_INIT_DISABLE_ALL;
|
|
||||||
config.camera_fps = K4A_FRAMES_PER_SECOND_15;
|
|
||||||
config.color_format = K4A_IMAGE_FORMAT_COLOR_BGRA32;
|
|
||||||
config.color_resolution = K4A_COLOR_RESOLUTION_3072P;
|
|
||||||
|
|
||||||
// Start the camera with the given configuration
|
// Start the camera with the given configuration
|
||||||
if (K4A_FAILED(k4a_device_start_cameras(device, &config)))
|
if (K4A_FAILED(k4a_device_start_cameras(device_, &config_)))
|
||||||
{
|
{
|
||||||
UERROR("Failed to start cameras!");
|
UERROR("Failed to start cameras!");
|
||||||
k4a_device_close(device);
|
close();
|
||||||
return false;
|
return false;
|
||||||
}*/
|
}
|
||||||
|
|
||||||
|
UINFO("K4A camera started successfully");
|
||||||
|
|
||||||
|
if (K4A_FAILED(k4a_device_get_calibration(device_, config_.depth_mode, config_.color_resolution, &calibration_)))
|
||||||
|
{
|
||||||
|
UERROR("k4a_device_get_calibration() failed!");
|
||||||
|
close();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ir_)
|
||||||
|
{
|
||||||
|
model_ = CameraModel(
|
||||||
|
calibration_.depth_camera_calibration.intrinsics.parameters.param.fx,
|
||||||
|
calibration_.depth_camera_calibration.intrinsics.parameters.param.fy,
|
||||||
|
calibration_.depth_camera_calibration.intrinsics.parameters.param.cx,
|
||||||
|
calibration_.depth_camera_calibration.intrinsics.parameters.param.cy,
|
||||||
|
this->getLocalTransform(),
|
||||||
|
0,
|
||||||
|
cv::Size(calibration_.depth_camera_calibration.resolution_width, calibration_.depth_camera_calibration.resolution_height));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
model_ = CameraModel(
|
||||||
|
calibration_.color_camera_calibration.intrinsics.parameters.param.fx,
|
||||||
|
calibration_.color_camera_calibration.intrinsics.parameters.param.fy,
|
||||||
|
calibration_.color_camera_calibration.intrinsics.parameters.param.cx,
|
||||||
|
calibration_.color_camera_calibration.intrinsics.parameters.param.cy,
|
||||||
|
this->getLocalTransform(),
|
||||||
|
0,
|
||||||
|
cv::Size(calibration_.color_camera_calibration.resolution_width, calibration_.color_camera_calibration.resolution_height));
|
||||||
|
}
|
||||||
|
|
||||||
|
transformation_ = k4a_transformation_create(&calibration_);
|
||||||
|
|
||||||
|
// Get imu transform
|
||||||
|
k4a_calibration_extrinsics_t* imu_extrinsics;
|
||||||
|
if(ir_)
|
||||||
|
{
|
||||||
|
imu_extrinsics = &calibration_.extrinsics[K4A_CALIBRATION_TYPE_ACCEL][K4A_CALIBRATION_TYPE_DEPTH];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
imu_extrinsics = &calibration_.extrinsics[K4A_CALIBRATION_TYPE_ACCEL][K4A_CALIBRATION_TYPE_COLOR];
|
||||||
|
}
|
||||||
|
imuLocalTransform_ = Transform(
|
||||||
|
imu_extrinsics->rotation[0], imu_extrinsics->rotation[1], imu_extrinsics->rotation[2], imu_extrinsics->translation[0] / 1000.0f,
|
||||||
|
imu_extrinsics->rotation[3], imu_extrinsics->rotation[4], imu_extrinsics->rotation[5], imu_extrinsics->translation[1] / 1000.0f,
|
||||||
|
imu_extrinsics->rotation[6], imu_extrinsics->rotation[7], imu_extrinsics->rotation[8], imu_extrinsics->translation[2] / 1000.0f);
|
||||||
|
|
||||||
|
UINFO("camera to imu=%s", imuLocalTransform_.prettyPrint().c_str());
|
||||||
|
UINFO("base to camera=%s", this->getLocalTransform().prettyPrint().c_str());
|
||||||
|
imuLocalTransform_ = this->getLocalTransform()*imuLocalTransform_;
|
||||||
|
UINFO("base to imu=%s", imuLocalTransform_.prettyPrint().c_str());
|
||||||
|
|
||||||
|
if (K4A_FAILED(k4a_device_start_imu(device_)))
|
||||||
|
{
|
||||||
|
UERROR("Failed to start K4A IMU");
|
||||||
|
close();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
UINFO("K4a IMU started successfully");
|
||||||
|
|
||||||
|
// Get an initial capture to put the camera in the right state
|
||||||
|
if (K4A_WAIT_RESULT_SUCCEEDED == k4a_device_get_capture(device_, &capture_, K4A_WAIT_INFINITE))
|
||||||
|
{
|
||||||
|
k4a_capture_release(capture_);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
close();
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
#else
|
#else
|
||||||
UERROR("CameraK4A: RTAB-Map is not built with Kinect for Azure SDK support!");
|
UERROR("CameraK4A: RTAB-Map is not built with Kinect for Azure SDK support!");
|
||||||
@@ -228,7 +379,11 @@ bool CameraK4A::isCalibrated() const
|
|||||||
std::string CameraK4A::getSerial() const
|
std::string CameraK4A::getSerial() const
|
||||||
{
|
{
|
||||||
#ifdef RTABMAP_K4A
|
#ifdef RTABMAP_K4A
|
||||||
return fileName_.empty()?"":fileName_;
|
if(!fileName_.empty())
|
||||||
|
{
|
||||||
|
return fileName_;
|
||||||
|
}
|
||||||
|
return(serial_number_);
|
||||||
#else
|
#else
|
||||||
return "";
|
return "";
|
||||||
#endif
|
#endif
|
||||||
@@ -405,7 +560,7 @@ SensorData CameraK4A::captureImage(CameraInfo * info)
|
|||||||
if (sleepTime > 10000)
|
if (sleepTime > 10000)
|
||||||
{
|
{
|
||||||
UWARN("Detected long delay (%d sec, stamps = %f vs %f). Waiting a maximum of 10 seconds.",
|
UWARN("Detected long delay (%d sec, stamps = %f vs %f). Waiting a maximum of 10 seconds.",
|
||||||
sleepTime / 1000, previousStamp_, stamp);
|
sleepTime / 1000, previousStamp_, stamp);
|
||||||
sleepTime = 10000;
|
sleepTime = 10000;
|
||||||
}
|
}
|
||||||
if (sleepTime > 2)
|
if (sleepTime > 2)
|
||||||
@@ -443,9 +598,129 @@ SensorData CameraK4A::captureImage(CameraInfo * info)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
UERROR("CameraK4A: Live camera stream is not yet supported, only recorded mkv files are.");
|
k4a_image_t ir_image_ = NULL;
|
||||||
}
|
k4a_image_t rgb_image_ = NULL;
|
||||||
|
k4a_imu_sample_t imu_sample_;
|
||||||
|
|
||||||
|
double t = UTimer::now();
|
||||||
|
k4a_wait_result_t result = K4A_WAIT_RESULT_FAILED;
|
||||||
|
while((UTimer::now()-t < 5.0) &&
|
||||||
|
(K4A_WAIT_RESULT_SUCCEEDED != (result=k4a_device_get_capture(device_, &capture_, K4A_WAIT_INFINITE)) ||
|
||||||
|
((ir_ && (ir_image_=k4a_capture_get_ir_image(capture_)) == NULL) || (!ir_ && (rgb_image_=k4a_capture_get_color_image(capture_)) == NULL))))
|
||||||
|
{
|
||||||
|
k4a_capture_release(capture_);
|
||||||
|
// the first frame may be null, just retry for 5 seconds
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result == K4A_WAIT_RESULT_SUCCEEDED && (rgb_image_!=NULL || ir_image_!=NULL))
|
||||||
|
{
|
||||||
|
cv::Mat bgrCV;
|
||||||
|
cv::Mat depthCV;
|
||||||
|
IMU imu;
|
||||||
|
|
||||||
|
if (ir_image_ != NULL)
|
||||||
|
{
|
||||||
|
// Convert IR image
|
||||||
|
cv::Mat bgrCV16(k4a_image_get_height_pixels(ir_image_),
|
||||||
|
k4a_image_get_width_pixels(ir_image_),
|
||||||
|
CV_16UC1,
|
||||||
|
(void*)k4a_image_get_buffer(ir_image_));
|
||||||
|
|
||||||
|
bgrCV16.convertTo(bgrCV, CV_8U);
|
||||||
|
|
||||||
|
// Release the image
|
||||||
|
k4a_image_release(ir_image_);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Convert RGB image
|
||||||
|
if (k4a_image_get_format(rgb_image_) == K4A_IMAGE_FORMAT_COLOR_MJPG)
|
||||||
|
{
|
||||||
|
bgrCV = uncompressImage(cv::Mat(1, (int)k4a_image_get_size(rgb_image_),
|
||||||
|
CV_8UC1,
|
||||||
|
(void*)k4a_image_get_buffer(rgb_image_)));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cv::Mat bgra(k4a_image_get_height_pixels(rgb_image_),
|
||||||
|
k4a_image_get_width_pixels(rgb_image_),
|
||||||
|
CV_8UC4,
|
||||||
|
(void*)k4a_image_get_buffer(rgb_image_));
|
||||||
|
|
||||||
|
cv::cvtColor(bgra, bgrCV, CV_BGRA2BGR);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Release the image
|
||||||
|
k4a_image_release(rgb_image_);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!bgrCV.empty())
|
||||||
|
{
|
||||||
|
// Retrieve depth image from capture
|
||||||
|
k4a_image_t depth_image_ = k4a_capture_get_depth_image(capture_);
|
||||||
|
|
||||||
|
if (depth_image_ != NULL)
|
||||||
|
{
|
||||||
|
if (ir_)
|
||||||
|
{
|
||||||
|
depthCV = cv::Mat(k4a_image_get_height_pixels(depth_image_),
|
||||||
|
k4a_image_get_width_pixels(depth_image_),
|
||||||
|
CV_16UC1,
|
||||||
|
(void*)k4a_image_get_buffer(depth_image_)).clone();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
k4a_image_t transformedDepth = NULL;
|
||||||
|
if (k4a_image_create(k4a_image_get_format(depth_image_),
|
||||||
|
bgrCV.cols, bgrCV.rows, bgrCV.cols * 2, &transformedDepth) == K4A_RESULT_SUCCEEDED)
|
||||||
|
{
|
||||||
|
if(k4a_transformation_depth_image_to_color_camera(transformation_, depth_image_, transformedDepth) == K4A_RESULT_SUCCEEDED)
|
||||||
|
{
|
||||||
|
depthCV = cv::Mat(k4a_image_get_height_pixels(transformedDepth),
|
||||||
|
k4a_image_get_width_pixels(transformedDepth),
|
||||||
|
CV_16UC1,
|
||||||
|
(void*)k4a_image_get_buffer(transformedDepth)).clone();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UERROR("K4A failed to register depth image");
|
||||||
|
}
|
||||||
|
|
||||||
|
k4a_image_release(transformedDepth);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UERROR("K4A failed to allocate registered depth image");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
k4a_image_release(depth_image_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
k4a_capture_release(capture_);
|
||||||
|
|
||||||
|
// Get IMU sample, clear buffer
|
||||||
|
if(K4A_WAIT_RESULT_SUCCEEDED == k4a_device_get_imu_sample(device_, &imu_sample_, 60))
|
||||||
|
{
|
||||||
|
imu = IMU(cv::Vec3d(imu_sample_.gyro_sample.xyz.x, imu_sample_.gyro_sample.xyz.y, imu_sample_.gyro_sample.xyz.z),
|
||||||
|
cv::Mat::eye(3, 3, CV_64FC1),
|
||||||
|
cv::Vec3d(imu_sample_.acc_sample.xyz.x, imu_sample_.acc_sample.xyz.y, imu_sample_.acc_sample.xyz.z),
|
||||||
|
cv::Mat::eye(3, 3, CV_64FC1),
|
||||||
|
imuLocalTransform_);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UERROR("IMU data NULL");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Relay the data to rtabmap
|
||||||
|
if (!bgrCV.empty() && !depthCV.empty())
|
||||||
|
{
|
||||||
|
data = SensorData(bgrCV, depthCV, model_, this->getNextSeqID(), UTimer::now());
|
||||||
|
data.setIMU(imu);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
UERROR("CameraK4A: RTAB-Map is not built with Kinect for Azure SDK support!");
|
UERROR("CameraK4A: RTAB-Map is not built with Kinect for Azure SDK support!");
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -33,6 +33,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <mynteye/api.h>
|
#include <mynteye/api.h>
|
||||||
#include <mynteye/device.h>
|
#include <mynteye/device.h>
|
||||||
#include <mynteye/context.h>
|
#include <mynteye/context.h>
|
||||||
|
|
||||||
|
#ifndef M_PI
|
||||||
|
#define M_PI 3.14159265358979323846
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace rtabmap
|
namespace rtabmap
|
||||||
@@ -45,13 +49,17 @@ CameraMyntEye::CameraMyntEye(const std::string & device, bool apiRectification,
|
|||||||
deviceName_(device),
|
deviceName_(device),
|
||||||
apiRectification_(apiRectification),
|
apiRectification_(apiRectification),
|
||||||
apiDepth_(apiDepth),
|
apiDepth_(apiDepth),
|
||||||
|
autoExposure_(true),
|
||||||
|
gain_(24),
|
||||||
|
brightness_(120),
|
||||||
|
contrast_(116),
|
||||||
dataReady_(0),
|
dataReady_(0),
|
||||||
lastFramesStamp_(0.0),
|
lastFramesStamp_(0.0),
|
||||||
stamp_(0),
|
stamp_(0),
|
||||||
publishInterIMU_(false),
|
publishInterIMU_(false),
|
||||||
softTimeBegin_(0.0),
|
softTimeBegin_(0.0),
|
||||||
hardTimeBegin_(0),
|
hardTimeBegin_(0),
|
||||||
unitHardTime(std::numeric_limits<std::uint32_t>::max()*10)
|
unitHardTime_(std::numeric_limits<std::uint32_t>::max()*10)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
#ifdef RTABMAP_MYNTEYE
|
#ifdef RTABMAP_MYNTEYE
|
||||||
@@ -133,13 +141,13 @@ inline bool is_overflow(std::uint64_t now, std::uint64_t pre, std::uint64_t unit
|
|||||||
|
|
||||||
double CameraMyntEye::checkUpTimeStamp(std::uint64_t _hard_time, std::uint8_t stream) {
|
double CameraMyntEye::checkUpTimeStamp(std::uint64_t _hard_time, std::uint8_t stream) {
|
||||||
UASSERT(stream < (std::uint8_t)mynteye::Stream::LAST+1);
|
UASSERT(stream < (std::uint8_t)mynteye::Stream::LAST+1);
|
||||||
if (is_overflow(_hard_time, lastHardTimes_[stream], unitHardTime)) {
|
if (is_overflow(_hard_time, lastHardTimes_[stream], unitHardTime_)) {
|
||||||
acc_[stream]++;
|
acc_[stream]++;
|
||||||
}
|
}
|
||||||
|
|
||||||
lastHardTimes_[stream] = _hard_time;
|
lastHardTimes_[stream] = _hard_time;
|
||||||
|
|
||||||
return hardTimeToSoftTime(acc_[stream] * unitHardTime + _hard_time);
|
return hardTimeToSoftTime(acc_[stream] * unitHardTime_ + _hard_time);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -150,6 +158,34 @@ void CameraMyntEye::publishInterIMU(bool enabled)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CameraMyntEye::setAutoExposure()
|
||||||
|
{
|
||||||
|
#ifdef RTABMAP_MYNTEYE
|
||||||
|
autoExposure_ = true;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void CameraMyntEye::setManualExposure(int gain, int brightness, int constrast)
|
||||||
|
{
|
||||||
|
#ifdef RTABMAP_MYNTEYE
|
||||||
|
UASSERT(gain>=0 && gain<=48);
|
||||||
|
UASSERT(brightness>=0 && brightness<=240);
|
||||||
|
UASSERT(constrast>=0 && constrast<=254);
|
||||||
|
autoExposure_ = false;
|
||||||
|
gain_ = gain;
|
||||||
|
brightness_ = brightness;
|
||||||
|
contrast_ = constrast;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void CameraMyntEye::setIrControl(int value)
|
||||||
|
{
|
||||||
|
#ifdef RTABMAP_MYNTEYE
|
||||||
|
UASSERT(value>=0 && value<=160);
|
||||||
|
irControl_ = value;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
bool CameraMyntEye::init(const std::string & calibrationFolder, const std::string & cameraName)
|
bool CameraMyntEye::init(const std::string & calibrationFolder, const std::string & cameraName)
|
||||||
{
|
{
|
||||||
#ifdef RTABMAP_MYNTEYE
|
#ifdef RTABMAP_MYNTEYE
|
||||||
@@ -430,6 +466,15 @@ bool CameraMyntEye::init(const std::string & calibrationFolder, const std::strin
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
api_->SetOptionValue(mynteye::Option::EXPOSURE_MODE, autoExposure_?0:1);
|
||||||
|
if(!autoExposure_)
|
||||||
|
{
|
||||||
|
api_->SetOptionValue(mynteye::Option::GAIN, gain_);
|
||||||
|
api_->SetOptionValue(mynteye::Option::BRIGHTNESS, brightness_);
|
||||||
|
api_->SetOptionValue(mynteye::Option::CONTRAST, contrast_);
|
||||||
|
}
|
||||||
|
api_->SetOptionValue(mynteye::Option::IR_CONTROL, irControl_);
|
||||||
|
|
||||||
api_->Start(mynteye::Source::ALL);
|
api_->Start(mynteye::Source::ALL);
|
||||||
uSleep(500); // To buffer some imus before sending images
|
uSleep(500); // To buffer some imus before sending images
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -76,10 +76,17 @@ CameraOpenni::~CameraOpenni()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#ifdef RTABMAP_OPENNI
|
#ifdef RTABMAP_OPENNI
|
||||||
|
#if PCL_VERSION_COMPARE(>=, 1, 10, 0)
|
||||||
|
void CameraOpenni::image_cb (
|
||||||
|
const std::shared_ptr<openni_wrapper::Image>& rgb,
|
||||||
|
const std::shared_ptr<openni_wrapper::DepthImage>& depth,
|
||||||
|
float constant)
|
||||||
|
#else
|
||||||
void CameraOpenni::image_cb (
|
void CameraOpenni::image_cb (
|
||||||
const boost::shared_ptr<openni_wrapper::Image>& rgb,
|
const boost::shared_ptr<openni_wrapper::Image>& rgb,
|
||||||
const boost::shared_ptr<openni_wrapper::DepthImage>& depth,
|
const boost::shared_ptr<openni_wrapper::DepthImage>& depth,
|
||||||
float constant)
|
float constant)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
UScopeMutex s(dataMutex_);
|
UScopeMutex s(dataMutex_);
|
||||||
|
|
||||||
@@ -123,10 +130,17 @@ bool CameraOpenni::init(const std::string & calibrationFolder, const std::string
|
|||||||
interface_ = new pcl::OpenNIGrabber(deviceId_);
|
interface_ = new pcl::OpenNIGrabber(deviceId_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if PCL_VERSION_COMPARE(>=, 1, 10, 0)
|
||||||
|
std::function<void (
|
||||||
|
const std::shared_ptr<openni_wrapper::Image>&,
|
||||||
|
const std::shared_ptr<openni_wrapper::DepthImage>&,
|
||||||
|
float)> f = std::bind (&CameraOpenni::image_cb, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
|
||||||
|
#else
|
||||||
boost::function<void (
|
boost::function<void (
|
||||||
const boost::shared_ptr<openni_wrapper::Image>&,
|
const boost::shared_ptr<openni_wrapper::Image>&,
|
||||||
const boost::shared_ptr<openni_wrapper::DepthImage>&,
|
const boost::shared_ptr<openni_wrapper::DepthImage>&,
|
||||||
float)> f = boost::bind (&CameraOpenni::image_cb, this, _1, _2, _3);
|
float)> f = boost::bind (&CameraOpenni::image_cb, this, _1, _2, _3);
|
||||||
|
#endif
|
||||||
connection_ = interface_->registerCallback (f);
|
connection_ = interface_->registerCallback (f);
|
||||||
|
|
||||||
interface_->start ();
|
interface_->start ();
|
||||||
|
|||||||
@@ -77,7 +77,8 @@ CameraRealSense2::CameraRealSense2(
|
|||||||
cameraHeight_(480),
|
cameraHeight_(480),
|
||||||
cameraFps_(30),
|
cameraFps_(30),
|
||||||
publishInterIMU_(false),
|
publishInterIMU_(false),
|
||||||
dualMode_(false)
|
dualMode_(false),
|
||||||
|
closing_(false)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
UDEBUG("");
|
UDEBUG("");
|
||||||
@@ -86,12 +87,15 @@ CameraRealSense2::CameraRealSense2(
|
|||||||
CameraRealSense2::~CameraRealSense2()
|
CameraRealSense2::~CameraRealSense2()
|
||||||
{
|
{
|
||||||
#ifdef RTABMAP_REALSENSE2
|
#ifdef RTABMAP_REALSENSE2
|
||||||
|
closing_ = true;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
UDEBUG("Closing device(s)...");
|
||||||
for(size_t i=0; i<dev_.size(); ++i)
|
for(size_t i=0; i<dev_.size(); ++i)
|
||||||
{
|
{
|
||||||
if(dev_[i])
|
if(dev_[i])
|
||||||
{
|
{
|
||||||
|
UDEBUG("Closing %d sensor(s) from device %d...", (int)dev_[i]->query_sensors().size(), (int)i);
|
||||||
for(rs2::sensor _sensor : dev_[i]->query_sensors())
|
for(rs2::sensor _sensor : dev_[i]->query_sensors())
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -104,6 +108,7 @@ CameraRealSense2::~CameraRealSense2()
|
|||||||
UWARN("%s", error.what());
|
UWARN("%s", error.what());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
dev_[i]->hardware_reset(); // To avoid freezing on some Windows computers in the following destructor
|
||||||
delete dev_[i];
|
delete dev_[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -250,7 +255,7 @@ void CameraRealSense2::getPoseAndIMU(
|
|||||||
{
|
{
|
||||||
if(maxWaitTimeMs > 0)
|
if(maxWaitTimeMs > 0)
|
||||||
{
|
{
|
||||||
UWARN("Could not find poses to interpolate at time %f after waiting %d ms (last is %f)...", stamp, maxWaitTimeMs, poseBuffer_.rbegin()->first);
|
UWARN("Could not find poses to interpolate at image time %f after waiting %d ms (last is %f)...", stamp, maxWaitTimeMs, poseBuffer_.rbegin()->first);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -303,7 +308,7 @@ void CameraRealSense2::getPoseAndIMU(
|
|||||||
{
|
{
|
||||||
if(maxWaitTimeMs>0)
|
if(maxWaitTimeMs>0)
|
||||||
{
|
{
|
||||||
UWARN("Could not find acc data to interpolate at time %f after waiting %d ms (last is %f)...", stamp, maxWaitTimeMs, accBuffer_.rbegin()->first);
|
UWARN("Could not find acc data to interpolate at image time %f after waiting %d ms (last is %f)...", stamp, maxWaitTimeMs, accBuffer_.rbegin()->first);
|
||||||
}
|
}
|
||||||
imuMutex_.unlock();
|
imuMutex_.unlock();
|
||||||
return;
|
return;
|
||||||
@@ -366,7 +371,7 @@ void CameraRealSense2::getPoseAndIMU(
|
|||||||
{
|
{
|
||||||
if(maxWaitTimeMs>0)
|
if(maxWaitTimeMs>0)
|
||||||
{
|
{
|
||||||
UWARN("Could not find gyro data to interpolate at time %f after waiting %d ms (last is %f)...", stamp, maxWaitTimeMs, gyroBuffer_.rbegin()->first);
|
UWARN("Could not find gyro data to interpolate at image time %f after waiting %d ms (last is %f)...", stamp, maxWaitTimeMs, gyroBuffer_.rbegin()->first);
|
||||||
}
|
}
|
||||||
imuMutex_.unlock();
|
imuMutex_.unlock();
|
||||||
return;
|
return;
|
||||||
@@ -519,7 +524,14 @@ bool CameraRealSense2::init(const std::string & calibrationFolder, const std::st
|
|||||||
{
|
{
|
||||||
if (info.was_removed(*dev_[i]))
|
if (info.was_removed(*dev_[i]))
|
||||||
{
|
{
|
||||||
UERROR("The device has been disconnected!");
|
if (closing_)
|
||||||
|
{
|
||||||
|
UDEBUG("The device %d has been disconnected!", i);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UERROR("The device %d has been disconnected!", i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1060,7 +1072,6 @@ SensorData CameraRealSense2::captureImage(CameraInfo * info)
|
|||||||
if (frameset.size() == 2)
|
if (frameset.size() == 2)
|
||||||
{
|
{
|
||||||
double now = UTimer::now();
|
double now = UTimer::now();
|
||||||
UDEBUG("Frameset arrived.");
|
|
||||||
bool is_rgb_arrived = false;
|
bool is_rgb_arrived = false;
|
||||||
bool is_depth_arrived = false;
|
bool is_depth_arrived = false;
|
||||||
bool is_left_fisheye_arrived = false;
|
bool is_left_fisheye_arrived = false;
|
||||||
@@ -1119,6 +1130,7 @@ SensorData CameraRealSense2::captureImage(CameraInfo * info)
|
|||||||
}
|
}
|
||||||
|
|
||||||
stamp /= 1000.0; // put in seconds
|
stamp /= 1000.0; // put in seconds
|
||||||
|
UDEBUG("Frameset arrived. system=%fs frame=%fs", now, stamp);
|
||||||
if(stamp - now > 1000000000.0)
|
if(stamp - now > 1000000000.0)
|
||||||
{
|
{
|
||||||
if(!clockSyncWarningShown_)
|
if(!clockSyncWarningShown_)
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ RTAB-Map integration: Mathieu Labbe
|
|||||||
#include <rtabmap/core/util3d.h>
|
#include <rtabmap/core/util3d.h>
|
||||||
#include <opencv2/highgui/highgui.hpp>
|
#include <opencv2/highgui/highgui.hpp>
|
||||||
#include <opencv2/imgproc/imgproc.hpp>
|
#include <opencv2/imgproc/imgproc.hpp>
|
||||||
|
#include <pcl/common/point_tests.h>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace Eigen;
|
using namespace Eigen;
|
||||||
|
|||||||
@@ -151,13 +151,6 @@ OdometryF2M::~OdometryF2M()
|
|||||||
{
|
{
|
||||||
delete map_;
|
delete map_;
|
||||||
delete lastFrame_;
|
delete lastFrame_;
|
||||||
scansBuffer_.clear();
|
|
||||||
bundleWordReferences_.clear();
|
|
||||||
bundlePoses_.clear();
|
|
||||||
bundleLinks_.clear();
|
|
||||||
bundleModels_.clear();
|
|
||||||
bundlePoseReferences_.clear();
|
|
||||||
imus_.clear();
|
|
||||||
delete sba_;
|
delete sba_;
|
||||||
delete regPipeline_;
|
delete regPipeline_;
|
||||||
UDEBUG("");
|
UDEBUG("");
|
||||||
@@ -181,7 +174,6 @@ void OdometryF2M::reset(const Transform & initialPose)
|
|||||||
bundlePoseReferences_.clear();
|
bundlePoseReferences_.clear();
|
||||||
bundleSeq_ = 0;
|
bundleSeq_ = 0;
|
||||||
lastFrameOldestNewId_ = 0;
|
lastFrameOldestNewId_ = 0;
|
||||||
imus_.clear();
|
|
||||||
}
|
}
|
||||||
initGravity_ = false;
|
initGravity_ = false;
|
||||||
}
|
}
|
||||||
@@ -206,30 +198,27 @@ Transform OdometryF2M::computeTransform(
|
|||||||
info->type = 0;
|
info->type = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Transform imuT;
|
||||||
if(sba_ && sba_->gravitySigma() > 0.0f && !data.imu().empty())
|
if(sba_ && sba_->gravitySigma() > 0.0f && !data.imu().empty())
|
||||||
{
|
{
|
||||||
if(data.imu().orientation()[0] == 0.0 && data.imu().orientation()[1] == 0.0 && data.imu().orientation()[2] == 0.0)
|
if(imus().empty())
|
||||||
{
|
{
|
||||||
UERROR("IMU received doesn't have orientation set, it is ignored. If you are using RTAB-Map standalone, enable IMU filtering in Preferences->Source panel. On ROS, use \"imu_filter_madgwick\" or \"imu_complementary_filter\" packages to compute the orientation.");
|
UERROR("IMU received doesn't have orientation set, it is ignored. If you are using RTAB-Map standalone, enable IMU filtering in Preferences->Source panel. On ROS, use \"imu_filter_madgwick\" or \"imu_complementary_filter\" packages to compute the orientation.");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Transform orientation(0,0,0, data.imu().orientation()[0], data.imu().orientation()[1], data.imu().orientation()[2], data.imu().orientation()[3]);
|
imuT = Transform::getTransform(imus(), data.stamp());
|
||||||
// orientation includes roll and pitch but not yaw in local transform
|
|
||||||
imus_.insert(std::make_pair(data.stamp(), Transform(0,0,data.imu().localTransform().theta()) * orientation*data.imu().localTransform().inverse()));
|
|
||||||
if(imus_.size() > 1000)
|
|
||||||
{
|
|
||||||
imus_.erase(imus_.begin());
|
|
||||||
}
|
|
||||||
|
|
||||||
if(this->getPose().r11() == 1.0f && this->getPose().r22() == 1.0f && this->getPose().r33() == 1.0f)
|
if(this->getPose().r11() == 1.0f && this->getPose().r22() == 1.0f && this->getPose().r33() == 1.0f)
|
||||||
{
|
{
|
||||||
Eigen::Quaterniond imuQuat = imus_.rbegin()->second.getQuaterniond();
|
if(!imuT.isNull())
|
||||||
Transform previous = this->getPose();
|
{
|
||||||
Transform newFramePose = Transform(previous.x(), previous.y(), previous.z(), imuQuat.x(), imuQuat.y(), imuQuat.z(), imuQuat.w());
|
Eigen::Quaterniond imuQuat = imuT.getQuaterniond();
|
||||||
UWARN("Updated initial pose from %s to %s with IMU orientation", previous.prettyPrint().c_str(), newFramePose.prettyPrint().c_str());
|
Transform previous = this->getPose();
|
||||||
initGravity_ = true;
|
Transform newFramePose = Transform(previous.x(), previous.y(), previous.z(), imuQuat.x(), imuQuat.y(), imuQuat.z(), imuQuat.w());
|
||||||
this->reset(newFramePose);
|
UWARN("Updated initial pose from %s to %s with IMU orientation", previous.prettyPrint().c_str(), newFramePose.prettyPrint().c_str());
|
||||||
|
initGravity_ = true;
|
||||||
|
this->reset(newFramePose);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -276,7 +265,6 @@ Transform OdometryF2M::computeTransform(
|
|||||||
std::map<int, Transform> bundlePoses;
|
std::map<int, Transform> bundlePoses;
|
||||||
std::multimap<int, Link> bundleLinks;
|
std::multimap<int, Link> bundleLinks;
|
||||||
std::map<int, CameraModel> bundleModels;
|
std::map<int, CameraModel> bundleModels;
|
||||||
std::map<int, StereoCameraModel> bundleStereoModels;
|
|
||||||
|
|
||||||
for(int guessIteration=0;
|
for(int guessIteration=0;
|
||||||
guessIteration<(!guess.isNull()&®Pipeline_->isImageRequired()?2:1) && transform.isNull();
|
guessIteration<(!guess.isNull()&®Pipeline_->isImageRequired()?2:1) && transform.isNull();
|
||||||
@@ -292,7 +280,6 @@ Transform OdometryF2M::computeTransform(
|
|||||||
bundlePoses.clear();
|
bundlePoses.clear();
|
||||||
bundleLinks.clear();
|
bundleLinks.clear();
|
||||||
bundleModels.clear();
|
bundleModels.clear();
|
||||||
bundleStereoModels.clear();
|
|
||||||
|
|
||||||
float maxCorrespondenceDistance = 0.0f;
|
float maxCorrespondenceDistance = 0.0f;
|
||||||
float pmOutlierRatio = 0.0f;
|
float pmOutlierRatio = 0.0f;
|
||||||
@@ -371,14 +358,9 @@ Transform OdometryF2M::computeTransform(
|
|||||||
bundleLinks.insert(std::make_pair(bundlePoses_.rbegin()->first, Link(bundlePoses_.rbegin()->first, lastFrame_->id(), Link::kNeighbor, bundlePoses_.rbegin()->second.inverse()*transform, regInfo.covariance.inv())));
|
bundleLinks.insert(std::make_pair(bundlePoses_.rbegin()->first, Link(bundlePoses_.rbegin()->first, lastFrame_->id(), Link::kNeighbor, bundlePoses_.rbegin()->second.inverse()*transform, regInfo.covariance.inv())));
|
||||||
bundlePoses.insert(std::make_pair(lastFrame_->id(), transform));
|
bundlePoses.insert(std::make_pair(lastFrame_->id(), transform));
|
||||||
|
|
||||||
Transform imuT;
|
if(!imuT.isNull())
|
||||||
if(!imus_.empty())
|
|
||||||
{
|
{
|
||||||
imuT = Transform::getTransform(imus_, lastFrame_->getStamp());
|
bundleLinks.insert(std::make_pair(lastFrame_->id(), Link(lastFrame_->id(), lastFrame_->id(), Link::kGravity, imuT)));
|
||||||
if(!imuT.isNull())
|
|
||||||
{
|
|
||||||
bundleLinks.insert(std::make_pair(lastFrame_->id(), Link(lastFrame_->id(), lastFrame_->id(), Link::kGravity, imuT)));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CameraModel model;
|
CameraModel model;
|
||||||
@@ -509,6 +491,17 @@ Transform OdometryF2M::computeTransform(
|
|||||||
std::multimap<int, Link>::iterator iter = graph::findLink(bundleLinks, bundlePoses_.rbegin()->first, lastFrame_->id(), false);
|
std::multimap<int, Link>::iterator iter = graph::findLink(bundleLinks, bundlePoses_.rbegin()->first, lastFrame_->id(), false);
|
||||||
UASSERT(iter != bundleLinks.end());
|
UASSERT(iter != bundleLinks.end());
|
||||||
iter->second.setTransform(bundlePoses_.rbegin()->second.inverse()*transform);
|
iter->second.setTransform(bundlePoses_.rbegin()->second.inverse()*transform);
|
||||||
|
|
||||||
|
iter = graph::findLink(bundleLinks, lastFrame_->id(), lastFrame_->id(), false);
|
||||||
|
if(info && iter!=bundleLinks.end() && iter->second.type() == Link::kGravity)
|
||||||
|
{
|
||||||
|
float rollImu,pitchImu,yaw;
|
||||||
|
iter->second.transform().getEulerAngles(rollImu, pitchImu, yaw);
|
||||||
|
float roll,pitch;
|
||||||
|
transform.getEulerAngles(roll, pitch, yaw);
|
||||||
|
info->gravityRollError = fabs(rollImu - roll);
|
||||||
|
info->gravityPitchError = fabs(pitchImu - pitch);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
UDEBUG("Local Bundle Adjustment After : %s", transform.prettyPrint().c_str());
|
UDEBUG("Local Bundle Adjustment After : %s", transform.prettyPrint().c_str());
|
||||||
@@ -1247,7 +1240,7 @@ Transform OdometryF2M::computeTransform(
|
|||||||
bundleModels_.insert(std::make_pair(lastFrame_->id(), model));
|
bundleModels_.insert(std::make_pair(lastFrame_->id(), model));
|
||||||
bundlePoses_.insert(std::make_pair(lastFrame_->id(), newFramePose));
|
bundlePoses_.insert(std::make_pair(lastFrame_->id(), newFramePose));
|
||||||
|
|
||||||
if(!imus_.empty())
|
if(!imuT.isNull())
|
||||||
{
|
{
|
||||||
bundleIMUOrientations_.insert(std::make_pair(lastFrame_->id(), Link(lastFrame_->id(), lastFrame_->id(), Link::kGravity, newFramePose)));
|
bundleIMUOrientations_.insert(std::make_pair(lastFrame_->id(), Link(lastFrame_->id(), lastFrame_->id(), Link::kGravity, newFramePose)));
|
||||||
}
|
}
|
||||||
@@ -1278,7 +1271,7 @@ Transform OdometryF2M::computeTransform(
|
|||||||
Parameters::parse(parameters_, Parameters::kIcpPointToPlaneMinComplexity(), minComplexity);
|
Parameters::parse(parameters_, Parameters::kIcpPointToPlaneMinComplexity(), minComplexity);
|
||||||
if(p2n && minComplexity>0.0f)
|
if(p2n && minComplexity>0.0f)
|
||||||
{
|
{
|
||||||
complexity = util3d::computeNormalsComplexity(*mapCloudNormals);
|
complexity = util3d::computeNormalsComplexity(*mapCloudNormals, Transform::getIdentity(), lastFrame_->sensorData().laserScanRaw().is2d());
|
||||||
if(complexity > minComplexity)
|
if(complexity > minComplexity)
|
||||||
{
|
{
|
||||||
frameValid = true;
|
frameValid = true;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,645 @@
|
|||||||
|
/* This is a 5-point algorithm contributed to OpenCV by the author, Bo Li.
|
||||||
|
It implements the 5-point algorithm solver from Nister's paper:
|
||||||
|
Nister, An efficient solution to the five-point relative pose problem, PAMI, 2004.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Copyright (c) 2013, Bo Li (prclibo@gmail.com), ETH Zurich
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
* Neither the name of the copyright holder nor the
|
||||||
|
names of its contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
|
||||||
|
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "solvepnp.h"
|
||||||
|
|
||||||
|
using namespace cv;
|
||||||
|
|
||||||
|
namespace cv3
|
||||||
|
{
|
||||||
|
|
||||||
|
class EMEstimatorCallback : public PointSetRegistrator::Callback
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int runKernel( InputArray _m1, InputArray _m2, OutputArray _model ) const
|
||||||
|
{
|
||||||
|
Mat q1 = _m1.getMat(), q2 = _m2.getMat();
|
||||||
|
Mat Q1 = q1.reshape(1, (int)q1.total());
|
||||||
|
Mat Q2 = q2.reshape(1, (int)q2.total());
|
||||||
|
|
||||||
|
int n = Q1.rows;
|
||||||
|
Mat Q(n, 9, CV_64F);
|
||||||
|
Q.col(0) = Q1.col(0).mul( Q2.col(0) );
|
||||||
|
Q.col(1) = Q1.col(1).mul( Q2.col(0) );
|
||||||
|
Q.col(2) = Q2.col(0) * 1.0;
|
||||||
|
Q.col(3) = Q1.col(0).mul( Q2.col(1) );
|
||||||
|
Q.col(4) = Q1.col(1).mul( Q2.col(1) );
|
||||||
|
Q.col(5) = Q2.col(1) * 1.0;
|
||||||
|
Q.col(6) = Q1.col(0) * 1.0;
|
||||||
|
Q.col(7) = Q1.col(1) * 1.0;
|
||||||
|
Q.col(8) = 1.0;
|
||||||
|
|
||||||
|
Mat U, W, Vt;
|
||||||
|
SVD::compute(Q, W, U, Vt, SVD::MODIFY_A | SVD::FULL_UV);
|
||||||
|
|
||||||
|
Mat EE = Mat(Vt.t()).colRange(5, 9) * 1.0;
|
||||||
|
Mat A(10, 20, CV_64F);
|
||||||
|
EE = EE.t();
|
||||||
|
getCoeffMat(EE.ptr<double>(), A.ptr<double>());
|
||||||
|
EE = EE.t();
|
||||||
|
|
||||||
|
A = A.colRange(0, 10).inv() * A.colRange(10, 20);
|
||||||
|
|
||||||
|
double b[3 * 13];
|
||||||
|
Mat B(3, 13, CV_64F, b);
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
Mat arow1 = A.row(i * 2 + 4) * 1.0;
|
||||||
|
Mat arow2 = A.row(i * 2 + 5) * 1.0;
|
||||||
|
Mat row1(1, 13, CV_64F, Scalar(0.0));
|
||||||
|
Mat row2(1, 13, CV_64F, Scalar(0.0));
|
||||||
|
|
||||||
|
row1.colRange(1, 4) = arow1.colRange(0, 3) * 1.0;
|
||||||
|
row1.colRange(5, 8) = arow1.colRange(3, 6) * 1.0;
|
||||||
|
row1.colRange(9, 13) = arow1.colRange(6, 10) * 1.0;
|
||||||
|
|
||||||
|
row2.colRange(0, 3) = arow2.colRange(0, 3) * 1.0;
|
||||||
|
row2.colRange(4, 7) = arow2.colRange(3, 6) * 1.0;
|
||||||
|
row2.colRange(8, 12) = arow2.colRange(6, 10) * 1.0;
|
||||||
|
|
||||||
|
B.row(i) = row1 - row2;
|
||||||
|
}
|
||||||
|
|
||||||
|
double c[11];
|
||||||
|
Mat coeffs(1, 11, CV_64F, c);
|
||||||
|
c[10] = (b[0]*b[17]*b[34]+b[26]*b[4]*b[21]-b[26]*b[17]*b[8]-b[13]*b[4]*b[34]-b[0]*b[21]*b[30]+b[13]*b[30]*b[8]);
|
||||||
|
c[9] = (b[26]*b[4]*b[22]+b[14]*b[30]*b[8]+b[13]*b[31]*b[8]+b[1]*b[17]*b[34]-b[13]*b[5]*b[34]+b[26]*b[5]*b[21]-b[0]*b[21]*b[31]-b[26]*b[17]*b[9]-b[1]*b[21]*b[30]+b[27]*b[4]*b[21]+b[0]*b[17]*b[35]-b[0]*b[22]*b[30]+b[13]*b[30]*b[9]+b[0]*b[18]*b[34]-b[27]*b[17]*b[8]-b[14]*b[4]*b[34]-b[13]*b[4]*b[35]-b[26]*b[18]*b[8]);
|
||||||
|
c[8] = (b[14]*b[30]*b[9]+b[14]*b[31]*b[8]+b[13]*b[31]*b[9]-b[13]*b[4]*b[36]-b[13]*b[5]*b[35]+b[15]*b[30]*b[8]-b[13]*b[6]*b[34]+b[13]*b[30]*b[10]+b[13]*b[32]*b[8]-b[14]*b[4]*b[35]-b[14]*b[5]*b[34]+b[26]*b[4]*b[23]+b[26]*b[5]*b[22]+b[26]*b[6]*b[21]-b[26]*b[17]*b[10]-b[15]*b[4]*b[34]-b[26]*b[18]*b[9]-b[26]*b[19]*b[8]+b[27]*b[4]*b[22]+b[27]*b[5]*b[21]-b[27]*b[17]*b[9]-b[27]*b[18]*b[8]-b[1]*b[21]*b[31]-b[0]*b[23]*b[30]-b[0]*b[21]*b[32]+b[28]*b[4]*b[21]-b[28]*b[17]*b[8]+b[2]*b[17]*b[34]+b[0]*b[18]*b[35]-b[0]*b[22]*b[31]+b[0]*b[17]*b[36]+b[0]*b[19]*b[34]-b[1]*b[22]*b[30]+b[1]*b[18]*b[34]+b[1]*b[17]*b[35]-b[2]*b[21]*b[30]);
|
||||||
|
c[7] = (b[14]*b[30]*b[10]+b[14]*b[32]*b[8]-b[3]*b[21]*b[30]+b[3]*b[17]*b[34]+b[13]*b[32]*b[9]+b[13]*b[33]*b[8]-b[13]*b[4]*b[37]-b[13]*b[5]*b[36]+b[15]*b[30]*b[9]+b[15]*b[31]*b[8]-b[16]*b[4]*b[34]-b[13]*b[6]*b[35]-b[13]*b[7]*b[34]+b[13]*b[30]*b[11]+b[13]*b[31]*b[10]+b[14]*b[31]*b[9]-b[14]*b[4]*b[36]-b[14]*b[5]*b[35]-b[14]*b[6]*b[34]+b[16]*b[30]*b[8]-b[26]*b[20]*b[8]+b[26]*b[4]*b[24]+b[26]*b[5]*b[23]+b[26]*b[6]*b[22]+b[26]*b[7]*b[21]-b[26]*b[17]*b[11]-b[15]*b[4]*b[35]-b[15]*b[5]*b[34]-b[26]*b[18]*b[10]-b[26]*b[19]*b[9]+b[27]*b[4]*b[23]+b[27]*b[5]*b[22]+b[27]*b[6]*b[21]-b[27]*b[17]*b[10]-b[27]*b[18]*b[9]-b[27]*b[19]*b[8]+b[0]*b[17]*b[37]-b[0]*b[23]*b[31]-b[0]*b[24]*b[30]-b[0]*b[21]*b[33]-b[29]*b[17]*b[8]+b[28]*b[4]*b[22]+b[28]*b[5]*b[21]-b[28]*b[17]*b[9]-b[28]*b[18]*b[8]+b[29]*b[4]*b[21]+b[1]*b[19]*b[34]-b[2]*b[21]*b[31]+b[0]*b[20]*b[34]+b[0]*b[19]*b[35]+b[0]*b[18]*b[36]-b[0]*b[22]*b[32]-b[1]*b[23]*b[30]-b[1]*b[21]*b[32]+b[1]*b[18]*b[35]-b[1]*b[22]*b[31]-b[2]*b[22]*b[30]+b[2]*b[17]*b[35]+b[1]*b[17]*b[36]+b[2]*b[18]*b[34]);
|
||||||
|
c[6] = (-b[14]*b[6]*b[35]-b[14]*b[7]*b[34]-b[3]*b[22]*b[30]-b[3]*b[21]*b[31]+b[3]*b[17]*b[35]+b[3]*b[18]*b[34]+b[13]*b[32]*b[10]+b[13]*b[33]*b[9]-b[13]*b[4]*b[38]-b[13]*b[5]*b[37]-b[15]*b[6]*b[34]+b[15]*b[30]*b[10]+b[15]*b[32]*b[8]-b[16]*b[4]*b[35]-b[13]*b[6]*b[36]-b[13]*b[7]*b[35]+b[13]*b[31]*b[11]+b[13]*b[30]*b[12]+b[14]*b[32]*b[9]+b[14]*b[33]*b[8]-b[14]*b[4]*b[37]-b[14]*b[5]*b[36]+b[16]*b[30]*b[9]+b[16]*b[31]*b[8]-b[26]*b[20]*b[9]+b[26]*b[4]*b[25]+b[26]*b[5]*b[24]+b[26]*b[6]*b[23]+b[26]*b[7]*b[22]-b[26]*b[17]*b[12]+b[14]*b[30]*b[11]+b[14]*b[31]*b[10]+b[15]*b[31]*b[9]-b[15]*b[4]*b[36]-b[15]*b[5]*b[35]-b[26]*b[18]*b[11]-b[26]*b[19]*b[10]-b[27]*b[20]*b[8]+b[27]*b[4]*b[24]+b[27]*b[5]*b[23]+b[27]*b[6]*b[22]+b[27]*b[7]*b[21]-b[27]*b[17]*b[11]-b[27]*b[18]*b[10]-b[27]*b[19]*b[9]-b[16]*b[5]*b[34]-b[29]*b[17]*b[9]-b[29]*b[18]*b[8]+b[28]*b[4]*b[23]+b[28]*b[5]*b[22]+b[28]*b[6]*b[21]-b[28]*b[17]*b[10]-b[28]*b[18]*b[9]-b[28]*b[19]*b[8]+b[29]*b[4]*b[22]+b[29]*b[5]*b[21]-b[2]*b[23]*b[30]+b[2]*b[18]*b[35]-b[1]*b[22]*b[32]-b[2]*b[21]*b[32]+b[2]*b[19]*b[34]+b[0]*b[19]*b[36]-b[0]*b[22]*b[33]+b[0]*b[20]*b[35]-b[0]*b[23]*b[32]-b[0]*b[25]*b[30]+b[0]*b[17]*b[38]+b[0]*b[18]*b[37]-b[0]*b[24]*b[31]+b[1]*b[17]*b[37]-b[1]*b[23]*b[31]-b[1]*b[24]*b[30]-b[1]*b[21]*b[33]+b[1]*b[20]*b[34]+b[1]*b[19]*b[35]+b[1]*b[18]*b[36]+b[2]*b[17]*b[36]-b[2]*b[22]*b[31]);
|
||||||
|
c[5] = (-b[14]*b[6]*b[36]-b[14]*b[7]*b[35]+b[14]*b[31]*b[11]-b[3]*b[23]*b[30]-b[3]*b[21]*b[32]+b[3]*b[18]*b[35]-b[3]*b[22]*b[31]+b[3]*b[17]*b[36]+b[3]*b[19]*b[34]+b[13]*b[32]*b[11]+b[13]*b[33]*b[10]-b[13]*b[5]*b[38]-b[15]*b[6]*b[35]-b[15]*b[7]*b[34]+b[15]*b[30]*b[11]+b[15]*b[31]*b[10]+b[16]*b[31]*b[9]-b[13]*b[6]*b[37]-b[13]*b[7]*b[36]+b[13]*b[31]*b[12]+b[14]*b[32]*b[10]+b[14]*b[33]*b[9]-b[14]*b[4]*b[38]-b[14]*b[5]*b[37]-b[16]*b[6]*b[34]+b[16]*b[30]*b[10]+b[16]*b[32]*b[8]-b[26]*b[20]*b[10]+b[26]*b[5]*b[25]+b[26]*b[6]*b[24]+b[26]*b[7]*b[23]+b[14]*b[30]*b[12]+b[15]*b[32]*b[9]+b[15]*b[33]*b[8]-b[15]*b[4]*b[37]-b[15]*b[5]*b[36]+b[29]*b[5]*b[22]+b[29]*b[6]*b[21]-b[26]*b[18]*b[12]-b[26]*b[19]*b[11]-b[27]*b[20]*b[9]+b[27]*b[4]*b[25]+b[27]*b[5]*b[24]+b[27]*b[6]*b[23]+b[27]*b[7]*b[22]-b[27]*b[17]*b[12]-b[27]*b[18]*b[11]-b[27]*b[19]*b[10]-b[28]*b[20]*b[8]-b[16]*b[4]*b[36]-b[16]*b[5]*b[35]-b[29]*b[17]*b[10]-b[29]*b[18]*b[9]-b[29]*b[19]*b[8]+b[28]*b[4]*b[24]+b[28]*b[5]*b[23]+b[28]*b[6]*b[22]+b[28]*b[7]*b[21]-b[28]*b[17]*b[11]-b[28]*b[18]*b[10]-b[28]*b[19]*b[9]+b[29]*b[4]*b[23]-b[2]*b[22]*b[32]-b[2]*b[21]*b[33]-b[1]*b[24]*b[31]+b[0]*b[18]*b[38]-b[0]*b[24]*b[32]+b[0]*b[19]*b[37]+b[0]*b[20]*b[36]-b[0]*b[25]*b[31]-b[0]*b[23]*b[33]+b[1]*b[19]*b[36]-b[1]*b[22]*b[33]+b[1]*b[20]*b[35]+b[2]*b[19]*b[35]-b[2]*b[24]*b[30]-b[2]*b[23]*b[31]+b[2]*b[20]*b[34]+b[2]*b[17]*b[37]-b[1]*b[25]*b[30]+b[1]*b[18]*b[37]+b[1]*b[17]*b[38]-b[1]*b[23]*b[32]+b[2]*b[18]*b[36]);
|
||||||
|
c[4] = (-b[14]*b[6]*b[37]-b[14]*b[7]*b[36]+b[14]*b[31]*b[12]+b[3]*b[17]*b[37]-b[3]*b[23]*b[31]-b[3]*b[24]*b[30]-b[3]*b[21]*b[33]+b[3]*b[20]*b[34]+b[3]*b[19]*b[35]+b[3]*b[18]*b[36]-b[3]*b[22]*b[32]+b[13]*b[32]*b[12]+b[13]*b[33]*b[11]-b[15]*b[6]*b[36]-b[15]*b[7]*b[35]+b[15]*b[31]*b[11]+b[15]*b[30]*b[12]+b[16]*b[32]*b[9]+b[16]*b[33]*b[8]-b[13]*b[6]*b[38]-b[13]*b[7]*b[37]+b[14]*b[32]*b[11]+b[14]*b[33]*b[10]-b[14]*b[5]*b[38]-b[16]*b[6]*b[35]-b[16]*b[7]*b[34]+b[16]*b[30]*b[11]+b[16]*b[31]*b[10]-b[26]*b[19]*b[12]-b[26]*b[20]*b[11]+b[26]*b[6]*b[25]+b[26]*b[7]*b[24]+b[15]*b[32]*b[10]+b[15]*b[33]*b[9]-b[15]*b[4]*b[38]-b[15]*b[5]*b[37]+b[29]*b[5]*b[23]+b[29]*b[6]*b[22]+b[29]*b[7]*b[21]-b[27]*b[20]*b[10]+b[27]*b[5]*b[25]+b[27]*b[6]*b[24]+b[27]*b[7]*b[23]-b[27]*b[18]*b[12]-b[27]*b[19]*b[11]-b[28]*b[20]*b[9]-b[16]*b[4]*b[37]-b[16]*b[5]*b[36]+b[0]*b[19]*b[38]-b[0]*b[24]*b[33]+b[0]*b[20]*b[37]-b[29]*b[17]*b[11]-b[29]*b[18]*b[10]-b[29]*b[19]*b[9]+b[28]*b[4]*b[25]+b[28]*b[5]*b[24]+b[28]*b[6]*b[23]+b[28]*b[7]*b[22]-b[28]*b[17]*b[12]-b[28]*b[18]*b[11]-b[28]*b[19]*b[10]-b[29]*b[20]*b[8]+b[29]*b[4]*b[24]+b[2]*b[18]*b[37]-b[0]*b[25]*b[32]+b[1]*b[18]*b[38]-b[1]*b[24]*b[32]+b[1]*b[19]*b[37]+b[1]*b[20]*b[36]-b[1]*b[25]*b[31]+b[2]*b[17]*b[38]+b[2]*b[19]*b[36]-b[2]*b[24]*b[31]-b[2]*b[22]*b[33]-b[2]*b[23]*b[32]+b[2]*b[20]*b[35]-b[1]*b[23]*b[33]-b[2]*b[25]*b[30]);
|
||||||
|
c[3] = (-b[14]*b[6]*b[38]-b[14]*b[7]*b[37]+b[3]*b[19]*b[36]-b[3]*b[22]*b[33]+b[3]*b[20]*b[35]-b[3]*b[23]*b[32]-b[3]*b[25]*b[30]+b[3]*b[17]*b[38]+b[3]*b[18]*b[37]-b[3]*b[24]*b[31]-b[15]*b[6]*b[37]-b[15]*b[7]*b[36]+b[15]*b[31]*b[12]+b[16]*b[32]*b[10]+b[16]*b[33]*b[9]+b[13]*b[33]*b[12]-b[13]*b[7]*b[38]+b[14]*b[32]*b[12]+b[14]*b[33]*b[11]-b[16]*b[6]*b[36]-b[16]*b[7]*b[35]+b[16]*b[31]*b[11]+b[16]*b[30]*b[12]+b[15]*b[32]*b[11]+b[15]*b[33]*b[10]-b[15]*b[5]*b[38]+b[29]*b[5]*b[24]+b[29]*b[6]*b[23]-b[26]*b[20]*b[12]+b[26]*b[7]*b[25]-b[27]*b[19]*b[12]-b[27]*b[20]*b[11]+b[27]*b[6]*b[25]+b[27]*b[7]*b[24]-b[28]*b[20]*b[10]-b[16]*b[4]*b[38]-b[16]*b[5]*b[37]+b[29]*b[7]*b[22]-b[29]*b[17]*b[12]-b[29]*b[18]*b[11]-b[29]*b[19]*b[10]+b[28]*b[5]*b[25]+b[28]*b[6]*b[24]+b[28]*b[7]*b[23]-b[28]*b[18]*b[12]-b[28]*b[19]*b[11]-b[29]*b[20]*b[9]+b[29]*b[4]*b[25]-b[2]*b[24]*b[32]+b[0]*b[20]*b[38]-b[0]*b[25]*b[33]+b[1]*b[19]*b[38]-b[1]*b[24]*b[33]+b[1]*b[20]*b[37]-b[2]*b[25]*b[31]+b[2]*b[20]*b[36]-b[1]*b[25]*b[32]+b[2]*b[19]*b[37]+b[2]*b[18]*b[38]-b[2]*b[23]*b[33]);
|
||||||
|
c[2] = (b[3]*b[18]*b[38]-b[3]*b[24]*b[32]+b[3]*b[19]*b[37]+b[3]*b[20]*b[36]-b[3]*b[25]*b[31]-b[3]*b[23]*b[33]-b[15]*b[6]*b[38]-b[15]*b[7]*b[37]+b[16]*b[32]*b[11]+b[16]*b[33]*b[10]-b[16]*b[5]*b[38]-b[16]*b[6]*b[37]-b[16]*b[7]*b[36]+b[16]*b[31]*b[12]+b[14]*b[33]*b[12]-b[14]*b[7]*b[38]+b[15]*b[32]*b[12]+b[15]*b[33]*b[11]+b[29]*b[5]*b[25]+b[29]*b[6]*b[24]-b[27]*b[20]*b[12]+b[27]*b[7]*b[25]-b[28]*b[19]*b[12]-b[28]*b[20]*b[11]+b[29]*b[7]*b[23]-b[29]*b[18]*b[12]-b[29]*b[19]*b[11]+b[28]*b[6]*b[25]+b[28]*b[7]*b[24]-b[29]*b[20]*b[10]+b[2]*b[19]*b[38]-b[1]*b[25]*b[33]+b[2]*b[20]*b[37]-b[2]*b[24]*b[33]-b[2]*b[25]*b[32]+b[1]*b[20]*b[38]);
|
||||||
|
c[1] = (b[29]*b[7]*b[24]-b[29]*b[20]*b[11]+b[2]*b[20]*b[38]-b[2]*b[25]*b[33]-b[28]*b[20]*b[12]+b[28]*b[7]*b[25]-b[29]*b[19]*b[12]-b[3]*b[24]*b[33]+b[15]*b[33]*b[12]+b[3]*b[19]*b[38]-b[16]*b[6]*b[38]+b[3]*b[20]*b[37]+b[16]*b[32]*b[12]+b[29]*b[6]*b[25]-b[16]*b[7]*b[37]-b[3]*b[25]*b[32]-b[15]*b[7]*b[38]+b[16]*b[33]*b[11]);
|
||||||
|
c[0] = -b[29]*b[20]*b[12]+b[29]*b[7]*b[25]+b[16]*b[33]*b[12]-b[16]*b[7]*b[38]+b[3]*b[20]*b[38]-b[3]*b[25]*b[33];
|
||||||
|
|
||||||
|
std::vector<Complex<double> > roots;
|
||||||
|
solvePoly(coeffs, roots);
|
||||||
|
|
||||||
|
std::vector<double> xs, ys, zs;
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
Mat ematrix(10*3, 3, CV_64F);
|
||||||
|
double* e = ematrix.ptr<double>();
|
||||||
|
for (size_t i = 0; i < roots.size(); i++)
|
||||||
|
{
|
||||||
|
if (fabs(roots[i].im) > 1e-10) continue;
|
||||||
|
double z1 = roots[i].re;
|
||||||
|
double z2 = z1 * z1;
|
||||||
|
double z3 = z2 * z1;
|
||||||
|
double z4 = z3 * z1;
|
||||||
|
|
||||||
|
double bz[3][3];
|
||||||
|
for (int j = 0; j < 3; j++)
|
||||||
|
{
|
||||||
|
const double * br = b + j * 13;
|
||||||
|
bz[j][0] = br[0] * z3 + br[1] * z2 + br[2] * z1 + br[3];
|
||||||
|
bz[j][1] = br[4] * z3 + br[5] * z2 + br[6] * z1 + br[7];
|
||||||
|
bz[j][2] = br[8] * z4 + br[9] * z3 + br[10] * z2 + br[11] * z1 + br[12];
|
||||||
|
}
|
||||||
|
|
||||||
|
Mat Bz(3, 3, CV_64F, bz);
|
||||||
|
cv::Mat xy1;
|
||||||
|
SVD::solveZ(Bz, xy1);
|
||||||
|
|
||||||
|
if (fabs(xy1.at<double>(2)) < 1e-10) continue;
|
||||||
|
xs.push_back(xy1.at<double>(0) / xy1.at<double>(2));
|
||||||
|
ys.push_back(xy1.at<double>(1) / xy1.at<double>(2));
|
||||||
|
zs.push_back(z1);
|
||||||
|
|
||||||
|
cv::Mat Evec = EE.col(0) * xs.back() + EE.col(1) * ys.back() + EE.col(2) * zs.back() + EE.col(3);
|
||||||
|
Evec /= norm(Evec);
|
||||||
|
|
||||||
|
memcpy(e + count * 9, Evec.ptr(), 9 * sizeof(double));
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
ematrix.rowRange(0, count*3).copyTo(_model);
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void getCoeffMat(double *e, double *A) const
|
||||||
|
{
|
||||||
|
double ep2[36], ep3[36];
|
||||||
|
for (int i = 0; i < 36; i++)
|
||||||
|
{
|
||||||
|
ep2[i] = e[i] * e[i];
|
||||||
|
ep3[i] = ep2[i] * e[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
A[0]=e[33]*e[28]*e[32]-e[33]*e[31]*e[29]+e[30]*e[34]*e[29]-e[30]*e[28]*e[35]-e[27]*e[32]*e[34]+e[27]*e[31]*e[35];
|
||||||
|
A[146]=.5000000000*e[6]*ep2[8]-.5000000000*e[6]*ep2[5]+.5000000000*ep3[6]+.5000000000*e[6]*ep2[7]-.5000000000*e[6]*ep2[4]+e[0]*e[2]*e[8]+e[3]*e[4]*e[7]+e[3]*e[5]*e[8]+e[0]*e[1]*e[7]-.5000000000*e[6]*ep2[1]-.5000000000*e[6]*ep2[2]+.5000000000*ep2[0]*e[6]+.5000000000*ep2[3]*e[6];
|
||||||
|
A[1]=e[30]*e[34]*e[2]+e[33]*e[1]*e[32]-e[3]*e[28]*e[35]+e[0]*e[31]*e[35]+e[3]*e[34]*e[29]-e[30]*e[1]*e[35]+e[27]*e[31]*e[8]-e[27]*e[32]*e[7]-e[30]*e[28]*e[8]-e[33]*e[31]*e[2]-e[0]*e[32]*e[34]+e[6]*e[28]*e[32]-e[33]*e[4]*e[29]+e[33]*e[28]*e[5]+e[30]*e[7]*e[29]+e[27]*e[4]*e[35]-e[27]*e[5]*e[34]-e[6]*e[31]*e[29];
|
||||||
|
A[147]=e[9]*e[27]*e[15]+e[9]*e[29]*e[17]+e[9]*e[11]*e[35]+e[9]*e[28]*e[16]+e[9]*e[10]*e[34]+e[27]*e[11]*e[17]+e[27]*e[10]*e[16]+e[12]*e[30]*e[15]+e[12]*e[32]*e[17]+e[12]*e[14]*e[35]+e[12]*e[31]*e[16]+e[12]*e[13]*e[34]+e[30]*e[14]*e[17]+e[30]*e[13]*e[16]+e[15]*e[35]*e[17]+e[15]*e[34]*e[16]-1.*e[15]*e[28]*e[10]-1.*e[15]*e[31]*e[13]-1.*e[15]*e[32]*e[14]-1.*e[15]*e[29]*e[11]+.5000000000*ep2[9]*e[33]+.5000000000*e[33]*ep2[16]-.5000000000*e[33]*ep2[11]+.5000000000*e[33]*ep2[12]+1.500000000*e[33]*ep2[15]+.5000000000*e[33]*ep2[17]-.5000000000*e[33]*ep2[10]-.5000000000*e[33]*ep2[14]-.5000000000*e[33]*ep2[13];
|
||||||
|
A[2]=-e[33]*e[22]*e[29]-e[33]*e[31]*e[20]-e[27]*e[32]*e[25]+e[27]*e[22]*e[35]-e[27]*e[23]*e[34]+e[27]*e[31]*e[26]+e[33]*e[28]*e[23]-e[21]*e[28]*e[35]+e[30]*e[25]*e[29]+e[24]*e[28]*e[32]-e[24]*e[31]*e[29]+e[18]*e[31]*e[35]-e[30]*e[28]*e[26]-e[30]*e[19]*e[35]+e[21]*e[34]*e[29]+e[33]*e[19]*e[32]-e[18]*e[32]*e[34]+e[30]*e[34]*e[20];
|
||||||
|
A[144]=e[18]*e[2]*e[17]+e[3]*e[21]*e[15]+e[3]*e[12]*e[24]+e[3]*e[23]*e[17]+e[3]*e[14]*e[26]+e[3]*e[22]*e[16]+e[3]*e[13]*e[25]+3.*e[6]*e[24]*e[15]+e[6]*e[26]*e[17]+e[6]*e[25]*e[16]+e[0]*e[20]*e[17]+e[0]*e[11]*e[26]+e[0]*e[19]*e[16]+e[0]*e[10]*e[25]+e[15]*e[26]*e[8]-1.*e[15]*e[20]*e[2]-1.*e[15]*e[19]*e[1]-1.*e[15]*e[22]*e[4]+e[15]*e[25]*e[7]-1.*e[15]*e[23]*e[5]+e[12]*e[21]*e[6]+e[12]*e[22]*e[7]+e[12]*e[4]*e[25]+e[12]*e[23]*e[8]+e[12]*e[5]*e[26]-1.*e[24]*e[11]*e[2]-1.*e[24]*e[10]*e[1]-1.*e[24]*e[13]*e[4]+e[24]*e[16]*e[7]-1.*e[24]*e[14]*e[5]+e[24]*e[17]*e[8]+e[21]*e[13]*e[7]+e[21]*e[4]*e[16]+e[21]*e[14]*e[8]+e[21]*e[5]*e[17]-1.*e[6]*e[23]*e[14]-1.*e[6]*e[20]*e[11]-1.*e[6]*e[19]*e[10]-1.*e[6]*e[22]*e[13]+e[9]*e[18]*e[6]+e[9]*e[0]*e[24]+e[9]*e[19]*e[7]+e[9]*e[1]*e[25]+e[9]*e[20]*e[8]+e[9]*e[2]*e[26]+e[18]*e[0]*e[15]+e[18]*e[10]*e[7]+e[18]*e[1]*e[16]+e[18]*e[11]*e[8];
|
||||||
|
A[3]=e[33]*e[10]*e[32]+e[33]*e[28]*e[14]-e[33]*e[13]*e[29]-e[33]*e[31]*e[11]+e[9]*e[31]*e[35]-e[9]*e[32]*e[34]+e[27]*e[13]*e[35]-e[27]*e[32]*e[16]+e[27]*e[31]*e[17]-e[27]*e[14]*e[34]+e[12]*e[34]*e[29]-e[12]*e[28]*e[35]+e[30]*e[34]*e[11]+e[30]*e[16]*e[29]-e[30]*e[10]*e[35]-e[30]*e[28]*e[17]+e[15]*e[28]*e[32]-e[15]*e[31]*e[29];
|
||||||
|
A[145]=e[0]*e[27]*e[6]+e[0]*e[28]*e[7]+e[0]*e[1]*e[34]+e[0]*e[29]*e[8]+e[0]*e[2]*e[35]+e[6]*e[34]*e[7]-1.*e[6]*e[32]*e[5]+e[6]*e[30]*e[3]+e[6]*e[35]*e[8]-1.*e[6]*e[29]*e[2]-1.*e[6]*e[28]*e[1]-1.*e[6]*e[31]*e[4]+e[27]*e[1]*e[7]+e[27]*e[2]*e[8]+e[3]*e[31]*e[7]+e[3]*e[4]*e[34]+e[3]*e[32]*e[8]+e[3]*e[5]*e[35]+e[30]*e[4]*e[7]+e[30]*e[5]*e[8]+.5000000000*ep2[0]*e[33]+1.500000000*e[33]*ep2[6]-.5000000000*e[33]*ep2[4]-.5000000000*e[33]*ep2[5]-.5000000000*e[33]*ep2[1]+.5000000000*e[33]*ep2[7]+.5000000000*e[33]*ep2[3]-.5000000000*e[33]*ep2[2]+.5000000000*e[33]*ep2[8];
|
||||||
|
A[4]=-e[0]*e[23]*e[16]+e[9]*e[4]*e[26]+e[9]*e[22]*e[8]-e[9]*e[5]*e[25]-e[9]*e[23]*e[7]+e[18]*e[4]*e[17]+e[18]*e[13]*e[8]-e[18]*e[5]*e[16]-e[18]*e[14]*e[7]+e[3]*e[16]*e[20]+e[3]*e[25]*e[11]-e[3]*e[10]*e[26]-e[3]*e[19]*e[17]+e[12]*e[7]*e[20]+e[12]*e[25]*e[2]-e[12]*e[1]*e[26]-e[12]*e[19]*e[8]+e[21]*e[7]*e[11]+e[21]*e[16]*e[2]-e[21]*e[1]*e[17]-e[21]*e[10]*e[8]+e[6]*e[10]*e[23]+e[6]*e[19]*e[14]-e[6]*e[13]*e[20]-e[6]*e[22]*e[11]+e[15]*e[1]*e[23]+e[15]*e[19]*e[5]-e[15]*e[4]*e[20]-e[15]*e[22]*e[2]+e[24]*e[1]*e[14]+e[24]*e[10]*e[5]-e[24]*e[4]*e[11]-e[24]*e[13]*e[2]+e[0]*e[13]*e[26]+e[0]*e[22]*e[17]-e[0]*e[14]*e[25];
|
||||||
|
A[150]=e[18]*e[19]*e[25]+.5000000000*ep3[24]-.5000000000*e[24]*ep2[23]+e[18]*e[20]*e[26]+e[21]*e[22]*e[25]+e[21]*e[23]*e[26]-.5000000000*e[24]*ep2[19]+.5000000000*ep2[21]*e[24]+.5000000000*e[24]*ep2[26]-.5000000000*e[24]*ep2[20]+.5000000000*ep2[18]*e[24]-.5000000000*e[24]*ep2[22]+.5000000000*e[24]*ep2[25];
|
||||||
|
A[5]=-e[3]*e[1]*e[35]-e[0]*e[32]*e[7]+e[27]*e[4]*e[8]+e[33]*e[1]*e[5]-e[33]*e[4]*e[2]+e[0]*e[4]*e[35]+e[3]*e[34]*e[2]-e[30]*e[1]*e[8]+e[30]*e[7]*e[2]-e[6]*e[4]*e[29]+e[3]*e[7]*e[29]+e[6]*e[1]*e[32]-e[0]*e[5]*e[34]-e[3]*e[28]*e[8]+e[0]*e[31]*e[8]+e[6]*e[28]*e[5]-e[6]*e[31]*e[2]-e[27]*e[5]*e[7];
|
||||||
|
A[151]=e[33]*e[16]*e[7]-1.*e[33]*e[14]*e[5]+e[33]*e[17]*e[8]+e[30]*e[13]*e[7]+e[30]*e[4]*e[16]+e[30]*e[14]*e[8]+e[30]*e[5]*e[17]+e[6]*e[27]*e[9]-1.*e[6]*e[28]*e[10]-1.*e[6]*e[31]*e[13]-1.*e[6]*e[32]*e[14]-1.*e[6]*e[29]*e[11]+e[9]*e[28]*e[7]+e[9]*e[1]*e[34]+e[9]*e[29]*e[8]+e[9]*e[2]*e[35]+e[27]*e[10]*e[7]+e[27]*e[1]*e[16]+e[27]*e[11]*e[8]+e[27]*e[2]*e[17]+e[3]*e[30]*e[15]+e[3]*e[12]*e[33]+e[3]*e[32]*e[17]+e[3]*e[14]*e[35]+e[3]*e[31]*e[16]+e[3]*e[13]*e[34]+3.*e[6]*e[33]*e[15]+e[6]*e[35]*e[17]+e[6]*e[34]*e[16]+e[0]*e[27]*e[15]+e[0]*e[9]*e[33]+e[0]*e[29]*e[17]+e[0]*e[11]*e[35]+e[0]*e[28]*e[16]+e[0]*e[10]*e[34]+e[15]*e[34]*e[7]-1.*e[15]*e[32]*e[5]+e[15]*e[35]*e[8]-1.*e[15]*e[29]*e[2]-1.*e[15]*e[28]*e[1]-1.*e[15]*e[31]*e[4]+e[12]*e[30]*e[6]+e[12]*e[31]*e[7]+e[12]*e[4]*e[34]+e[12]*e[32]*e[8]+e[12]*e[5]*e[35]-1.*e[33]*e[11]*e[2]-1.*e[33]*e[10]*e[1]-1.*e[33]*e[13]*e[4];
|
||||||
|
A[6]=e[6]*e[1]*e[5]-e[6]*e[4]*e[2]+e[3]*e[7]*e[2]+e[0]*e[4]*e[8]-e[0]*e[5]*e[7]-e[3]*e[1]*e[8];
|
||||||
|
A[148]=.5000000000*ep3[15]+e[9]*e[10]*e[16]-.5000000000*e[15]*ep2[11]+e[9]*e[11]*e[17]+.5000000000*ep2[12]*e[15]+.5000000000*e[15]*ep2[16]+.5000000000*e[15]*ep2[17]-.5000000000*e[15]*ep2[13]+.5000000000*ep2[9]*e[15]+e[12]*e[14]*e[17]-.5000000000*e[15]*ep2[10]-.5000000000*e[15]*ep2[14]+e[12]*e[13]*e[16];
|
||||||
|
A[7]=e[15]*e[28]*e[14]-e[15]*e[13]*e[29]-e[15]*e[31]*e[11]+e[33]*e[10]*e[14]-e[33]*e[13]*e[11]+e[9]*e[13]*e[35]-e[9]*e[32]*e[16]+e[9]*e[31]*e[17]-e[9]*e[14]*e[34]+e[27]*e[13]*e[17]-e[27]*e[14]*e[16]+e[12]*e[34]*e[11]+e[12]*e[16]*e[29]-e[12]*e[10]*e[35]-e[12]*e[28]*e[17]+e[30]*e[16]*e[11]-e[30]*e[10]*e[17]+e[15]*e[10]*e[32];
|
||||||
|
A[149]=e[18]*e[27]*e[24]+e[18]*e[28]*e[25]+e[18]*e[19]*e[34]+e[18]*e[29]*e[26]+e[18]*e[20]*e[35]+e[27]*e[19]*e[25]+e[27]*e[20]*e[26]+e[21]*e[30]*e[24]+e[21]*e[31]*e[25]+e[21]*e[22]*e[34]+e[21]*e[32]*e[26]+e[21]*e[23]*e[35]+e[30]*e[22]*e[25]+e[30]*e[23]*e[26]+e[24]*e[34]*e[25]+e[24]*e[35]*e[26]-1.*e[24]*e[29]*e[20]-1.*e[24]*e[31]*e[22]-1.*e[24]*e[32]*e[23]-1.*e[24]*e[28]*e[19]+1.500000000*e[33]*ep2[24]+.5000000000*e[33]*ep2[25]+.5000000000*e[33]*ep2[26]-.5000000000*e[33]*ep2[23]-.5000000000*e[33]*ep2[19]-.5000000000*e[33]*ep2[20]-.5000000000*e[33]*ep2[22]+.5000000000*ep2[18]*e[33]+.5000000000*ep2[21]*e[33];
|
||||||
|
A[9]=e[21]*e[25]*e[29]-e[27]*e[23]*e[25]+e[24]*e[19]*e[32]-e[21]*e[28]*e[26]-e[21]*e[19]*e[35]+e[18]*e[31]*e[26]-e[30]*e[19]*e[26]-e[24]*e[31]*e[20]+e[24]*e[28]*e[23]+e[27]*e[22]*e[26]+e[30]*e[25]*e[20]-e[33]*e[22]*e[20]+e[33]*e[19]*e[23]+e[21]*e[34]*e[20]-e[18]*e[23]*e[34]-e[24]*e[22]*e[29]-e[18]*e[32]*e[25]+e[18]*e[22]*e[35];
|
||||||
|
A[155]=e[12]*e[14]*e[8]+e[12]*e[5]*e[17]+e[15]*e[16]*e[7]+e[15]*e[17]*e[8]+e[0]*e[11]*e[17]+e[0]*e[9]*e[15]+e[0]*e[10]*e[16]+e[3]*e[14]*e[17]+e[3]*e[13]*e[16]+e[9]*e[10]*e[7]+e[9]*e[1]*e[16]+e[9]*e[11]*e[8]+e[9]*e[2]*e[17]-1.*e[15]*e[11]*e[2]-1.*e[15]*e[10]*e[1]-1.*e[15]*e[13]*e[4]-1.*e[15]*e[14]*e[5]+e[12]*e[3]*e[15]+e[12]*e[13]*e[7]+e[12]*e[4]*e[16]+.5000000000*ep2[12]*e[6]+1.500000000*ep2[15]*e[6]+.5000000000*e[6]*ep2[17]+.5000000000*e[6]*ep2[16]+.5000000000*e[6]*ep2[9]-.5000000000*e[6]*ep2[11]-.5000000000*e[6]*ep2[10]-.5000000000*e[6]*ep2[14]-.5000000000*e[6]*ep2[13];
|
||||||
|
A[8]=-e[9]*e[14]*e[16]-e[12]*e[10]*e[17]+e[9]*e[13]*e[17]-e[15]*e[13]*e[11]+e[15]*e[10]*e[14]+e[12]*e[16]*e[11];
|
||||||
|
A[154]=e[21]*e[14]*e[17]+e[21]*e[13]*e[16]+e[15]*e[26]*e[17]+e[15]*e[25]*e[16]-1.*e[15]*e[23]*e[14]-1.*e[15]*e[20]*e[11]-1.*e[15]*e[19]*e[10]-1.*e[15]*e[22]*e[13]+e[9]*e[20]*e[17]+e[9]*e[11]*e[26]+e[9]*e[19]*e[16]+e[9]*e[10]*e[25]+.5000000000*ep2[12]*e[24]+1.500000000*e[24]*ep2[15]+.5000000000*e[24]*ep2[17]+.5000000000*e[24]*ep2[16]+.5000000000*ep2[9]*e[24]-.5000000000*e[24]*ep2[11]-.5000000000*e[24]*ep2[10]-.5000000000*e[24]*ep2[14]-.5000000000*e[24]*ep2[13]+e[18]*e[11]*e[17]+e[18]*e[9]*e[15]+e[18]*e[10]*e[16]+e[12]*e[21]*e[15]+e[12]*e[23]*e[17]+e[12]*e[14]*e[26]+e[12]*e[22]*e[16]+e[12]*e[13]*e[25];
|
||||||
|
A[11]=-e[9]*e[5]*e[34]+e[9]*e[31]*e[8]-e[9]*e[32]*e[7]+e[27]*e[4]*e[17]+e[27]*e[13]*e[8]-e[27]*e[5]*e[16]-e[27]*e[14]*e[7]+e[0]*e[13]*e[35]-e[0]*e[32]*e[16]+e[0]*e[31]*e[17]-e[0]*e[14]*e[34]+e[9]*e[4]*e[35]+e[6]*e[10]*e[32]+e[6]*e[28]*e[14]-e[6]*e[13]*e[29]-e[6]*e[31]*e[11]+e[15]*e[1]*e[32]+e[3]*e[34]*e[11]+e[3]*e[16]*e[29]-e[3]*e[10]*e[35]-e[3]*e[28]*e[17]-e[12]*e[1]*e[35]+e[12]*e[7]*e[29]+e[12]*e[34]*e[2]-e[12]*e[28]*e[8]+e[15]*e[28]*e[5]-e[15]*e[4]*e[29]-e[15]*e[31]*e[2]+e[33]*e[1]*e[14]+e[33]*e[10]*e[5]-e[33]*e[4]*e[11]-e[33]*e[13]*e[2]+e[30]*e[7]*e[11]+e[30]*e[16]*e[2]-e[30]*e[1]*e[17]-e[30]*e[10]*e[8];
|
||||||
|
A[153]=e[21]*e[31]*e[7]+e[21]*e[4]*e[34]+e[21]*e[32]*e[8]+e[21]*e[5]*e[35]+e[30]*e[22]*e[7]+e[30]*e[4]*e[25]+e[30]*e[23]*e[8]+e[30]*e[5]*e[26]+3.*e[24]*e[33]*e[6]+e[24]*e[34]*e[7]+e[24]*e[35]*e[8]+e[33]*e[25]*e[7]+e[33]*e[26]*e[8]+e[0]*e[27]*e[24]+e[0]*e[18]*e[33]+e[0]*e[28]*e[25]+e[0]*e[19]*e[34]+e[0]*e[29]*e[26]+e[0]*e[20]*e[35]+e[18]*e[27]*e[6]+e[18]*e[28]*e[7]+e[18]*e[1]*e[34]+e[18]*e[29]*e[8]+e[18]*e[2]*e[35]+e[27]*e[19]*e[7]+e[27]*e[1]*e[25]+e[27]*e[20]*e[8]+e[27]*e[2]*e[26]+e[3]*e[30]*e[24]+e[3]*e[21]*e[33]+e[3]*e[31]*e[25]+e[3]*e[22]*e[34]+e[3]*e[32]*e[26]+e[3]*e[23]*e[35]+e[6]*e[30]*e[21]-1.*e[6]*e[29]*e[20]+e[6]*e[35]*e[26]-1.*e[6]*e[31]*e[22]-1.*e[6]*e[32]*e[23]-1.*e[6]*e[28]*e[19]+e[6]*e[34]*e[25]-1.*e[24]*e[32]*e[5]-1.*e[24]*e[29]*e[2]-1.*e[24]*e[28]*e[1]-1.*e[24]*e[31]*e[4]-1.*e[33]*e[20]*e[2]-1.*e[33]*e[19]*e[1]-1.*e[33]*e[22]*e[4]-1.*e[33]*e[23]*e[5];
|
||||||
|
A[10]=e[21]*e[25]*e[20]-e[21]*e[19]*e[26]+e[18]*e[22]*e[26]-e[18]*e[23]*e[25]-e[24]*e[22]*e[20]+e[24]*e[19]*e[23];
|
||||||
|
A[152]=e[3]*e[4]*e[25]+e[3]*e[23]*e[8]+e[3]*e[5]*e[26]+e[21]*e[4]*e[7]+e[21]*e[5]*e[8]+e[6]*e[25]*e[7]+e[6]*e[26]*e[8]+e[0]*e[19]*e[7]+e[0]*e[1]*e[25]+e[0]*e[20]*e[8]+e[0]*e[2]*e[26]-1.*e[6]*e[20]*e[2]-1.*e[6]*e[19]*e[1]-1.*e[6]*e[22]*e[4]-1.*e[6]*e[23]*e[5]+e[18]*e[1]*e[7]+e[18]*e[0]*e[6]+e[18]*e[2]*e[8]+e[3]*e[21]*e[6]+e[3]*e[22]*e[7]-.5000000000*e[24]*ep2[4]+.5000000000*e[24]*ep2[0]+1.500000000*e[24]*ep2[6]-.5000000000*e[24]*ep2[5]-.5000000000*e[24]*ep2[1]+.5000000000*e[24]*ep2[7]+.5000000000*e[24]*ep2[3]-.5000000000*e[24]*ep2[2]+.5000000000*e[24]*ep2[8];
|
||||||
|
A[13]=e[6]*e[28]*e[23]-e[6]*e[22]*e[29]-e[6]*e[31]*e[20]-e[3]*e[19]*e[35]+e[3]*e[34]*e[20]+e[3]*e[25]*e[29]-e[21]*e[1]*e[35]+e[21]*e[7]*e[29]+e[21]*e[34]*e[2]+e[24]*e[1]*e[32]+e[24]*e[28]*e[5]-e[24]*e[4]*e[29]-e[24]*e[31]*e[2]+e[33]*e[1]*e[23]+e[33]*e[19]*e[5]-e[33]*e[4]*e[20]-e[33]*e[22]*e[2]-e[21]*e[28]*e[8]+e[30]*e[7]*e[20]+e[30]*e[25]*e[2]-e[30]*e[1]*e[26]+e[18]*e[4]*e[35]-e[18]*e[5]*e[34]+e[18]*e[31]*e[8]-e[18]*e[32]*e[7]+e[27]*e[4]*e[26]+e[27]*e[22]*e[8]-e[27]*e[5]*e[25]-e[27]*e[23]*e[7]-e[3]*e[28]*e[26]-e[0]*e[32]*e[25]+e[0]*e[22]*e[35]-e[0]*e[23]*e[34]+e[0]*e[31]*e[26]-e[30]*e[19]*e[8]+e[6]*e[19]*e[32];
|
||||||
|
A[159]=.5000000000*ep2[18]*e[6]+.5000000000*ep2[21]*e[6]+1.500000000*ep2[24]*e[6]+.5000000000*e[6]*ep2[26]-.5000000000*e[6]*ep2[23]-.5000000000*e[6]*ep2[19]-.5000000000*e[6]*ep2[20]-.5000000000*e[6]*ep2[22]+.5000000000*e[6]*ep2[25]+e[21]*e[3]*e[24]+e[18]*e[20]*e[8]+e[21]*e[4]*e[25]+e[18]*e[19]*e[7]+e[18]*e[1]*e[25]+e[21]*e[22]*e[7]+e[21]*e[23]*e[8]+e[18]*e[0]*e[24]+e[18]*e[2]*e[26]+e[21]*e[5]*e[26]+e[24]*e[26]*e[8]-1.*e[24]*e[20]*e[2]-1.*e[24]*e[19]*e[1]-1.*e[24]*e[22]*e[4]+e[24]*e[25]*e[7]-1.*e[24]*e[23]*e[5]+e[0]*e[19]*e[25]+e[0]*e[20]*e[26]+e[3]*e[22]*e[25]+e[3]*e[23]*e[26];
|
||||||
|
A[12]=e[18]*e[4]*e[8]+e[3]*e[7]*e[20]+e[3]*e[25]*e[2]-e[3]*e[1]*e[26]-e[18]*e[5]*e[7]+e[6]*e[1]*e[23]+e[6]*e[19]*e[5]-e[6]*e[4]*e[20]-e[6]*e[22]*e[2]+e[21]*e[7]*e[2]-e[21]*e[1]*e[8]+e[24]*e[1]*e[5]-e[24]*e[4]*e[2]-e[3]*e[19]*e[8]+e[0]*e[4]*e[26]+e[0]*e[22]*e[8]-e[0]*e[5]*e[25]-e[0]*e[23]*e[7];
|
||||||
|
A[158]=e[9]*e[1]*e[7]+e[9]*e[0]*e[6]+e[9]*e[2]*e[8]+e[3]*e[12]*e[6]+e[3]*e[13]*e[7]+e[3]*e[4]*e[16]+e[3]*e[14]*e[8]+e[3]*e[5]*e[17]+e[12]*e[4]*e[7]+e[12]*e[5]*e[8]+e[6]*e[16]*e[7]+e[6]*e[17]*e[8]-1.*e[6]*e[11]*e[2]-1.*e[6]*e[10]*e[1]-1.*e[6]*e[13]*e[4]-1.*e[6]*e[14]*e[5]+e[0]*e[10]*e[7]+e[0]*e[1]*e[16]+e[0]*e[11]*e[8]+e[0]*e[2]*e[17]+.5000000000*ep2[3]*e[15]+1.500000000*e[15]*ep2[6]+.5000000000*e[15]*ep2[7]+.5000000000*e[15]*ep2[8]+.5000000000*ep2[0]*e[15]-.5000000000*e[15]*ep2[4]-.5000000000*e[15]*ep2[5]-.5000000000*e[15]*ep2[1]-.5000000000*e[15]*ep2[2];
|
||||||
|
A[15]=-e[15]*e[13]*e[2]-e[6]*e[13]*e[11]-e[15]*e[4]*e[11]+e[12]*e[16]*e[2]-e[3]*e[10]*e[17]+e[3]*e[16]*e[11]+e[0]*e[13]*e[17]-e[0]*e[14]*e[16]+e[15]*e[1]*e[14]-e[12]*e[10]*e[8]+e[9]*e[4]*e[17]+e[9]*e[13]*e[8]-e[9]*e[5]*e[16]-e[9]*e[14]*e[7]+e[15]*e[10]*e[5]+e[12]*e[7]*e[11]+e[6]*e[10]*e[14]-e[12]*e[1]*e[17];
|
||||||
|
A[157]=e[12]*e[30]*e[24]+e[12]*e[21]*e[33]+e[12]*e[31]*e[25]+e[12]*e[22]*e[34]+e[12]*e[32]*e[26]+e[12]*e[23]*e[35]+e[9]*e[27]*e[24]+e[9]*e[18]*e[33]+e[9]*e[28]*e[25]+e[9]*e[19]*e[34]+e[9]*e[29]*e[26]+e[9]*e[20]*e[35]+e[21]*e[30]*e[15]+e[21]*e[32]*e[17]+e[21]*e[14]*e[35]+e[21]*e[31]*e[16]+e[21]*e[13]*e[34]+e[30]*e[23]*e[17]+e[30]*e[14]*e[26]+e[30]*e[22]*e[16]+e[30]*e[13]*e[25]+e[15]*e[27]*e[18]+3.*e[15]*e[33]*e[24]-1.*e[15]*e[29]*e[20]+e[15]*e[35]*e[26]-1.*e[15]*e[31]*e[22]-1.*e[15]*e[32]*e[23]-1.*e[15]*e[28]*e[19]+e[15]*e[34]*e[25]+e[18]*e[29]*e[17]+e[18]*e[11]*e[35]+e[18]*e[28]*e[16]+e[18]*e[10]*e[34]+e[27]*e[20]*e[17]+e[27]*e[11]*e[26]+e[27]*e[19]*e[16]+e[27]*e[10]*e[25]-1.*e[24]*e[28]*e[10]-1.*e[24]*e[31]*e[13]-1.*e[24]*e[32]*e[14]+e[24]*e[34]*e[16]+e[24]*e[35]*e[17]-1.*e[24]*e[29]*e[11]-1.*e[33]*e[23]*e[14]+e[33]*e[25]*e[16]+e[33]*e[26]*e[17]-1.*e[33]*e[20]*e[11]-1.*e[33]*e[19]*e[10]-1.*e[33]*e[22]*e[13];
|
||||||
|
A[14]=e[18]*e[13]*e[17]+e[9]*e[13]*e[26]+e[9]*e[22]*e[17]-e[9]*e[14]*e[25]-e[18]*e[14]*e[16]-e[15]*e[13]*e[20]-e[15]*e[22]*e[11]+e[12]*e[16]*e[20]+e[12]*e[25]*e[11]-e[12]*e[10]*e[26]-e[12]*e[19]*e[17]+e[21]*e[16]*e[11]-e[21]*e[10]*e[17]-e[9]*e[23]*e[16]+e[24]*e[10]*e[14]-e[24]*e[13]*e[11]+e[15]*e[10]*e[23]+e[15]*e[19]*e[14];
|
||||||
|
A[156]=e[21]*e[12]*e[24]+e[21]*e[23]*e[17]+e[21]*e[14]*e[26]+e[21]*e[22]*e[16]+e[21]*e[13]*e[25]+e[24]*e[26]*e[17]+e[24]*e[25]*e[16]+e[9]*e[19]*e[25]+e[9]*e[18]*e[24]+e[9]*e[20]*e[26]+e[12]*e[22]*e[25]+e[12]*e[23]*e[26]+e[18]*e[20]*e[17]+e[18]*e[11]*e[26]+e[18]*e[19]*e[16]+e[18]*e[10]*e[25]-1.*e[24]*e[23]*e[14]-1.*e[24]*e[20]*e[11]-1.*e[24]*e[19]*e[10]-1.*e[24]*e[22]*e[13]+.5000000000*ep2[21]*e[15]+1.500000000*ep2[24]*e[15]+.5000000000*e[15]*ep2[25]+.5000000000*e[15]*ep2[26]+.5000000000*e[15]*ep2[18]-.5000000000*e[15]*ep2[23]-.5000000000*e[15]*ep2[19]-.5000000000*e[15]*ep2[20]-.5000000000*e[15]*ep2[22];
|
||||||
|
A[18]=e[6]*e[1]*e[14]+e[15]*e[1]*e[5]-e[0]*e[5]*e[16]-e[0]*e[14]*e[7]+e[0]*e[13]*e[8]-e[15]*e[4]*e[2]+e[12]*e[7]*e[2]+e[6]*e[10]*e[5]+e[3]*e[7]*e[11]-e[6]*e[4]*e[11]+e[3]*e[16]*e[2]-e[6]*e[13]*e[2]-e[3]*e[1]*e[17]-e[9]*e[5]*e[7]-e[3]*e[10]*e[8]-e[12]*e[1]*e[8]+e[0]*e[4]*e[17]+e[9]*e[4]*e[8];
|
||||||
|
A[128]=-.5000000000*e[14]*ep2[16]-.5000000000*e[14]*ep2[10]-.5000000000*e[14]*ep2[9]+e[11]*e[9]*e[12]+.5000000000*ep3[14]+e[17]*e[13]*e[16]+.5000000000*e[14]*ep2[12]+e[11]*e[10]*e[13]-.5000000000*e[14]*ep2[15]+.5000000000*e[14]*ep2[17]+e[17]*e[12]*e[15]+.5000000000*ep2[11]*e[14]+.5000000000*e[14]*ep2[13];
|
||||||
|
A[19]=-e[21]*e[19]*e[8]+e[18]*e[4]*e[26]-e[18]*e[5]*e[25]-e[18]*e[23]*e[7]+e[21]*e[25]*e[2]-e[21]*e[1]*e[26]+e[6]*e[19]*e[23]+e[18]*e[22]*e[8]-e[0]*e[23]*e[25]-e[6]*e[22]*e[20]+e[24]*e[1]*e[23]+e[24]*e[19]*e[5]-e[24]*e[4]*e[20]-e[24]*e[22]*e[2]+e[3]*e[25]*e[20]-e[3]*e[19]*e[26]+e[0]*e[22]*e[26]+e[21]*e[7]*e[20];
|
||||||
|
A[129]=.5000000000*ep2[20]*e[32]+1.500000000*e[32]*ep2[23]+.5000000000*e[32]*ep2[22]+.5000000000*e[32]*ep2[21]+.5000000000*e[32]*ep2[26]-.5000000000*e[32]*ep2[18]-.5000000000*e[32]*ep2[19]-.5000000000*e[32]*ep2[24]-.5000000000*e[32]*ep2[25]+e[20]*e[27]*e[21]+e[20]*e[18]*e[30]+e[20]*e[28]*e[22]+e[20]*e[19]*e[31]+e[20]*e[29]*e[23]+e[29]*e[19]*e[22]+e[29]*e[18]*e[21]+e[23]*e[30]*e[21]+e[23]*e[31]*e[22]+e[26]*e[30]*e[24]+e[26]*e[21]*e[33]+e[26]*e[31]*e[25]+e[26]*e[22]*e[34]+e[26]*e[23]*e[35]+e[35]*e[22]*e[25]+e[35]*e[21]*e[24]-1.*e[23]*e[27]*e[18]-1.*e[23]*e[33]*e[24]-1.*e[23]*e[28]*e[19]-1.*e[23]*e[34]*e[25];
|
||||||
|
A[16]=-e[9]*e[23]*e[25]-e[21]*e[10]*e[26]-e[21]*e[19]*e[17]-e[18]*e[23]*e[16]+e[18]*e[13]*e[26]+e[12]*e[25]*e[20]-e[12]*e[19]*e[26]-e[15]*e[22]*e[20]+e[21]*e[16]*e[20]+e[21]*e[25]*e[11]+e[24]*e[10]*e[23]+e[24]*e[19]*e[14]-e[24]*e[13]*e[20]-e[24]*e[22]*e[11]+e[18]*e[22]*e[17]-e[18]*e[14]*e[25]+e[9]*e[22]*e[26]+e[15]*e[19]*e[23];
|
||||||
|
A[130]=.5000000000*e[23]*ep2[21]+e[20]*e[19]*e[22]+e[20]*e[18]*e[21]+.5000000000*ep3[23]+e[26]*e[22]*e[25]+.5000000000*e[23]*ep2[26]-.5000000000*e[23]*ep2[18]+.5000000000*e[23]*ep2[22]-.5000000000*e[23]*ep2[19]+e[26]*e[21]*e[24]+.5000000000*ep2[20]*e[23]-.5000000000*e[23]*ep2[24]-.5000000000*e[23]*ep2[25];
|
||||||
|
A[17]=e[18]*e[13]*e[35]-e[18]*e[32]*e[16]+e[18]*e[31]*e[17]-e[18]*e[14]*e[34]+e[27]*e[13]*e[26]+e[27]*e[22]*e[17]-e[27]*e[14]*e[25]-e[27]*e[23]*e[16]-e[9]*e[32]*e[25]+e[9]*e[22]*e[35]-e[9]*e[23]*e[34]+e[9]*e[31]*e[26]+e[15]*e[19]*e[32]+e[15]*e[28]*e[23]-e[15]*e[22]*e[29]-e[15]*e[31]*e[20]+e[24]*e[10]*e[32]+e[24]*e[28]*e[14]-e[24]*e[13]*e[29]-e[24]*e[31]*e[11]+e[33]*e[10]*e[23]+e[33]*e[19]*e[14]-e[33]*e[13]*e[20]-e[33]*e[22]*e[11]+e[21]*e[16]*e[29]-e[21]*e[10]*e[35]-e[21]*e[28]*e[17]+e[30]*e[16]*e[20]+e[30]*e[25]*e[11]-e[30]*e[10]*e[26]-e[30]*e[19]*e[17]-e[12]*e[28]*e[26]-e[12]*e[19]*e[35]+e[12]*e[34]*e[20]+e[12]*e[25]*e[29]+e[21]*e[34]*e[11];
|
||||||
|
A[131]=-1.*e[32]*e[10]*e[1]+e[32]*e[13]*e[4]-1.*e[32]*e[16]*e[7]-1.*e[32]*e[15]*e[6]-1.*e[32]*e[9]*e[0]+e[32]*e[12]*e[3]+e[17]*e[30]*e[6]+e[17]*e[3]*e[33]+e[17]*e[31]*e[7]+e[17]*e[4]*e[34]+e[17]*e[5]*e[35]-1.*e[5]*e[27]*e[9]-1.*e[5]*e[28]*e[10]-1.*e[5]*e[33]*e[15]-1.*e[5]*e[34]*e[16]+e[5]*e[29]*e[11]+e[35]*e[12]*e[6]+e[35]*e[3]*e[15]+e[35]*e[13]*e[7]+e[35]*e[4]*e[16]+e[11]*e[27]*e[3]+e[11]*e[0]*e[30]+e[11]*e[28]*e[4]+e[11]*e[1]*e[31]+e[29]*e[9]*e[3]+e[29]*e[0]*e[12]+e[29]*e[10]*e[4]+e[29]*e[1]*e[13]+e[5]*e[30]*e[12]+3.*e[5]*e[32]*e[14]+e[5]*e[31]*e[13]+e[8]*e[30]*e[15]+e[8]*e[12]*e[33]+e[8]*e[32]*e[17]+e[8]*e[14]*e[35]+e[8]*e[31]*e[16]+e[8]*e[13]*e[34]+e[2]*e[27]*e[12]+e[2]*e[9]*e[30]+e[2]*e[29]*e[14]+e[2]*e[11]*e[32]+e[2]*e[28]*e[13]+e[2]*e[10]*e[31]-1.*e[14]*e[27]*e[0]-1.*e[14]*e[34]*e[7]-1.*e[14]*e[33]*e[6]+e[14]*e[30]*e[3]-1.*e[14]*e[28]*e[1]+e[14]*e[31]*e[4];
|
||||||
|
A[22]=.5000000000*e[18]*ep2[29]+.5000000000*e[18]*ep2[28]+.5000000000*e[18]*ep2[30]+.5000000000*e[18]*ep2[33]-.5000000000*e[18]*ep2[32]-.5000000000*e[18]*ep2[31]-.5000000000*e[18]*ep2[34]-.5000000000*e[18]*ep2[35]+1.500000000*e[18]*ep2[27]+e[27]*e[28]*e[19]+e[27]*e[29]*e[20]+e[21]*e[27]*e[30]+e[21]*e[29]*e[32]+e[21]*e[28]*e[31]+e[30]*e[28]*e[22]+e[30]*e[19]*e[31]+e[30]*e[29]*e[23]+e[30]*e[20]*e[32]+e[24]*e[27]*e[33]+e[24]*e[29]*e[35]+e[24]*e[28]*e[34]+e[33]*e[28]*e[25]+e[33]*e[19]*e[34]+e[33]*e[29]*e[26]+e[33]*e[20]*e[35]-1.*e[27]*e[35]*e[26]-1.*e[27]*e[31]*e[22]-1.*e[27]*e[32]*e[23]-1.*e[27]*e[34]*e[25];
|
||||||
|
A[132]=e[20]*e[1]*e[4]+e[20]*e[0]*e[3]+e[20]*e[2]*e[5]+e[5]*e[21]*e[3]+e[5]*e[22]*e[4]+e[8]*e[21]*e[6]+e[8]*e[3]*e[24]+e[8]*e[22]*e[7]+e[8]*e[4]*e[25]+e[8]*e[5]*e[26]+e[26]*e[4]*e[7]+e[26]*e[3]*e[6]+e[2]*e[18]*e[3]+e[2]*e[0]*e[21]+e[2]*e[19]*e[4]+e[2]*e[1]*e[22]-1.*e[5]*e[19]*e[1]-1.*e[5]*e[18]*e[0]-1.*e[5]*e[25]*e[7]-1.*e[5]*e[24]*e[6]+.5000000000*e[23]*ep2[4]-.5000000000*e[23]*ep2[0]-.5000000000*e[23]*ep2[6]+1.500000000*e[23]*ep2[5]-.5000000000*e[23]*ep2[1]-.5000000000*e[23]*ep2[7]+.5000000000*e[23]*ep2[3]+.5000000000*e[23]*ep2[2]+.5000000000*e[23]*ep2[8];
|
||||||
|
A[23]=1.500000000*e[9]*ep2[27]+.5000000000*e[9]*ep2[29]+.5000000000*e[9]*ep2[28]-.5000000000*e[9]*ep2[32]-.5000000000*e[9]*ep2[31]+.5000000000*e[9]*ep2[33]+.5000000000*e[9]*ep2[30]-.5000000000*e[9]*ep2[34]-.5000000000*e[9]*ep2[35]+e[33]*e[27]*e[15]+e[33]*e[29]*e[17]+e[33]*e[11]*e[35]+e[33]*e[28]*e[16]+e[33]*e[10]*e[34]+e[27]*e[29]*e[11]+e[27]*e[28]*e[10]+e[27]*e[30]*e[12]-1.*e[27]*e[31]*e[13]-1.*e[27]*e[32]*e[14]-1.*e[27]*e[34]*e[16]-1.*e[27]*e[35]*e[17]+e[30]*e[29]*e[14]+e[30]*e[11]*e[32]+e[30]*e[28]*e[13]+e[30]*e[10]*e[31]+e[12]*e[29]*e[32]+e[12]*e[28]*e[31]+e[15]*e[29]*e[35]+e[15]*e[28]*e[34];
|
||||||
|
A[133]=-1.*e[32]*e[24]*e[6]+e[8]*e[30]*e[24]+e[8]*e[21]*e[33]+e[8]*e[31]*e[25]+e[8]*e[22]*e[34]+e[26]*e[30]*e[6]+e[26]*e[3]*e[33]+e[26]*e[31]*e[7]+e[26]*e[4]*e[34]+e[26]*e[32]*e[8]+e[26]*e[5]*e[35]+e[35]*e[21]*e[6]+e[35]*e[3]*e[24]+e[35]*e[22]*e[7]+e[35]*e[4]*e[25]+e[35]*e[23]*e[8]+e[2]*e[27]*e[21]+e[2]*e[18]*e[30]+e[2]*e[28]*e[22]+e[2]*e[19]*e[31]+e[2]*e[29]*e[23]+e[2]*e[20]*e[32]+e[20]*e[27]*e[3]+e[20]*e[0]*e[30]+e[20]*e[28]*e[4]+e[20]*e[1]*e[31]+e[20]*e[29]*e[5]+e[29]*e[18]*e[3]+e[29]*e[0]*e[21]+e[29]*e[19]*e[4]+e[29]*e[1]*e[22]+e[5]*e[30]*e[21]+e[5]*e[31]*e[22]+3.*e[5]*e[32]*e[23]-1.*e[5]*e[27]*e[18]-1.*e[5]*e[33]*e[24]-1.*e[5]*e[28]*e[19]-1.*e[5]*e[34]*e[25]-1.*e[23]*e[27]*e[0]-1.*e[23]*e[34]*e[7]-1.*e[23]*e[33]*e[6]+e[23]*e[30]*e[3]-1.*e[23]*e[28]*e[1]+e[23]*e[31]*e[4]+e[32]*e[21]*e[3]-1.*e[32]*e[19]*e[1]+e[32]*e[22]*e[4]-1.*e[32]*e[18]*e[0]-1.*e[32]*e[25]*e[7];
|
||||||
|
A[20]=.5000000000*e[27]*ep2[33]-.5000000000*e[27]*ep2[32]-.5000000000*e[27]*ep2[31]-.5000000000*e[27]*ep2[34]-.5000000000*e[27]*ep2[35]+e[33]*e[29]*e[35]+.5000000000*e[27]*ep2[29]+e[30]*e[29]*e[32]+e[30]*e[28]*e[31]+e[33]*e[28]*e[34]+.5000000000*e[27]*ep2[28]+.5000000000*e[27]*ep2[30]+.5000000000*ep3[27];
|
||||||
|
A[134]=e[14]*e[21]*e[12]+e[14]*e[22]*e[13]+e[17]*e[21]*e[15]+e[17]*e[12]*e[24]+e[17]*e[14]*e[26]+e[17]*e[22]*e[16]+e[17]*e[13]*e[25]+e[26]*e[12]*e[15]+e[26]*e[13]*e[16]-1.*e[14]*e[24]*e[15]-1.*e[14]*e[25]*e[16]-1.*e[14]*e[18]*e[9]-1.*e[14]*e[19]*e[10]+e[11]*e[18]*e[12]+e[11]*e[9]*e[21]+e[11]*e[19]*e[13]+e[11]*e[10]*e[22]+e[20]*e[11]*e[14]+e[20]*e[9]*e[12]+e[20]*e[10]*e[13]+1.500000000*e[23]*ep2[14]+.5000000000*e[23]*ep2[12]+.5000000000*e[23]*ep2[13]+.5000000000*e[23]*ep2[17]+.5000000000*ep2[11]*e[23]-.5000000000*e[23]*ep2[16]-.5000000000*e[23]*ep2[9]-.5000000000*e[23]*ep2[15]-.5000000000*e[23]*ep2[10];
|
||||||
|
A[21]=1.500000000*e[0]*ep2[27]+.5000000000*e[0]*ep2[29]+.5000000000*e[0]*ep2[28]+.5000000000*e[0]*ep2[30]-.5000000000*e[0]*ep2[32]-.5000000000*e[0]*ep2[31]+.5000000000*e[0]*ep2[33]-.5000000000*e[0]*ep2[34]-.5000000000*e[0]*ep2[35]-1.*e[27]*e[31]*e[4]+e[3]*e[27]*e[30]+e[3]*e[29]*e[32]+e[3]*e[28]*e[31]+e[30]*e[28]*e[4]+e[30]*e[1]*e[31]+e[30]*e[29]*e[5]+e[30]*e[2]*e[32]+e[6]*e[27]*e[33]+e[6]*e[29]*e[35]+e[6]*e[28]*e[34]+e[27]*e[28]*e[1]+e[27]*e[29]*e[2]+e[33]*e[28]*e[7]+e[33]*e[1]*e[34]+e[33]*e[29]*e[8]+e[33]*e[2]*e[35]-1.*e[27]*e[34]*e[7]-1.*e[27]*e[32]*e[5]-1.*e[27]*e[35]*e[8];
|
||||||
|
A[135]=e[14]*e[12]*e[3]+e[14]*e[13]*e[4]+e[17]*e[12]*e[6]+e[17]*e[3]*e[15]+e[17]*e[13]*e[7]+e[17]*e[4]*e[16]+e[17]*e[14]*e[8]+e[8]*e[12]*e[15]+e[8]*e[13]*e[16]+e[2]*e[11]*e[14]+e[2]*e[9]*e[12]+e[2]*e[10]*e[13]+e[11]*e[9]*e[3]+e[11]*e[0]*e[12]+e[11]*e[10]*e[4]+e[11]*e[1]*e[13]-1.*e[14]*e[10]*e[1]-1.*e[14]*e[16]*e[7]-1.*e[14]*e[15]*e[6]-1.*e[14]*e[9]*e[0]-.5000000000*e[5]*ep2[16]-.5000000000*e[5]*ep2[9]+.5000000000*e[5]*ep2[11]+.5000000000*e[5]*ep2[12]-.5000000000*e[5]*ep2[15]-.5000000000*e[5]*ep2[10]+.5000000000*e[5]*ep2[13]+1.500000000*ep2[14]*e[5]+.5000000000*e[5]*ep2[17];
|
||||||
|
A[27]=1.500000000*e[27]*ep2[9]-.5000000000*e[27]*ep2[16]+.5000000000*e[27]*ep2[11]+.5000000000*e[27]*ep2[12]+.5000000000*e[27]*ep2[15]-.5000000000*e[27]*ep2[17]+.5000000000*e[27]*ep2[10]-.5000000000*e[27]*ep2[14]-.5000000000*e[27]*ep2[13]+e[12]*e[10]*e[31]+e[30]*e[11]*e[14]+e[30]*e[10]*e[13]+e[15]*e[9]*e[33]+e[15]*e[29]*e[17]+e[15]*e[11]*e[35]+e[15]*e[28]*e[16]+e[15]*e[10]*e[34]+e[33]*e[11]*e[17]+e[33]*e[10]*e[16]-1.*e[9]*e[31]*e[13]-1.*e[9]*e[32]*e[14]-1.*e[9]*e[34]*e[16]-1.*e[9]*e[35]*e[17]+e[9]*e[29]*e[11]+e[9]*e[28]*e[10]+e[12]*e[9]*e[30]+e[12]*e[29]*e[14]+e[12]*e[11]*e[32]+e[12]*e[28]*e[13];
|
||||||
|
A[137]=e[29]*e[18]*e[12]+e[29]*e[9]*e[21]+e[29]*e[19]*e[13]+e[29]*e[10]*e[22]+e[17]*e[30]*e[24]+e[17]*e[21]*e[33]+e[17]*e[31]*e[25]+e[17]*e[22]*e[34]+e[17]*e[32]*e[26]+e[17]*e[23]*e[35]-1.*e[23]*e[27]*e[9]-1.*e[23]*e[28]*e[10]-1.*e[23]*e[33]*e[15]-1.*e[23]*e[34]*e[16]-1.*e[32]*e[24]*e[15]-1.*e[32]*e[25]*e[16]-1.*e[32]*e[18]*e[9]-1.*e[32]*e[19]*e[10]+e[26]*e[30]*e[15]+e[26]*e[12]*e[33]+e[26]*e[31]*e[16]+e[26]*e[13]*e[34]+e[35]*e[21]*e[15]+e[35]*e[12]*e[24]+e[35]*e[22]*e[16]+e[35]*e[13]*e[25]+e[14]*e[30]*e[21]+e[14]*e[31]*e[22]+3.*e[14]*e[32]*e[23]+e[11]*e[27]*e[21]+e[11]*e[18]*e[30]+e[11]*e[28]*e[22]+e[11]*e[19]*e[31]+e[11]*e[29]*e[23]+e[11]*e[20]*e[32]+e[23]*e[30]*e[12]+e[23]*e[31]*e[13]+e[32]*e[21]*e[12]+e[32]*e[22]*e[13]-1.*e[14]*e[27]*e[18]-1.*e[14]*e[33]*e[24]+e[14]*e[29]*e[20]+e[14]*e[35]*e[26]-1.*e[14]*e[28]*e[19]-1.*e[14]*e[34]*e[25]+e[20]*e[27]*e[12]+e[20]*e[9]*e[30]+e[20]*e[28]*e[13]+e[20]*e[10]*e[31];
|
||||||
|
A[26]=.5000000000*e[0]*ep2[1]+.5000000000*e[0]*ep2[2]+e[6]*e[2]*e[8]+e[6]*e[1]*e[7]+.5000000000*e[0]*ep2[3]+e[3]*e[1]*e[4]+.5000000000*e[0]*ep2[6]+e[3]*e[2]*e[5]-.5000000000*e[0]*ep2[5]-.5000000000*e[0]*ep2[8]+.5000000000*ep3[0]-.5000000000*e[0]*ep2[7]-.5000000000*e[0]*ep2[4];
|
||||||
|
A[136]=1.500000000*ep2[23]*e[14]+.5000000000*e[14]*ep2[26]-.5000000000*e[14]*ep2[18]-.5000000000*e[14]*ep2[19]+.5000000000*e[14]*ep2[20]+.5000000000*e[14]*ep2[22]-.5000000000*e[14]*ep2[24]+.5000000000*e[14]*ep2[21]-.5000000000*e[14]*ep2[25]+e[23]*e[21]*e[12]+e[23]*e[22]*e[13]+e[26]*e[21]*e[15]+e[26]*e[12]*e[24]+e[26]*e[23]*e[17]+e[26]*e[22]*e[16]+e[26]*e[13]*e[25]+e[17]*e[22]*e[25]+e[17]*e[21]*e[24]+e[11]*e[19]*e[22]+e[11]*e[18]*e[21]+e[11]*e[20]*e[23]+e[20]*e[18]*e[12]+e[20]*e[9]*e[21]+e[20]*e[19]*e[13]+e[20]*e[10]*e[22]-1.*e[23]*e[24]*e[15]-1.*e[23]*e[25]*e[16]-1.*e[23]*e[18]*e[9]-1.*e[23]*e[19]*e[10];
|
||||||
|
A[25]=1.500000000*e[27]*ep2[0]-.5000000000*e[27]*ep2[4]+.5000000000*e[27]*ep2[6]-.5000000000*e[27]*ep2[5]+.5000000000*e[27]*ep2[1]-.5000000000*e[27]*ep2[7]+.5000000000*e[27]*ep2[3]+.5000000000*e[27]*ep2[2]-.5000000000*e[27]*ep2[8]+e[0]*e[33]*e[6]+e[0]*e[30]*e[3]-1.*e[0]*e[35]*e[8]-1.*e[0]*e[31]*e[4]+e[3]*e[28]*e[4]+e[3]*e[1]*e[31]+e[3]*e[29]*e[5]+e[3]*e[2]*e[32]+e[30]*e[1]*e[4]+e[30]*e[2]*e[5]+e[6]*e[28]*e[7]+e[6]*e[1]*e[34]+e[6]*e[29]*e[8]+e[6]*e[2]*e[35]+e[33]*e[1]*e[7]+e[33]*e[2]*e[8]+e[0]*e[28]*e[1]+e[0]*e[29]*e[2]-1.*e[0]*e[34]*e[7]-1.*e[0]*e[32]*e[5];
|
||||||
|
A[139]=e[8]*e[22]*e[25]+e[8]*e[21]*e[24]+e[20]*e[18]*e[3]+e[20]*e[0]*e[21]+e[20]*e[19]*e[4]+e[20]*e[1]*e[22]+e[20]*e[2]*e[23]+e[23]*e[21]*e[3]+e[23]*e[22]*e[4]+e[23]*e[26]*e[8]-1.*e[23]*e[19]*e[1]-1.*e[23]*e[18]*e[0]-1.*e[23]*e[25]*e[7]-1.*e[23]*e[24]*e[6]+e[2]*e[19]*e[22]+e[2]*e[18]*e[21]+e[26]*e[21]*e[6]+e[26]*e[3]*e[24]+e[26]*e[22]*e[7]+e[26]*e[4]*e[25]+.5000000000*ep2[20]*e[5]+1.500000000*ep2[23]*e[5]+.5000000000*e[5]*ep2[22]+.5000000000*e[5]*ep2[21]+.5000000000*e[5]*ep2[26]-.5000000000*e[5]*ep2[18]-.5000000000*e[5]*ep2[19]-.5000000000*e[5]*ep2[24]-.5000000000*e[5]*ep2[25];
|
||||||
|
A[24]=e[24]*e[11]*e[8]+e[24]*e[2]*e[17]+3.*e[9]*e[18]*e[0]+e[9]*e[19]*e[1]+e[9]*e[20]*e[2]+e[18]*e[10]*e[1]+e[18]*e[11]*e[2]+e[3]*e[18]*e[12]+e[3]*e[9]*e[21]+e[3]*e[20]*e[14]+e[3]*e[11]*e[23]+e[3]*e[19]*e[13]+e[3]*e[10]*e[22]+e[6]*e[18]*e[15]+e[6]*e[9]*e[24]+e[6]*e[20]*e[17]+e[6]*e[11]*e[26]+e[6]*e[19]*e[16]+e[6]*e[10]*e[25]+e[0]*e[20]*e[11]+e[0]*e[19]*e[10]-1.*e[9]*e[26]*e[8]-1.*e[9]*e[22]*e[4]-1.*e[9]*e[25]*e[7]-1.*e[9]*e[23]*e[5]+e[12]*e[0]*e[21]+e[12]*e[19]*e[4]+e[12]*e[1]*e[22]+e[12]*e[20]*e[5]+e[12]*e[2]*e[23]-1.*e[18]*e[13]*e[4]-1.*e[18]*e[16]*e[7]-1.*e[18]*e[14]*e[5]-1.*e[18]*e[17]*e[8]+e[21]*e[10]*e[4]+e[21]*e[1]*e[13]+e[21]*e[11]*e[5]+e[21]*e[2]*e[14]+e[15]*e[0]*e[24]+e[15]*e[19]*e[7]+e[15]*e[1]*e[25]+e[15]*e[20]*e[8]+e[15]*e[2]*e[26]-1.*e[0]*e[23]*e[14]-1.*e[0]*e[25]*e[16]-1.*e[0]*e[26]*e[17]-1.*e[0]*e[22]*e[13]+e[24]*e[10]*e[7]+e[24]*e[1]*e[16];
|
||||||
|
A[138]=e[11]*e[1]*e[4]+e[11]*e[0]*e[3]+e[11]*e[2]*e[5]+e[5]*e[12]*e[3]+e[5]*e[13]*e[4]+e[8]*e[12]*e[6]+e[8]*e[3]*e[15]+e[8]*e[13]*e[7]+e[8]*e[4]*e[16]+e[8]*e[5]*e[17]+e[17]*e[4]*e[7]+e[17]*e[3]*e[6]-1.*e[5]*e[10]*e[1]-1.*e[5]*e[16]*e[7]-1.*e[5]*e[15]*e[6]-1.*e[5]*e[9]*e[0]+e[2]*e[9]*e[3]+e[2]*e[0]*e[12]+e[2]*e[10]*e[4]+e[2]*e[1]*e[13]+.5000000000*ep2[2]*e[14]-.5000000000*e[14]*ep2[0]-.5000000000*e[14]*ep2[6]-.5000000000*e[14]*ep2[1]-.5000000000*e[14]*ep2[7]+1.500000000*e[14]*ep2[5]+.5000000000*e[14]*ep2[4]+.5000000000*e[14]*ep2[3]+.5000000000*e[14]*ep2[8];
|
||||||
|
A[31]=e[3]*e[27]*e[12]+e[3]*e[9]*e[30]+e[3]*e[29]*e[14]+e[3]*e[11]*e[32]+e[3]*e[28]*e[13]+e[3]*e[10]*e[31]+e[6]*e[27]*e[15]+e[6]*e[9]*e[33]+e[6]*e[29]*e[17]+e[6]*e[11]*e[35]+e[6]*e[28]*e[16]+e[6]*e[10]*e[34]+3.*e[0]*e[27]*e[9]+e[0]*e[29]*e[11]+e[0]*e[28]*e[10]-1.*e[9]*e[34]*e[7]-1.*e[9]*e[32]*e[5]-1.*e[9]*e[35]*e[8]+e[9]*e[29]*e[2]+e[9]*e[28]*e[1]-1.*e[9]*e[31]*e[4]+e[12]*e[0]*e[30]+e[12]*e[28]*e[4]+e[12]*e[1]*e[31]+e[12]*e[29]*e[5]+e[12]*e[2]*e[32]+e[27]*e[11]*e[2]+e[27]*e[10]*e[1]-1.*e[27]*e[13]*e[4]-1.*e[27]*e[16]*e[7]-1.*e[27]*e[14]*e[5]-1.*e[27]*e[17]*e[8]+e[30]*e[10]*e[4]+e[30]*e[1]*e[13]+e[30]*e[11]*e[5]+e[30]*e[2]*e[14]+e[15]*e[0]*e[33]+e[15]*e[28]*e[7]+e[15]*e[1]*e[34]+e[15]*e[29]*e[8]+e[15]*e[2]*e[35]-1.*e[0]*e[31]*e[13]-1.*e[0]*e[32]*e[14]-1.*e[0]*e[34]*e[16]-1.*e[0]*e[35]*e[17]+e[33]*e[10]*e[7]+e[33]*e[1]*e[16]+e[33]*e[11]*e[8]+e[33]*e[2]*e[17];
|
||||||
|
A[141]=.5000000000*ep2[30]*e[6]+.5000000000*e[6]*ep2[27]-.5000000000*e[6]*ep2[32]-.5000000000*e[6]*ep2[28]-.5000000000*e[6]*ep2[29]-.5000000000*e[6]*ep2[31]+1.500000000*e[6]*ep2[33]+.5000000000*e[6]*ep2[34]+.5000000000*e[6]*ep2[35]+e[0]*e[27]*e[33]+e[0]*e[29]*e[35]+e[0]*e[28]*e[34]+e[3]*e[30]*e[33]+e[3]*e[32]*e[35]+e[3]*e[31]*e[34]+e[30]*e[31]*e[7]+e[30]*e[4]*e[34]+e[30]*e[32]*e[8]+e[30]*e[5]*e[35]+e[27]*e[28]*e[7]+e[27]*e[1]*e[34]+e[27]*e[29]*e[8]+e[27]*e[2]*e[35]+e[33]*e[34]*e[7]+e[33]*e[35]*e[8]-1.*e[33]*e[32]*e[5]-1.*e[33]*e[29]*e[2]-1.*e[33]*e[28]*e[1]-1.*e[33]*e[31]*e[4];
|
||||||
|
A[30]=e[24]*e[20]*e[26]+e[21]*e[19]*e[22]-.5000000000*e[18]*ep2[22]-.5000000000*e[18]*ep2[25]+.5000000000*ep3[18]+.5000000000*e[18]*ep2[21]+e[21]*e[20]*e[23]+.5000000000*e[18]*ep2[20]+.5000000000*e[18]*ep2[19]+.5000000000*e[18]*ep2[24]+e[24]*e[19]*e[25]-.5000000000*e[18]*ep2[23]-.5000000000*e[18]*ep2[26];
|
||||||
|
A[140]=.5000000000*e[33]*ep2[35]+.5000000000*ep3[33]+.5000000000*ep2[27]*e[33]+.5000000000*ep2[30]*e[33]-.5000000000*e[33]*ep2[29]+.5000000000*e[33]*ep2[34]-.5000000000*e[33]*ep2[32]-.5000000000*e[33]*ep2[28]+e[30]*e[32]*e[35]-.5000000000*e[33]*ep2[31]+e[27]*e[29]*e[35]+e[27]*e[28]*e[34]+e[30]*e[31]*e[34];
|
||||||
|
A[29]=1.500000000*e[27]*ep2[18]+.5000000000*e[27]*ep2[19]+.5000000000*e[27]*ep2[20]+.5000000000*e[27]*ep2[21]+.5000000000*e[27]*ep2[24]-.5000000000*e[27]*ep2[26]-.5000000000*e[27]*ep2[23]-.5000000000*e[27]*ep2[22]-.5000000000*e[27]*ep2[25]+e[33]*e[20]*e[26]-1.*e[18]*e[35]*e[26]-1.*e[18]*e[31]*e[22]-1.*e[18]*e[32]*e[23]-1.*e[18]*e[34]*e[25]+e[18]*e[28]*e[19]+e[18]*e[29]*e[20]+e[21]*e[18]*e[30]+e[21]*e[28]*e[22]+e[21]*e[19]*e[31]+e[21]*e[29]*e[23]+e[21]*e[20]*e[32]+e[30]*e[19]*e[22]+e[30]*e[20]*e[23]+e[24]*e[18]*e[33]+e[24]*e[28]*e[25]+e[24]*e[19]*e[34]+e[24]*e[29]*e[26]+e[24]*e[20]*e[35]+e[33]*e[19]*e[25];
|
||||||
|
A[143]=e[9]*e[27]*e[33]+e[9]*e[29]*e[35]+e[9]*e[28]*e[34]+e[33]*e[35]*e[17]+e[33]*e[34]*e[16]+e[27]*e[29]*e[17]+e[27]*e[11]*e[35]+e[27]*e[28]*e[16]+e[27]*e[10]*e[34]+e[33]*e[30]*e[12]-1.*e[33]*e[28]*e[10]-1.*e[33]*e[31]*e[13]-1.*e[33]*e[32]*e[14]-1.*e[33]*e[29]*e[11]+e[30]*e[32]*e[17]+e[30]*e[14]*e[35]+e[30]*e[31]*e[16]+e[30]*e[13]*e[34]+e[12]*e[32]*e[35]+e[12]*e[31]*e[34]+.5000000000*e[15]*ep2[27]-.5000000000*e[15]*ep2[32]-.5000000000*e[15]*ep2[28]-.5000000000*e[15]*ep2[29]-.5000000000*e[15]*ep2[31]+1.500000000*e[15]*ep2[33]+.5000000000*e[15]*ep2[30]+.5000000000*e[15]*ep2[34]+.5000000000*e[15]*ep2[35];
|
||||||
|
A[28]=.5000000000*e[9]*ep2[12]-.5000000000*e[9]*ep2[16]+.5000000000*e[9]*ep2[10]-.5000000000*e[9]*ep2[17]-.5000000000*e[9]*ep2[13]+e[15]*e[10]*e[16]+e[12]*e[11]*e[14]+.5000000000*e[9]*ep2[11]+.5000000000*e[9]*ep2[15]-.5000000000*e[9]*ep2[14]+e[15]*e[11]*e[17]+.5000000000*ep3[9]+e[12]*e[10]*e[13];
|
||||||
|
A[142]=e[18]*e[27]*e[33]+e[18]*e[29]*e[35]+e[18]*e[28]*e[34]+e[27]*e[28]*e[25]+e[27]*e[19]*e[34]+e[27]*e[29]*e[26]+e[27]*e[20]*e[35]+e[21]*e[30]*e[33]+e[21]*e[32]*e[35]+e[21]*e[31]*e[34]+e[30]*e[31]*e[25]+e[30]*e[22]*e[34]+e[30]*e[32]*e[26]+e[30]*e[23]*e[35]+e[33]*e[34]*e[25]+e[33]*e[35]*e[26]-1.*e[33]*e[29]*e[20]-1.*e[33]*e[31]*e[22]-1.*e[33]*e[32]*e[23]-1.*e[33]*e[28]*e[19]+.5000000000*ep2[27]*e[24]+.5000000000*ep2[30]*e[24]+1.500000000*e[24]*ep2[33]+.5000000000*e[24]*ep2[35]+.5000000000*e[24]*ep2[34]-.5000000000*e[24]*ep2[32]-.5000000000*e[24]*ep2[28]-.5000000000*e[24]*ep2[29]-.5000000000*e[24]*ep2[31];
|
||||||
|
A[36]=.5000000000*e[9]*ep2[21]+.5000000000*e[9]*ep2[24]+.5000000000*e[9]*ep2[19]+1.500000000*e[9]*ep2[18]+.5000000000*e[9]*ep2[20]-.5000000000*e[9]*ep2[26]-.5000000000*e[9]*ep2[23]-.5000000000*e[9]*ep2[22]-.5000000000*e[9]*ep2[25]+e[21]*e[18]*e[12]+e[21]*e[20]*e[14]+e[21]*e[11]*e[23]+e[21]*e[19]*e[13]+e[21]*e[10]*e[22]+e[24]*e[18]*e[15]+e[24]*e[20]*e[17]+e[24]*e[11]*e[26]+e[24]*e[19]*e[16]+e[24]*e[10]*e[25]+e[15]*e[19]*e[25]+e[15]*e[20]*e[26]+e[12]*e[19]*e[22]+e[12]*e[20]*e[23]+e[18]*e[20]*e[11]+e[18]*e[19]*e[10]-1.*e[18]*e[23]*e[14]-1.*e[18]*e[25]*e[16]-1.*e[18]*e[26]*e[17]-1.*e[18]*e[22]*e[13];
|
||||||
|
A[182]=.5000000000*ep2[29]*e[26]+.5000000000*ep2[32]*e[26]+.5000000000*e[26]*ep2[33]+1.500000000*e[26]*ep2[35]+.5000000000*e[26]*ep2[34]-.5000000000*e[26]*ep2[27]-.5000000000*e[26]*ep2[28]-.5000000000*e[26]*ep2[31]-.5000000000*e[26]*ep2[30]+e[20]*e[27]*e[33]+e[20]*e[29]*e[35]+e[20]*e[28]*e[34]+e[29]*e[27]*e[24]+e[29]*e[18]*e[33]+e[29]*e[28]*e[25]+e[29]*e[19]*e[34]+e[23]*e[30]*e[33]+e[23]*e[32]*e[35]+e[23]*e[31]*e[34]+e[32]*e[30]*e[24]+e[32]*e[21]*e[33]+e[32]*e[31]*e[25]+e[32]*e[22]*e[34]+e[35]*e[33]*e[24]+e[35]*e[34]*e[25]-1.*e[35]*e[27]*e[18]-1.*e[35]*e[30]*e[21]-1.*e[35]*e[31]*e[22]-1.*e[35]*e[28]*e[19];
|
||||||
|
A[37]=e[12]*e[19]*e[31]+e[12]*e[29]*e[23]+e[12]*e[20]*e[32]+3.*e[9]*e[27]*e[18]+e[9]*e[28]*e[19]+e[9]*e[29]*e[20]+e[21]*e[9]*e[30]+e[21]*e[29]*e[14]+e[21]*e[11]*e[32]+e[21]*e[28]*e[13]+e[21]*e[10]*e[31]+e[30]*e[20]*e[14]+e[30]*e[11]*e[23]+e[30]*e[19]*e[13]+e[30]*e[10]*e[22]+e[9]*e[33]*e[24]-1.*e[9]*e[35]*e[26]-1.*e[9]*e[31]*e[22]-1.*e[9]*e[32]*e[23]-1.*e[9]*e[34]*e[25]+e[18]*e[29]*e[11]+e[18]*e[28]*e[10]+e[27]*e[20]*e[11]+e[27]*e[19]*e[10]+e[15]*e[27]*e[24]+e[15]*e[18]*e[33]+e[15]*e[28]*e[25]+e[15]*e[19]*e[34]+e[15]*e[29]*e[26]+e[15]*e[20]*e[35]-1.*e[18]*e[31]*e[13]-1.*e[18]*e[32]*e[14]-1.*e[18]*e[34]*e[16]-1.*e[18]*e[35]*e[17]-1.*e[27]*e[23]*e[14]-1.*e[27]*e[25]*e[16]-1.*e[27]*e[26]*e[17]-1.*e[27]*e[22]*e[13]+e[24]*e[29]*e[17]+e[24]*e[11]*e[35]+e[24]*e[28]*e[16]+e[24]*e[10]*e[34]+e[33]*e[20]*e[17]+e[33]*e[11]*e[26]+e[33]*e[19]*e[16]+e[33]*e[10]*e[25]+e[12]*e[27]*e[21]+e[12]*e[18]*e[30]+e[12]*e[28]*e[22];
|
||||||
|
A[183]=-.5000000000*e[17]*ep2[27]+.5000000000*e[17]*ep2[32]-.5000000000*e[17]*ep2[28]+.5000000000*e[17]*ep2[29]-.5000000000*e[17]*ep2[31]+.5000000000*e[17]*ep2[33]-.5000000000*e[17]*ep2[30]+.5000000000*e[17]*ep2[34]+1.500000000*e[17]*ep2[35]+e[32]*e[30]*e[15]+e[32]*e[12]*e[33]+e[32]*e[31]*e[16]+e[32]*e[13]*e[34]+e[14]*e[30]*e[33]+e[14]*e[31]*e[34]+e[11]*e[27]*e[33]+e[11]*e[29]*e[35]+e[11]*e[28]*e[34]+e[35]*e[33]*e[15]+e[35]*e[34]*e[16]+e[29]*e[27]*e[15]+e[29]*e[9]*e[33]+e[29]*e[28]*e[16]+e[29]*e[10]*e[34]-1.*e[35]*e[27]*e[9]-1.*e[35]*e[30]*e[12]-1.*e[35]*e[28]*e[10]-1.*e[35]*e[31]*e[13]+e[35]*e[32]*e[14];
|
||||||
|
A[38]=.5000000000*e[9]*ep2[1]+1.500000000*e[9]*ep2[0]+.5000000000*e[9]*ep2[2]+.5000000000*e[9]*ep2[3]+.5000000000*e[9]*ep2[6]-.5000000000*e[9]*ep2[4]-.5000000000*e[9]*ep2[5]-.5000000000*e[9]*ep2[7]-.5000000000*e[9]*ep2[8]+e[6]*e[0]*e[15]+e[6]*e[10]*e[7]+e[6]*e[1]*e[16]+e[6]*e[11]*e[8]+e[6]*e[2]*e[17]+e[15]*e[1]*e[7]+e[15]*e[2]*e[8]+e[0]*e[11]*e[2]+e[0]*e[10]*e[1]-1.*e[0]*e[13]*e[4]-1.*e[0]*e[16]*e[7]-1.*e[0]*e[14]*e[5]-1.*e[0]*e[17]*e[8]+e[3]*e[0]*e[12]+e[3]*e[10]*e[4]+e[3]*e[1]*e[13]+e[3]*e[11]*e[5]+e[3]*e[2]*e[14]+e[12]*e[1]*e[4]+e[12]*e[2]*e[5];
|
||||||
|
A[180]=.5000000000*e[35]*ep2[33]+.5000000000*e[35]*ep2[34]-.5000000000*e[35]*ep2[27]-.5000000000*e[35]*ep2[28]-.5000000000*e[35]*ep2[31]-.5000000000*e[35]*ep2[30]+e[32]*e[31]*e[34]+.5000000000*ep2[29]*e[35]+.5000000000*ep2[32]*e[35]+e[29]*e[28]*e[34]+e[32]*e[30]*e[33]+.5000000000*ep3[35]+e[29]*e[27]*e[33];
|
||||||
|
A[39]=.5000000000*e[0]*ep2[19]+.5000000000*e[0]*ep2[20]+.5000000000*e[0]*ep2[24]-.5000000000*e[0]*ep2[26]-.5000000000*e[0]*ep2[23]-.5000000000*e[0]*ep2[22]-.5000000000*e[0]*ep2[25]+1.500000000*ep2[18]*e[0]+.5000000000*e[0]*ep2[21]+e[18]*e[19]*e[1]+e[18]*e[20]*e[2]+e[21]*e[18]*e[3]+e[21]*e[19]*e[4]+e[21]*e[1]*e[22]+e[21]*e[20]*e[5]+e[21]*e[2]*e[23]-1.*e[18]*e[26]*e[8]-1.*e[18]*e[22]*e[4]-1.*e[18]*e[25]*e[7]-1.*e[18]*e[23]*e[5]+e[18]*e[24]*e[6]+e[3]*e[19]*e[22]+e[3]*e[20]*e[23]+e[24]*e[19]*e[7]+e[24]*e[1]*e[25]+e[24]*e[20]*e[8]+e[24]*e[2]*e[26]+e[6]*e[19]*e[25]+e[6]*e[20]*e[26];
|
||||||
|
A[181]=.5000000000*ep2[32]*e[8]-.5000000000*e[8]*ep2[27]-.5000000000*e[8]*ep2[28]+.5000000000*e[8]*ep2[29]-.5000000000*e[8]*ep2[31]+.5000000000*e[8]*ep2[33]-.5000000000*e[8]*ep2[30]+.5000000000*e[8]*ep2[34]+1.500000000*e[8]*ep2[35]+e[2]*e[27]*e[33]+e[2]*e[29]*e[35]+e[2]*e[28]*e[34]+e[5]*e[30]*e[33]+e[5]*e[32]*e[35]+e[5]*e[31]*e[34]+e[32]*e[30]*e[6]+e[32]*e[3]*e[33]+e[32]*e[31]*e[7]+e[32]*e[4]*e[34]+e[29]*e[27]*e[6]+e[29]*e[0]*e[33]+e[29]*e[28]*e[7]+e[29]*e[1]*e[34]+e[35]*e[33]*e[6]+e[35]*e[34]*e[7]-1.*e[35]*e[27]*e[0]-1.*e[35]*e[30]*e[3]-1.*e[35]*e[28]*e[1]-1.*e[35]*e[31]*e[4];
|
||||||
|
A[32]=-.5000000000*e[18]*ep2[4]+1.500000000*e[18]*ep2[0]+.5000000000*e[18]*ep2[6]-.5000000000*e[18]*ep2[5]+.5000000000*e[18]*ep2[1]-.5000000000*e[18]*ep2[7]+.5000000000*e[18]*ep2[3]+.5000000000*e[18]*ep2[2]-.5000000000*e[18]*ep2[8]+e[3]*e[0]*e[21]+e[3]*e[19]*e[4]+e[3]*e[1]*e[22]+e[3]*e[20]*e[5]+e[3]*e[2]*e[23]+e[21]*e[1]*e[4]+e[21]*e[2]*e[5]+e[6]*e[0]*e[24]+e[6]*e[19]*e[7]+e[6]*e[1]*e[25]+e[6]*e[20]*e[8]+e[6]*e[2]*e[26]+e[24]*e[1]*e[7]+e[24]*e[2]*e[8]+e[0]*e[19]*e[1]+e[0]*e[20]*e[2]-1.*e[0]*e[26]*e[8]-1.*e[0]*e[22]*e[4]-1.*e[0]*e[25]*e[7]-1.*e[0]*e[23]*e[5];
|
||||||
|
A[178]=e[10]*e[1]*e[7]+e[10]*e[0]*e[6]+e[10]*e[2]*e[8]+e[4]*e[12]*e[6]+e[4]*e[3]*e[15]+e[4]*e[13]*e[7]+e[4]*e[14]*e[8]+e[4]*e[5]*e[17]+e[13]*e[3]*e[6]+e[13]*e[5]*e[8]+e[7]*e[15]*e[6]+e[7]*e[17]*e[8]-1.*e[7]*e[11]*e[2]-1.*e[7]*e[9]*e[0]-1.*e[7]*e[14]*e[5]-1.*e[7]*e[12]*e[3]+e[1]*e[9]*e[6]+e[1]*e[0]*e[15]+e[1]*e[11]*e[8]+e[1]*e[2]*e[17]+1.500000000*e[16]*ep2[7]+.5000000000*e[16]*ep2[6]+.5000000000*e[16]*ep2[8]+.5000000000*ep2[1]*e[16]-.5000000000*e[16]*ep2[0]-.5000000000*e[16]*ep2[5]-.5000000000*e[16]*ep2[3]-.5000000000*e[16]*ep2[2]+.5000000000*ep2[4]*e[16];
|
||||||
|
A[33]=e[0]*e[30]*e[21]-1.*e[0]*e[35]*e[26]-1.*e[0]*e[31]*e[22]-1.*e[0]*e[32]*e[23]-1.*e[0]*e[34]*e[25]-1.*e[18]*e[34]*e[7]-1.*e[18]*e[32]*e[5]-1.*e[18]*e[35]*e[8]-1.*e[18]*e[31]*e[4]-1.*e[27]*e[26]*e[8]-1.*e[27]*e[22]*e[4]-1.*e[27]*e[25]*e[7]-1.*e[27]*e[23]*e[5]+e[6]*e[28]*e[25]+e[6]*e[19]*e[34]+e[6]*e[29]*e[26]+e[6]*e[20]*e[35]+e[21]*e[28]*e[4]+e[21]*e[1]*e[31]+e[21]*e[29]*e[5]+e[21]*e[2]*e[32]+e[30]*e[19]*e[4]+e[30]*e[1]*e[22]+e[30]*e[20]*e[5]+e[30]*e[2]*e[23]+e[24]*e[27]*e[6]+e[24]*e[0]*e[33]+e[24]*e[28]*e[7]+e[24]*e[1]*e[34]+e[24]*e[29]*e[8]+e[24]*e[2]*e[35]+e[33]*e[18]*e[6]+e[33]*e[19]*e[7]+e[33]*e[1]*e[25]+e[33]*e[20]*e[8]+e[33]*e[2]*e[26]+3.*e[0]*e[27]*e[18]+e[0]*e[28]*e[19]+e[0]*e[29]*e[20]+e[18]*e[28]*e[1]+e[18]*e[29]*e[2]+e[27]*e[19]*e[1]+e[27]*e[20]*e[2]+e[3]*e[27]*e[21]+e[3]*e[18]*e[30]+e[3]*e[28]*e[22]+e[3]*e[19]*e[31]+e[3]*e[29]*e[23]+e[3]*e[20]*e[32];
|
||||||
|
A[179]=e[19]*e[18]*e[6]+e[19]*e[0]*e[24]+e[19]*e[1]*e[25]+e[19]*e[20]*e[8]+e[19]*e[2]*e[26]+e[22]*e[21]*e[6]+e[22]*e[3]*e[24]+e[22]*e[4]*e[25]+e[22]*e[23]*e[8]+e[22]*e[5]*e[26]-1.*e[25]*e[21]*e[3]+e[25]*e[26]*e[8]-1.*e[25]*e[20]*e[2]-1.*e[25]*e[18]*e[0]-1.*e[25]*e[23]*e[5]+e[25]*e[24]*e[6]+e[1]*e[18]*e[24]+e[1]*e[20]*e[26]+e[4]*e[21]*e[24]+e[4]*e[23]*e[26]+.5000000000*ep2[19]*e[7]+.5000000000*ep2[22]*e[7]+1.500000000*ep2[25]*e[7]+.5000000000*e[7]*ep2[26]-.5000000000*e[7]*ep2[18]-.5000000000*e[7]*ep2[23]-.5000000000*e[7]*ep2[20]+.5000000000*e[7]*ep2[24]-.5000000000*e[7]*ep2[21];
|
||||||
|
A[34]=.5000000000*e[18]*ep2[11]+1.500000000*e[18]*ep2[9]+.5000000000*e[18]*ep2[10]+.5000000000*e[18]*ep2[12]+.5000000000*e[18]*ep2[15]-.5000000000*e[18]*ep2[16]-.5000000000*e[18]*ep2[17]-.5000000000*e[18]*ep2[14]-.5000000000*e[18]*ep2[13]+e[12]*e[9]*e[21]+e[12]*e[20]*e[14]+e[12]*e[11]*e[23]+e[12]*e[19]*e[13]+e[12]*e[10]*e[22]+e[21]*e[11]*e[14]+e[21]*e[10]*e[13]+e[15]*e[9]*e[24]+e[15]*e[20]*e[17]+e[15]*e[11]*e[26]+e[15]*e[19]*e[16]+e[15]*e[10]*e[25]+e[24]*e[11]*e[17]+e[24]*e[10]*e[16]-1.*e[9]*e[23]*e[14]-1.*e[9]*e[25]*e[16]-1.*e[9]*e[26]*e[17]+e[9]*e[20]*e[11]+e[9]*e[19]*e[10]-1.*e[9]*e[22]*e[13];
|
||||||
|
A[176]=e[13]*e[21]*e[24]+e[13]*e[23]*e[26]+e[19]*e[18]*e[15]+e[19]*e[9]*e[24]+e[19]*e[20]*e[17]+e[19]*e[11]*e[26]-1.*e[25]*e[23]*e[14]-1.*e[25]*e[20]*e[11]-1.*e[25]*e[18]*e[9]-1.*e[25]*e[21]*e[12]+e[22]*e[21]*e[15]+e[22]*e[12]*e[24]+e[22]*e[23]*e[17]+e[22]*e[14]*e[26]+e[22]*e[13]*e[25]+e[25]*e[24]*e[15]+e[25]*e[26]*e[17]+e[10]*e[19]*e[25]+e[10]*e[18]*e[24]+e[10]*e[20]*e[26]-.5000000000*e[16]*ep2[18]-.5000000000*e[16]*ep2[23]+.5000000000*e[16]*ep2[19]-.5000000000*e[16]*ep2[20]-.5000000000*e[16]*ep2[21]+.5000000000*ep2[22]*e[16]+1.500000000*ep2[25]*e[16]+.5000000000*e[16]*ep2[24]+.5000000000*e[16]*ep2[26];
|
||||||
|
A[35]=.5000000000*e[0]*ep2[12]+.5000000000*e[0]*ep2[15]+.5000000000*e[0]*ep2[11]+1.500000000*e[0]*ep2[9]+.5000000000*e[0]*ep2[10]-.5000000000*e[0]*ep2[16]-.5000000000*e[0]*ep2[17]-.5000000000*e[0]*ep2[14]-.5000000000*e[0]*ep2[13]+e[12]*e[9]*e[3]+e[12]*e[10]*e[4]+e[12]*e[1]*e[13]+e[12]*e[11]*e[5]+e[12]*e[2]*e[14]+e[15]*e[9]*e[6]+e[15]*e[10]*e[7]+e[15]*e[1]*e[16]+e[15]*e[11]*e[8]+e[15]*e[2]*e[17]+e[6]*e[11]*e[17]+e[6]*e[10]*e[16]+e[3]*e[11]*e[14]+e[3]*e[10]*e[13]+e[9]*e[10]*e[1]+e[9]*e[11]*e[2]-1.*e[9]*e[13]*e[4]-1.*e[9]*e[16]*e[7]-1.*e[9]*e[14]*e[5]-1.*e[9]*e[17]*e[8];
|
||||||
|
A[177]=e[19]*e[11]*e[35]+e[28]*e[18]*e[15]+e[28]*e[9]*e[24]+e[28]*e[20]*e[17]+e[28]*e[11]*e[26]-1.*e[25]*e[27]*e[9]-1.*e[25]*e[30]*e[12]-1.*e[25]*e[32]*e[14]+e[25]*e[33]*e[15]+e[25]*e[35]*e[17]-1.*e[25]*e[29]*e[11]-1.*e[34]*e[23]*e[14]+e[34]*e[24]*e[15]+e[34]*e[26]*e[17]-1.*e[34]*e[20]*e[11]-1.*e[34]*e[18]*e[9]-1.*e[34]*e[21]*e[12]+e[13]*e[30]*e[24]+e[13]*e[21]*e[33]+e[13]*e[31]*e[25]+e[13]*e[22]*e[34]+e[13]*e[32]*e[26]+e[13]*e[23]*e[35]+e[10]*e[27]*e[24]+e[10]*e[18]*e[33]+e[10]*e[28]*e[25]+e[10]*e[19]*e[34]+e[10]*e[29]*e[26]+e[10]*e[20]*e[35]+e[22]*e[30]*e[15]+e[22]*e[12]*e[33]+e[22]*e[32]*e[17]+e[22]*e[14]*e[35]+e[22]*e[31]*e[16]+e[31]*e[21]*e[15]+e[31]*e[12]*e[24]+e[31]*e[23]*e[17]+e[31]*e[14]*e[26]-1.*e[16]*e[27]*e[18]+e[16]*e[33]*e[24]-1.*e[16]*e[30]*e[21]-1.*e[16]*e[29]*e[20]+e[16]*e[35]*e[26]-1.*e[16]*e[32]*e[23]+e[16]*e[28]*e[19]+3.*e[16]*e[34]*e[25]+e[19]*e[27]*e[15]+e[19]*e[9]*e[33]+e[19]*e[29]*e[17];
|
||||||
|
A[45]=e[4]*e[27]*e[3]+e[4]*e[0]*e[30]+e[4]*e[29]*e[5]+e[4]*e[2]*e[32]+e[31]*e[0]*e[3]+e[31]*e[2]*e[5]+e[7]*e[27]*e[6]+e[7]*e[0]*e[33]+e[7]*e[29]*e[8]+e[7]*e[2]*e[35]+e[34]*e[0]*e[6]+e[34]*e[2]*e[8]+e[1]*e[27]*e[0]+e[1]*e[29]*e[2]+e[1]*e[34]*e[7]-1.*e[1]*e[32]*e[5]-1.*e[1]*e[33]*e[6]-1.*e[1]*e[30]*e[3]-1.*e[1]*e[35]*e[8]+e[1]*e[31]*e[4]+1.500000000*e[28]*ep2[1]+.5000000000*e[28]*ep2[4]+.5000000000*e[28]*ep2[0]-.5000000000*e[28]*ep2[6]-.5000000000*e[28]*ep2[5]+.5000000000*e[28]*ep2[7]-.5000000000*e[28]*ep2[3]+.5000000000*e[28]*ep2[2]-.5000000000*e[28]*ep2[8];
|
||||||
|
A[191]=-1.*e[35]*e[10]*e[1]-1.*e[35]*e[13]*e[4]+e[35]*e[16]*e[7]+e[35]*e[15]*e[6]-1.*e[35]*e[9]*e[0]-1.*e[35]*e[12]*e[3]+e[32]*e[12]*e[6]+e[32]*e[3]*e[15]+e[32]*e[13]*e[7]+e[32]*e[4]*e[16]-1.*e[8]*e[27]*e[9]-1.*e[8]*e[30]*e[12]-1.*e[8]*e[28]*e[10]-1.*e[8]*e[31]*e[13]+e[8]*e[29]*e[11]+e[11]*e[27]*e[6]+e[11]*e[0]*e[33]+e[11]*e[28]*e[7]+e[11]*e[1]*e[34]+e[29]*e[9]*e[6]+e[29]*e[0]*e[15]+e[29]*e[10]*e[7]+e[29]*e[1]*e[16]+e[5]*e[30]*e[15]+e[5]*e[12]*e[33]+e[5]*e[32]*e[17]+e[5]*e[14]*e[35]+e[5]*e[31]*e[16]+e[5]*e[13]*e[34]+e[8]*e[33]*e[15]+3.*e[8]*e[35]*e[17]+e[8]*e[34]*e[16]+e[2]*e[27]*e[15]+e[2]*e[9]*e[33]+e[2]*e[29]*e[17]+e[2]*e[11]*e[35]+e[2]*e[28]*e[16]+e[2]*e[10]*e[34]-1.*e[17]*e[27]*e[0]+e[17]*e[34]*e[7]+e[17]*e[33]*e[6]-1.*e[17]*e[30]*e[3]-1.*e[17]*e[28]*e[1]-1.*e[17]*e[31]*e[4]+e[14]*e[30]*e[6]+e[14]*e[3]*e[33]+e[14]*e[31]*e[7]+e[14]*e[4]*e[34]+e[14]*e[32]*e[8];
|
||||||
|
A[44]=e[19]*e[11]*e[2]+e[4]*e[18]*e[12]+e[4]*e[9]*e[21]+e[4]*e[20]*e[14]+e[4]*e[11]*e[23]+e[4]*e[19]*e[13]+e[4]*e[10]*e[22]+e[7]*e[18]*e[15]+e[7]*e[9]*e[24]+e[7]*e[20]*e[17]+e[7]*e[11]*e[26]+e[7]*e[19]*e[16]+e[7]*e[10]*e[25]+e[1]*e[18]*e[9]+e[1]*e[20]*e[11]-1.*e[10]*e[21]*e[3]-1.*e[10]*e[26]*e[8]-1.*e[10]*e[23]*e[5]-1.*e[10]*e[24]*e[6]+e[13]*e[18]*e[3]+e[13]*e[0]*e[21]+e[13]*e[1]*e[22]+e[13]*e[20]*e[5]+e[13]*e[2]*e[23]-1.*e[19]*e[15]*e[6]-1.*e[19]*e[14]*e[5]-1.*e[19]*e[12]*e[3]-1.*e[19]*e[17]*e[8]+e[22]*e[9]*e[3]+e[22]*e[0]*e[12]+e[22]*e[11]*e[5]+e[22]*e[2]*e[14]+e[16]*e[18]*e[6]+e[16]*e[0]*e[24]+e[16]*e[1]*e[25]+e[16]*e[20]*e[8]+e[16]*e[2]*e[26]-1.*e[1]*e[23]*e[14]-1.*e[1]*e[24]*e[15]-1.*e[1]*e[26]*e[17]-1.*e[1]*e[21]*e[12]+e[25]*e[9]*e[6]+e[25]*e[0]*e[15]+e[25]*e[11]*e[8]+e[25]*e[2]*e[17]+e[10]*e[18]*e[0]+3.*e[10]*e[19]*e[1]+e[10]*e[20]*e[2]+e[19]*e[9]*e[0];
|
||||||
|
A[190]=.5000000000*ep2[23]*e[26]+.5000000000*e[26]*ep2[25]+.5000000000*ep2[20]*e[26]-.5000000000*e[26]*ep2[18]+.5000000000*ep3[26]+.5000000000*e[26]*ep2[24]+e[20]*e[19]*e[25]-.5000000000*e[26]*ep2[19]-.5000000000*e[26]*ep2[21]+e[20]*e[18]*e[24]-.5000000000*e[26]*ep2[22]+e[23]*e[21]*e[24]+e[23]*e[22]*e[25];
|
||||||
|
A[47]=e[16]*e[9]*e[33]+e[16]*e[29]*e[17]+e[16]*e[11]*e[35]+e[16]*e[10]*e[34]+e[34]*e[11]*e[17]+e[34]*e[9]*e[15]-1.*e[10]*e[30]*e[12]-1.*e[10]*e[32]*e[14]-1.*e[10]*e[33]*e[15]-1.*e[10]*e[35]*e[17]+e[10]*e[27]*e[9]+e[10]*e[29]*e[11]+e[13]*e[27]*e[12]+e[13]*e[9]*e[30]+e[13]*e[29]*e[14]+e[13]*e[11]*e[32]+e[13]*e[10]*e[31]+e[31]*e[11]*e[14]+e[31]*e[9]*e[12]+e[16]*e[27]*e[15]+1.500000000*e[28]*ep2[10]+.5000000000*e[28]*ep2[16]+.5000000000*e[28]*ep2[9]+.5000000000*e[28]*ep2[11]-.5000000000*e[28]*ep2[12]-.5000000000*e[28]*ep2[15]-.5000000000*e[28]*ep2[17]-.5000000000*e[28]*ep2[14]+.5000000000*e[28]*ep2[13];
|
||||||
|
A[189]=.5000000000*ep2[20]*e[35]+.5000000000*ep2[23]*e[35]+1.500000000*e[35]*ep2[26]+.5000000000*e[35]*ep2[25]+.5000000000*e[35]*ep2[24]-.5000000000*e[35]*ep2[18]-.5000000000*e[35]*ep2[19]-.5000000000*e[35]*ep2[22]-.5000000000*e[35]*ep2[21]+e[20]*e[27]*e[24]+e[20]*e[18]*e[33]+e[20]*e[28]*e[25]+e[20]*e[19]*e[34]+e[20]*e[29]*e[26]+e[29]*e[19]*e[25]+e[29]*e[18]*e[24]+e[23]*e[30]*e[24]+e[23]*e[21]*e[33]+e[23]*e[31]*e[25]+e[23]*e[22]*e[34]+e[23]*e[32]*e[26]+e[32]*e[22]*e[25]+e[32]*e[21]*e[24]+e[26]*e[33]*e[24]+e[26]*e[34]*e[25]-1.*e[26]*e[27]*e[18]-1.*e[26]*e[30]*e[21]-1.*e[26]*e[31]*e[22]-1.*e[26]*e[28]*e[19];
|
||||||
|
A[46]=e[4]*e[2]*e[5]+.5000000000*e[1]*ep2[0]-.5000000000*e[1]*ep2[6]+e[7]*e[0]*e[6]+.5000000000*e[1]*ep2[7]+.5000000000*e[1]*ep2[4]-.5000000000*e[1]*ep2[8]+.5000000000*e[1]*ep2[2]-.5000000000*e[1]*ep2[3]+.5000000000*ep3[1]+e[7]*e[2]*e[8]-.5000000000*e[1]*ep2[5]+e[4]*e[0]*e[3];
|
||||||
|
A[188]=-.5000000000*e[17]*ep2[13]-.5000000000*e[17]*ep2[9]+.5000000000*e[17]*ep2[16]+.5000000000*e[17]*ep2[15]+.5000000000*ep3[17]-.5000000000*e[17]*ep2[10]+e[14]*e[13]*e[16]+e[14]*e[12]*e[15]+.5000000000*ep2[14]*e[17]+e[11]*e[10]*e[16]-.5000000000*e[17]*ep2[12]+.5000000000*ep2[11]*e[17]+e[11]*e[9]*e[15];
|
||||||
|
A[41]=e[4]*e[27]*e[30]+e[4]*e[29]*e[32]+e[4]*e[28]*e[31]+e[31]*e[27]*e[3]+e[31]*e[0]*e[30]+e[31]*e[29]*e[5]+e[31]*e[2]*e[32]+e[7]*e[27]*e[33]+e[7]*e[29]*e[35]+e[7]*e[28]*e[34]+e[28]*e[27]*e[0]+e[28]*e[29]*e[2]+e[34]*e[27]*e[6]+e[34]*e[0]*e[33]+e[34]*e[29]*e[8]+e[34]*e[2]*e[35]-1.*e[28]*e[32]*e[5]-1.*e[28]*e[33]*e[6]-1.*e[28]*e[30]*e[3]-1.*e[28]*e[35]*e[8]+.5000000000*e[1]*ep2[27]+.5000000000*e[1]*ep2[29]+1.500000000*e[1]*ep2[28]+.5000000000*e[1]*ep2[31]-.5000000000*e[1]*ep2[32]-.5000000000*e[1]*ep2[33]-.5000000000*e[1]*ep2[30]+.5000000000*e[1]*ep2[34]-.5000000000*e[1]*ep2[35];
|
||||||
|
A[187]=.5000000000*ep2[11]*e[35]+.5000000000*e[35]*ep2[16]-.5000000000*e[35]*ep2[9]-.5000000000*e[35]*ep2[12]+.5000000000*e[35]*ep2[15]+1.500000000*e[35]*ep2[17]-.5000000000*e[35]*ep2[10]+.5000000000*e[35]*ep2[14]-.5000000000*e[35]*ep2[13]+e[11]*e[27]*e[15]+e[11]*e[9]*e[33]+e[11]*e[29]*e[17]+e[11]*e[28]*e[16]+e[11]*e[10]*e[34]+e[29]*e[9]*e[15]+e[29]*e[10]*e[16]+e[14]*e[30]*e[15]+e[14]*e[12]*e[33]+e[14]*e[32]*e[17]+e[14]*e[31]*e[16]+e[14]*e[13]*e[34]+e[32]*e[12]*e[15]+e[32]*e[13]*e[16]+e[17]*e[33]*e[15]+e[17]*e[34]*e[16]-1.*e[17]*e[27]*e[9]-1.*e[17]*e[30]*e[12]-1.*e[17]*e[28]*e[10]-1.*e[17]*e[31]*e[13];
|
||||||
|
A[40]=e[34]*e[27]*e[33]+e[34]*e[29]*e[35]-.5000000000*e[28]*ep2[30]-.5000000000*e[28]*ep2[35]+.5000000000*ep3[28]+.5000000000*e[28]*ep2[27]+.5000000000*e[28]*ep2[29]+e[31]*e[27]*e[30]+e[31]*e[29]*e[32]-.5000000000*e[28]*ep2[32]-.5000000000*e[28]*ep2[33]+.5000000000*e[28]*ep2[31]+.5000000000*e[28]*ep2[34];
|
||||||
|
A[186]=.5000000000*ep2[5]*e[8]+e[2]*e[0]*e[6]+.5000000000*ep2[2]*e[8]+.5000000000*ep3[8]-.5000000000*e[8]*ep2[0]+e[5]*e[4]*e[7]+e[5]*e[3]*e[6]+.5000000000*e[8]*ep2[7]+e[2]*e[1]*e[7]-.5000000000*e[8]*ep2[1]-.5000000000*e[8]*ep2[4]-.5000000000*e[8]*ep2[3]+.5000000000*e[8]*ep2[6];
|
||||||
|
A[43]=e[28]*e[27]*e[9]+e[28]*e[29]*e[11]-1.*e[28]*e[30]*e[12]+e[28]*e[31]*e[13]-1.*e[28]*e[32]*e[14]-1.*e[28]*e[33]*e[15]-1.*e[28]*e[35]*e[17]+e[31]*e[27]*e[12]+e[31]*e[9]*e[30]+e[31]*e[29]*e[14]+e[31]*e[11]*e[32]+e[13]*e[27]*e[30]+e[13]*e[29]*e[32]+e[16]*e[27]*e[33]+e[16]*e[29]*e[35]+e[34]*e[27]*e[15]+e[34]*e[9]*e[33]+e[34]*e[29]*e[17]+e[34]*e[11]*e[35]+e[34]*e[28]*e[16]+.5000000000*e[10]*ep2[27]+.5000000000*e[10]*ep2[29]+1.500000000*e[10]*ep2[28]-.5000000000*e[10]*ep2[32]+.5000000000*e[10]*ep2[31]-.5000000000*e[10]*ep2[33]-.5000000000*e[10]*ep2[30]+.5000000000*e[10]*ep2[34]-.5000000000*e[10]*ep2[35];
|
||||||
|
A[185]=-.5000000000*e[35]*ep2[1]+.5000000000*e[35]*ep2[7]-.5000000000*e[35]*ep2[3]+.5000000000*ep2[2]*e[35]+1.500000000*e[35]*ep2[8]-.5000000000*e[35]*ep2[4]-.5000000000*e[35]*ep2[0]+.5000000000*e[35]*ep2[6]+.5000000000*e[35]*ep2[5]+e[2]*e[27]*e[6]+e[2]*e[0]*e[33]+e[2]*e[28]*e[7]+e[2]*e[1]*e[34]+e[2]*e[29]*e[8]-1.*e[8]*e[27]*e[0]+e[8]*e[34]*e[7]+e[8]*e[32]*e[5]+e[8]*e[33]*e[6]-1.*e[8]*e[30]*e[3]-1.*e[8]*e[28]*e[1]-1.*e[8]*e[31]*e[4]+e[29]*e[1]*e[7]+e[29]*e[0]*e[6]+e[5]*e[30]*e[6]+e[5]*e[3]*e[33]+e[5]*e[31]*e[7]+e[5]*e[4]*e[34]+e[32]*e[4]*e[7]+e[32]*e[3]*e[6];
|
||||||
|
A[42]=e[28]*e[27]*e[18]+e[28]*e[29]*e[20]+e[22]*e[27]*e[30]+e[22]*e[29]*e[32]+e[22]*e[28]*e[31]+e[31]*e[27]*e[21]+e[31]*e[18]*e[30]+e[31]*e[29]*e[23]+e[31]*e[20]*e[32]+e[25]*e[27]*e[33]+e[25]*e[29]*e[35]+e[25]*e[28]*e[34]+e[34]*e[27]*e[24]+e[34]*e[18]*e[33]+e[34]*e[29]*e[26]+e[34]*e[20]*e[35]-1.*e[28]*e[33]*e[24]-1.*e[28]*e[30]*e[21]-1.*e[28]*e[35]*e[26]-1.*e[28]*e[32]*e[23]-.5000000000*e[19]*ep2[33]-.5000000000*e[19]*ep2[30]-.5000000000*e[19]*ep2[35]+.5000000000*e[19]*ep2[27]+.5000000000*e[19]*ep2[29]+1.500000000*e[19]*ep2[28]+.5000000000*e[19]*ep2[31]+.5000000000*e[19]*ep2[34]-.5000000000*e[19]*ep2[32];
|
||||||
|
A[184]=e[23]*e[3]*e[15]-1.*e[17]*e[19]*e[1]-1.*e[17]*e[22]*e[4]-1.*e[17]*e[18]*e[0]+e[17]*e[25]*e[7]+e[17]*e[24]*e[6]+e[14]*e[21]*e[6]+e[14]*e[3]*e[24]+e[14]*e[22]*e[7]+e[14]*e[4]*e[25]+e[14]*e[23]*e[8]-1.*e[26]*e[10]*e[1]-1.*e[26]*e[13]*e[4]+e[26]*e[16]*e[7]+e[26]*e[15]*e[6]-1.*e[26]*e[9]*e[0]-1.*e[26]*e[12]*e[3]+e[23]*e[12]*e[6]+e[11]*e[18]*e[6]+e[11]*e[0]*e[24]+e[11]*e[19]*e[7]+e[11]*e[1]*e[25]+e[11]*e[20]*e[8]+e[11]*e[2]*e[26]+e[20]*e[9]*e[6]+e[20]*e[0]*e[15]+e[20]*e[10]*e[7]+e[20]*e[1]*e[16]+e[20]*e[2]*e[17]+e[5]*e[21]*e[15]+e[5]*e[12]*e[24]+e[5]*e[23]*e[17]+e[5]*e[14]*e[26]+e[5]*e[22]*e[16]+e[5]*e[13]*e[25]+e[8]*e[24]*e[15]+3.*e[8]*e[26]*e[17]+e[8]*e[25]*e[16]+e[2]*e[18]*e[15]+e[2]*e[9]*e[24]+e[2]*e[19]*e[16]+e[2]*e[10]*e[25]-1.*e[17]*e[21]*e[3]+e[23]*e[4]*e[16]+e[23]*e[13]*e[7]-1.*e[8]*e[18]*e[9]-1.*e[8]*e[21]*e[12]-1.*e[8]*e[19]*e[10]-1.*e[8]*e[22]*e[13];
|
||||||
|
A[54]=e[13]*e[18]*e[12]+e[13]*e[9]*e[21]+e[13]*e[20]*e[14]+e[13]*e[11]*e[23]+e[13]*e[10]*e[22]+e[22]*e[11]*e[14]+e[22]*e[9]*e[12]+e[16]*e[18]*e[15]+e[16]*e[9]*e[24]+e[16]*e[20]*e[17]+e[16]*e[11]*e[26]+e[16]*e[10]*e[25]+e[25]*e[11]*e[17]+e[25]*e[9]*e[15]-1.*e[10]*e[23]*e[14]-1.*e[10]*e[24]*e[15]-1.*e[10]*e[26]*e[17]+e[10]*e[20]*e[11]+e[10]*e[18]*e[9]-1.*e[10]*e[21]*e[12]+.5000000000*e[19]*ep2[11]+.5000000000*e[19]*ep2[9]+1.500000000*e[19]*ep2[10]+.5000000000*e[19]*ep2[13]+.5000000000*e[19]*ep2[16]-.5000000000*e[19]*ep2[12]-.5000000000*e[19]*ep2[15]-.5000000000*e[19]*ep2[17]-.5000000000*e[19]*ep2[14];
|
||||||
|
A[164]=e[10]*e[18]*e[6]+e[10]*e[0]*e[24]+e[10]*e[19]*e[7]+e[10]*e[1]*e[25]+e[10]*e[20]*e[8]+e[10]*e[2]*e[26]+e[19]*e[9]*e[6]+e[19]*e[0]*e[15]+e[19]*e[1]*e[16]+e[19]*e[11]*e[8]+e[19]*e[2]*e[17]+e[4]*e[21]*e[15]+e[4]*e[12]*e[24]+e[4]*e[23]*e[17]+e[4]*e[14]*e[26]+e[4]*e[22]*e[16]+e[4]*e[13]*e[25]+e[7]*e[24]*e[15]+e[7]*e[26]*e[17]+3.*e[7]*e[25]*e[16]+e[1]*e[18]*e[15]+e[1]*e[9]*e[24]+e[1]*e[20]*e[17]+e[1]*e[11]*e[26]-1.*e[16]*e[21]*e[3]+e[16]*e[26]*e[8]-1.*e[16]*e[20]*e[2]-1.*e[16]*e[18]*e[0]-1.*e[16]*e[23]*e[5]+e[16]*e[24]*e[6]+e[13]*e[21]*e[6]+e[13]*e[3]*e[24]+e[13]*e[22]*e[7]+e[13]*e[23]*e[8]+e[13]*e[5]*e[26]-1.*e[25]*e[11]*e[2]+e[25]*e[15]*e[6]-1.*e[25]*e[9]*e[0]-1.*e[25]*e[14]*e[5]-1.*e[25]*e[12]*e[3]+e[25]*e[17]*e[8]+e[22]*e[12]*e[6]+e[22]*e[3]*e[15]+e[22]*e[14]*e[8]+e[22]*e[5]*e[17]-1.*e[7]*e[23]*e[14]-1.*e[7]*e[20]*e[11]-1.*e[7]*e[18]*e[9]-1.*e[7]*e[21]*e[12];
|
||||||
|
A[55]=e[13]*e[9]*e[3]+e[13]*e[0]*e[12]+e[13]*e[10]*e[4]+e[13]*e[11]*e[5]+e[13]*e[2]*e[14]+e[16]*e[9]*e[6]+e[16]*e[0]*e[15]+e[16]*e[10]*e[7]+e[16]*e[11]*e[8]+e[16]*e[2]*e[17]+e[7]*e[11]*e[17]+e[7]*e[9]*e[15]+e[4]*e[11]*e[14]+e[4]*e[9]*e[12]+e[10]*e[9]*e[0]+e[10]*e[11]*e[2]-1.*e[10]*e[15]*e[6]-1.*e[10]*e[14]*e[5]-1.*e[10]*e[12]*e[3]-1.*e[10]*e[17]*e[8]+.5000000000*e[1]*ep2[11]+.5000000000*e[1]*ep2[9]+1.500000000*e[1]*ep2[10]-.5000000000*e[1]*ep2[12]-.5000000000*e[1]*ep2[15]-.5000000000*e[1]*ep2[17]-.5000000000*e[1]*ep2[14]+.5000000000*e[1]*ep2[13]+.5000000000*e[1]*ep2[16];
|
||||||
|
A[165]=e[1]*e[27]*e[6]+e[1]*e[0]*e[33]+e[1]*e[28]*e[7]+e[1]*e[29]*e[8]+e[1]*e[2]*e[35]-1.*e[7]*e[27]*e[0]-1.*e[7]*e[32]*e[5]+e[7]*e[33]*e[6]-1.*e[7]*e[30]*e[3]+e[7]*e[35]*e[8]-1.*e[7]*e[29]*e[2]+e[7]*e[31]*e[4]+e[28]*e[0]*e[6]+e[28]*e[2]*e[8]+e[4]*e[30]*e[6]+e[4]*e[3]*e[33]+e[4]*e[32]*e[8]+e[4]*e[5]*e[35]+e[31]*e[3]*e[6]+e[31]*e[5]*e[8]+.5000000000*ep2[1]*e[34]+1.500000000*e[34]*ep2[7]+.5000000000*e[34]*ep2[4]-.5000000000*e[34]*ep2[0]+.5000000000*e[34]*ep2[6]-.5000000000*e[34]*ep2[5]-.5000000000*e[34]*ep2[3]-.5000000000*e[34]*ep2[2]+.5000000000*e[34]*ep2[8];
|
||||||
|
A[52]=e[4]*e[18]*e[3]+e[4]*e[0]*e[21]+e[4]*e[1]*e[22]+e[4]*e[20]*e[5]+e[4]*e[2]*e[23]+e[22]*e[0]*e[3]+e[22]*e[2]*e[5]+e[7]*e[18]*e[6]+e[7]*e[0]*e[24]+e[7]*e[1]*e[25]+e[7]*e[20]*e[8]+e[7]*e[2]*e[26]+e[25]*e[0]*e[6]+e[25]*e[2]*e[8]+e[1]*e[18]*e[0]+e[1]*e[20]*e[2]-1.*e[1]*e[21]*e[3]-1.*e[1]*e[26]*e[8]-1.*e[1]*e[23]*e[5]-1.*e[1]*e[24]*e[6]+.5000000000*e[19]*ep2[4]+.5000000000*e[19]*ep2[0]-.5000000000*e[19]*ep2[6]-.5000000000*e[19]*ep2[5]+1.500000000*e[19]*ep2[1]+.5000000000*e[19]*ep2[7]-.5000000000*e[19]*ep2[3]+.5000000000*e[19]*ep2[2]-.5000000000*e[19]*ep2[8];
|
||||||
|
A[166]=-.5000000000*e[7]*ep2[0]+e[4]*e[5]*e[8]+.5000000000*ep2[4]*e[7]-.5000000000*e[7]*ep2[2]+.5000000000*e[7]*ep2[8]-.5000000000*e[7]*ep2[5]+.5000000000*e[7]*ep2[6]+e[1]*e[0]*e[6]+.5000000000*ep3[7]+e[4]*e[3]*e[6]+e[1]*e[2]*e[8]-.5000000000*e[7]*ep2[3]+.5000000000*ep2[1]*e[7];
|
||||||
|
A[53]=-1.*e[1]*e[32]*e[23]-1.*e[19]*e[32]*e[5]-1.*e[19]*e[33]*e[6]-1.*e[19]*e[30]*e[3]-1.*e[19]*e[35]*e[8]-1.*e[28]*e[21]*e[3]-1.*e[28]*e[26]*e[8]-1.*e[28]*e[23]*e[5]-1.*e[28]*e[24]*e[6]+e[7]*e[27]*e[24]+e[7]*e[18]*e[33]+e[7]*e[29]*e[26]+e[7]*e[20]*e[35]+e[22]*e[27]*e[3]+e[22]*e[0]*e[30]+e[22]*e[29]*e[5]+e[22]*e[2]*e[32]+e[31]*e[18]*e[3]+e[31]*e[0]*e[21]+e[31]*e[20]*e[5]+e[31]*e[2]*e[23]+e[25]*e[27]*e[6]+e[25]*e[0]*e[33]+e[25]*e[28]*e[7]+e[25]*e[1]*e[34]+e[25]*e[29]*e[8]+e[25]*e[2]*e[35]+e[34]*e[18]*e[6]+e[34]*e[0]*e[24]+e[34]*e[19]*e[7]+e[34]*e[20]*e[8]+e[34]*e[2]*e[26]+e[1]*e[27]*e[18]+3.*e[1]*e[28]*e[19]+e[1]*e[29]*e[20]+e[19]*e[27]*e[0]+e[19]*e[29]*e[2]+e[28]*e[18]*e[0]+e[28]*e[20]*e[2]+e[4]*e[27]*e[21]+e[4]*e[18]*e[30]+e[4]*e[28]*e[22]+e[4]*e[19]*e[31]+e[4]*e[29]*e[23]+e[4]*e[20]*e[32]-1.*e[1]*e[33]*e[24]-1.*e[1]*e[30]*e[21]-1.*e[1]*e[35]*e[26]+e[1]*e[31]*e[22];
|
||||||
|
A[167]=e[10]*e[27]*e[15]+e[10]*e[9]*e[33]+e[10]*e[29]*e[17]+e[10]*e[11]*e[35]+e[10]*e[28]*e[16]+e[28]*e[11]*e[17]+e[28]*e[9]*e[15]+e[13]*e[30]*e[15]+e[13]*e[12]*e[33]+e[13]*e[32]*e[17]+e[13]*e[14]*e[35]+e[13]*e[31]*e[16]+e[31]*e[14]*e[17]+e[31]*e[12]*e[15]+e[16]*e[33]*e[15]+e[16]*e[35]*e[17]-1.*e[16]*e[27]*e[9]-1.*e[16]*e[30]*e[12]-1.*e[16]*e[32]*e[14]-1.*e[16]*e[29]*e[11]+.5000000000*ep2[10]*e[34]+1.500000000*e[34]*ep2[16]-.5000000000*e[34]*ep2[9]-.5000000000*e[34]*ep2[11]-.5000000000*e[34]*ep2[12]+.5000000000*e[34]*ep2[15]+.5000000000*e[34]*ep2[17]-.5000000000*e[34]*ep2[14]+.5000000000*e[34]*ep2[13];
|
||||||
|
A[50]=.5000000000*e[19]*ep2[18]+.5000000000*e[19]*ep2[25]+.5000000000*e[19]*ep2[22]+e[25]*e[20]*e[26]-.5000000000*e[19]*ep2[21]+.5000000000*e[19]*ep2[20]-.5000000000*e[19]*ep2[26]-.5000000000*e[19]*ep2[23]-.5000000000*e[19]*ep2[24]+.5000000000*ep3[19]+e[22]*e[20]*e[23]+e[25]*e[18]*e[24]+e[22]*e[18]*e[21];
|
||||||
|
A[160]=.5000000000*e[34]*ep2[33]+.5000000000*e[34]*ep2[35]-.5000000000*e[34]*ep2[27]-.5000000000*e[34]*ep2[32]-.5000000000*e[34]*ep2[29]-.5000000000*e[34]*ep2[30]+.5000000000*ep2[28]*e[34]+e[31]*e[30]*e[33]+e[31]*e[32]*e[35]+e[28]*e[27]*e[33]+.5000000000*ep3[34]+e[28]*e[29]*e[35]+.5000000000*ep2[31]*e[34];
|
||||||
|
A[51]=e[4]*e[28]*e[13]+e[4]*e[10]*e[31]+e[7]*e[27]*e[15]+e[7]*e[9]*e[33]+e[7]*e[29]*e[17]+e[7]*e[11]*e[35]+e[7]*e[28]*e[16]+e[7]*e[10]*e[34]+e[1]*e[27]*e[9]+e[1]*e[29]*e[11]+3.*e[1]*e[28]*e[10]+e[10]*e[27]*e[0]-1.*e[10]*e[32]*e[5]-1.*e[10]*e[33]*e[6]-1.*e[10]*e[30]*e[3]-1.*e[10]*e[35]*e[8]+e[10]*e[29]*e[2]+e[13]*e[27]*e[3]+e[13]*e[0]*e[30]+e[13]*e[1]*e[31]+e[13]*e[29]*e[5]+e[13]*e[2]*e[32]+e[28]*e[11]*e[2]-1.*e[28]*e[15]*e[6]+e[28]*e[9]*e[0]-1.*e[28]*e[14]*e[5]-1.*e[28]*e[12]*e[3]-1.*e[28]*e[17]*e[8]+e[31]*e[9]*e[3]+e[31]*e[0]*e[12]+e[31]*e[11]*e[5]+e[31]*e[2]*e[14]+e[16]*e[27]*e[6]+e[16]*e[0]*e[33]+e[16]*e[1]*e[34]+e[16]*e[29]*e[8]+e[16]*e[2]*e[35]-1.*e[1]*e[30]*e[12]-1.*e[1]*e[32]*e[14]-1.*e[1]*e[33]*e[15]-1.*e[1]*e[35]*e[17]+e[34]*e[9]*e[6]+e[34]*e[0]*e[15]+e[34]*e[11]*e[8]+e[34]*e[2]*e[17]+e[4]*e[27]*e[12]+e[4]*e[9]*e[30]+e[4]*e[29]*e[14]+e[4]*e[11]*e[32];
|
||||||
|
A[161]=e[4]*e[30]*e[33]+e[4]*e[32]*e[35]+e[4]*e[31]*e[34]+e[31]*e[30]*e[6]+e[31]*e[3]*e[33]+e[31]*e[32]*e[8]+e[31]*e[5]*e[35]+e[28]*e[27]*e[6]+e[28]*e[0]*e[33]+e[28]*e[29]*e[8]+e[28]*e[2]*e[35]+e[34]*e[33]*e[6]+e[34]*e[35]*e[8]-1.*e[34]*e[27]*e[0]-1.*e[34]*e[32]*e[5]-1.*e[34]*e[30]*e[3]-1.*e[34]*e[29]*e[2]+e[1]*e[27]*e[33]+e[1]*e[29]*e[35]+e[1]*e[28]*e[34]+.5000000000*ep2[31]*e[7]-.5000000000*e[7]*ep2[27]-.5000000000*e[7]*ep2[32]+.5000000000*e[7]*ep2[28]-.5000000000*e[7]*ep2[29]+.5000000000*e[7]*ep2[33]-.5000000000*e[7]*ep2[30]+1.500000000*e[7]*ep2[34]+.5000000000*e[7]*ep2[35];
|
||||||
|
A[48]=-.5000000000*e[10]*ep2[14]-.5000000000*e[10]*ep2[17]-.5000000000*e[10]*ep2[15]+e[13]*e[11]*e[14]+e[16]*e[11]*e[17]+.5000000000*e[10]*ep2[13]+e[13]*e[9]*e[12]-.5000000000*e[10]*ep2[12]+.5000000000*ep3[10]+e[16]*e[9]*e[15]+.5000000000*e[10]*ep2[16]+.5000000000*e[10]*ep2[11]+.5000000000*e[10]*ep2[9];
|
||||||
|
A[162]=e[22]*e[32]*e[35]+e[22]*e[31]*e[34]+e[31]*e[30]*e[24]+e[31]*e[21]*e[33]+e[31]*e[32]*e[26]+e[31]*e[23]*e[35]+e[34]*e[33]*e[24]+e[34]*e[35]*e[26]-1.*e[34]*e[27]*e[18]-1.*e[34]*e[30]*e[21]-1.*e[34]*e[29]*e[20]-1.*e[34]*e[32]*e[23]+e[19]*e[27]*e[33]+e[19]*e[29]*e[35]+e[19]*e[28]*e[34]+e[28]*e[27]*e[24]+e[28]*e[18]*e[33]+e[28]*e[29]*e[26]+e[28]*e[20]*e[35]+e[22]*e[30]*e[33]+.5000000000*ep2[28]*e[25]+.5000000000*ep2[31]*e[25]+.5000000000*e[25]*ep2[33]+.5000000000*e[25]*ep2[35]+1.500000000*e[25]*ep2[34]-.5000000000*e[25]*ep2[27]-.5000000000*e[25]*ep2[32]-.5000000000*e[25]*ep2[29]-.5000000000*e[25]*ep2[30];
|
||||||
|
A[49]=-1.*e[19]*e[35]*e[26]-1.*e[19]*e[32]*e[23]+e[19]*e[27]*e[18]+e[19]*e[29]*e[20]+e[22]*e[27]*e[21]+e[22]*e[18]*e[30]+e[22]*e[19]*e[31]+e[22]*e[29]*e[23]+e[22]*e[20]*e[32]+e[31]*e[18]*e[21]+e[31]*e[20]*e[23]+e[25]*e[27]*e[24]+e[25]*e[18]*e[33]+e[25]*e[19]*e[34]+e[25]*e[29]*e[26]+e[25]*e[20]*e[35]+e[34]*e[18]*e[24]+e[34]*e[20]*e[26]-1.*e[19]*e[33]*e[24]-1.*e[19]*e[30]*e[21]+1.500000000*e[28]*ep2[19]+.5000000000*e[28]*ep2[18]+.5000000000*e[28]*ep2[20]+.5000000000*e[28]*ep2[22]+.5000000000*e[28]*ep2[25]-.5000000000*e[28]*ep2[26]-.5000000000*e[28]*ep2[23]-.5000000000*e[28]*ep2[24]-.5000000000*e[28]*ep2[21];
|
||||||
|
A[163]=e[10]*e[27]*e[33]+e[10]*e[29]*e[35]+e[10]*e[28]*e[34]+e[34]*e[33]*e[15]+e[34]*e[35]*e[17]+e[28]*e[27]*e[15]+e[28]*e[9]*e[33]+e[28]*e[29]*e[17]+e[28]*e[11]*e[35]-1.*e[34]*e[27]*e[9]-1.*e[34]*e[30]*e[12]+e[34]*e[31]*e[13]-1.*e[34]*e[32]*e[14]-1.*e[34]*e[29]*e[11]+e[31]*e[30]*e[15]+e[31]*e[12]*e[33]+e[31]*e[32]*e[17]+e[31]*e[14]*e[35]+e[13]*e[30]*e[33]+e[13]*e[32]*e[35]-.5000000000*e[16]*ep2[27]-.5000000000*e[16]*ep2[32]+.5000000000*e[16]*ep2[28]-.5000000000*e[16]*ep2[29]+.5000000000*e[16]*ep2[31]+.5000000000*e[16]*ep2[33]-.5000000000*e[16]*ep2[30]+1.500000000*e[16]*ep2[34]+.5000000000*e[16]*ep2[35];
|
||||||
|
A[63]=e[29]*e[32]*e[14]-1.*e[29]*e[33]*e[15]-1.*e[29]*e[34]*e[16]+e[32]*e[27]*e[12]+e[32]*e[9]*e[30]+e[32]*e[28]*e[13]+e[32]*e[10]*e[31]+e[14]*e[27]*e[30]+e[14]*e[28]*e[31]+e[17]*e[27]*e[33]+e[17]*e[28]*e[34]+e[35]*e[27]*e[15]+e[35]*e[9]*e[33]+e[35]*e[29]*e[17]+e[35]*e[28]*e[16]+e[35]*e[10]*e[34]+e[29]*e[27]*e[9]+e[29]*e[28]*e[10]-1.*e[29]*e[30]*e[12]-1.*e[29]*e[31]*e[13]+.5000000000*e[11]*ep2[27]+1.500000000*e[11]*ep2[29]+.5000000000*e[11]*ep2[28]+.5000000000*e[11]*ep2[32]-.5000000000*e[11]*ep2[31]-.5000000000*e[11]*ep2[33]-.5000000000*e[11]*ep2[30]-.5000000000*e[11]*ep2[34]+.5000000000*e[11]*ep2[35];
|
||||||
|
A[173]=e[1]*e[20]*e[35]+e[19]*e[27]*e[6]+e[19]*e[0]*e[33]+e[19]*e[28]*e[7]+e[19]*e[29]*e[8]+e[19]*e[2]*e[35]+e[28]*e[18]*e[6]+e[28]*e[0]*e[24]+e[28]*e[20]*e[8]+e[28]*e[2]*e[26]+e[4]*e[30]*e[24]+e[4]*e[21]*e[33]+e[4]*e[31]*e[25]+e[4]*e[22]*e[34]+e[4]*e[32]*e[26]+e[4]*e[23]*e[35]-1.*e[7]*e[27]*e[18]+e[7]*e[33]*e[24]-1.*e[7]*e[30]*e[21]-1.*e[7]*e[29]*e[20]+e[7]*e[35]*e[26]+e[7]*e[31]*e[22]-1.*e[7]*e[32]*e[23]-1.*e[25]*e[27]*e[0]-1.*e[25]*e[32]*e[5]-1.*e[25]*e[30]*e[3]-1.*e[25]*e[29]*e[2]-1.*e[34]*e[21]*e[3]-1.*e[34]*e[20]*e[2]-1.*e[34]*e[18]*e[0]-1.*e[34]*e[23]*e[5]+e[22]*e[30]*e[6]+e[22]*e[3]*e[33]+e[22]*e[32]*e[8]+e[22]*e[5]*e[35]+e[31]*e[21]*e[6]+e[31]*e[3]*e[24]+e[31]*e[23]*e[8]+e[31]*e[5]*e[26]+e[34]*e[26]*e[8]+e[1]*e[27]*e[24]+e[1]*e[18]*e[33]+e[1]*e[28]*e[25]+e[1]*e[19]*e[34]+e[1]*e[29]*e[26]+e[34]*e[24]*e[6]+e[25]*e[33]*e[6]+3.*e[25]*e[34]*e[7]+e[25]*e[35]*e[8];
|
||||||
|
A[62]=.5000000000*e[20]*ep2[27]+1.500000000*e[20]*ep2[29]+.5000000000*e[20]*ep2[28]+.5000000000*e[20]*ep2[32]+.5000000000*e[20]*ep2[35]-.5000000000*e[20]*ep2[31]-.5000000000*e[20]*ep2[33]-.5000000000*e[20]*ep2[30]-.5000000000*e[20]*ep2[34]+e[29]*e[27]*e[18]+e[29]*e[28]*e[19]+e[23]*e[27]*e[30]+e[23]*e[29]*e[32]+e[23]*e[28]*e[31]+e[32]*e[27]*e[21]+e[32]*e[18]*e[30]+e[32]*e[28]*e[22]+e[32]*e[19]*e[31]+e[26]*e[27]*e[33]+e[26]*e[29]*e[35]+e[26]*e[28]*e[34]+e[35]*e[27]*e[24]+e[35]*e[18]*e[33]+e[35]*e[28]*e[25]+e[35]*e[19]*e[34]-1.*e[29]*e[33]*e[24]-1.*e[29]*e[30]*e[21]-1.*e[29]*e[31]*e[22]-1.*e[29]*e[34]*e[25];
|
||||||
|
A[172]=e[19]*e[1]*e[7]+e[19]*e[0]*e[6]+e[19]*e[2]*e[8]+e[4]*e[21]*e[6]+e[4]*e[3]*e[24]+e[4]*e[22]*e[7]+e[4]*e[23]*e[8]+e[4]*e[5]*e[26]+e[22]*e[3]*e[6]+e[22]*e[5]*e[8]+e[7]*e[24]*e[6]+e[7]*e[26]*e[8]+e[1]*e[18]*e[6]+e[1]*e[0]*e[24]+e[1]*e[20]*e[8]+e[1]*e[2]*e[26]-1.*e[7]*e[21]*e[3]-1.*e[7]*e[20]*e[2]-1.*e[7]*e[18]*e[0]-1.*e[7]*e[23]*e[5]+.5000000000*e[25]*ep2[4]-.5000000000*e[25]*ep2[0]+.5000000000*e[25]*ep2[6]-.5000000000*e[25]*ep2[5]+.5000000000*e[25]*ep2[1]+1.500000000*e[25]*ep2[7]-.5000000000*e[25]*ep2[3]-.5000000000*e[25]*ep2[2]+.5000000000*e[25]*ep2[8];
|
||||||
|
A[61]=e[5]*e[27]*e[30]+e[5]*e[29]*e[32]+e[5]*e[28]*e[31]+e[32]*e[27]*e[3]+e[32]*e[0]*e[30]+e[32]*e[28]*e[4]+e[32]*e[1]*e[31]+e[8]*e[27]*e[33]+e[8]*e[29]*e[35]+e[8]*e[28]*e[34]+e[29]*e[27]*e[0]+e[29]*e[28]*e[1]+e[35]*e[27]*e[6]+e[35]*e[0]*e[33]+e[35]*e[28]*e[7]+e[35]*e[1]*e[34]-1.*e[29]*e[34]*e[7]-1.*e[29]*e[33]*e[6]-1.*e[29]*e[30]*e[3]-1.*e[29]*e[31]*e[4]+.5000000000*e[2]*ep2[27]+1.500000000*e[2]*ep2[29]+.5000000000*e[2]*ep2[28]+.5000000000*e[2]*ep2[32]-.5000000000*e[2]*ep2[31]-.5000000000*e[2]*ep2[33]-.5000000000*e[2]*ep2[30]-.5000000000*e[2]*ep2[34]+.5000000000*e[2]*ep2[35];
|
||||||
|
A[175]=e[13]*e[12]*e[6]+e[13]*e[3]*e[15]+e[13]*e[4]*e[16]+e[13]*e[14]*e[8]+e[13]*e[5]*e[17]+e[16]*e[15]*e[6]+e[16]*e[17]*e[8]+e[1]*e[11]*e[17]+e[1]*e[9]*e[15]+e[1]*e[10]*e[16]+e[4]*e[14]*e[17]+e[4]*e[12]*e[15]+e[10]*e[9]*e[6]+e[10]*e[0]*e[15]+e[10]*e[11]*e[8]+e[10]*e[2]*e[17]-1.*e[16]*e[11]*e[2]-1.*e[16]*e[9]*e[0]-1.*e[16]*e[14]*e[5]-1.*e[16]*e[12]*e[3]+.5000000000*ep2[13]*e[7]+1.500000000*ep2[16]*e[7]+.5000000000*e[7]*ep2[17]+.5000000000*e[7]*ep2[15]-.5000000000*e[7]*ep2[9]-.5000000000*e[7]*ep2[11]-.5000000000*e[7]*ep2[12]+.5000000000*e[7]*ep2[10]-.5000000000*e[7]*ep2[14];
|
||||||
|
A[60]=.5000000000*e[29]*ep2[32]+.5000000000*e[29]*ep2[35]-.5000000000*e[29]*ep2[31]-.5000000000*e[29]*ep2[33]-.5000000000*e[29]*ep2[30]-.5000000000*e[29]*ep2[34]+e[32]*e[27]*e[30]+.5000000000*ep3[29]+.5000000000*e[29]*ep2[28]+e[35]*e[28]*e[34]+.5000000000*e[29]*ep2[27]+e[35]*e[27]*e[33]+e[32]*e[28]*e[31];
|
||||||
|
A[174]=-1.*e[16]*e[21]*e[12]+e[10]*e[18]*e[15]+e[10]*e[9]*e[24]+e[10]*e[20]*e[17]+e[10]*e[11]*e[26]+e[19]*e[11]*e[17]+e[19]*e[9]*e[15]+e[19]*e[10]*e[16]+e[13]*e[21]*e[15]+e[13]*e[12]*e[24]+e[13]*e[23]*e[17]+e[13]*e[14]*e[26]+e[13]*e[22]*e[16]+e[22]*e[14]*e[17]+e[22]*e[12]*e[15]+e[16]*e[24]*e[15]+e[16]*e[26]*e[17]-1.*e[16]*e[23]*e[14]-1.*e[16]*e[20]*e[11]-1.*e[16]*e[18]*e[9]+.5000000000*ep2[13]*e[25]+1.500000000*e[25]*ep2[16]+.5000000000*e[25]*ep2[17]+.5000000000*e[25]*ep2[15]+.5000000000*ep2[10]*e[25]-.5000000000*e[25]*ep2[9]-.5000000000*e[25]*ep2[11]-.5000000000*e[25]*ep2[12]-.5000000000*e[25]*ep2[14];
|
||||||
|
A[59]=e[19]*e[20]*e[2]+e[22]*e[18]*e[3]+e[22]*e[0]*e[21]+e[22]*e[19]*e[4]+e[22]*e[20]*e[5]+e[22]*e[2]*e[23]-1.*e[19]*e[21]*e[3]-1.*e[19]*e[26]*e[8]+e[19]*e[25]*e[7]-1.*e[19]*e[23]*e[5]-1.*e[19]*e[24]*e[6]+e[4]*e[18]*e[21]+e[4]*e[20]*e[23]+e[25]*e[18]*e[6]+e[25]*e[0]*e[24]+e[25]*e[20]*e[8]+e[25]*e[2]*e[26]+e[7]*e[18]*e[24]+e[7]*e[20]*e[26]+e[19]*e[18]*e[0]+1.500000000*ep2[19]*e[1]+.5000000000*e[1]*ep2[22]+.5000000000*e[1]*ep2[18]+.5000000000*e[1]*ep2[20]+.5000000000*e[1]*ep2[25]-.5000000000*e[1]*ep2[26]-.5000000000*e[1]*ep2[23]-.5000000000*e[1]*ep2[24]-.5000000000*e[1]*ep2[21];
|
||||||
|
A[169]=e[19]*e[27]*e[24]+e[19]*e[18]*e[33]+e[19]*e[28]*e[25]+e[19]*e[29]*e[26]+e[19]*e[20]*e[35]+e[28]*e[18]*e[24]+e[28]*e[20]*e[26]+e[22]*e[30]*e[24]+e[22]*e[21]*e[33]+e[22]*e[31]*e[25]+e[22]*e[32]*e[26]+e[22]*e[23]*e[35]+e[31]*e[21]*e[24]+e[31]*e[23]*e[26]+e[25]*e[33]*e[24]+e[25]*e[35]*e[26]-1.*e[25]*e[27]*e[18]-1.*e[25]*e[30]*e[21]-1.*e[25]*e[29]*e[20]-1.*e[25]*e[32]*e[23]-.5000000000*e[34]*ep2[18]-.5000000000*e[34]*ep2[23]-.5000000000*e[34]*ep2[20]-.5000000000*e[34]*ep2[21]+.5000000000*ep2[19]*e[34]+.5000000000*ep2[22]*e[34]+1.500000000*e[34]*ep2[25]+.5000000000*e[34]*ep2[24]+.5000000000*e[34]*ep2[26];
|
||||||
|
A[58]=e[16]*e[0]*e[6]+e[16]*e[2]*e[8]+e[1]*e[11]*e[2]-1.*e[1]*e[15]*e[6]+e[1]*e[9]*e[0]-1.*e[1]*e[14]*e[5]-1.*e[1]*e[12]*e[3]-1.*e[1]*e[17]*e[8]+e[4]*e[9]*e[3]+e[4]*e[0]*e[12]+e[4]*e[1]*e[13]+e[4]*e[11]*e[5]+e[4]*e[2]*e[14]+e[13]*e[0]*e[3]+e[13]*e[2]*e[5]+e[7]*e[9]*e[6]+e[7]*e[0]*e[15]+e[7]*e[1]*e[16]+e[7]*e[11]*e[8]+e[7]*e[2]*e[17]-.5000000000*e[10]*ep2[6]-.5000000000*e[10]*ep2[5]-.5000000000*e[10]*ep2[3]-.5000000000*e[10]*ep2[8]+1.500000000*e[10]*ep2[1]+.5000000000*e[10]*ep2[0]+.5000000000*e[10]*ep2[2]+.5000000000*e[10]*ep2[4]+.5000000000*e[10]*ep2[7];
|
||||||
|
A[168]=e[13]*e[14]*e[17]+e[13]*e[12]*e[15]+e[10]*e[9]*e[15]+.5000000000*e[16]*ep2[15]-.5000000000*e[16]*ep2[11]-.5000000000*e[16]*ep2[12]-.5000000000*e[16]*ep2[14]+e[10]*e[11]*e[17]+.5000000000*ep2[10]*e[16]+.5000000000*ep3[16]-.5000000000*e[16]*ep2[9]+.5000000000*e[16]*ep2[17]+.5000000000*ep2[13]*e[16];
|
||||||
|
A[57]=e[10]*e[29]*e[20]+e[22]*e[27]*e[12]+e[22]*e[9]*e[30]+e[22]*e[29]*e[14]+e[22]*e[11]*e[32]+e[22]*e[10]*e[31]+e[31]*e[18]*e[12]+e[31]*e[9]*e[21]+e[31]*e[20]*e[14]+e[31]*e[11]*e[23]-1.*e[10]*e[33]*e[24]-1.*e[10]*e[30]*e[21]-1.*e[10]*e[35]*e[26]-1.*e[10]*e[32]*e[23]+e[10]*e[34]*e[25]+e[19]*e[27]*e[9]+e[19]*e[29]*e[11]+e[28]*e[18]*e[9]+e[28]*e[20]*e[11]+e[16]*e[27]*e[24]+e[16]*e[18]*e[33]+e[16]*e[28]*e[25]+e[16]*e[19]*e[34]+e[16]*e[29]*e[26]+e[16]*e[20]*e[35]-1.*e[19]*e[30]*e[12]-1.*e[19]*e[32]*e[14]-1.*e[19]*e[33]*e[15]-1.*e[19]*e[35]*e[17]-1.*e[28]*e[23]*e[14]-1.*e[28]*e[24]*e[15]-1.*e[28]*e[26]*e[17]-1.*e[28]*e[21]*e[12]+e[25]*e[27]*e[15]+e[25]*e[9]*e[33]+e[25]*e[29]*e[17]+e[25]*e[11]*e[35]+e[34]*e[18]*e[15]+e[34]*e[9]*e[24]+e[34]*e[20]*e[17]+e[34]*e[11]*e[26]+e[13]*e[27]*e[21]+e[13]*e[18]*e[30]+e[13]*e[28]*e[22]+e[13]*e[19]*e[31]+e[13]*e[29]*e[23]+e[13]*e[20]*e[32]+e[10]*e[27]*e[18]+3.*e[10]*e[28]*e[19];
|
||||||
|
A[171]=e[4]*e[30]*e[15]+e[4]*e[12]*e[33]+e[4]*e[32]*e[17]+e[4]*e[14]*e[35]+e[4]*e[31]*e[16]+e[4]*e[13]*e[34]+e[7]*e[33]*e[15]+e[7]*e[35]*e[17]+3.*e[7]*e[34]*e[16]+e[1]*e[27]*e[15]+e[1]*e[9]*e[33]+e[1]*e[29]*e[17]+e[1]*e[11]*e[35]+e[1]*e[28]*e[16]+e[1]*e[10]*e[34]-1.*e[16]*e[27]*e[0]-1.*e[16]*e[32]*e[5]+e[16]*e[33]*e[6]-1.*e[16]*e[30]*e[3]+e[16]*e[35]*e[8]-1.*e[16]*e[29]*e[2]+e[13]*e[30]*e[6]+e[13]*e[3]*e[33]+e[13]*e[31]*e[7]+e[13]*e[32]*e[8]+e[13]*e[5]*e[35]-1.*e[34]*e[11]*e[2]+e[34]*e[15]*e[6]-1.*e[34]*e[9]*e[0]-1.*e[34]*e[14]*e[5]-1.*e[34]*e[12]*e[3]+e[34]*e[17]*e[8]+e[31]*e[12]*e[6]+e[31]*e[3]*e[15]+e[31]*e[14]*e[8]+e[31]*e[5]*e[17]-1.*e[7]*e[27]*e[9]-1.*e[7]*e[30]*e[12]+e[7]*e[28]*e[10]-1.*e[7]*e[32]*e[14]+e[10]*e[27]*e[6]+e[10]*e[0]*e[33]+e[10]*e[29]*e[8]+e[10]*e[2]*e[35]+e[28]*e[9]*e[6]+e[28]*e[0]*e[15]+e[28]*e[11]*e[8]+e[28]*e[2]*e[17]-1.*e[7]*e[29]*e[11];
|
||||||
|
A[56]=e[22]*e[18]*e[12]+e[22]*e[9]*e[21]+e[22]*e[20]*e[14]+e[22]*e[11]*e[23]+e[22]*e[19]*e[13]+e[25]*e[18]*e[15]+e[25]*e[9]*e[24]+e[25]*e[20]*e[17]+e[25]*e[11]*e[26]+e[25]*e[19]*e[16]+e[16]*e[18]*e[24]+e[16]*e[20]*e[26]+e[13]*e[18]*e[21]+e[13]*e[20]*e[23]+e[19]*e[18]*e[9]+e[19]*e[20]*e[11]-1.*e[19]*e[23]*e[14]-1.*e[19]*e[24]*e[15]-1.*e[19]*e[26]*e[17]-1.*e[19]*e[21]*e[12]+.5000000000*e[10]*ep2[22]+.5000000000*e[10]*ep2[25]+1.500000000*e[10]*ep2[19]+.5000000000*e[10]*ep2[18]+.5000000000*e[10]*ep2[20]-.5000000000*e[10]*ep2[26]-.5000000000*e[10]*ep2[23]-.5000000000*e[10]*ep2[24]-.5000000000*e[10]*ep2[21];
|
||||||
|
A[170]=e[19]*e[20]*e[26]-.5000000000*e[25]*ep2[20]+e[22]*e[21]*e[24]+e[19]*e[18]*e[24]+.5000000000*ep2[22]*e[25]-.5000000000*e[25]*ep2[21]-.5000000000*e[25]*ep2[23]+.5000000000*ep2[19]*e[25]-.5000000000*e[25]*ep2[18]+.5000000000*e[25]*ep2[24]+.5000000000*e[25]*ep2[26]+.5000000000*ep3[25]+e[22]*e[23]*e[26];
|
||||||
|
A[73]=-1.*e[20]*e[33]*e[6]-1.*e[20]*e[30]*e[3]-1.*e[20]*e[31]*e[4]-1.*e[29]*e[21]*e[3]-1.*e[29]*e[22]*e[4]-1.*e[29]*e[25]*e[7]-1.*e[29]*e[24]*e[6]+e[8]*e[27]*e[24]+e[8]*e[18]*e[33]+e[8]*e[28]*e[25]+e[8]*e[19]*e[34]+e[23]*e[27]*e[3]+e[23]*e[0]*e[30]+e[23]*e[28]*e[4]+e[23]*e[1]*e[31]+e[32]*e[18]*e[3]+e[32]*e[0]*e[21]+e[32]*e[19]*e[4]+e[32]*e[1]*e[22]+e[26]*e[27]*e[6]+e[26]*e[0]*e[33]+e[26]*e[28]*e[7]+e[26]*e[1]*e[34]+e[26]*e[29]*e[8]+e[26]*e[2]*e[35]+e[35]*e[18]*e[6]+e[35]*e[0]*e[24]+e[35]*e[19]*e[7]+e[35]*e[1]*e[25]+e[35]*e[20]*e[8]+e[2]*e[27]*e[18]+e[2]*e[28]*e[19]+3.*e[2]*e[29]*e[20]+e[20]*e[27]*e[0]+e[20]*e[28]*e[1]+e[29]*e[18]*e[0]+e[29]*e[19]*e[1]+e[5]*e[27]*e[21]+e[5]*e[18]*e[30]+e[5]*e[28]*e[22]+e[5]*e[19]*e[31]+e[5]*e[29]*e[23]+e[5]*e[20]*e[32]-1.*e[2]*e[33]*e[24]-1.*e[2]*e[30]*e[21]-1.*e[2]*e[31]*e[22]+e[2]*e[32]*e[23]-1.*e[2]*e[34]*e[25]-1.*e[20]*e[34]*e[7];
|
||||||
|
A[72]=e[5]*e[18]*e[3]+e[5]*e[0]*e[21]+e[5]*e[19]*e[4]+e[5]*e[1]*e[22]+e[5]*e[2]*e[23]+e[23]*e[1]*e[4]+e[23]*e[0]*e[3]+e[8]*e[18]*e[6]+e[8]*e[0]*e[24]+e[8]*e[19]*e[7]+e[8]*e[1]*e[25]+e[8]*e[2]*e[26]+e[26]*e[1]*e[7]+e[26]*e[0]*e[6]+e[2]*e[18]*e[0]+e[2]*e[19]*e[1]-1.*e[2]*e[21]*e[3]-1.*e[2]*e[22]*e[4]-1.*e[2]*e[25]*e[7]-1.*e[2]*e[24]*e[6]-.5000000000*e[20]*ep2[4]+.5000000000*e[20]*ep2[0]-.5000000000*e[20]*ep2[6]+.5000000000*e[20]*ep2[5]+.5000000000*e[20]*ep2[1]-.5000000000*e[20]*ep2[7]-.5000000000*e[20]*ep2[3]+1.500000000*e[20]*ep2[2]+.5000000000*e[20]*ep2[8];
|
||||||
|
A[75]=e[14]*e[9]*e[3]+e[14]*e[0]*e[12]+e[14]*e[10]*e[4]+e[14]*e[1]*e[13]+e[14]*e[11]*e[5]+e[17]*e[9]*e[6]+e[17]*e[0]*e[15]+e[17]*e[10]*e[7]+e[17]*e[1]*e[16]+e[17]*e[11]*e[8]+e[8]*e[9]*e[15]+e[8]*e[10]*e[16]+e[5]*e[9]*e[12]+e[5]*e[10]*e[13]+e[11]*e[9]*e[0]+e[11]*e[10]*e[1]-1.*e[11]*e[13]*e[4]-1.*e[11]*e[16]*e[7]-1.*e[11]*e[15]*e[6]-1.*e[11]*e[12]*e[3]+.5000000000*e[2]*ep2[14]+.5000000000*e[2]*ep2[17]+1.500000000*e[2]*ep2[11]+.5000000000*e[2]*ep2[9]+.5000000000*e[2]*ep2[10]-.5000000000*e[2]*ep2[16]-.5000000000*e[2]*ep2[12]-.5000000000*e[2]*ep2[15]-.5000000000*e[2]*ep2[13];
|
||||||
|
A[74]=e[14]*e[18]*e[12]+e[14]*e[9]*e[21]+e[14]*e[11]*e[23]+e[14]*e[19]*e[13]+e[14]*e[10]*e[22]+e[23]*e[9]*e[12]+e[23]*e[10]*e[13]+e[17]*e[18]*e[15]+e[17]*e[9]*e[24]+e[17]*e[11]*e[26]+e[17]*e[19]*e[16]+e[17]*e[10]*e[25]+e[26]*e[9]*e[15]+e[26]*e[10]*e[16]-1.*e[11]*e[24]*e[15]-1.*e[11]*e[25]*e[16]+e[11]*e[18]*e[9]-1.*e[11]*e[21]*e[12]+e[11]*e[19]*e[10]-1.*e[11]*e[22]*e[13]+1.500000000*e[20]*ep2[11]+.5000000000*e[20]*ep2[9]+.5000000000*e[20]*ep2[10]+.5000000000*e[20]*ep2[14]+.5000000000*e[20]*ep2[17]-.5000000000*e[20]*ep2[16]-.5000000000*e[20]*ep2[12]-.5000000000*e[20]*ep2[15]-.5000000000*e[20]*ep2[13];
|
||||||
|
A[77]=e[23]*e[10]*e[31]+e[32]*e[18]*e[12]+e[32]*e[9]*e[21]+e[32]*e[19]*e[13]+e[32]*e[10]*e[22]-1.*e[11]*e[33]*e[24]-1.*e[11]*e[30]*e[21]+e[11]*e[35]*e[26]-1.*e[11]*e[31]*e[22]-1.*e[11]*e[34]*e[25]+e[20]*e[27]*e[9]+e[20]*e[28]*e[10]+e[29]*e[18]*e[9]+e[29]*e[19]*e[10]+e[17]*e[27]*e[24]+e[17]*e[18]*e[33]+e[17]*e[28]*e[25]+e[17]*e[19]*e[34]+e[17]*e[29]*e[26]+e[17]*e[20]*e[35]-1.*e[20]*e[30]*e[12]-1.*e[20]*e[31]*e[13]-1.*e[20]*e[33]*e[15]-1.*e[20]*e[34]*e[16]-1.*e[29]*e[24]*e[15]-1.*e[29]*e[25]*e[16]-1.*e[29]*e[21]*e[12]-1.*e[29]*e[22]*e[13]+e[26]*e[27]*e[15]+e[26]*e[9]*e[33]+e[26]*e[28]*e[16]+e[26]*e[10]*e[34]+e[35]*e[18]*e[15]+e[35]*e[9]*e[24]+e[35]*e[19]*e[16]+e[35]*e[10]*e[25]+e[14]*e[27]*e[21]+e[14]*e[18]*e[30]+e[14]*e[28]*e[22]+e[14]*e[19]*e[31]+e[14]*e[29]*e[23]+e[14]*e[20]*e[32]+e[11]*e[27]*e[18]+e[11]*e[28]*e[19]+3.*e[11]*e[29]*e[20]+e[23]*e[27]*e[12]+e[23]*e[9]*e[30]+e[23]*e[11]*e[32]+e[23]*e[28]*e[13];
|
||||||
|
A[76]=e[23]*e[18]*e[12]+e[23]*e[9]*e[21]+e[23]*e[20]*e[14]+e[23]*e[19]*e[13]+e[23]*e[10]*e[22]+e[26]*e[18]*e[15]+e[26]*e[9]*e[24]+e[26]*e[20]*e[17]+e[26]*e[19]*e[16]+e[26]*e[10]*e[25]+e[17]*e[19]*e[25]+e[17]*e[18]*e[24]+e[14]*e[19]*e[22]+e[14]*e[18]*e[21]+e[20]*e[18]*e[9]+e[20]*e[19]*e[10]-1.*e[20]*e[24]*e[15]-1.*e[20]*e[25]*e[16]-1.*e[20]*e[21]*e[12]-1.*e[20]*e[22]*e[13]+.5000000000*e[11]*ep2[23]+.5000000000*e[11]*ep2[26]+.5000000000*e[11]*ep2[19]+.5000000000*e[11]*ep2[18]+1.500000000*e[11]*ep2[20]-.5000000000*e[11]*ep2[22]-.5000000000*e[11]*ep2[24]-.5000000000*e[11]*ep2[21]-.5000000000*e[11]*ep2[25];
|
||||||
|
A[79]=-1.*e[20]*e[21]*e[3]+e[20]*e[26]*e[8]-1.*e[20]*e[22]*e[4]-1.*e[20]*e[25]*e[7]-1.*e[20]*e[24]*e[6]+e[5]*e[19]*e[22]+e[5]*e[18]*e[21]+e[26]*e[18]*e[6]+e[26]*e[0]*e[24]+e[26]*e[19]*e[7]+e[26]*e[1]*e[25]+e[8]*e[19]*e[25]+e[8]*e[18]*e[24]+e[20]*e[18]*e[0]+e[20]*e[19]*e[1]+e[23]*e[18]*e[3]+e[23]*e[0]*e[21]+e[23]*e[19]*e[4]+e[23]*e[1]*e[22]+e[23]*e[20]*e[5]+1.500000000*ep2[20]*e[2]+.5000000000*e[2]*ep2[23]+.5000000000*e[2]*ep2[19]+.5000000000*e[2]*ep2[18]+.5000000000*e[2]*ep2[26]-.5000000000*e[2]*ep2[22]-.5000000000*e[2]*ep2[24]-.5000000000*e[2]*ep2[21]-.5000000000*e[2]*ep2[25];
|
||||||
|
A[78]=-1.*e[2]*e[15]*e[6]+e[2]*e[9]*e[0]-1.*e[2]*e[12]*e[3]+e[5]*e[9]*e[3]+e[5]*e[0]*e[12]+e[5]*e[10]*e[4]+e[5]*e[1]*e[13]+e[5]*e[2]*e[14]+e[14]*e[1]*e[4]+e[14]*e[0]*e[3]+e[8]*e[9]*e[6]+e[8]*e[0]*e[15]+e[8]*e[10]*e[7]+e[8]*e[1]*e[16]+e[8]*e[2]*e[17]+e[17]*e[1]*e[7]+e[17]*e[0]*e[6]+e[2]*e[10]*e[1]-1.*e[2]*e[13]*e[4]-1.*e[2]*e[16]*e[7]+.5000000000*e[11]*ep2[1]+.5000000000*e[11]*ep2[0]+1.500000000*e[11]*ep2[2]+.5000000000*e[11]*ep2[5]+.5000000000*e[11]*ep2[8]-.5000000000*e[11]*ep2[4]-.5000000000*e[11]*ep2[6]-.5000000000*e[11]*ep2[7]-.5000000000*e[11]*ep2[3];
|
||||||
|
A[64]=e[5]*e[19]*e[13]+e[5]*e[10]*e[22]+e[8]*e[18]*e[15]+e[8]*e[9]*e[24]+e[8]*e[20]*e[17]+e[8]*e[11]*e[26]+e[8]*e[19]*e[16]+e[8]*e[10]*e[25]+e[2]*e[18]*e[9]+e[2]*e[19]*e[10]-1.*e[11]*e[21]*e[3]-1.*e[11]*e[22]*e[4]-1.*e[11]*e[25]*e[7]-1.*e[11]*e[24]*e[6]+e[14]*e[18]*e[3]+e[14]*e[0]*e[21]+e[14]*e[19]*e[4]+e[14]*e[1]*e[22]+e[14]*e[2]*e[23]-1.*e[20]*e[13]*e[4]-1.*e[20]*e[16]*e[7]-1.*e[20]*e[15]*e[6]-1.*e[20]*e[12]*e[3]+e[23]*e[9]*e[3]+e[23]*e[0]*e[12]+e[23]*e[10]*e[4]+e[23]*e[1]*e[13]+e[17]*e[18]*e[6]+e[17]*e[0]*e[24]+e[17]*e[19]*e[7]+e[17]*e[1]*e[25]+e[17]*e[2]*e[26]-1.*e[2]*e[24]*e[15]-1.*e[2]*e[25]*e[16]-1.*e[2]*e[21]*e[12]-1.*e[2]*e[22]*e[13]+e[26]*e[9]*e[6]+e[26]*e[0]*e[15]+e[26]*e[10]*e[7]+e[26]*e[1]*e[16]+e[11]*e[18]*e[0]+e[11]*e[19]*e[1]+3.*e[11]*e[20]*e[2]+e[20]*e[9]*e[0]+e[20]*e[10]*e[1]+e[5]*e[18]*e[12]+e[5]*e[9]*e[21]+e[5]*e[20]*e[14]+e[5]*e[11]*e[23];
|
||||||
|
A[65]=e[32]*e[1]*e[4]+e[32]*e[0]*e[3]+e[8]*e[27]*e[6]+e[8]*e[0]*e[33]+e[8]*e[28]*e[7]+e[8]*e[1]*e[34]+e[35]*e[1]*e[7]+e[35]*e[0]*e[6]+e[2]*e[27]*e[0]+e[2]*e[28]*e[1]-1.*e[2]*e[34]*e[7]+e[2]*e[32]*e[5]-1.*e[2]*e[33]*e[6]-1.*e[2]*e[30]*e[3]+e[2]*e[35]*e[8]-1.*e[2]*e[31]*e[4]+e[5]*e[27]*e[3]+e[5]*e[0]*e[30]+e[5]*e[28]*e[4]+e[5]*e[1]*e[31]+1.500000000*e[29]*ep2[2]-.5000000000*e[29]*ep2[4]+.5000000000*e[29]*ep2[0]-.5000000000*e[29]*ep2[6]+.5000000000*e[29]*ep2[5]+.5000000000*e[29]*ep2[1]-.5000000000*e[29]*ep2[7]-.5000000000*e[29]*ep2[3]+.5000000000*e[29]*ep2[8];
|
||||||
|
A[66]=e[5]*e[0]*e[3]+e[8]*e[1]*e[7]+e[8]*e[0]*e[6]+e[5]*e[1]*e[4]-.5000000000*e[2]*ep2[4]+.5000000000*ep3[2]+.5000000000*e[2]*ep2[1]-.5000000000*e[2]*ep2[3]+.5000000000*e[2]*ep2[0]+.5000000000*e[2]*ep2[8]+.5000000000*e[2]*ep2[5]-.5000000000*e[2]*ep2[6]-.5000000000*e[2]*ep2[7];
|
||||||
|
A[67]=e[35]*e[9]*e[15]+e[35]*e[10]*e[16]-1.*e[11]*e[30]*e[12]-1.*e[11]*e[31]*e[13]-1.*e[11]*e[33]*e[15]-1.*e[11]*e[34]*e[16]+e[11]*e[27]*e[9]+e[11]*e[28]*e[10]+e[14]*e[27]*e[12]+e[14]*e[9]*e[30]+e[14]*e[11]*e[32]+e[14]*e[28]*e[13]+e[14]*e[10]*e[31]+e[32]*e[9]*e[12]+e[32]*e[10]*e[13]+e[17]*e[27]*e[15]+e[17]*e[9]*e[33]+e[17]*e[11]*e[35]+e[17]*e[28]*e[16]+e[17]*e[10]*e[34]+1.500000000*e[29]*ep2[11]-.5000000000*e[29]*ep2[16]+.5000000000*e[29]*ep2[9]-.5000000000*e[29]*ep2[12]-.5000000000*e[29]*ep2[15]+.5000000000*e[29]*ep2[17]+.5000000000*e[29]*ep2[10]+.5000000000*e[29]*ep2[14]-.5000000000*e[29]*ep2[13];
|
||||||
|
A[68]=e[14]*e[9]*e[12]+e[17]*e[10]*e[16]+e[17]*e[9]*e[15]+.5000000000*ep3[11]+e[14]*e[10]*e[13]+.5000000000*e[11]*ep2[10]-.5000000000*e[11]*ep2[15]+.5000000000*e[11]*ep2[14]-.5000000000*e[11]*ep2[13]-.5000000000*e[11]*ep2[12]+.5000000000*e[11]*ep2[9]-.5000000000*e[11]*ep2[16]+.5000000000*e[11]*ep2[17];
|
||||||
|
A[69]=e[20]*e[27]*e[18]+e[20]*e[28]*e[19]+e[23]*e[27]*e[21]+e[23]*e[18]*e[30]+e[23]*e[28]*e[22]+e[23]*e[19]*e[31]+e[23]*e[20]*e[32]+e[32]*e[19]*e[22]+e[32]*e[18]*e[21]+e[26]*e[27]*e[24]+e[26]*e[18]*e[33]+e[26]*e[28]*e[25]+e[26]*e[19]*e[34]+e[26]*e[20]*e[35]+e[35]*e[19]*e[25]+e[35]*e[18]*e[24]-1.*e[20]*e[33]*e[24]-1.*e[20]*e[30]*e[21]-1.*e[20]*e[31]*e[22]-1.*e[20]*e[34]*e[25]+.5000000000*e[29]*ep2[23]+.5000000000*e[29]*ep2[26]-.5000000000*e[29]*ep2[22]-.5000000000*e[29]*ep2[24]-.5000000000*e[29]*ep2[21]-.5000000000*e[29]*ep2[25]+1.500000000*e[29]*ep2[20]+.5000000000*e[29]*ep2[19]+.5000000000*e[29]*ep2[18];
|
||||||
|
A[70]=.5000000000*e[20]*ep2[26]+.5000000000*e[20]*ep2[18]+.5000000000*ep3[20]+.5000000000*e[20]*ep2[19]+e[26]*e[18]*e[24]+.5000000000*e[20]*ep2[23]-.5000000000*e[20]*ep2[25]+e[23]*e[19]*e[22]-.5000000000*e[20]*ep2[24]-.5000000000*e[20]*ep2[21]-.5000000000*e[20]*ep2[22]+e[23]*e[18]*e[21]+e[26]*e[19]*e[25];
|
||||||
|
A[71]=e[8]*e[28]*e[16]+e[8]*e[10]*e[34]+e[2]*e[27]*e[9]+3.*e[2]*e[29]*e[11]+e[2]*e[28]*e[10]+e[11]*e[27]*e[0]-1.*e[11]*e[34]*e[7]-1.*e[11]*e[33]*e[6]-1.*e[11]*e[30]*e[3]+e[11]*e[28]*e[1]-1.*e[11]*e[31]*e[4]+e[14]*e[27]*e[3]+e[14]*e[0]*e[30]+e[14]*e[28]*e[4]+e[14]*e[1]*e[31]+e[14]*e[2]*e[32]+e[29]*e[10]*e[1]-1.*e[29]*e[13]*e[4]-1.*e[29]*e[16]*e[7]-1.*e[29]*e[15]*e[6]+e[29]*e[9]*e[0]-1.*e[29]*e[12]*e[3]+e[32]*e[9]*e[3]+e[32]*e[0]*e[12]+e[32]*e[10]*e[4]+e[32]*e[1]*e[13]+e[17]*e[27]*e[6]+e[17]*e[0]*e[33]+e[17]*e[28]*e[7]+e[17]*e[1]*e[34]+e[17]*e[2]*e[35]-1.*e[2]*e[30]*e[12]-1.*e[2]*e[31]*e[13]-1.*e[2]*e[33]*e[15]-1.*e[2]*e[34]*e[16]+e[35]*e[9]*e[6]+e[35]*e[0]*e[15]+e[35]*e[10]*e[7]+e[35]*e[1]*e[16]+e[5]*e[27]*e[12]+e[5]*e[9]*e[30]+e[5]*e[29]*e[14]+e[5]*e[11]*e[32]+e[5]*e[28]*e[13]+e[5]*e[10]*e[31]+e[8]*e[27]*e[15]+e[8]*e[9]*e[33]+e[8]*e[29]*e[17]+e[8]*e[11]*e[35];
|
||||||
|
A[91]=-1.*e[12]*e[34]*e[7]+e[12]*e[32]*e[5]-1.*e[12]*e[35]*e[8]-1.*e[12]*e[29]*e[2]-1.*e[12]*e[28]*e[1]+e[12]*e[31]*e[4]-1.*e[30]*e[11]*e[2]-1.*e[30]*e[10]*e[1]+e[30]*e[13]*e[4]-1.*e[30]*e[16]*e[7]+e[30]*e[14]*e[5]-1.*e[30]*e[17]*e[8]+e[15]*e[3]*e[33]+e[15]*e[31]*e[7]+e[15]*e[4]*e[34]+e[15]*e[32]*e[8]+e[15]*e[5]*e[35]+e[3]*e[27]*e[9]-1.*e[3]*e[28]*e[10]-1.*e[3]*e[34]*e[16]-1.*e[3]*e[35]*e[17]-1.*e[3]*e[29]*e[11]+e[33]*e[13]*e[7]+e[33]*e[4]*e[16]+e[33]*e[14]*e[8]+e[33]*e[5]*e[17]+e[9]*e[28]*e[4]+e[9]*e[1]*e[31]+e[9]*e[29]*e[5]+e[9]*e[2]*e[32]+e[27]*e[10]*e[4]+e[27]*e[1]*e[13]+e[27]*e[11]*e[5]+e[27]*e[2]*e[14]+3.*e[3]*e[30]*e[12]+e[3]*e[32]*e[14]+e[3]*e[31]*e[13]+e[6]*e[30]*e[15]+e[6]*e[12]*e[33]+e[6]*e[32]*e[17]+e[6]*e[14]*e[35]+e[6]*e[31]*e[16]+e[6]*e[13]*e[34]+e[0]*e[27]*e[12]+e[0]*e[9]*e[30]+e[0]*e[29]*e[14]+e[0]*e[11]*e[32]+e[0]*e[28]*e[13]+e[0]*e[10]*e[31];
|
||||||
|
A[90]=.5000000000*e[21]*ep2[24]-.5000000000*e[21]*ep2[25]+.5000000000*e[21]*ep2[23]-.5000000000*e[21]*ep2[26]+.5000000000*ep2[18]*e[21]+.5000000000*e[21]*ep2[22]-.5000000000*e[21]*ep2[20]+e[24]*e[22]*e[25]+e[24]*e[23]*e[26]-.5000000000*e[21]*ep2[19]+e[18]*e[19]*e[22]+e[18]*e[20]*e[23]+.5000000000*ep3[21];
|
||||||
|
A[89]=-.5000000000*e[30]*ep2[26]-.5000000000*e[30]*ep2[19]-.5000000000*e[30]*ep2[20]-.5000000000*e[30]*ep2[25]+.5000000000*ep2[18]*e[30]+1.500000000*e[30]*ep2[21]+.5000000000*e[30]*ep2[22]+.5000000000*e[30]*ep2[23]+.5000000000*e[30]*ep2[24]+e[18]*e[27]*e[21]+e[18]*e[28]*e[22]+e[18]*e[19]*e[31]+e[18]*e[29]*e[23]+e[18]*e[20]*e[32]+e[27]*e[19]*e[22]+e[27]*e[20]*e[23]+e[21]*e[31]*e[22]+e[21]*e[32]*e[23]+e[24]*e[21]*e[33]+e[24]*e[31]*e[25]+e[24]*e[22]*e[34]+e[24]*e[32]*e[26]+e[24]*e[23]*e[35]+e[33]*e[22]*e[25]+e[33]*e[23]*e[26]-1.*e[21]*e[29]*e[20]-1.*e[21]*e[35]*e[26]-1.*e[21]*e[28]*e[19]-1.*e[21]*e[34]*e[25];
|
||||||
|
A[88]=.5000000000*e[12]*ep2[15]-.5000000000*e[12]*ep2[17]+e[15]*e[13]*e[16]-.5000000000*e[12]*ep2[10]+e[15]*e[14]*e[17]-.5000000000*e[12]*ep2[16]-.5000000000*e[12]*ep2[11]+e[9]*e[10]*e[13]+.5000000000*e[12]*ep2[13]+.5000000000*ep2[9]*e[12]+.5000000000*ep3[12]+e[9]*e[11]*e[14]+.5000000000*e[12]*ep2[14];
|
||||||
|
A[95]=e[12]*e[13]*e[4]+e[12]*e[14]*e[5]+e[15]*e[12]*e[6]+e[15]*e[13]*e[7]+e[15]*e[4]*e[16]+e[15]*e[14]*e[8]+e[15]*e[5]*e[17]+e[6]*e[14]*e[17]+e[6]*e[13]*e[16]+e[0]*e[11]*e[14]+e[0]*e[9]*e[12]+e[0]*e[10]*e[13]+e[9]*e[10]*e[4]+e[9]*e[1]*e[13]+e[9]*e[11]*e[5]+e[9]*e[2]*e[14]-1.*e[12]*e[11]*e[2]-1.*e[12]*e[10]*e[1]-1.*e[12]*e[16]*e[7]-1.*e[12]*e[17]*e[8]+1.500000000*ep2[12]*e[3]+.5000000000*e[3]*ep2[15]-.5000000000*e[3]*ep2[16]+.5000000000*e[3]*ep2[9]-.5000000000*e[3]*ep2[11]-.5000000000*e[3]*ep2[17]-.5000000000*e[3]*ep2[10]+.5000000000*e[3]*ep2[14]+.5000000000*e[3]*ep2[13];
|
||||||
|
A[94]=e[18]*e[11]*e[14]+e[18]*e[9]*e[12]+e[18]*e[10]*e[13]+e[12]*e[23]*e[14]+e[12]*e[22]*e[13]+e[15]*e[12]*e[24]+e[15]*e[23]*e[17]+e[15]*e[14]*e[26]+e[15]*e[22]*e[16]+e[15]*e[13]*e[25]+e[24]*e[14]*e[17]+e[24]*e[13]*e[16]-1.*e[12]*e[25]*e[16]-1.*e[12]*e[26]*e[17]-1.*e[12]*e[20]*e[11]-1.*e[12]*e[19]*e[10]+e[9]*e[20]*e[14]+e[9]*e[11]*e[23]+e[9]*e[19]*e[13]+e[9]*e[10]*e[22]+.5000000000*ep2[9]*e[21]-.5000000000*e[21]*ep2[16]-.5000000000*e[21]*ep2[11]-.5000000000*e[21]*ep2[17]-.5000000000*e[21]*ep2[10]+1.500000000*e[21]*ep2[12]+.5000000000*e[21]*ep2[14]+.5000000000*e[21]*ep2[13]+.5000000000*e[21]*ep2[15];
|
||||||
|
A[93]=-1.*e[21]*e[35]*e[8]-1.*e[21]*e[29]*e[2]-1.*e[21]*e[28]*e[1]+e[21]*e[31]*e[4]-1.*e[30]*e[26]*e[8]-1.*e[30]*e[20]*e[2]-1.*e[30]*e[19]*e[1]+e[30]*e[22]*e[4]-1.*e[30]*e[25]*e[7]+e[30]*e[23]*e[5]+e[6]*e[31]*e[25]+e[6]*e[22]*e[34]+e[6]*e[32]*e[26]+e[6]*e[23]*e[35]+e[24]*e[30]*e[6]+e[24]*e[3]*e[33]+e[24]*e[31]*e[7]+e[24]*e[4]*e[34]+e[24]*e[32]*e[8]+e[24]*e[5]*e[35]+e[33]*e[21]*e[6]+e[33]*e[22]*e[7]+e[33]*e[4]*e[25]+e[33]*e[23]*e[8]+e[33]*e[5]*e[26]+e[0]*e[27]*e[21]+e[0]*e[18]*e[30]+e[0]*e[28]*e[22]+e[0]*e[19]*e[31]+e[0]*e[29]*e[23]+e[0]*e[20]*e[32]+e[18]*e[27]*e[3]+e[18]*e[28]*e[4]+e[18]*e[1]*e[31]+e[18]*e[29]*e[5]+e[18]*e[2]*e[32]+e[27]*e[19]*e[4]+e[27]*e[1]*e[22]+e[27]*e[20]*e[5]+e[27]*e[2]*e[23]+3.*e[3]*e[30]*e[21]+e[3]*e[31]*e[22]+e[3]*e[32]*e[23]-1.*e[3]*e[29]*e[20]-1.*e[3]*e[35]*e[26]-1.*e[3]*e[28]*e[19]-1.*e[3]*e[34]*e[25]-1.*e[21]*e[34]*e[7]+e[21]*e[32]*e[5];
|
||||||
|
A[92]=e[18]*e[1]*e[4]+e[18]*e[0]*e[3]+e[18]*e[2]*e[5]+e[3]*e[22]*e[4]+e[3]*e[23]*e[5]+e[6]*e[3]*e[24]+e[6]*e[22]*e[7]+e[6]*e[4]*e[25]+e[6]*e[23]*e[8]+e[6]*e[5]*e[26]+e[24]*e[4]*e[7]+e[24]*e[5]*e[8]+e[0]*e[19]*e[4]+e[0]*e[1]*e[22]+e[0]*e[20]*e[5]+e[0]*e[2]*e[23]-1.*e[3]*e[26]*e[8]-1.*e[3]*e[20]*e[2]-1.*e[3]*e[19]*e[1]-1.*e[3]*e[25]*e[7]+.5000000000*e[21]*ep2[4]+.5000000000*e[21]*ep2[0]+.5000000000*e[21]*ep2[6]+.5000000000*e[21]*ep2[5]-.5000000000*e[21]*ep2[1]-.5000000000*e[21]*ep2[7]+1.500000000*e[21]*ep2[3]-.5000000000*e[21]*ep2[2]-.5000000000*e[21]*ep2[8];
|
||||||
|
A[82]=.5000000000*ep2[27]*e[21]+1.500000000*e[21]*ep2[30]+.5000000000*e[21]*ep2[32]+.5000000000*e[21]*ep2[31]+.5000000000*e[21]*ep2[33]-.5000000000*e[21]*ep2[28]-.5000000000*e[21]*ep2[29]-.5000000000*e[21]*ep2[34]-.5000000000*e[21]*ep2[35]+e[18]*e[27]*e[30]+e[18]*e[29]*e[32]+e[18]*e[28]*e[31]+e[27]*e[28]*e[22]+e[27]*e[19]*e[31]+e[27]*e[29]*e[23]+e[27]*e[20]*e[32]+e[30]*e[31]*e[22]+e[30]*e[32]*e[23]+e[24]*e[30]*e[33]+e[24]*e[32]*e[35]+e[24]*e[31]*e[34]+e[33]*e[31]*e[25]+e[33]*e[22]*e[34]+e[33]*e[32]*e[26]+e[33]*e[23]*e[35]-1.*e[30]*e[29]*e[20]-1.*e[30]*e[35]*e[26]-1.*e[30]*e[28]*e[19]-1.*e[30]*e[34]*e[25];
|
||||||
|
A[192]=-.5000000000*e[26]*ep2[4]-.5000000000*e[26]*ep2[0]+.5000000000*e[26]*ep2[6]+.5000000000*e[26]*ep2[5]-.5000000000*e[26]*ep2[1]+.5000000000*e[26]*ep2[7]-.5000000000*e[26]*ep2[3]+.5000000000*e[26]*ep2[2]+1.500000000*e[26]*ep2[8]+e[20]*e[0]*e[6]+e[20]*e[2]*e[8]+e[5]*e[21]*e[6]+e[5]*e[3]*e[24]+e[5]*e[22]*e[7]+e[5]*e[4]*e[25]+e[5]*e[23]*e[8]+e[23]*e[4]*e[7]+e[23]*e[3]*e[6]+e[8]*e[24]*e[6]+e[8]*e[25]*e[7]+e[2]*e[18]*e[6]+e[2]*e[0]*e[24]+e[2]*e[19]*e[7]+e[2]*e[1]*e[25]-1.*e[8]*e[21]*e[3]-1.*e[8]*e[19]*e[1]-1.*e[8]*e[22]*e[4]-1.*e[8]*e[18]*e[0]+e[20]*e[1]*e[7];
|
||||||
|
A[83]=e[9]*e[27]*e[30]+e[9]*e[29]*e[32]+e[9]*e[28]*e[31]+e[33]*e[30]*e[15]+e[33]*e[32]*e[17]+e[33]*e[14]*e[35]+e[33]*e[31]*e[16]+e[33]*e[13]*e[34]+e[27]*e[29]*e[14]+e[27]*e[11]*e[32]+e[27]*e[28]*e[13]+e[27]*e[10]*e[31]-1.*e[30]*e[28]*e[10]+e[30]*e[31]*e[13]+e[30]*e[32]*e[14]-1.*e[30]*e[34]*e[16]-1.*e[30]*e[35]*e[17]-1.*e[30]*e[29]*e[11]+e[15]*e[32]*e[35]+e[15]*e[31]*e[34]-.5000000000*e[12]*ep2[34]-.5000000000*e[12]*ep2[35]+.5000000000*e[12]*ep2[27]+.5000000000*e[12]*ep2[32]-.5000000000*e[12]*ep2[28]-.5000000000*e[12]*ep2[29]+.5000000000*e[12]*ep2[31]+.5000000000*e[12]*ep2[33]+1.500000000*e[12]*ep2[30];
|
||||||
|
A[193]=e[23]*e[30]*e[6]+e[23]*e[3]*e[33]+e[23]*e[31]*e[7]+e[23]*e[4]*e[34]+e[32]*e[21]*e[6]+e[32]*e[3]*e[24]+e[32]*e[22]*e[7]+e[32]*e[4]*e[25]+e[26]*e[33]*e[6]+e[26]*e[34]*e[7]+3.*e[26]*e[35]*e[8]+e[35]*e[24]*e[6]+e[35]*e[25]*e[7]+e[2]*e[27]*e[24]+e[2]*e[18]*e[33]+e[2]*e[28]*e[25]+e[2]*e[19]*e[34]+e[2]*e[29]*e[26]+e[2]*e[20]*e[35]+e[20]*e[27]*e[6]+e[20]*e[0]*e[33]+e[20]*e[28]*e[7]+e[20]*e[1]*e[34]+e[20]*e[29]*e[8]+e[29]*e[18]*e[6]+e[29]*e[0]*e[24]+e[29]*e[19]*e[7]+e[29]*e[1]*e[25]+e[5]*e[30]*e[24]+e[5]*e[21]*e[33]+e[5]*e[31]*e[25]+e[5]*e[22]*e[34]+e[5]*e[32]*e[26]+e[5]*e[23]*e[35]-1.*e[8]*e[27]*e[18]+e[8]*e[33]*e[24]-1.*e[8]*e[30]*e[21]-1.*e[8]*e[31]*e[22]+e[8]*e[32]*e[23]-1.*e[8]*e[28]*e[19]+e[8]*e[34]*e[25]-1.*e[26]*e[27]*e[0]-1.*e[26]*e[30]*e[3]-1.*e[26]*e[28]*e[1]-1.*e[26]*e[31]*e[4]-1.*e[35]*e[21]*e[3]-1.*e[35]*e[19]*e[1]-1.*e[35]*e[22]*e[4]-1.*e[35]*e[18]*e[0];
|
||||||
|
A[80]=e[27]*e[29]*e[32]+e[27]*e[28]*e[31]+e[33]*e[32]*e[35]+e[33]*e[31]*e[34]+.5000000000*ep3[30]-.5000000000*e[30]*ep2[28]-.5000000000*e[30]*ep2[29]-.5000000000*e[30]*ep2[34]+.5000000000*e[30]*ep2[33]+.5000000000*ep2[27]*e[30]+.5000000000*e[30]*ep2[32]+.5000000000*e[30]*ep2[31]-.5000000000*e[30]*ep2[35];
|
||||||
|
A[194]=.5000000000*ep2[14]*e[26]+1.500000000*e[26]*ep2[17]+.5000000000*e[26]*ep2[15]+.5000000000*e[26]*ep2[16]+.5000000000*ep2[11]*e[26]-.5000000000*e[26]*ep2[9]-.5000000000*e[26]*ep2[12]-.5000000000*e[26]*ep2[10]-.5000000000*e[26]*ep2[13]+e[20]*e[11]*e[17]+e[20]*e[9]*e[15]+e[20]*e[10]*e[16]+e[14]*e[21]*e[15]+e[14]*e[12]*e[24]+e[14]*e[23]*e[17]+e[14]*e[22]*e[16]+e[14]*e[13]*e[25]+e[23]*e[12]*e[15]+e[23]*e[13]*e[16]+e[17]*e[24]*e[15]+e[17]*e[25]*e[16]-1.*e[17]*e[18]*e[9]-1.*e[17]*e[21]*e[12]-1.*e[17]*e[19]*e[10]-1.*e[17]*e[22]*e[13]+e[11]*e[18]*e[15]+e[11]*e[9]*e[24]+e[11]*e[19]*e[16]+e[11]*e[10]*e[25];
|
||||||
|
A[81]=e[0]*e[27]*e[30]+e[0]*e[29]*e[32]+e[0]*e[28]*e[31]+e[30]*e[31]*e[4]+e[30]*e[32]*e[5]+e[6]*e[30]*e[33]+e[6]*e[32]*e[35]+e[6]*e[31]*e[34]+e[27]*e[28]*e[4]+e[27]*e[1]*e[31]+e[27]*e[29]*e[5]+e[27]*e[2]*e[32]+e[33]*e[31]*e[7]+e[33]*e[4]*e[34]+e[33]*e[32]*e[8]+e[33]*e[5]*e[35]-1.*e[30]*e[34]*e[7]-1.*e[30]*e[35]*e[8]-1.*e[30]*e[29]*e[2]-1.*e[30]*e[28]*e[1]+1.500000000*e[3]*ep2[30]+.5000000000*e[3]*ep2[32]+.5000000000*e[3]*ep2[31]+.5000000000*e[3]*ep2[27]-.5000000000*e[3]*ep2[28]-.5000000000*e[3]*ep2[29]+.5000000000*e[3]*ep2[33]-.5000000000*e[3]*ep2[34]-.5000000000*e[3]*ep2[35];
|
||||||
|
A[195]=.5000000000*ep2[14]*e[8]+1.500000000*ep2[17]*e[8]+.5000000000*e[8]*ep2[15]+.5000000000*e[8]*ep2[16]-.5000000000*e[8]*ep2[9]+.5000000000*e[8]*ep2[11]-.5000000000*e[8]*ep2[12]-.5000000000*e[8]*ep2[10]-.5000000000*e[8]*ep2[13]+e[14]*e[12]*e[6]+e[14]*e[3]*e[15]+e[14]*e[13]*e[7]+e[14]*e[4]*e[16]+e[14]*e[5]*e[17]+e[17]*e[15]*e[6]+e[17]*e[16]*e[7]+e[2]*e[11]*e[17]+e[2]*e[9]*e[15]+e[2]*e[10]*e[16]+e[5]*e[12]*e[15]+e[5]*e[13]*e[16]+e[11]*e[9]*e[6]+e[11]*e[0]*e[15]+e[11]*e[10]*e[7]+e[11]*e[1]*e[16]-1.*e[17]*e[10]*e[1]-1.*e[17]*e[13]*e[4]-1.*e[17]*e[9]*e[0]-1.*e[17]*e[12]*e[3];
|
||||||
|
A[86]=-.5000000000*e[3]*ep2[1]-.5000000000*e[3]*ep2[7]+.5000000000*ep3[3]-.5000000000*e[3]*ep2[8]+e[0]*e[2]*e[5]+.5000000000*e[3]*ep2[6]+.5000000000*e[3]*ep2[4]-.5000000000*e[3]*ep2[2]+e[0]*e[1]*e[4]+e[6]*e[4]*e[7]+.5000000000*ep2[0]*e[3]+.5000000000*e[3]*ep2[5]+e[6]*e[5]*e[8];
|
||||||
|
A[196]=.5000000000*ep2[23]*e[17]+1.500000000*ep2[26]*e[17]+.5000000000*e[17]*ep2[25]+.5000000000*e[17]*ep2[24]-.5000000000*e[17]*ep2[18]-.5000000000*e[17]*ep2[19]+.5000000000*e[17]*ep2[20]-.5000000000*e[17]*ep2[22]-.5000000000*e[17]*ep2[21]+e[23]*e[21]*e[15]+e[23]*e[12]*e[24]+e[23]*e[14]*e[26]+e[23]*e[22]*e[16]+e[23]*e[13]*e[25]+e[26]*e[24]*e[15]+e[26]*e[25]*e[16]+e[11]*e[19]*e[25]+e[11]*e[18]*e[24]+e[11]*e[20]*e[26]+e[14]*e[22]*e[25]+e[14]*e[21]*e[24]+e[20]*e[18]*e[15]+e[20]*e[9]*e[24]+e[20]*e[19]*e[16]+e[20]*e[10]*e[25]-1.*e[26]*e[18]*e[9]-1.*e[26]*e[21]*e[12]-1.*e[26]*e[19]*e[10]-1.*e[26]*e[22]*e[13];
|
||||||
|
A[87]=-1.*e[12]*e[34]*e[16]-1.*e[12]*e[35]*e[17]-1.*e[12]*e[29]*e[11]+e[9]*e[27]*e[12]+e[9]*e[29]*e[14]+e[9]*e[11]*e[32]+e[9]*e[28]*e[13]+e[9]*e[10]*e[31]+e[27]*e[11]*e[14]+e[27]*e[10]*e[13]+e[12]*e[32]*e[14]+e[12]*e[31]*e[13]+e[15]*e[12]*e[33]+e[15]*e[32]*e[17]+e[15]*e[14]*e[35]+e[15]*e[31]*e[16]+e[15]*e[13]*e[34]+e[33]*e[14]*e[17]+e[33]*e[13]*e[16]-1.*e[12]*e[28]*e[10]+.5000000000*ep2[9]*e[30]-.5000000000*e[30]*ep2[16]-.5000000000*e[30]*ep2[11]+1.500000000*e[30]*ep2[12]+.5000000000*e[30]*ep2[15]-.5000000000*e[30]*ep2[17]-.5000000000*e[30]*ep2[10]+.5000000000*e[30]*ep2[14]+.5000000000*e[30]*ep2[13];
|
||||||
|
A[197]=e[32]*e[22]*e[16]+e[32]*e[13]*e[25]-1.*e[17]*e[27]*e[18]+e[17]*e[33]*e[24]-1.*e[17]*e[30]*e[21]+e[17]*e[29]*e[20]+3.*e[17]*e[35]*e[26]-1.*e[17]*e[31]*e[22]-1.*e[17]*e[28]*e[19]+e[17]*e[34]*e[25]+e[20]*e[27]*e[15]+e[20]*e[9]*e[33]+e[20]*e[28]*e[16]+e[20]*e[10]*e[34]+e[29]*e[18]*e[15]+e[29]*e[9]*e[24]+e[29]*e[19]*e[16]+e[29]*e[10]*e[25]-1.*e[26]*e[27]*e[9]-1.*e[26]*e[30]*e[12]-1.*e[26]*e[28]*e[10]-1.*e[26]*e[31]*e[13]+e[26]*e[33]*e[15]+e[26]*e[34]*e[16]+e[35]*e[24]*e[15]+e[35]*e[25]*e[16]-1.*e[35]*e[18]*e[9]-1.*e[35]*e[21]*e[12]-1.*e[35]*e[19]*e[10]-1.*e[35]*e[22]*e[13]+e[14]*e[30]*e[24]+e[14]*e[21]*e[33]+e[14]*e[31]*e[25]+e[14]*e[22]*e[34]+e[14]*e[32]*e[26]+e[14]*e[23]*e[35]+e[11]*e[27]*e[24]+e[11]*e[18]*e[33]+e[11]*e[28]*e[25]+e[11]*e[19]*e[34]+e[11]*e[29]*e[26]+e[11]*e[20]*e[35]+e[23]*e[30]*e[15]+e[23]*e[12]*e[33]+e[23]*e[32]*e[17]+e[23]*e[31]*e[16]+e[23]*e[13]*e[34]+e[32]*e[21]*e[15]+e[32]*e[12]*e[24];
|
||||||
|
A[84]=e[6]*e[23]*e[17]+e[6]*e[14]*e[26]+e[6]*e[22]*e[16]+e[6]*e[13]*e[25]+e[0]*e[20]*e[14]+e[0]*e[11]*e[23]+e[0]*e[19]*e[13]+e[0]*e[10]*e[22]-1.*e[12]*e[26]*e[8]-1.*e[12]*e[20]*e[2]-1.*e[12]*e[19]*e[1]+e[12]*e[22]*e[4]-1.*e[12]*e[25]*e[7]+e[12]*e[23]*e[5]-1.*e[21]*e[11]*e[2]-1.*e[21]*e[10]*e[1]+e[21]*e[13]*e[4]-1.*e[21]*e[16]*e[7]+e[21]*e[14]*e[5]-1.*e[21]*e[17]*e[8]+e[15]*e[3]*e[24]+e[15]*e[22]*e[7]+e[15]*e[4]*e[25]+e[15]*e[23]*e[8]+e[15]*e[5]*e[26]-1.*e[3]*e[25]*e[16]-1.*e[3]*e[26]*e[17]-1.*e[3]*e[20]*e[11]-1.*e[3]*e[19]*e[10]+e[24]*e[13]*e[7]+e[24]*e[4]*e[16]+e[24]*e[14]*e[8]+e[24]*e[5]*e[17]+e[9]*e[18]*e[3]+e[9]*e[0]*e[21]+e[9]*e[19]*e[4]+e[9]*e[1]*e[22]+e[9]*e[20]*e[5]+e[9]*e[2]*e[23]+e[18]*e[0]*e[12]+e[18]*e[10]*e[4]+e[18]*e[1]*e[13]+e[18]*e[11]*e[5]+e[18]*e[2]*e[14]+3.*e[3]*e[21]*e[12]+e[3]*e[23]*e[14]+e[3]*e[22]*e[13]+e[6]*e[21]*e[15]+e[6]*e[12]*e[24];
|
||||||
|
A[198]=.5000000000*ep2[5]*e[17]+1.500000000*e[17]*ep2[8]+.5000000000*e[17]*ep2[7]+.5000000000*e[17]*ep2[6]+.5000000000*ep2[2]*e[17]-.5000000000*e[17]*ep2[4]-.5000000000*e[17]*ep2[0]-.5000000000*e[17]*ep2[1]-.5000000000*e[17]*ep2[3]+e[11]*e[1]*e[7]+e[11]*e[0]*e[6]+e[11]*e[2]*e[8]+e[5]*e[12]*e[6]+e[5]*e[3]*e[15]+e[5]*e[13]*e[7]+e[5]*e[4]*e[16]+e[5]*e[14]*e[8]+e[14]*e[4]*e[7]+e[14]*e[3]*e[6]+e[8]*e[15]*e[6]+e[8]*e[16]*e[7]-1.*e[8]*e[10]*e[1]-1.*e[8]*e[13]*e[4]-1.*e[8]*e[9]*e[0]-1.*e[8]*e[12]*e[3]+e[2]*e[9]*e[6]+e[2]*e[0]*e[15]+e[2]*e[10]*e[7]+e[2]*e[1]*e[16];
|
||||||
|
A[85]=e[6]*e[4]*e[34]+e[6]*e[32]*e[8]+e[6]*e[5]*e[35]+e[33]*e[4]*e[7]+e[33]*e[5]*e[8]+e[0]*e[27]*e[3]+e[0]*e[28]*e[4]+e[0]*e[1]*e[31]+e[0]*e[29]*e[5]+e[0]*e[2]*e[32]-1.*e[3]*e[34]*e[7]+e[3]*e[32]*e[5]+e[3]*e[33]*e[6]-1.*e[3]*e[35]*e[8]-1.*e[3]*e[29]*e[2]-1.*e[3]*e[28]*e[1]+e[3]*e[31]*e[4]+e[27]*e[1]*e[4]+e[27]*e[2]*e[5]+e[6]*e[31]*e[7]+.5000000000*e[30]*ep2[4]+.5000000000*e[30]*ep2[6]+.5000000000*e[30]*ep2[5]-.5000000000*e[30]*ep2[1]-.5000000000*e[30]*ep2[7]-.5000000000*e[30]*ep2[2]-.5000000000*e[30]*ep2[8]+.5000000000*ep2[0]*e[30]+1.500000000*e[30]*ep2[3];
|
||||||
|
A[199]=.5000000000*ep2[23]*e[8]+1.500000000*ep2[26]*e[8]-.5000000000*e[8]*ep2[18]-.5000000000*e[8]*ep2[19]-.5000000000*e[8]*ep2[22]+.5000000000*e[8]*ep2[24]-.5000000000*e[8]*ep2[21]+.5000000000*e[8]*ep2[25]+.5000000000*ep2[20]*e[8]+e[20]*e[18]*e[6]+e[20]*e[0]*e[24]+e[20]*e[19]*e[7]+e[20]*e[1]*e[25]+e[20]*e[2]*e[26]+e[23]*e[21]*e[6]+e[23]*e[3]*e[24]+e[23]*e[22]*e[7]+e[23]*e[4]*e[25]+e[23]*e[5]*e[26]-1.*e[26]*e[21]*e[3]-1.*e[26]*e[19]*e[1]-1.*e[26]*e[22]*e[4]-1.*e[26]*e[18]*e[0]+e[26]*e[25]*e[7]+e[26]*e[24]*e[6]+e[2]*e[19]*e[25]+e[2]*e[18]*e[24]+e[5]*e[22]*e[25]+e[5]*e[21]*e[24];
|
||||||
|
A[109]=e[19]*e[27]*e[21]+e[19]*e[18]*e[30]+e[19]*e[28]*e[22]+e[19]*e[29]*e[23]+e[19]*e[20]*e[32]+e[28]*e[18]*e[21]+e[28]*e[20]*e[23]+e[22]*e[30]*e[21]+e[22]*e[32]*e[23]+e[25]*e[30]*e[24]+e[25]*e[21]*e[33]+e[25]*e[22]*e[34]+e[25]*e[32]*e[26]+e[25]*e[23]*e[35]+e[34]*e[21]*e[24]+e[34]*e[23]*e[26]-1.*e[22]*e[27]*e[18]-1.*e[22]*e[33]*e[24]-1.*e[22]*e[29]*e[20]-1.*e[22]*e[35]*e[26]+.5000000000*ep2[19]*e[31]+1.500000000*e[31]*ep2[22]+.5000000000*e[31]*ep2[21]+.5000000000*e[31]*ep2[23]+.5000000000*e[31]*ep2[25]-.5000000000*e[31]*ep2[26]-.5000000000*e[31]*ep2[18]-.5000000000*e[31]*ep2[20]-.5000000000*e[31]*ep2[24];
|
||||||
|
A[108]=-.5000000000*e[13]*ep2[15]+.5000000000*e[13]*ep2[16]+.5000000000*e[13]*ep2[12]+e[16]*e[12]*e[15]+.5000000000*ep3[13]+e[10]*e[11]*e[14]+.5000000000*e[13]*ep2[14]-.5000000000*e[13]*ep2[17]-.5000000000*e[13]*ep2[11]-.5000000000*e[13]*ep2[9]+.5000000000*ep2[10]*e[13]+e[10]*e[9]*e[12]+e[16]*e[14]*e[17];
|
||||||
|
A[111]=-1.*e[13]*e[29]*e[2]-1.*e[31]*e[11]*e[2]-1.*e[31]*e[15]*e[6]-1.*e[31]*e[9]*e[0]+e[31]*e[14]*e[5]+e[31]*e[12]*e[3]-1.*e[31]*e[17]*e[8]+e[16]*e[30]*e[6]+e[16]*e[3]*e[33]+e[16]*e[4]*e[34]+e[16]*e[32]*e[8]+e[16]*e[5]*e[35]-1.*e[4]*e[27]*e[9]+e[4]*e[28]*e[10]-1.*e[4]*e[33]*e[15]-1.*e[4]*e[35]*e[17]-1.*e[4]*e[29]*e[11]+e[34]*e[12]*e[6]+e[34]*e[3]*e[15]+e[34]*e[14]*e[8]+e[34]*e[5]*e[17]+e[10]*e[27]*e[3]+e[10]*e[0]*e[30]+e[10]*e[29]*e[5]+e[10]*e[2]*e[32]+e[28]*e[9]*e[3]+e[28]*e[0]*e[12]+e[28]*e[11]*e[5]+e[28]*e[2]*e[14]+e[4]*e[30]*e[12]+e[4]*e[32]*e[14]+3.*e[4]*e[31]*e[13]+e[7]*e[30]*e[15]+e[7]*e[12]*e[33]+e[7]*e[32]*e[17]+e[7]*e[14]*e[35]+e[7]*e[31]*e[16]+e[7]*e[13]*e[34]+e[1]*e[27]*e[12]+e[1]*e[9]*e[30]+e[1]*e[29]*e[14]+e[1]*e[11]*e[32]+e[1]*e[28]*e[13]+e[1]*e[10]*e[31]-1.*e[13]*e[27]*e[0]+e[13]*e[32]*e[5]-1.*e[13]*e[33]*e[6]+e[13]*e[30]*e[3]-1.*e[13]*e[35]*e[8];
|
||||||
|
A[110]=e[25]*e[23]*e[26]+e[19]*e[20]*e[23]+e[19]*e[18]*e[21]+e[25]*e[21]*e[24]+.5000000000*ep3[22]+.5000000000*e[22]*ep2[23]+.5000000000*ep2[19]*e[22]-.5000000000*e[22]*ep2[18]-.5000000000*e[22]*ep2[24]+.5000000000*e[22]*ep2[21]+.5000000000*e[22]*ep2[25]-.5000000000*e[22]*ep2[20]-.5000000000*e[22]*ep2[26];
|
||||||
|
A[105]=e[34]*e[5]*e[8]+e[1]*e[27]*e[3]+e[1]*e[0]*e[30]+e[1]*e[28]*e[4]+e[1]*e[29]*e[5]+e[1]*e[2]*e[32]-1.*e[4]*e[27]*e[0]+e[4]*e[34]*e[7]+e[4]*e[32]*e[5]-1.*e[4]*e[33]*e[6]+e[4]*e[30]*e[3]-1.*e[4]*e[35]*e[8]-1.*e[4]*e[29]*e[2]+e[28]*e[0]*e[3]+e[28]*e[2]*e[5]+e[7]*e[30]*e[6]+e[7]*e[3]*e[33]+e[7]*e[32]*e[8]+e[7]*e[5]*e[35]+e[34]*e[3]*e[6]+.5000000000*ep2[1]*e[31]+1.500000000*e[31]*ep2[4]-.5000000000*e[31]*ep2[0]-.5000000000*e[31]*ep2[6]+.5000000000*e[31]*ep2[5]+.5000000000*e[31]*ep2[7]+.5000000000*e[31]*ep2[3]-.5000000000*e[31]*ep2[2]-.5000000000*e[31]*ep2[8];
|
||||||
|
A[104]=e[1]*e[20]*e[14]+e[1]*e[11]*e[23]+e[13]*e[21]*e[3]-1.*e[13]*e[26]*e[8]-1.*e[13]*e[20]*e[2]-1.*e[13]*e[18]*e[0]+e[13]*e[23]*e[5]-1.*e[13]*e[24]*e[6]-1.*e[22]*e[11]*e[2]-1.*e[22]*e[15]*e[6]-1.*e[22]*e[9]*e[0]+e[22]*e[14]*e[5]+e[22]*e[12]*e[3]-1.*e[22]*e[17]*e[8]+e[16]*e[21]*e[6]+e[16]*e[3]*e[24]+e[16]*e[4]*e[25]+e[16]*e[23]*e[8]+e[16]*e[5]*e[26]-1.*e[4]*e[24]*e[15]-1.*e[4]*e[26]*e[17]-1.*e[4]*e[20]*e[11]-1.*e[4]*e[18]*e[9]+e[25]*e[12]*e[6]+e[25]*e[3]*e[15]+e[25]*e[14]*e[8]+e[25]*e[5]*e[17]+e[10]*e[18]*e[3]+e[10]*e[0]*e[21]+e[10]*e[19]*e[4]+e[10]*e[1]*e[22]+e[10]*e[20]*e[5]+e[10]*e[2]*e[23]+e[19]*e[9]*e[3]+e[19]*e[0]*e[12]+e[19]*e[1]*e[13]+e[19]*e[11]*e[5]+e[19]*e[2]*e[14]+e[4]*e[21]*e[12]+e[4]*e[23]*e[14]+3.*e[4]*e[22]*e[13]+e[7]*e[21]*e[15]+e[7]*e[12]*e[24]+e[7]*e[23]*e[17]+e[7]*e[14]*e[26]+e[7]*e[22]*e[16]+e[7]*e[13]*e[25]+e[1]*e[18]*e[12]+e[1]*e[9]*e[21];
|
||||||
|
A[107]=e[10]*e[27]*e[12]+e[10]*e[9]*e[30]+e[10]*e[29]*e[14]+e[10]*e[11]*e[32]+e[10]*e[28]*e[13]+e[28]*e[11]*e[14]+e[28]*e[9]*e[12]+e[13]*e[30]*e[12]+e[13]*e[32]*e[14]+e[16]*e[30]*e[15]+e[16]*e[12]*e[33]+e[16]*e[32]*e[17]+e[16]*e[14]*e[35]+e[16]*e[13]*e[34]+e[34]*e[14]*e[17]+e[34]*e[12]*e[15]-1.*e[13]*e[27]*e[9]-1.*e[13]*e[33]*e[15]-1.*e[13]*e[35]*e[17]-1.*e[13]*e[29]*e[11]+.5000000000*ep2[10]*e[31]+.5000000000*e[31]*ep2[16]-.5000000000*e[31]*ep2[9]-.5000000000*e[31]*ep2[11]+.5000000000*e[31]*ep2[12]-.5000000000*e[31]*ep2[15]-.5000000000*e[31]*ep2[17]+.5000000000*e[31]*ep2[14]+1.500000000*e[31]*ep2[13];
|
||||||
|
A[106]=-.5000000000*e[4]*ep2[6]-.5000000000*e[4]*ep2[0]+e[1]*e[2]*e[5]+.5000000000*e[4]*ep2[7]+e[1]*e[0]*e[3]+e[7]*e[5]*e[8]-.5000000000*e[4]*ep2[8]+.5000000000*e[4]*ep2[3]+.5000000000*e[4]*ep2[5]+e[7]*e[3]*e[6]-.5000000000*e[4]*ep2[2]+.5000000000*ep3[4]+.5000000000*ep2[1]*e[4];
|
||||||
|
A[100]=e[34]*e[32]*e[35]-.5000000000*e[31]*ep2[35]+.5000000000*e[31]*ep2[34]+.5000000000*ep2[28]*e[31]+.5000000000*ep3[31]+.5000000000*e[31]*ep2[32]+e[34]*e[30]*e[33]-.5000000000*e[31]*ep2[27]+.5000000000*e[31]*ep2[30]-.5000000000*e[31]*ep2[33]-.5000000000*e[31]*ep2[29]+e[28]*e[29]*e[32]+e[28]*e[27]*e[30];
|
||||||
|
A[101]=e[1]*e[27]*e[30]+e[1]*e[29]*e[32]+e[1]*e[28]*e[31]+e[31]*e[30]*e[3]+e[31]*e[32]*e[5]+e[7]*e[30]*e[33]+e[7]*e[32]*e[35]+e[7]*e[31]*e[34]+e[28]*e[27]*e[3]+e[28]*e[0]*e[30]+e[28]*e[29]*e[5]+e[28]*e[2]*e[32]+e[34]*e[30]*e[6]+e[34]*e[3]*e[33]+e[34]*e[32]*e[8]+e[34]*e[5]*e[35]-1.*e[31]*e[27]*e[0]-1.*e[31]*e[33]*e[6]-1.*e[31]*e[35]*e[8]-1.*e[31]*e[29]*e[2]+.5000000000*e[4]*ep2[30]+.5000000000*e[4]*ep2[32]+1.500000000*e[4]*ep2[31]-.5000000000*e[4]*ep2[27]+.5000000000*e[4]*ep2[28]-.5000000000*e[4]*ep2[29]-.5000000000*e[4]*ep2[33]+.5000000000*e[4]*ep2[34]-.5000000000*e[4]*ep2[35];
|
||||||
|
A[102]=.5000000000*e[22]*ep2[30]+.5000000000*e[22]*ep2[32]+1.500000000*e[22]*ep2[31]+.5000000000*e[22]*ep2[34]-.5000000000*e[22]*ep2[27]-.5000000000*e[22]*ep2[29]-.5000000000*e[22]*ep2[33]-.5000000000*e[22]*ep2[35]+e[28]*e[18]*e[30]+e[28]*e[29]*e[23]+e[28]*e[20]*e[32]+e[31]*e[30]*e[21]+e[31]*e[32]*e[23]+e[25]*e[30]*e[33]+e[25]*e[32]*e[35]+e[25]*e[31]*e[34]+e[34]*e[30]*e[24]+e[34]*e[21]*e[33]+e[34]*e[32]*e[26]+e[34]*e[23]*e[35]-1.*e[31]*e[27]*e[18]-1.*e[31]*e[33]*e[24]-1.*e[31]*e[29]*e[20]-1.*e[31]*e[35]*e[26]+e[19]*e[27]*e[30]+e[19]*e[29]*e[32]+e[19]*e[28]*e[31]+e[28]*e[27]*e[21]+.5000000000*ep2[28]*e[22];
|
||||||
|
A[103]=e[16]*e[30]*e[33]+e[16]*e[32]*e[35]+e[10]*e[27]*e[30]+e[10]*e[29]*e[32]+e[10]*e[28]*e[31]+e[34]*e[30]*e[15]+e[34]*e[12]*e[33]+e[34]*e[32]*e[17]+e[34]*e[14]*e[35]+e[34]*e[31]*e[16]+e[28]*e[27]*e[12]+e[28]*e[9]*e[30]+e[28]*e[29]*e[14]+e[28]*e[11]*e[32]-1.*e[31]*e[27]*e[9]+e[31]*e[30]*e[12]+e[31]*e[32]*e[14]-1.*e[31]*e[33]*e[15]-1.*e[31]*e[35]*e[17]-1.*e[31]*e[29]*e[11]-.5000000000*e[13]*ep2[27]+.5000000000*e[13]*ep2[32]+.5000000000*e[13]*ep2[28]-.5000000000*e[13]*ep2[29]+1.500000000*e[13]*ep2[31]-.5000000000*e[13]*ep2[33]+.5000000000*e[13]*ep2[30]+.5000000000*e[13]*ep2[34]-.5000000000*e[13]*ep2[35];
|
||||||
|
A[96]=e[21]*e[23]*e[14]+e[21]*e[22]*e[13]+e[24]*e[21]*e[15]+e[24]*e[23]*e[17]+e[24]*e[14]*e[26]+e[24]*e[22]*e[16]+e[24]*e[13]*e[25]+e[15]*e[22]*e[25]+e[15]*e[23]*e[26]+e[9]*e[19]*e[22]+e[9]*e[18]*e[21]+e[9]*e[20]*e[23]+e[18]*e[20]*e[14]+e[18]*e[11]*e[23]+e[18]*e[19]*e[13]+e[18]*e[10]*e[22]-1.*e[21]*e[25]*e[16]-1.*e[21]*e[26]*e[17]-1.*e[21]*e[20]*e[11]-1.*e[21]*e[19]*e[10]+1.500000000*ep2[21]*e[12]+.5000000000*e[12]*ep2[24]-.5000000000*e[12]*ep2[26]+.5000000000*e[12]*ep2[18]+.5000000000*e[12]*ep2[23]-.5000000000*e[12]*ep2[19]-.5000000000*e[12]*ep2[20]+.5000000000*e[12]*ep2[22]-.5000000000*e[12]*ep2[25];
|
||||||
|
A[97]=-1.*e[12]*e[29]*e[20]-1.*e[12]*e[35]*e[26]-1.*e[12]*e[28]*e[19]-1.*e[12]*e[34]*e[25]+e[18]*e[29]*e[14]+e[18]*e[11]*e[32]+e[18]*e[28]*e[13]+e[18]*e[10]*e[31]+e[27]*e[20]*e[14]+e[27]*e[11]*e[23]+e[27]*e[19]*e[13]+e[27]*e[10]*e[22]+e[15]*e[30]*e[24]+e[15]*e[21]*e[33]+e[15]*e[31]*e[25]+e[15]*e[22]*e[34]+e[15]*e[32]*e[26]+e[15]*e[23]*e[35]-1.*e[21]*e[28]*e[10]-1.*e[21]*e[34]*e[16]-1.*e[21]*e[35]*e[17]-1.*e[21]*e[29]*e[11]-1.*e[30]*e[25]*e[16]-1.*e[30]*e[26]*e[17]-1.*e[30]*e[20]*e[11]-1.*e[30]*e[19]*e[10]+e[24]*e[32]*e[17]+e[24]*e[14]*e[35]+e[24]*e[31]*e[16]+e[24]*e[13]*e[34]+e[33]*e[23]*e[17]+e[33]*e[14]*e[26]+e[33]*e[22]*e[16]+e[33]*e[13]*e[25]+3.*e[12]*e[30]*e[21]+e[12]*e[31]*e[22]+e[12]*e[32]*e[23]+e[9]*e[27]*e[21]+e[9]*e[18]*e[30]+e[9]*e[28]*e[22]+e[9]*e[19]*e[31]+e[9]*e[29]*e[23]+e[9]*e[20]*e[32]+e[21]*e[32]*e[14]+e[21]*e[31]*e[13]+e[30]*e[23]*e[14]+e[30]*e[22]*e[13]+e[12]*e[27]*e[18]+e[12]*e[33]*e[24];
|
||||||
|
A[98]=e[0]*e[11]*e[5]+e[0]*e[2]*e[14]+e[9]*e[1]*e[4]+e[9]*e[0]*e[3]+e[9]*e[2]*e[5]+e[3]*e[13]*e[4]+e[3]*e[14]*e[5]+e[6]*e[3]*e[15]+e[6]*e[13]*e[7]+e[6]*e[4]*e[16]+e[6]*e[14]*e[8]+e[6]*e[5]*e[17]+e[15]*e[4]*e[7]+e[15]*e[5]*e[8]-1.*e[3]*e[11]*e[2]-1.*e[3]*e[10]*e[1]-1.*e[3]*e[16]*e[7]-1.*e[3]*e[17]*e[8]+e[0]*e[10]*e[4]+e[0]*e[1]*e[13]+1.500000000*e[12]*ep2[3]+.5000000000*e[12]*ep2[4]+.5000000000*e[12]*ep2[5]+.5000000000*e[12]*ep2[6]+.5000000000*ep2[0]*e[12]-.5000000000*e[12]*ep2[1]-.5000000000*e[12]*ep2[7]-.5000000000*e[12]*ep2[2]-.5000000000*e[12]*ep2[8];
|
||||||
|
A[99]=e[21]*e[24]*e[6]+e[0]*e[19]*e[22]+e[0]*e[20]*e[23]+e[24]*e[22]*e[7]+e[24]*e[4]*e[25]+e[24]*e[23]*e[8]+e[24]*e[5]*e[26]+e[6]*e[22]*e[25]+e[6]*e[23]*e[26]+e[18]*e[0]*e[21]+e[18]*e[19]*e[4]+e[18]*e[1]*e[22]+e[18]*e[20]*e[5]+e[18]*e[2]*e[23]+e[21]*e[22]*e[4]+e[21]*e[23]*e[5]-1.*e[21]*e[26]*e[8]-1.*e[21]*e[20]*e[2]-1.*e[21]*e[19]*e[1]-1.*e[21]*e[25]*e[7]+1.500000000*ep2[21]*e[3]+.5000000000*e[3]*ep2[22]+.5000000000*e[3]*ep2[23]+.5000000000*e[3]*ep2[24]-.5000000000*e[3]*ep2[26]-.5000000000*e[3]*ep2[19]-.5000000000*e[3]*ep2[20]-.5000000000*e[3]*ep2[25]+.5000000000*ep2[18]*e[3];
|
||||||
|
A[127]=e[11]*e[27]*e[12]+e[11]*e[9]*e[30]+e[11]*e[29]*e[14]+e[11]*e[28]*e[13]+e[11]*e[10]*e[31]+e[29]*e[9]*e[12]+e[29]*e[10]*e[13]+e[14]*e[30]*e[12]+e[14]*e[31]*e[13]+e[17]*e[30]*e[15]+e[17]*e[12]*e[33]+e[17]*e[14]*e[35]+e[17]*e[31]*e[16]+e[17]*e[13]*e[34]+e[35]*e[12]*e[15]+e[35]*e[13]*e[16]-1.*e[14]*e[27]*e[9]-1.*e[14]*e[28]*e[10]-1.*e[14]*e[33]*e[15]-1.*e[14]*e[34]*e[16]+.5000000000*ep2[11]*e[32]-.5000000000*e[32]*ep2[16]-.5000000000*e[32]*ep2[9]+.5000000000*e[32]*ep2[12]-.5000000000*e[32]*ep2[15]+.5000000000*e[32]*ep2[17]-.5000000000*e[32]*ep2[10]+1.500000000*e[32]*ep2[14]+.5000000000*e[32]*ep2[13];
|
||||||
|
A[126]=e[8]*e[3]*e[6]+.5000000000*ep2[2]*e[5]-.5000000000*e[5]*ep2[0]+.5000000000*e[5]*ep2[4]-.5000000000*e[5]*ep2[6]+.5000000000*e[5]*ep2[8]+e[8]*e[4]*e[7]+.5000000000*ep3[5]+e[2]*e[0]*e[3]+.5000000000*e[5]*ep2[3]-.5000000000*e[5]*ep2[7]+e[2]*e[1]*e[4]-.5000000000*e[5]*ep2[1];
|
||||||
|
A[125]=e[2]*e[27]*e[3]+e[2]*e[0]*e[30]+e[2]*e[28]*e[4]+e[2]*e[1]*e[31]+e[2]*e[29]*e[5]-1.*e[5]*e[27]*e[0]-1.*e[5]*e[34]*e[7]-1.*e[5]*e[33]*e[6]+e[5]*e[30]*e[3]+e[5]*e[35]*e[8]-1.*e[5]*e[28]*e[1]+e[5]*e[31]*e[4]+e[29]*e[1]*e[4]+e[29]*e[0]*e[3]+e[8]*e[30]*e[6]+e[8]*e[3]*e[33]+e[8]*e[31]*e[7]+e[8]*e[4]*e[34]+e[35]*e[4]*e[7]+e[35]*e[3]*e[6]+.5000000000*ep2[2]*e[32]+1.500000000*e[32]*ep2[5]+.5000000000*e[32]*ep2[4]-.5000000000*e[32]*ep2[0]-.5000000000*e[32]*ep2[6]-.5000000000*e[32]*ep2[1]-.5000000000*e[32]*ep2[7]+.5000000000*e[32]*ep2[3]+.5000000000*e[32]*ep2[8];
|
||||||
|
A[124]=-1.*e[14]*e[19]*e[1]+e[14]*e[22]*e[4]-1.*e[14]*e[18]*e[0]-1.*e[14]*e[25]*e[7]-1.*e[14]*e[24]*e[6]-1.*e[23]*e[10]*e[1]+e[23]*e[13]*e[4]-1.*e[23]*e[16]*e[7]-1.*e[23]*e[15]*e[6]-1.*e[23]*e[9]*e[0]+e[23]*e[12]*e[3]+e[17]*e[21]*e[6]+e[17]*e[3]*e[24]+e[17]*e[22]*e[7]+e[17]*e[4]*e[25]+e[17]*e[5]*e[26]-1.*e[5]*e[24]*e[15]-1.*e[5]*e[25]*e[16]-1.*e[5]*e[18]*e[9]-1.*e[5]*e[19]*e[10]+e[26]*e[12]*e[6]+e[26]*e[3]*e[15]+e[26]*e[13]*e[7]+e[26]*e[4]*e[16]+e[11]*e[18]*e[3]+e[11]*e[0]*e[21]+e[11]*e[19]*e[4]+e[11]*e[1]*e[22]+e[11]*e[20]*e[5]+e[11]*e[2]*e[23]+e[20]*e[9]*e[3]+e[20]*e[0]*e[12]+e[20]*e[10]*e[4]+e[20]*e[1]*e[13]+e[20]*e[2]*e[14]+e[5]*e[21]*e[12]+3.*e[5]*e[23]*e[14]+e[5]*e[22]*e[13]+e[8]*e[21]*e[15]+e[8]*e[12]*e[24]+e[8]*e[23]*e[17]+e[8]*e[14]*e[26]+e[8]*e[22]*e[16]+e[8]*e[13]*e[25]+e[2]*e[18]*e[12]+e[2]*e[9]*e[21]+e[2]*e[19]*e[13]+e[2]*e[10]*e[22]+e[14]*e[21]*e[3];
|
||||||
|
A[123]=-.5000000000*e[14]*ep2[27]+1.500000000*e[14]*ep2[32]-.5000000000*e[14]*ep2[28]+.5000000000*e[14]*ep2[29]+.5000000000*e[14]*ep2[31]-.5000000000*e[14]*ep2[33]+.5000000000*e[14]*ep2[30]-.5000000000*e[14]*ep2[34]+.5000000000*e[14]*ep2[35]+e[11]*e[27]*e[30]+e[11]*e[29]*e[32]+e[11]*e[28]*e[31]+e[35]*e[30]*e[15]+e[35]*e[12]*e[33]+e[35]*e[32]*e[17]+e[35]*e[31]*e[16]+e[35]*e[13]*e[34]+e[29]*e[27]*e[12]+e[29]*e[9]*e[30]+e[29]*e[28]*e[13]+e[29]*e[10]*e[31]-1.*e[32]*e[27]*e[9]+e[32]*e[30]*e[12]-1.*e[32]*e[28]*e[10]+e[32]*e[31]*e[13]-1.*e[32]*e[33]*e[15]-1.*e[32]*e[34]*e[16]+e[17]*e[30]*e[33]+e[17]*e[31]*e[34];
|
||||||
|
A[122]=-.5000000000*e[23]*ep2[33]-.5000000000*e[23]*ep2[34]+.5000000000*ep2[29]*e[23]+.5000000000*e[23]*ep2[30]+1.500000000*e[23]*ep2[32]+.5000000000*e[23]*ep2[31]+.5000000000*e[23]*ep2[35]-.5000000000*e[23]*ep2[27]-.5000000000*e[23]*ep2[28]+e[32]*e[30]*e[21]+e[32]*e[31]*e[22]+e[26]*e[30]*e[33]+e[26]*e[32]*e[35]+e[26]*e[31]*e[34]+e[35]*e[30]*e[24]+e[35]*e[21]*e[33]+e[35]*e[31]*e[25]+e[35]*e[22]*e[34]-1.*e[32]*e[27]*e[18]-1.*e[32]*e[33]*e[24]-1.*e[32]*e[28]*e[19]-1.*e[32]*e[34]*e[25]+e[20]*e[27]*e[30]+e[20]*e[29]*e[32]+e[20]*e[28]*e[31]+e[29]*e[27]*e[21]+e[29]*e[18]*e[30]+e[29]*e[28]*e[22]+e[29]*e[19]*e[31];
|
||||||
|
A[121]=e[2]*e[27]*e[30]+e[2]*e[29]*e[32]+e[2]*e[28]*e[31]+e[32]*e[30]*e[3]+e[32]*e[31]*e[4]+e[8]*e[30]*e[33]+e[8]*e[32]*e[35]+e[8]*e[31]*e[34]+e[29]*e[27]*e[3]+e[29]*e[0]*e[30]+e[29]*e[28]*e[4]+e[29]*e[1]*e[31]+e[35]*e[30]*e[6]+e[35]*e[3]*e[33]+e[35]*e[31]*e[7]+e[35]*e[4]*e[34]-1.*e[32]*e[27]*e[0]-1.*e[32]*e[34]*e[7]-1.*e[32]*e[33]*e[6]-1.*e[32]*e[28]*e[1]+.5000000000*e[5]*ep2[30]+1.500000000*e[5]*ep2[32]+.5000000000*e[5]*ep2[31]-.5000000000*e[5]*ep2[27]-.5000000000*e[5]*ep2[28]+.5000000000*e[5]*ep2[29]-.5000000000*e[5]*ep2[33]-.5000000000*e[5]*ep2[34]+.5000000000*e[5]*ep2[35];
|
||||||
|
A[120]=.5000000000*e[32]*ep2[31]+.5000000000*e[32]*ep2[35]-.5000000000*e[32]*ep2[27]+e[29]*e[27]*e[30]+e[29]*e[28]*e[31]+e[35]*e[30]*e[33]+e[35]*e[31]*e[34]+.5000000000*ep2[29]*e[32]+.5000000000*ep3[32]-.5000000000*e[32]*ep2[33]-.5000000000*e[32]*ep2[34]+.5000000000*e[32]*ep2[30]-.5000000000*e[32]*ep2[28];
|
||||||
|
A[118]=e[10]*e[1]*e[4]+e[10]*e[0]*e[3]+e[10]*e[2]*e[5]+e[4]*e[12]*e[3]+e[4]*e[14]*e[5]+e[7]*e[12]*e[6]+e[7]*e[3]*e[15]+e[7]*e[4]*e[16]+e[7]*e[14]*e[8]+e[7]*e[5]*e[17]+e[16]*e[3]*e[6]+e[16]*e[5]*e[8]-1.*e[4]*e[11]*e[2]-1.*e[4]*e[15]*e[6]-1.*e[4]*e[9]*e[0]-1.*e[4]*e[17]*e[8]+e[1]*e[9]*e[3]+e[1]*e[0]*e[12]+e[1]*e[11]*e[5]+e[1]*e[2]*e[14]+1.500000000*e[13]*ep2[4]+.5000000000*e[13]*ep2[3]+.5000000000*e[13]*ep2[5]+.5000000000*e[13]*ep2[7]+.5000000000*ep2[1]*e[13]-.5000000000*e[13]*ep2[0]-.5000000000*e[13]*ep2[6]-.5000000000*e[13]*ep2[2]-.5000000000*e[13]*ep2[8];
|
||||||
|
A[119]=e[25]*e[21]*e[6]+e[25]*e[3]*e[24]+e[25]*e[23]*e[8]+e[25]*e[5]*e[26]+e[7]*e[21]*e[24]+e[7]*e[23]*e[26]+e[19]*e[18]*e[3]+e[19]*e[0]*e[21]+e[19]*e[1]*e[22]+e[19]*e[20]*e[5]+e[19]*e[2]*e[23]+e[22]*e[21]*e[3]+e[22]*e[23]*e[5]-1.*e[22]*e[26]*e[8]-1.*e[22]*e[20]*e[2]-1.*e[22]*e[18]*e[0]+e[22]*e[25]*e[7]-1.*e[22]*e[24]*e[6]+e[1]*e[18]*e[21]+e[1]*e[20]*e[23]+.5000000000*e[4]*ep2[25]-.5000000000*e[4]*ep2[26]-.5000000000*e[4]*ep2[18]-.5000000000*e[4]*ep2[20]-.5000000000*e[4]*ep2[24]+.5000000000*ep2[19]*e[4]+1.500000000*ep2[22]*e[4]+.5000000000*e[4]*ep2[21]+.5000000000*e[4]*ep2[23];
|
||||||
|
A[116]=e[22]*e[21]*e[12]+e[22]*e[23]*e[14]+e[25]*e[21]*e[15]+e[25]*e[12]*e[24]+e[25]*e[23]*e[17]+e[25]*e[14]*e[26]+e[25]*e[22]*e[16]+e[16]*e[21]*e[24]+e[16]*e[23]*e[26]+e[10]*e[19]*e[22]+e[10]*e[18]*e[21]+e[10]*e[20]*e[23]+e[19]*e[18]*e[12]+e[19]*e[9]*e[21]+e[19]*e[20]*e[14]+e[19]*e[11]*e[23]-1.*e[22]*e[24]*e[15]-1.*e[22]*e[26]*e[17]-1.*e[22]*e[20]*e[11]-1.*e[22]*e[18]*e[9]-.5000000000*e[13]*ep2[26]-.5000000000*e[13]*ep2[18]+.5000000000*e[13]*ep2[23]+.5000000000*e[13]*ep2[19]-.5000000000*e[13]*ep2[20]-.5000000000*e[13]*ep2[24]+.5000000000*e[13]*ep2[21]+1.500000000*ep2[22]*e[13]+.5000000000*e[13]*ep2[25];
|
||||||
|
A[117]=e[13]*e[30]*e[21]+3.*e[13]*e[31]*e[22]+e[13]*e[32]*e[23]+e[10]*e[27]*e[21]+e[10]*e[18]*e[30]+e[10]*e[28]*e[22]+e[10]*e[19]*e[31]+e[10]*e[29]*e[23]+e[10]*e[20]*e[32]+e[22]*e[30]*e[12]+e[22]*e[32]*e[14]+e[31]*e[21]*e[12]+e[31]*e[23]*e[14]-1.*e[13]*e[27]*e[18]-1.*e[13]*e[33]*e[24]-1.*e[13]*e[29]*e[20]-1.*e[13]*e[35]*e[26]+e[13]*e[28]*e[19]+e[13]*e[34]*e[25]+e[19]*e[27]*e[12]+e[19]*e[9]*e[30]+e[19]*e[29]*e[14]+e[19]*e[11]*e[32]+e[28]*e[18]*e[12]+e[28]*e[9]*e[21]+e[28]*e[20]*e[14]+e[28]*e[11]*e[23]+e[16]*e[30]*e[24]+e[16]*e[21]*e[33]+e[16]*e[31]*e[25]+e[16]*e[22]*e[34]+e[16]*e[32]*e[26]+e[16]*e[23]*e[35]-1.*e[22]*e[27]*e[9]-1.*e[22]*e[33]*e[15]-1.*e[22]*e[35]*e[17]-1.*e[22]*e[29]*e[11]-1.*e[31]*e[24]*e[15]-1.*e[31]*e[26]*e[17]-1.*e[31]*e[20]*e[11]-1.*e[31]*e[18]*e[9]+e[25]*e[30]*e[15]+e[25]*e[12]*e[33]+e[25]*e[32]*e[17]+e[25]*e[14]*e[35]+e[34]*e[21]*e[15]+e[34]*e[12]*e[24]+e[34]*e[23]*e[17]+e[34]*e[14]*e[26];
|
||||||
|
A[114]=e[19]*e[11]*e[14]+e[19]*e[9]*e[12]+e[19]*e[10]*e[13]+e[13]*e[21]*e[12]+e[13]*e[23]*e[14]+e[16]*e[21]*e[15]+e[16]*e[12]*e[24]+e[16]*e[23]*e[17]+e[16]*e[14]*e[26]+e[16]*e[13]*e[25]+e[25]*e[14]*e[17]+e[25]*e[12]*e[15]-1.*e[13]*e[24]*e[15]-1.*e[13]*e[26]*e[17]-1.*e[13]*e[20]*e[11]-1.*e[13]*e[18]*e[9]+e[10]*e[18]*e[12]+e[10]*e[9]*e[21]+e[10]*e[20]*e[14]+e[10]*e[11]*e[23]+1.500000000*e[22]*ep2[13]+.5000000000*e[22]*ep2[14]+.5000000000*e[22]*ep2[12]+.5000000000*e[22]*ep2[16]+.5000000000*ep2[10]*e[22]-.5000000000*e[22]*ep2[9]-.5000000000*e[22]*ep2[11]-.5000000000*e[22]*ep2[15]-.5000000000*e[22]*ep2[17];
|
||||||
|
A[115]=e[13]*e[12]*e[3]+e[13]*e[14]*e[5]+e[16]*e[12]*e[6]+e[16]*e[3]*e[15]+e[16]*e[13]*e[7]+e[16]*e[14]*e[8]+e[16]*e[5]*e[17]+e[7]*e[14]*e[17]+e[7]*e[12]*e[15]+e[1]*e[11]*e[14]+e[1]*e[9]*e[12]+e[1]*e[10]*e[13]+e[10]*e[9]*e[3]+e[10]*e[0]*e[12]+e[10]*e[11]*e[5]+e[10]*e[2]*e[14]-1.*e[13]*e[11]*e[2]-1.*e[13]*e[15]*e[6]-1.*e[13]*e[9]*e[0]-1.*e[13]*e[17]*e[8]+1.500000000*ep2[13]*e[4]+.5000000000*e[4]*ep2[16]-.5000000000*e[4]*ep2[9]-.5000000000*e[4]*ep2[11]+.5000000000*e[4]*ep2[12]-.5000000000*e[4]*ep2[15]-.5000000000*e[4]*ep2[17]+.5000000000*e[4]*ep2[10]+.5000000000*e[4]*ep2[14];
|
||||||
|
A[112]=e[19]*e[1]*e[4]+e[19]*e[0]*e[3]+e[19]*e[2]*e[5]+e[4]*e[21]*e[3]+e[4]*e[23]*e[5]+e[7]*e[21]*e[6]+e[7]*e[3]*e[24]+e[7]*e[4]*e[25]+e[7]*e[23]*e[8]+e[7]*e[5]*e[26]+e[25]*e[3]*e[6]+e[25]*e[5]*e[8]+e[1]*e[18]*e[3]+e[1]*e[0]*e[21]+e[1]*e[20]*e[5]+e[1]*e[2]*e[23]-1.*e[4]*e[26]*e[8]-1.*e[4]*e[20]*e[2]-1.*e[4]*e[18]*e[0]-1.*e[4]*e[24]*e[6]+1.500000000*e[22]*ep2[4]-.5000000000*e[22]*ep2[0]-.5000000000*e[22]*ep2[6]+.5000000000*e[22]*ep2[5]+.5000000000*e[22]*ep2[1]+.5000000000*e[22]*ep2[7]+.5000000000*e[22]*ep2[3]-.5000000000*e[22]*ep2[2]-.5000000000*e[22]*ep2[8];
|
||||||
|
A[113]=-1.*e[31]*e[20]*e[2]-1.*e[31]*e[18]*e[0]+e[31]*e[23]*e[5]-1.*e[31]*e[24]*e[6]+e[7]*e[30]*e[24]+e[7]*e[21]*e[33]+e[7]*e[32]*e[26]+e[7]*e[23]*e[35]+e[25]*e[30]*e[6]+e[25]*e[3]*e[33]+e[25]*e[31]*e[7]+e[25]*e[4]*e[34]+e[25]*e[32]*e[8]+e[25]*e[5]*e[35]+e[34]*e[21]*e[6]+e[34]*e[3]*e[24]+e[34]*e[22]*e[7]+e[34]*e[23]*e[8]+e[34]*e[5]*e[26]+e[1]*e[27]*e[21]+e[1]*e[18]*e[30]+e[1]*e[28]*e[22]+e[1]*e[19]*e[31]+e[1]*e[29]*e[23]+e[1]*e[20]*e[32]+e[19]*e[27]*e[3]+e[19]*e[0]*e[30]+e[19]*e[28]*e[4]+e[19]*e[29]*e[5]+e[19]*e[2]*e[32]+e[28]*e[18]*e[3]+e[28]*e[0]*e[21]+e[28]*e[20]*e[5]+e[28]*e[2]*e[23]+e[4]*e[30]*e[21]+3.*e[4]*e[31]*e[22]+e[4]*e[32]*e[23]-1.*e[4]*e[27]*e[18]-1.*e[4]*e[33]*e[24]-1.*e[4]*e[29]*e[20]-1.*e[4]*e[35]*e[26]-1.*e[22]*e[27]*e[0]+e[22]*e[32]*e[5]-1.*e[22]*e[33]*e[6]+e[22]*e[30]*e[3]-1.*e[22]*e[35]*e[8]-1.*e[22]*e[29]*e[2]+e[31]*e[21]*e[3]-1.*e[31]*e[26]*e[8];
|
||||||
|
|
||||||
|
int perm[20] = {6, 8, 18, 15, 12, 5, 14, 7, 4, 11, 19, 13, 1, 16, 17, 3, 10, 9, 2, 0};
|
||||||
|
double AA[200];
|
||||||
|
for (int i = 0; i < 20; i++)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < 10; j++) AA[i + j * 20] = A[perm[i] + j * 20];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 200; i++)
|
||||||
|
{
|
||||||
|
A[i] = AA[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void computeError( InputArray _m1, InputArray _m2, InputArray _model, OutputArray _err ) const
|
||||||
|
{
|
||||||
|
Mat X1 = _m1.getMat(), X2 = _m2.getMat(), model = _model.getMat();
|
||||||
|
const Point2d* x1ptr = X1.ptr<Point2d>();
|
||||||
|
const Point2d* x2ptr = X2.ptr<Point2d>();
|
||||||
|
int n = X1.checkVector(2);
|
||||||
|
Matx33d E(model.ptr<double>());
|
||||||
|
|
||||||
|
_err.create(n, 1, CV_32F);
|
||||||
|
Mat err = _err.getMat();
|
||||||
|
|
||||||
|
for (int i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
Vec3d x1(x1ptr[i].x, x1ptr[i].y, 1.);
|
||||||
|
Vec3d x2(x2ptr[i].x, x2ptr[i].y, 1.);
|
||||||
|
Vec3d Ex1 = E * x1;
|
||||||
|
Vec3d Etx2 = E.t() * x2;
|
||||||
|
double x2tEx1 = x2.dot(Ex1);
|
||||||
|
|
||||||
|
double a = Ex1[0] * Ex1[0];
|
||||||
|
double b = Ex1[1] * Ex1[1];
|
||||||
|
double c = Etx2[0] * Etx2[0];
|
||||||
|
double d = Etx2[1] * Etx2[1];
|
||||||
|
|
||||||
|
err.at<float>(i) = (float)(x2tEx1 * x2tEx1 / (a + b + c + d));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Input should be a vector of n 2D points or a Nx2 matrix
|
||||||
|
cv::Mat findEssentialMat( InputArray _points1, InputArray _points2, InputArray _cameraMatrix,
|
||||||
|
int method, double prob, double threshold, OutputArray _mask)
|
||||||
|
{
|
||||||
|
Mat points1, points2, cameraMatrix;
|
||||||
|
_points1.getMat().convertTo(points1, CV_64F);
|
||||||
|
_points2.getMat().convertTo(points2, CV_64F);
|
||||||
|
_cameraMatrix.getMat().convertTo(cameraMatrix, CV_64F);
|
||||||
|
|
||||||
|
int npoints = points1.checkVector(2);
|
||||||
|
CV_Assert( npoints >= 0 && points2.checkVector(2) == npoints &&
|
||||||
|
points1.type() == points2.type());
|
||||||
|
|
||||||
|
CV_Assert(cameraMatrix.rows == 3 && cameraMatrix.cols == 3 && cameraMatrix.channels() == 1);
|
||||||
|
|
||||||
|
if (points1.channels() > 1)
|
||||||
|
{
|
||||||
|
points1 = points1.reshape(1, npoints);
|
||||||
|
points2 = points2.reshape(1, npoints);
|
||||||
|
}
|
||||||
|
|
||||||
|
double fx = cameraMatrix.at<double>(0,0);
|
||||||
|
double fy = cameraMatrix.at<double>(1,1);
|
||||||
|
double cx = cameraMatrix.at<double>(0,2);
|
||||||
|
double cy = cameraMatrix.at<double>(1,2);
|
||||||
|
|
||||||
|
points1.col(0) = (points1.col(0) - cx) / fx;
|
||||||
|
points2.col(0) = (points2.col(0) - cx) / fx;
|
||||||
|
points1.col(1) = (points1.col(1) - cy) / fy;
|
||||||
|
points2.col(1) = (points2.col(1) - cy) / fy;
|
||||||
|
|
||||||
|
// Reshape data to fit opencv ransac function
|
||||||
|
points1 = points1.reshape(2, npoints);
|
||||||
|
points2 = points2.reshape(2, npoints);
|
||||||
|
|
||||||
|
threshold /= (fx+fy)/2;
|
||||||
|
|
||||||
|
Mat E;
|
||||||
|
Ptr<PointSetRegistrator::Callback> cb; // pointer to callback
|
||||||
|
cb = Ptr<EMEstimatorCallback>(new EMEstimatorCallback());
|
||||||
|
|
||||||
|
if( method == RANSAC )
|
||||||
|
createRANSACPointSetRegistrator(cb, 6, threshold, prob)->run(points1, points2, E, _mask);
|
||||||
|
else
|
||||||
|
createLMeDSPointSetRegistrator(cb, 6, prob)->run(points1, points2, E, _mask);
|
||||||
|
|
||||||
|
return E;
|
||||||
|
}
|
||||||
|
|
||||||
|
void decomposeEssentialMat( InputArray _E, OutputArray _R1, OutputArray _R2, OutputArray _t )
|
||||||
|
{
|
||||||
|
Mat E = _E.getMat().reshape(1, 3);
|
||||||
|
CV_Assert(E.cols == 3 && E.rows == 3);
|
||||||
|
|
||||||
|
Mat D, U, Vt;
|
||||||
|
SVD::compute(E, D, U, Vt);
|
||||||
|
|
||||||
|
if (determinant(U) < 0) U *= -1.;
|
||||||
|
if (determinant(Vt) < 0) Vt *= -1.;
|
||||||
|
|
||||||
|
Mat W = (Mat_<double>(3, 3) << 0, 1, 0, -1, 0, 0, 0, 0, 1);
|
||||||
|
W.convertTo(W, E.type());
|
||||||
|
|
||||||
|
Mat R1, R2, t;
|
||||||
|
R1 = U * W * Vt;
|
||||||
|
R2 = U * W.t() * Vt;
|
||||||
|
t = U.col(2) * 1.0;
|
||||||
|
|
||||||
|
R1.copyTo(_R1);
|
||||||
|
R2.copyTo(_R2);
|
||||||
|
t.copyTo(_t);
|
||||||
|
}
|
||||||
|
|
||||||
|
int recoverPose( InputArray E, InputArray _points1, InputArray _points2,
|
||||||
|
InputArray _cameraMatrix, OutputArray _R, OutputArray _t, double distanceThresh,
|
||||||
|
InputOutputArray _mask, OutputArray triangulatedPoints)
|
||||||
|
{
|
||||||
|
Mat points1, points2, cameraMatrix;
|
||||||
|
_points1.getMat().convertTo(points1, CV_64F);
|
||||||
|
_points2.getMat().convertTo(points2, CV_64F);
|
||||||
|
_cameraMatrix.getMat().convertTo(cameraMatrix, CV_64F);
|
||||||
|
|
||||||
|
int npoints = points1.checkVector(2);
|
||||||
|
CV_Assert( npoints >= 0 && points2.checkVector(2) == npoints &&
|
||||||
|
points1.type() == points2.type());
|
||||||
|
|
||||||
|
CV_Assert(cameraMatrix.rows == 3 && cameraMatrix.cols == 3 && cameraMatrix.channels() == 1);
|
||||||
|
|
||||||
|
if (points1.channels() > 1)
|
||||||
|
{
|
||||||
|
points1 = points1.reshape(1, npoints);
|
||||||
|
points2 = points2.reshape(1, npoints);
|
||||||
|
}
|
||||||
|
|
||||||
|
double fx = cameraMatrix.at<double>(0,0);
|
||||||
|
double fy = cameraMatrix.at<double>(1,1);
|
||||||
|
double cx = cameraMatrix.at<double>(0,2);
|
||||||
|
double cy = cameraMatrix.at<double>(1,2);
|
||||||
|
|
||||||
|
points1.col(0) = (points1.col(0) - cx) / fx;
|
||||||
|
points2.col(0) = (points2.col(0) - cx) / fx;
|
||||||
|
points1.col(1) = (points1.col(1) - cy) / fy;
|
||||||
|
points2.col(1) = (points2.col(1) - cy) / fy;
|
||||||
|
|
||||||
|
points1 = points1.t();
|
||||||
|
points2 = points2.t();
|
||||||
|
|
||||||
|
Mat R1, R2, t;
|
||||||
|
cv3::decomposeEssentialMat(E, R1, R2, t);
|
||||||
|
Mat P0 = Mat::eye(3, 4, R1.type());
|
||||||
|
Mat P1(3, 4, R1.type()), P2(3, 4, R1.type()), P3(3, 4, R1.type()), P4(3, 4, R1.type());
|
||||||
|
P1(Range::all(), Range(0, 3)) = R1 * 1.0; P1.col(3) = t * 1.0;
|
||||||
|
P2(Range::all(), Range(0, 3)) = R2 * 1.0; P2.col(3) = t * 1.0;
|
||||||
|
P3(Range::all(), Range(0, 3)) = R1 * 1.0; P3.col(3) = -t * 1.0;
|
||||||
|
P4(Range::all(), Range(0, 3)) = R2 * 1.0; P4.col(3) = -t * 1.0;
|
||||||
|
|
||||||
|
// Do the cheirality check.
|
||||||
|
// Notice here a threshold dist is used to filter
|
||||||
|
// out far away points (i.e. infinite points) since
|
||||||
|
// their depth may vary between positive and negative.
|
||||||
|
std::vector<Mat> allTriangulations(4);
|
||||||
|
Mat Q;
|
||||||
|
|
||||||
|
triangulatePoints(P0, P1, points1, points2, Q);
|
||||||
|
if(triangulatedPoints.needed())
|
||||||
|
Q.copyTo(allTriangulations[0]);
|
||||||
|
Mat mask1 = Q.row(2).mul(Q.row(3)) > 0;
|
||||||
|
Q.row(0) /= Q.row(3);
|
||||||
|
Q.row(1) /= Q.row(3);
|
||||||
|
Q.row(2) /= Q.row(3);
|
||||||
|
Q.row(3) /= Q.row(3);
|
||||||
|
mask1 = (Q.row(2) < distanceThresh) & mask1;
|
||||||
|
Q = P1 * Q;
|
||||||
|
mask1 = (Q.row(2) > 0) & mask1;
|
||||||
|
mask1 = (Q.row(2) < distanceThresh) & mask1;
|
||||||
|
|
||||||
|
triangulatePoints(P0, P2, points1, points2, Q);
|
||||||
|
if(triangulatedPoints.needed())
|
||||||
|
Q.copyTo(allTriangulations[1]);
|
||||||
|
Mat mask2 = Q.row(2).mul(Q.row(3)) > 0;
|
||||||
|
Q.row(0) /= Q.row(3);
|
||||||
|
Q.row(1) /= Q.row(3);
|
||||||
|
Q.row(2) /= Q.row(3);
|
||||||
|
Q.row(3) /= Q.row(3);
|
||||||
|
mask2 = (Q.row(2) < distanceThresh) & mask2;
|
||||||
|
Q = P2 * Q;
|
||||||
|
mask2 = (Q.row(2) > 0) & mask2;
|
||||||
|
mask2 = (Q.row(2) < distanceThresh) & mask2;
|
||||||
|
|
||||||
|
triangulatePoints(P0, P3, points1, points2, Q);
|
||||||
|
if(triangulatedPoints.needed())
|
||||||
|
Q.copyTo(allTriangulations[2]);
|
||||||
|
Mat mask3 = Q.row(2).mul(Q.row(3)) > 0;
|
||||||
|
Q.row(0) /= Q.row(3);
|
||||||
|
Q.row(1) /= Q.row(3);
|
||||||
|
Q.row(2) /= Q.row(3);
|
||||||
|
Q.row(3) /= Q.row(3);
|
||||||
|
mask3 = (Q.row(2) < distanceThresh) & mask3;
|
||||||
|
Q = P3 * Q;
|
||||||
|
mask3 = (Q.row(2) > 0) & mask3;
|
||||||
|
mask3 = (Q.row(2) < distanceThresh) & mask3;
|
||||||
|
|
||||||
|
triangulatePoints(P0, P4, points1, points2, Q);
|
||||||
|
if(triangulatedPoints.needed())
|
||||||
|
Q.copyTo(allTriangulations[3]);
|
||||||
|
Mat mask4 = Q.row(2).mul(Q.row(3)) > 0;
|
||||||
|
Q.row(0) /= Q.row(3);
|
||||||
|
Q.row(1) /= Q.row(3);
|
||||||
|
Q.row(2) /= Q.row(3);
|
||||||
|
Q.row(3) /= Q.row(3);
|
||||||
|
mask4 = (Q.row(2) < distanceThresh) & mask4;
|
||||||
|
Q = P4 * Q;
|
||||||
|
mask4 = (Q.row(2) > 0) & mask4;
|
||||||
|
mask4 = (Q.row(2) < distanceThresh) & mask4;
|
||||||
|
|
||||||
|
mask1 = mask1.t();
|
||||||
|
mask2 = mask2.t();
|
||||||
|
mask3 = mask3.t();
|
||||||
|
mask4 = mask4.t();
|
||||||
|
|
||||||
|
// If _mask is given, then use it to filter outliers.
|
||||||
|
if (!_mask.empty())
|
||||||
|
{
|
||||||
|
Mat mask = _mask.getMat();
|
||||||
|
CV_Assert(npoints == mask.checkVector(1));
|
||||||
|
mask = mask.reshape(1, npoints);
|
||||||
|
bitwise_and(mask, mask1, mask1);
|
||||||
|
bitwise_and(mask, mask2, mask2);
|
||||||
|
bitwise_and(mask, mask3, mask3);
|
||||||
|
bitwise_and(mask, mask4, mask4);
|
||||||
|
}
|
||||||
|
if (_mask.empty() && _mask.needed())
|
||||||
|
{
|
||||||
|
_mask.create(mask1.size(), CV_8U);
|
||||||
|
}
|
||||||
|
|
||||||
|
CV_Assert(_R.needed() && _t.needed());
|
||||||
|
_R.create(3, 3, R1.type());
|
||||||
|
_t.create(3, 1, t.type());
|
||||||
|
|
||||||
|
int good1 = countNonZero(mask1);
|
||||||
|
int good2 = countNonZero(mask2);
|
||||||
|
int good3 = countNonZero(mask3);
|
||||||
|
int good4 = countNonZero(mask4);
|
||||||
|
|
||||||
|
if (good1 >= good2 && good1 >= good3 && good1 >= good4)
|
||||||
|
{
|
||||||
|
if(triangulatedPoints.needed()) allTriangulations[0].copyTo(triangulatedPoints);
|
||||||
|
R1.copyTo(_R);
|
||||||
|
t.copyTo(_t);
|
||||||
|
if (_mask.needed()) mask1.copyTo(_mask);
|
||||||
|
return good1;
|
||||||
|
}
|
||||||
|
else if (good2 >= good1 && good2 >= good3 && good2 >= good4)
|
||||||
|
{
|
||||||
|
if(triangulatedPoints.needed()) allTriangulations[1].copyTo(triangulatedPoints);
|
||||||
|
R2.copyTo(_R);
|
||||||
|
t.copyTo(_t);
|
||||||
|
if (_mask.needed()) mask2.copyTo(_mask);
|
||||||
|
return good2;
|
||||||
|
}
|
||||||
|
else if (good3 >= good1 && good3 >= good2 && good3 >= good4)
|
||||||
|
{
|
||||||
|
if(triangulatedPoints.needed()) allTriangulations[2].copyTo(triangulatedPoints);
|
||||||
|
t = -t;
|
||||||
|
R1.copyTo(_R);
|
||||||
|
t.copyTo(_t);
|
||||||
|
if (_mask.needed()) mask3.copyTo(_mask);
|
||||||
|
return good3;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(triangulatedPoints.needed()) allTriangulations[3].copyTo(triangulatedPoints);
|
||||||
|
t = -t;
|
||||||
|
R2.copyTo(_R);
|
||||||
|
t.copyTo(_t);
|
||||||
|
if (_mask.needed()) mask4.copyTo(_mask);
|
||||||
|
return good4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* five-point.h
|
||||||
|
*
|
||||||
|
* Created on: May 18, 2020
|
||||||
|
* Author: mathieu
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CORELIB_SRC_OPENCV_FIVE_POINT_H_
|
||||||
|
#define CORELIB_SRC_OPENCV_FIVE_POINT_H_
|
||||||
|
|
||||||
|
namespace cv3
|
||||||
|
{
|
||||||
|
|
||||||
|
cv::Mat findEssentialMat( cv::InputArray _points1, cv::InputArray _points2, cv::InputArray _cameraMatrix,
|
||||||
|
int method, double prob, double threshold, cv::OutputArray _mask = cv::noArray());
|
||||||
|
|
||||||
|
int recoverPose( cv::InputArray E, cv::InputArray _points1, cv::InputArray _points2,
|
||||||
|
cv::InputArray _cameraMatrix, cv::OutputArray _R, cv::OutputArray _t, double distanceThresh,
|
||||||
|
cv::InputOutputArray _mask, cv::OutputArray triangulatedPoints);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* CORELIB_SRC_OPENCV_FIVE_POINT_H_ */
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
|
|
||||||
These files are built only if RTAB-Map is built against OpenCV 2.
|
Used with OpenCV 2:
|
||||||
|
|
||||||
* Orb.cpp is a modified version of OpenCV2 Orb with FAST object from rtabmap (FAST with Grid adaptor).
|
* Orb.cpp is a modified version of OpenCV2 Orb with FAST object from rtabmap (FAST with Grid adaptor).
|
||||||
* solvepnp.cpp is a copy of the OpenCV3 version of solvePnPRansac.
|
|
||||||
|
Used for all OpenCV versions:
|
||||||
|
* solvepnp.cpp is a copy of the OpenCV3 version of solvePnPRansac.
|
||||||
|
* five-point.cpp is a copy of the same file in OpenCV (d2872afce0fcc84a52b5753960730595550e1b62) but with RANSAC estimator using 6 points instead of 5 points to avoid "DLT algorithm needs at least 6 points for pose estimation from 3D-2D point correspondences. (expected: 'count >= 6')" error on recent OpenCV versions using DLT by default.
|
||||||
@@ -197,7 +197,7 @@ std::map<int, Transform> OptimizerG2O::optimize(
|
|||||||
// Apply g2o optimization
|
// Apply g2o optimization
|
||||||
|
|
||||||
g2o::SparseOptimizer optimizer;
|
g2o::SparseOptimizer optimizer;
|
||||||
optimizer.setVerbose(ULogger::level()==ULogger::kDebug);
|
//optimizer.setVerbose(ULogger::level()==ULogger::kDebug);
|
||||||
if (isSlam2d())
|
if (isSlam2d())
|
||||||
{
|
{
|
||||||
g2o::ParameterSE2Offset* odomOffset = new g2o::ParameterSE2Offset();
|
g2o::ParameterSE2Offset* odomOffset = new g2o::ParameterSE2Offset();
|
||||||
@@ -1260,7 +1260,7 @@ std::map<int, Transform> OptimizerG2O::optimizeBA(
|
|||||||
if(poses.size()>=2 && iterations() > 0 && (models.size() == poses.size() || poses.begin()->first < 0))
|
if(poses.size()>=2 && iterations() > 0 && (models.size() == poses.size() || poses.begin()->first < 0))
|
||||||
{
|
{
|
||||||
g2o::SparseOptimizer optimizer;
|
g2o::SparseOptimizer optimizer;
|
||||||
optimizer.setVerbose(ULogger::level()==ULogger::kDebug);
|
//optimizer.setVerbose(ULogger::level()==ULogger::kDebug);
|
||||||
#if defined(RTABMAP_G2O_CPP11) and not defined(RTABMAP_ORB_SLAM2)
|
#if defined(RTABMAP_G2O_CPP11) and not defined(RTABMAP_ORB_SLAM2)
|
||||||
std::unique_ptr<g2o::BlockSolver_6_3::LinearSolverType> linearSolver;
|
std::unique_ptr<g2o::BlockSolver_6_3::LinearSolverType> linearSolver;
|
||||||
#else
|
#else
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user