Rotate a std::vector as a rigid transformation?
I have a few 3d points, stored in a std::vector<Eigen::Vector3d>. I need to rigidly rotate and translate these points, without changing their relationship to one another. As if moving the cloud as a whole.
Based on this question:
https://stackoverflow.com/questions/50507665/eigen-rotate-a-vector3d-with-a-quaternion
I have this code:
std::vector<Eigen::Vector3d> pts, ptsMoved;
Eigen::Quaterniond rotateBy = Eigen::Quaterniond(0.1,0.5,0.08,0.02);
Eigen::Vector3d translateBy(1, 2.5, 1.5);
for (int i = 0; i < pts.size(); i++)
{
//transform point
Vector3d rot = rotateBy * (pts[i] + translateBy);
ptsMoved.push_back(rot);
}
When i view the points and compare them to the original points, however, I get this: (White are the original, green are the transformed).

What i expect, is the cloud as a whole to look the same, just in a different position and orientation. What i get, is a moved and rotated and scaled cloud, that looks different to the original. What am i doing wrong?
EDIT:
If i apply the inverse transform to the adjusted points, using:
std::vector<Eigen::Vector3d> pntsBack;
for (int i = 0; i < ptsMoved.size(); i++)
{
//transform point
Vector3d rot = rotateBy.inverse() * (ptsMoved[i] - translateBy);
pntsBack.push_back(rot);
}
It gives me an even worse result. (dark green = original points, white = transformed, light green = transformed inverse)

c++ eigen point-clouds
|
show 7 more comments
I have a few 3d points, stored in a std::vector<Eigen::Vector3d>. I need to rigidly rotate and translate these points, without changing their relationship to one another. As if moving the cloud as a whole.
Based on this question:
https://stackoverflow.com/questions/50507665/eigen-rotate-a-vector3d-with-a-quaternion
I have this code:
std::vector<Eigen::Vector3d> pts, ptsMoved;
Eigen::Quaterniond rotateBy = Eigen::Quaterniond(0.1,0.5,0.08,0.02);
Eigen::Vector3d translateBy(1, 2.5, 1.5);
for (int i = 0; i < pts.size(); i++)
{
//transform point
Vector3d rot = rotateBy * (pts[i] + translateBy);
ptsMoved.push_back(rot);
}
When i view the points and compare them to the original points, however, I get this: (White are the original, green are the transformed).

What i expect, is the cloud as a whole to look the same, just in a different position and orientation. What i get, is a moved and rotated and scaled cloud, that looks different to the original. What am i doing wrong?
EDIT:
If i apply the inverse transform to the adjusted points, using:
std::vector<Eigen::Vector3d> pntsBack;
for (int i = 0; i < ptsMoved.size(); i++)
{
//transform point
Vector3d rot = rotateBy.inverse() * (ptsMoved[i] - translateBy);
pntsBack.push_back(rot);
}
It gives me an even worse result. (dark green = original points, white = transformed, light green = transformed inverse)

c++ eigen point-clouds
If you apply the inverse transform to the transformed points, do you get back to where you started?
– Caleth
Nov 23 '18 at 12:49
Or even better, apply the inverse transform to the camera, and compare those pictures
– Caleth
Nov 23 '18 at 12:55
thanks for your reply. usingVector3d rot = rotateBy.inverse() * (ptsMoved[i] -translateBy);to apply the inverse, I get a very incorrect result.
– anti
Nov 23 '18 at 12:56
that isn't the opposite transformation. Iirc it would be(rotateBy.inverse() * ptsMoved[i]) - translateBy;
– Caleth
Nov 23 '18 at 12:57
To me, the differences look like parallax
– Caleth
Nov 23 '18 at 12:58
|
show 7 more comments
I have a few 3d points, stored in a std::vector<Eigen::Vector3d>. I need to rigidly rotate and translate these points, without changing their relationship to one another. As if moving the cloud as a whole.
Based on this question:
https://stackoverflow.com/questions/50507665/eigen-rotate-a-vector3d-with-a-quaternion
I have this code:
std::vector<Eigen::Vector3d> pts, ptsMoved;
Eigen::Quaterniond rotateBy = Eigen::Quaterniond(0.1,0.5,0.08,0.02);
Eigen::Vector3d translateBy(1, 2.5, 1.5);
for (int i = 0; i < pts.size(); i++)
{
//transform point
Vector3d rot = rotateBy * (pts[i] + translateBy);
ptsMoved.push_back(rot);
}
When i view the points and compare them to the original points, however, I get this: (White are the original, green are the transformed).

What i expect, is the cloud as a whole to look the same, just in a different position and orientation. What i get, is a moved and rotated and scaled cloud, that looks different to the original. What am i doing wrong?
EDIT:
If i apply the inverse transform to the adjusted points, using:
std::vector<Eigen::Vector3d> pntsBack;
for (int i = 0; i < ptsMoved.size(); i++)
{
//transform point
Vector3d rot = rotateBy.inverse() * (ptsMoved[i] - translateBy);
pntsBack.push_back(rot);
}
It gives me an even worse result. (dark green = original points, white = transformed, light green = transformed inverse)

c++ eigen point-clouds
I have a few 3d points, stored in a std::vector<Eigen::Vector3d>. I need to rigidly rotate and translate these points, without changing their relationship to one another. As if moving the cloud as a whole.
Based on this question:
https://stackoverflow.com/questions/50507665/eigen-rotate-a-vector3d-with-a-quaternion
I have this code:
std::vector<Eigen::Vector3d> pts, ptsMoved;
Eigen::Quaterniond rotateBy = Eigen::Quaterniond(0.1,0.5,0.08,0.02);
Eigen::Vector3d translateBy(1, 2.5, 1.5);
for (int i = 0; i < pts.size(); i++)
{
//transform point
Vector3d rot = rotateBy * (pts[i] + translateBy);
ptsMoved.push_back(rot);
}
When i view the points and compare them to the original points, however, I get this: (White are the original, green are the transformed).

What i expect, is the cloud as a whole to look the same, just in a different position and orientation. What i get, is a moved and rotated and scaled cloud, that looks different to the original. What am i doing wrong?
EDIT:
If i apply the inverse transform to the adjusted points, using:
std::vector<Eigen::Vector3d> pntsBack;
for (int i = 0; i < ptsMoved.size(); i++)
{
//transform point
Vector3d rot = rotateBy.inverse() * (ptsMoved[i] - translateBy);
pntsBack.push_back(rot);
}
It gives me an even worse result. (dark green = original points, white = transformed, light green = transformed inverse)

c++ eigen point-clouds
c++ eigen point-clouds
edited Nov 23 '18 at 13:01
anti
asked Nov 23 '18 at 12:36
antianti
9571231
9571231
If you apply the inverse transform to the transformed points, do you get back to where you started?
– Caleth
Nov 23 '18 at 12:49
Or even better, apply the inverse transform to the camera, and compare those pictures
– Caleth
Nov 23 '18 at 12:55
thanks for your reply. usingVector3d rot = rotateBy.inverse() * (ptsMoved[i] -translateBy);to apply the inverse, I get a very incorrect result.
– anti
Nov 23 '18 at 12:56
that isn't the opposite transformation. Iirc it would be(rotateBy.inverse() * ptsMoved[i]) - translateBy;
– Caleth
Nov 23 '18 at 12:57
To me, the differences look like parallax
– Caleth
Nov 23 '18 at 12:58
|
show 7 more comments
If you apply the inverse transform to the transformed points, do you get back to where you started?
– Caleth
Nov 23 '18 at 12:49
Or even better, apply the inverse transform to the camera, and compare those pictures
– Caleth
Nov 23 '18 at 12:55
thanks for your reply. usingVector3d rot = rotateBy.inverse() * (ptsMoved[i] -translateBy);to apply the inverse, I get a very incorrect result.
– anti
Nov 23 '18 at 12:56
that isn't the opposite transformation. Iirc it would be(rotateBy.inverse() * ptsMoved[i]) - translateBy;
– Caleth
Nov 23 '18 at 12:57
To me, the differences look like parallax
– Caleth
Nov 23 '18 at 12:58
If you apply the inverse transform to the transformed points, do you get back to where you started?
– Caleth
Nov 23 '18 at 12:49
If you apply the inverse transform to the transformed points, do you get back to where you started?
– Caleth
Nov 23 '18 at 12:49
Or even better, apply the inverse transform to the camera, and compare those pictures
– Caleth
Nov 23 '18 at 12:55
Or even better, apply the inverse transform to the camera, and compare those pictures
– Caleth
Nov 23 '18 at 12:55
thanks for your reply. using
Vector3d rot = rotateBy.inverse() * (ptsMoved[i] -translateBy); to apply the inverse, I get a very incorrect result.– anti
Nov 23 '18 at 12:56
thanks for your reply. using
Vector3d rot = rotateBy.inverse() * (ptsMoved[i] -translateBy); to apply the inverse, I get a very incorrect result.– anti
Nov 23 '18 at 12:56
that isn't the opposite transformation. Iirc it would be
(rotateBy.inverse() * ptsMoved[i]) - translateBy;– Caleth
Nov 23 '18 at 12:57
that isn't the opposite transformation. Iirc it would be
(rotateBy.inverse() * ptsMoved[i]) - translateBy;– Caleth
Nov 23 '18 at 12:57
To me, the differences look like parallax
– Caleth
Nov 23 '18 at 12:58
To me, the differences look like parallax
– Caleth
Nov 23 '18 at 12:58
|
show 7 more comments
1 Answer
1
active
oldest
votes
Your Quaternion is not a unit-Quaternion, therefore you will get unspecified results.
If you are not sure your quaternion is normalized, just write
rotateBy.normalize();
before using it. Additionally, if you want to rotate more than one vector it is more efficient to convert the Quaternion to a rotation matrix:
Eigen::Matrix3d rotMat = rotateBy.toRotationMatrix();
// ...
// inside for loop:
Vector3d rot = rotMat * (ptsMoved[i] - translateBy);
Also, instead of .inverse() you can use .conjugate() for unit quaternions and .adjoint() or .transpose() for orthogonal Matrices.
Thank you! This has indeed fixed my issue. However, when I try to get the points back to where they started, usingVector3d rot = rotateBy.conjugate() * (ptsMoved[i] - translateBy);The rotation looks correct, but the translation is off in one axis.
– anti
Nov 23 '18 at 13:55
Adjusting teh order of operations has fixed this last part.Vector3d rot = rotateBy.conjugate() * (ptsMoved[i]); rot = rot - translateBy;thank you again for your help!
– anti
Nov 23 '18 at 14:19
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53446831%2frotate-a-stdvectoreigenvector3d-as-a-rigid-transformation%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
Your Quaternion is not a unit-Quaternion, therefore you will get unspecified results.
If you are not sure your quaternion is normalized, just write
rotateBy.normalize();
before using it. Additionally, if you want to rotate more than one vector it is more efficient to convert the Quaternion to a rotation matrix:
Eigen::Matrix3d rotMat = rotateBy.toRotationMatrix();
// ...
// inside for loop:
Vector3d rot = rotMat * (ptsMoved[i] - translateBy);
Also, instead of .inverse() you can use .conjugate() for unit quaternions and .adjoint() or .transpose() for orthogonal Matrices.
Thank you! This has indeed fixed my issue. However, when I try to get the points back to where they started, usingVector3d rot = rotateBy.conjugate() * (ptsMoved[i] - translateBy);The rotation looks correct, but the translation is off in one axis.
– anti
Nov 23 '18 at 13:55
Adjusting teh order of operations has fixed this last part.Vector3d rot = rotateBy.conjugate() * (ptsMoved[i]); rot = rot - translateBy;thank you again for your help!
– anti
Nov 23 '18 at 14:19
add a comment |
Your Quaternion is not a unit-Quaternion, therefore you will get unspecified results.
If you are not sure your quaternion is normalized, just write
rotateBy.normalize();
before using it. Additionally, if you want to rotate more than one vector it is more efficient to convert the Quaternion to a rotation matrix:
Eigen::Matrix3d rotMat = rotateBy.toRotationMatrix();
// ...
// inside for loop:
Vector3d rot = rotMat * (ptsMoved[i] - translateBy);
Also, instead of .inverse() you can use .conjugate() for unit quaternions and .adjoint() or .transpose() for orthogonal Matrices.
Thank you! This has indeed fixed my issue. However, when I try to get the points back to where they started, usingVector3d rot = rotateBy.conjugate() * (ptsMoved[i] - translateBy);The rotation looks correct, but the translation is off in one axis.
– anti
Nov 23 '18 at 13:55
Adjusting teh order of operations has fixed this last part.Vector3d rot = rotateBy.conjugate() * (ptsMoved[i]); rot = rot - translateBy;thank you again for your help!
– anti
Nov 23 '18 at 14:19
add a comment |
Your Quaternion is not a unit-Quaternion, therefore you will get unspecified results.
If you are not sure your quaternion is normalized, just write
rotateBy.normalize();
before using it. Additionally, if you want to rotate more than one vector it is more efficient to convert the Quaternion to a rotation matrix:
Eigen::Matrix3d rotMat = rotateBy.toRotationMatrix();
// ...
// inside for loop:
Vector3d rot = rotMat * (ptsMoved[i] - translateBy);
Also, instead of .inverse() you can use .conjugate() for unit quaternions and .adjoint() or .transpose() for orthogonal Matrices.
Your Quaternion is not a unit-Quaternion, therefore you will get unspecified results.
If you are not sure your quaternion is normalized, just write
rotateBy.normalize();
before using it. Additionally, if you want to rotate more than one vector it is more efficient to convert the Quaternion to a rotation matrix:
Eigen::Matrix3d rotMat = rotateBy.toRotationMatrix();
// ...
// inside for loop:
Vector3d rot = rotMat * (ptsMoved[i] - translateBy);
Also, instead of .inverse() you can use .conjugate() for unit quaternions and .adjoint() or .transpose() for orthogonal Matrices.
answered Nov 23 '18 at 13:49
chtzchtz
6,96811232
6,96811232
Thank you! This has indeed fixed my issue. However, when I try to get the points back to where they started, usingVector3d rot = rotateBy.conjugate() * (ptsMoved[i] - translateBy);The rotation looks correct, but the translation is off in one axis.
– anti
Nov 23 '18 at 13:55
Adjusting teh order of operations has fixed this last part.Vector3d rot = rotateBy.conjugate() * (ptsMoved[i]); rot = rot - translateBy;thank you again for your help!
– anti
Nov 23 '18 at 14:19
add a comment |
Thank you! This has indeed fixed my issue. However, when I try to get the points back to where they started, usingVector3d rot = rotateBy.conjugate() * (ptsMoved[i] - translateBy);The rotation looks correct, but the translation is off in one axis.
– anti
Nov 23 '18 at 13:55
Adjusting teh order of operations has fixed this last part.Vector3d rot = rotateBy.conjugate() * (ptsMoved[i]); rot = rot - translateBy;thank you again for your help!
– anti
Nov 23 '18 at 14:19
Thank you! This has indeed fixed my issue. However, when I try to get the points back to where they started, using
Vector3d rot = rotateBy.conjugate() * (ptsMoved[i] - translateBy); The rotation looks correct, but the translation is off in one axis.– anti
Nov 23 '18 at 13:55
Thank you! This has indeed fixed my issue. However, when I try to get the points back to where they started, using
Vector3d rot = rotateBy.conjugate() * (ptsMoved[i] - translateBy); The rotation looks correct, but the translation is off in one axis.– anti
Nov 23 '18 at 13:55
Adjusting teh order of operations has fixed this last part.
Vector3d rot = rotateBy.conjugate() * (ptsMoved[i]); rot = rot - translateBy; thank you again for your help!– anti
Nov 23 '18 at 14:19
Adjusting teh order of operations has fixed this last part.
Vector3d rot = rotateBy.conjugate() * (ptsMoved[i]); rot = rot - translateBy; thank you again for your help!– anti
Nov 23 '18 at 14:19
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53446831%2frotate-a-stdvectoreigenvector3d-as-a-rigid-transformation%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
If you apply the inverse transform to the transformed points, do you get back to where you started?
– Caleth
Nov 23 '18 at 12:49
Or even better, apply the inverse transform to the camera, and compare those pictures
– Caleth
Nov 23 '18 at 12:55
thanks for your reply. using
Vector3d rot = rotateBy.inverse() * (ptsMoved[i] -translateBy);to apply the inverse, I get a very incorrect result.– anti
Nov 23 '18 at 12:56
that isn't the opposite transformation. Iirc it would be
(rotateBy.inverse() * ptsMoved[i]) - translateBy;– Caleth
Nov 23 '18 at 12:57
To me, the differences look like parallax
– Caleth
Nov 23 '18 at 12:58