Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
PublicProjects
qtransforms
Commits
6e058168
Commit
6e058168
authored
Jul 25, 2016
by
Sören Schwertfeger
Browse files
ok not bad so far...
parent
a04d4f76
Changes
4
Hide whitespace changes
Inline
Side-by-side
qTransformsPlugin.cpp
View file @
6e058168
...
...
@@ -20,6 +20,9 @@
//Qt
#include <QtGui>
#include <QFileDialog>
#include "sttl.h"
...
...
@@ -55,9 +58,25 @@ void qTransformsPlugin::getActions(QActionGroup& group)
m_action
->
setIcon
(
getIcon
());
//connect appropriate signal
connect
(
m_action
,
SIGNAL
(
triggered
()),
this
,
SLOT
(
doAction
()));
m_actionLoadTransform
=
new
QAction
(
"Load Transforms..."
,
this
);
m_actionLoadTransform
->
setToolTip
(
"Load transforms from a JSON file and apply to the visible point clouds."
);
m_actionLoadTransform
->
setIcon
(
getIcon
());
//connect appropriate signal
connect
(
m_actionLoadTransform
,
SIGNAL
(
triggered
()),
this
,
SLOT
(
loadTransforms
()));
m_actionSaveTransform
=
new
QAction
(
"Save Transforms..."
,
this
);
m_actionSaveTransform
->
setToolTip
(
"Save transforms to a JSON file."
);
m_actionSaveTransform
->
setIcon
(
getIcon
());
//connect appropriate signal
connect
(
m_actionSaveTransform
,
SIGNAL
(
triggered
()),
this
,
SLOT
(
saveTransforms
()));
}
group
.
addAction
(
m_action
);
group
.
addAction
(
m_actionLoadTransform
);
group
.
addAction
(
m_actionSaveTransform
);
}
...
...
@@ -85,12 +104,12 @@ void qTransformsPlugin::recTravTree(ccHObject * obj, QString spaces){
}
void
qTransformsPlugin
::
recTravTree
(
ccHObject
*
obj
,
sttl
::
F
ram
e
*
parent
){
sttl
::
F
ram
e
*
current
=
parent
;
void
qTransformsPlugin
::
recTravTree
(
ccHObject
*
obj
,
sttl
::
T
ra
nsfor
m
*
parent
){
sttl
::
T
ra
nsfor
m
*
current
=
parent
;
if
(
obj
->
getClassID
()
==
CC_TYPES
::
POINT_CLOUD
){
// this is a point cloud - will be a new parent...
sttl
::
F
ra
me
frame
;
frame
.
n
ame
=
obj
->
getName
().
toStdString
();
sttl
::
T
ra
nsform
transform
;
transform
.
frame
N
ame
=
obj
->
getName
().
toStdString
();
const
ccGLMatrix
&
transf
=
obj
->
getGLTransformationHistory
();
Eigen
::
Transform
<
double
,
3
,
Eigen
::
Affine
>
globalT
;
for
(
int
i
=
0
;
i
<
16
;
++
i
){
...
...
@@ -98,14 +117,13 @@ void qTransformsPlugin::recTravTree(ccHObject * obj, sttl::Frame * parent){
}
// ToDo: properly compute the transform of this frame wrt the parent... - I think this is correct...
Eigen
::
Transform
<
double
,
3
,
Eigen
::
Affine
>
result
=
globalT
*
parent
->
transform
.
inverse
();
f
ram
e
.
transform
=
result
;
t
ra
nsfor
m
.
transform
=
result
;
frame
.
referenceFrameName
=
parent
->
name
;
frame
.
referenceFrame
=
parent
;
m_frames
.
push_back
(
frame
);
current
=
&
m_frames
.
back
();
transform
.
referenceFrameName
=
parent
->
frameName
;
transform
.
generateId
();
m_transforms
.
push_back
(
transform
);
current
=
&
m_transforms
.
back
();
}
// recursively call the children...
...
...
@@ -115,6 +133,44 @@ void qTransformsPlugin::recTravTree(ccHObject * obj, sttl::Frame * parent){
}
void
qTransformsPlugin
::
loadTransforms
(){
ccHObject
*
root
=
getMainAppInterface
()
->
dbRootObject
();
QString
file
=
QFileDialog
::
getOpenFileName
(
0
,
"SaveTransforms"
,
""
,
"*.stt"
,
0
,
0
);
m_transforms
.
clear
();
if
(
!
file
.
isEmpty
()){
sttl
::
loadList
(
m_transforms
,
file
.
toStdString
());
}
std
::
cerr
<<
"We now have "
<<
m_transforms
.
size
()
<<
" transforms! "
<<
std
::
endl
;
}
void
qTransformsPlugin
::
saveTransforms
(){
ccHObject
*
root
=
getMainAppInterface
()
->
dbRootObject
();
recTravTree
(
root
,
QString
(
""
));
m_transforms
.
clear
();
sttl
::
Transform
rootFrame
;
rootFrame
.
frameName
=
"root"
;
rootFrame
.
transform
=
Eigen
::
Transform
<
double
,
3
,
Eigen
::
Affine
>::
Identity
();
rootFrame
.
referenceFrameName
=
""
;
rootFrame
.
byUser
=
"Schwerti"
;
m_transforms
.
push_back
(
rootFrame
);
recTravTree
(
root
,
&
m_transforms
.
front
());
QString
file
=
QFileDialog
::
getSaveFileName
(
0
,
"SaveTransforms"
,
""
,
"*.stt"
,
0
,
0
);
if
(
!
file
.
isEmpty
()){
sttl
::
saveList
(
m_transforms
,
file
.
toStdString
());
}
}
//This is an example of an action's slot called when the corresponding action
//is triggered (i.e. the corresponding icon or menu entry is clicked in CC's
//main interface). You can access to most of CC components (database,
...
...
@@ -138,16 +194,16 @@ void qTransformsPlugin::doAction()
ccHObject
*
root
=
getMainAppInterface
()
->
dbRootObject
();
recTravTree
(
root
,
QString
(
""
));
m_
f
ram
e
s
.
clear
();
sttl
::
F
ram
e
rootFrame
;
rootFrame
.
n
ame
=
"root"
;
m_
t
ra
nsfor
ms
.
clear
();
sttl
::
T
ra
nsfor
m
rootFrame
;
rootFrame
.
frameN
ame
=
"root"
;
rootFrame
.
transform
=
Eigen
::
Transform
<
double
,
3
,
Eigen
::
Affine
>::
Identity
();
rootFrame
.
referenceFrameName
=
""
;
rootFrame
.
byUser
=
"Schwerti"
;
m_
f
ram
e
s
.
push_back
(
rootFrame
);
recTravTree
(
root
,
&
m_
f
ram
e
s
.
front
());
sttl
::
saveList
(
m_frames
);
m_
t
ra
nsfor
ms
.
push_back
(
rootFrame
);
recTravTree
(
root
,
&
m_
t
ra
nsfor
ms
.
front
());
}
...
...
qTransformsPlugin.h
View file @
6e058168
...
...
@@ -63,6 +63,8 @@ protected slots:
/*** ADD YOUR CUSTOM ACTIONS' SLOTS HERE ***/
void
doAction
();
void
loadTransforms
();
void
saveTransforms
();
protected:
...
...
@@ -73,11 +75,13 @@ protected:
**/
void
recTravTree
(
ccHObject
*
obj
,
QString
spaces
);
void
recTravTree
(
ccHObject
*
obj
,
sttl
::
F
ram
e
*
parent
);
void
recTravTree
(
ccHObject
*
obj
,
sttl
::
T
ra
nsfor
m
*
parent
);
std
::
list
<
sttl
::
F
ram
e
>
m_
f
ram
e
s
;
std
::
list
<
sttl
::
T
ra
nsfor
m
>
m_
t
ra
nsfor
ms
;
QAction
*
m_action
;
QAction
*
m_actionLoadTransform
;
QAction
*
m_actionSaveTransform
;
};
#endif
sttl/sttl.cpp
View file @
6e058168
#include "sttl.h"
#include <iostream>
#include <fstream>
#include <json/json.h>
#include <json/value.h>
using
namespace
std
;
void
testSTTL
(){
cout
<<
"Hello STTL"
<<
endl
;
}
#include <chrono>
#include <functional>
#include <cstdlib>
using
namespace
std
;
Eigen
::
MatrixXd
ReadJsonMatrix
(
Json
::
Value
Array
){
int
rows
=
Array
.
size
();
int
cols
=
Array
[
0
].
size
();
Eigen
::
MatrixXd
Matrix
(
rows
,
cols
)
;
for
(
int
i
=
0
;
i
<
rows
;
i
++
){
for
(
int
j
=
0
;
j
<
cols
;
j
++
){
Matrix
(
i
,
j
)
=
Array
[
i
][
j
].
asDouble
()
;
}
}
return
Matrix
;
std
::
string
sttl
::
Transform
::
Id
::
toString
()
const
{
std
::
stringstream
str
;
str
.
fill
(
'0'
);
str
.
width
(
16
);
str
<<
std
::
hex
<<
id
[
0
];
str
.
fill
(
'0'
);
str
.
width
(
16
);
str
<<
std
::
hex
<<
id
[
1
];
return
str
.
str
();
}
//// Read Json Array and return as Eigen Vector
Eigen
::
VectorXd
ReadJsonVector
(
Json
::
Value
Array
){
int
size
=
Array
.
size
();
Eigen
::
VectorXd
Vector
(
size
);
for
(
int
i
=
0
;
i
<
size
;
i
++
){
Vector
(
i
)
=
Array
[
i
].
asDouble
();
}
return
Vector
;
bool
sttl
::
Transform
::
Id
::
fromString
(
const
std
::
string
&
string
){
for
(
int
i
=
0
;
i
<
2
;
++
i
){
std
::
stringstream
str
(
string
.
substr
(
i
*
16
,
16
));
str
>>
std
::
hex
>>
id
[
i
];
}
return
true
;
}
bool
fillJson
(
const
sttl
::
Frame
&
frame
,
Json
::
Value
&
node
){
node
[
"name"
]
=
frame
.
name
;
bool
readJson
(
sttl
::
Transform
&
transform
,
Json
::
Value
&
node
){
transform
.
frameName
=
node
[
"name"
].
asString
();
transform
.
referenceFrameName
=
node
[
"referenceFrame"
].
asString
();
transform
.
id
.
fromString
(
node
[
"id"
].
asString
());
if
(
node
[
"transform"
].
size
()
!=
4
){
std
::
cerr
<<
"transform does not have 4 elements!"
<<
std
::
endl
;
return
false
;
}
if
(
node
[
"transform"
][
0
].
size
()
!=
4
){
std
::
cerr
<<
"transform does not have 4x4 elements!"
<<
std
::
endl
;
return
false
;
}
for
(
int
i
=
0
;
i
<
4
;
++
i
){
for
(
int
j
=
0
;
j
<
4
;
++
j
){
transform
.
transform
(
i
,
j
)
=
node
[
"transform"
][
i
][
j
].
asDouble
();
}
}
transform
.
hasCovariance
=
false
;
if
(
node
.
isMember
(
"covariance"
)){
transform
.
hasCovariance
=
true
;
if
(
node
[
"covariance"
].
size
()
!=
7
){
std
::
cerr
<<
"covariance does not have 7 elements!"
<<
std
::
endl
;
return
false
;
}
if
(
node
[
"covariance"
][
0
].
size
()
!=
7
){
std
::
cerr
<<
"covariance does not have 7x7 elements!"
<<
std
::
endl
;
return
false
;
}
for
(
int
i
=
0
;
i
<
7
;
++
i
){
for
(
int
j
=
0
;
j
<
7
;
++
j
){
transform
.
covariance
(
i
,
j
)
=
node
[
"covariance"
][
i
][
j
].
asDouble
();
}
}
}
return
true
;
}
bool
fillJson
(
const
sttl
::
Transform
&
transform
,
Json
::
Value
&
node
){
node
[
"name"
]
=
transform
.
frameName
;
Json
::
Value
trans
(
Json
::
arrayValue
);
trans
.
resize
(
4
);
for
(
int
i
=
0
;
i
<
4
;
++
i
){
trans
[
i
]
=
Json
::
Value
(
Json
::
arrayValue
);
trans
[
i
].
resize
(
4
);
for
(
int
k
=
0
;
k
<
4
;
++
k
){
trans
[
i
][
k
]
=
f
ram
e
.
transform
(
i
,
k
);
trans
[
i
][
k
]
=
t
ra
nsfor
m
.
transform
(
i
,
k
);
}
}
node
[
"transform"
]
=
trans
;
if
(
f
ram
e
.
hasCovariance
){
if
(
t
ra
nsfor
m
.
hasCovariance
){
Json
::
Value
cov
(
Json
::
arrayValue
);
cov
.
resize
(
7
);
for
(
int
i
=
0
;
i
<
7
;
++
i
){
cov
[
i
]
=
Json
::
Value
(
Json
::
arrayValue
);
cov
[
i
].
resize
(
7
);
for
(
int
k
=
0
;
k
<
7
;
++
k
){
cov
[
i
][
k
]
=
f
ram
e
.
covariance
(
i
,
k
);
cov
[
i
][
k
]
=
t
ra
nsfor
m
.
covariance
(
i
,
k
);
}
}
node
[
"covariance"
]
=
cov
;
node
[
"covariance"
]
=
cov
;
}
node
[
"referenceFrame"
]
=
frame
.
referenceFrameName
;
node
[
"referenceFrame"
]
=
transform
.
referenceFrameName
;
node
[
"id"
]
=
transform
.
id
.
toString
();
//std::cout<<node;
return
true
;
}
bool
sttl
::
saveList
(
const
std
::
list
<
sttl
::
Frame
>
&
frames
){
uint64_t
hash_combine
(
uint64_t
&
seed
,
const
uint64_t
&
hash
)
{
seed
^=
hash
+
0x9e3773e79b4319b9
+
(
seed
<<
6
)
+
(
seed
>>
2
);
return
seed
;
}
// inline void hash_combine(std::size_t& seed, const std::size_t &hash) {
// seed ^= hash + 0x9e3779b9 + (seed<<6) + (seed>>2);
// }
bool
sttl
::
Transform
::
generateId
(){
if
(
!
(
id
==
Id
())){
std
::
cerr
<<
"Id was not empty when calling generateId()!"
<<
std
::
endl
;
return
false
;
}
uint64_t
id_time
=
std
::
chrono
::
duration_cast
<
std
::
chrono
::
seconds
>
(
std
::
chrono
::
system_clock
::
now
().
time_since_epoch
()).
count
();
uint64_t
hashNames
=
0
;
hash_combine
(
hashNames
,
std
::
hash
<
std
::
string
>
()(
frameName
));
hash_combine
(
hashNames
,
std
::
hash
<
std
::
string
>
()(
referenceFrameName
));
hash_combine
(
hashNames
,
std
::
hash
<
std
::
string
>
()(
byUser
));
hash_combine
(
hashNames
,
std
::
hash
<
std
::
string
>
()(
method
));
hash_combine
(
hashNames
,
std
::
hash
<
std
::
string
>
()(
program
));
uint64_t
hashTransf
=
0
;
for
(
int
i
=
0
;
i
<
4
;
++
i
)
for
(
int
k
=
0
;
k
<
4
;
++
k
){
hash_combine
(
hashTransf
,
std
::
hash
<
double
>
()(
transform
(
i
,
k
)));
}
static
bool
srandCalled
=
false
;
if
(
!
srandCalled
){
srandCalled
=
true
;
std
::
srand
(
id_time
);
}
uint64_t
random
=
std
::
rand
();
hash_combine
(
random
,
std
::
rand
());
hash_combine
(
random
,
std
::
rand
());
hash_combine
(
random
,
std
::
rand
());
hash_combine
(
random
,
std
::
rand
());
id
=
Id
(
hash_combine
(
random
,
id_time
),
hash_combine
(
hashNames
,
hashTransf
));
return
true
;
}
bool
sttl
::
saveList
(
const
std
::
list
<
sttl
::
Transform
>
&
transfs
,
const
std
::
string
&
file
){
Json
::
Value
root
(
Json
::
arrayValue
);
for
(
std
::
list
<
sttl
::
F
ram
e
>::
const_iterator
itr
=
f
ra
me
s
.
begin
();
itr
!=
f
ra
me
s
.
end
();
++
itr
){
for
(
std
::
list
<
sttl
::
T
ra
nsfor
m
>::
const_iterator
itr
=
t
ra
nsf
s
.
begin
();
itr
!=
t
ra
nsf
s
.
end
();
++
itr
){
Json
::
Value
frame
;
fillJson
(
*
itr
,
frame
);
root
.
append
(
frame
);
}
std
::
fstream
fs
;
fs
.
open
(
file
,
std
::
fstream
::
out
);
if
(
fs
.
is_open
()){
std
::
cout
<<
root
;
fs
<<
root
;
fs
.
close
();
}
else
{
cerr
<<
"Unable to open file "
<<
file
<<
" for writing..."
<<
std
::
endl
;
return
false
;
}
return
true
;
}
bool
sttl
::
loadList
(
std
::
list
<
sttl
::
Transform
>
&
transfs
,
const
std
::
string
&
file
){
if
(
!
transfs
.
empty
()){
std
::
cerr
<<
"Load list - list provided not empty!"
<<
std
::
endl
;
return
false
;
}
std
::
fstream
fs
;
fs
.
open
(
file
,
std
::
fstream
::
in
);
if
(
!
fs
.
is_open
()){
std
::
cerr
<<
"Error opening file "
<<
file
<<
std
::
endl
;
return
false
;
}
Json
::
Value
root
;
fs
>>
root
;
for
(
int
i
=
0
;
i
<
root
.
size
()
;
++
i
){
sttl
::
Transform
trans
;
bool
ret
=
readJson
(
trans
,
root
[
i
]);
if
(
!
ret
){
std
::
cerr
<<
"Error reading transform # "
<<
i
<<
std
::
endl
;
return
false
;
}
transfs
.
push_back
(
trans
);
}
return
true
;
}
sttl/sttl.h
View file @
6e058168
...
...
@@ -2,35 +2,83 @@
#define STTL
// #include <stdlib.h>
// #include <stdio.h>
#include <Eigen/Geometry>
#include <iomanip>
#include <iostream>
#include <string>
#include <list>
namespace
sttl
{
class
Frame
{
/*
* A Transform between two frames
* There might be multiple transforms for every frame - maybe even with the same reference frame.
* Those are not specially handeled here - just more than one Transform will exist.
*/
class
Transform
{
public:
std
::
string
name
;
Eigen
::
Transform
<
double
,
3
,
Eigen
::
Affine
>
transform
;
Eigen
::
Matrix
<
double
,
7
,
7
>
covariance
;
//< the 7x7 covariance matrix of translation and rotation as quaternion
bool
hasCovariance
;
//< only true ifthe covariance matrix has proper values
Frame
*
referenceFrame
;
struct
Id
{
uint64_t
id
[
2
];
Id
(){
id
[
0
]
=
0
;
id
[
1
]
=
0
;
// id[2] = 0;
// id[3] = 0;
}
Id
(
uint64_t
id0
,
uint64_t
id1
){
id
[
0
]
=
id0
;
id
[
1
]
=
id1
;
// id[2] = id2;
// id[3] = id3;
}
bool
operator
==
(
const
Id
&
other
)
const
{
return
id
[
0
]
==
other
.
id
[
0
]
&&
id
[
1
]
==
other
.
id
[
1
];
}
std
::
string
toString
()
const
;
bool
fromString
(
const
std
::
string
&
string
);
};
std
::
string
frameName
;
//< the name of the frame we are describing
std
::
string
referenceFrameName
;
//< in case the reference Frame cannot be found
Frame
()
:
hasCovariance
(
false
),
referenceFrame
(
0
){}
Eigen
::
Transform
<
double
,
3
,
Eigen
::
Affine
>
transform
;
//< the transfrom of this frame wrt the reference frame
bool
hasCovariance
;
//< only true if the covariance matrix below has proper values
Eigen
::
Matrix
<
double
,
7
,
7
>
covariance
;
//< the 7x7 covariance matrix of translation and rotation as quaternion
std
::
string
byUser
;
//< The user responsible for generating this transform
std
::
string
time
;
//< the time this transform was generated
std
::
string
method
;
//< Name of the method used to generate this transform - use the constants below if possible
std
::
string
program
;
//< Name of the program used to generate this transform (e.g. "cloudcompare")
std
::
string
details
;
//< Any additional data that this method/ program wants to save
Id
id
;
//< special 256bit (hopefully) unique id generated once by generateId()
std
::
string
byUser
;
std
::
string
time
;
std
::
list
<
std
::
string
>
files
;
std
::
list
<
Id
>
history
;
//< list of other transforms between these frames that influenced this result.
Transform
()
:
hasCovariance
(
false
){}
bool
generateId
();
};
bool
saveList
(
const
std
::
list
<
sttl
::
Frame
>
&
frames
);
static
const
std
::
string
METHOD_MANUAL
=
"Manual"
;
static
const
std
::
string
METHOD_ICP
=
"ICP"
;
static
const
std
::
string
METHOD_G2O
=
"g2o"
;
void
testSTTL
();
bool
saveList
(
const
std
::
list
<
sttl
::
Transform
>
&
frames
,
const
std
::
string
&
file
);
bool
loadList
(
std
::
list
<
sttl
::
Transform
>
&
frames
,
const
std
::
string
&
file
);
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment