This is for a robot simulation that I'm currently working on.
If you look at the diagram provided, you'll see two co-ordinate frames. Frame A, Frame B; and you will find a point p.
Co-ordinate frame A is the world-frame, and frame B is the local frame for my robot (where the x-axis is the heading-direction of the robot, as per convention). The robot is able to rotate and drive around in the world.
My goal here is to find the point p, expressed in terms of frame A, and re-express it in terms of the frame B.
The standard equation that I would use to implement this would be as follows:
point_in_frameB_x = point_in_frameA_x * cos(theta) - point_in_frameA_y * sin(theta) + t_x
point_in_frameB_y = point_in_frameA_x * sin(theta) + point_in_frameA_y * cos(theta) + t_y
Where t_x and t_y make up the translation transformation of frame B to frame A.
However, there are some complications here that prevent me from getting my desired results:
Since the robot can rotate around (with its default pose being with a heading direction north--and this has a rotation of 0 radians), I don't know how I would define t_x and t_y in the above code. Because if the robot has a heading direction (i.e. x-axis) parallel to the y-axis of frame A, the translation vector would be different from the situation where the robot has a heading direction parallel to the x-axis of frame A.
You would notice that the transformation from frame A to frame B isn't straightforward. I'm using this convention simply because I'm implementing this simulator which uses this convention for its image-frame.
Any help would be greatly appreciated. Thanks in advance.
Follow right hand rule for assigning coordinate frames. In your picture axes of either frame A or frame B must be changed.
Related
I'd like to simulate the shift of a tilt-shift/perspective-control lens in Scene Kit on MacOS.
Imagine the user has the camera facing a tall building at ground level, I'd like to be able to shift the 'lens' so that the projective distortion shifts (see e.g. Wikipedia).
Apple provides lots of physically-based parameters for SCNCamera (sensor height, aperture blade count), but I can't see anything obvious for this. It seems to exist in Unity.
Crucially I'd like to shift the lens so that the object stays in the same position relative to the camera. Obviously I could move the camera to get the effect, but the object needs to stay centred in the viewport (and I can't see a way to modify the viewport either). I've tried to modify the .projectionTransform matrix directly, but it was unsuccessful.
Thanks!
There's is no API on SCNCamera that does that out of the box. As you guessed one has to create a custom projection matrix and set it to the projectionTransform property.
I finally worked out the correct adjustment to the projection matrix – it's quite confusing to follow the maths, because it is a 4x4 matrix rather than 3x4 or 4x3 as you'd use for a plain camera projection matrix, which additionally makes it especially confusing to work out whether it is expecting row vectors or column vectors.
Anyway, the correct element is .m32 for the y axis
let camera = SCNNode()
camera.camera = SCNCamera()
let yShift: CGFloat = 1.0
camera.camera!.projectionTransform.m32 = yShift
Presumably .m31 will shift in the x axis, but I have to admit I haven't tested this.
When I thought about it a bit more, I also realised that the effect I actually wanted involves moving the camera too. Adjusting .m32 simulates moving the sensor, which will appear to move the subject relative to the camera, as if you had a wide angle lens and you were moving the crop. To keep the subject centred in frame, you need to move the camera's position too.
With a bit (a lot) of help from this blog post and in particular this code, I implemented this too:
let distance: CGFloat = 1.0 // calculate distance from subject here
let fovRadians = camera.camera!.fieldOfView * CGFloat.pi / 180.0
let yAdjust = tan(fovRadians / 2) * distance * yShift
camera.position = camera.position - camera.worldUp * yAdjust
(any interested readers could presumably work out the x axis shift from the source above)
Using GDI+ in Delphi 10.2.3: I have an elliptical (not circular) arc drawn from a rectangular RectF and defined start and swept angles using DrawArcF. I need to be able to find any point along the centerline of the arc (regardless of pen width) based just on the degrees of the point - e.g., if the arc starts at 210 for 120 degrees, I need to find the point at, say, 284 degrees, relative to the RectF.
In this case, the aspect ratio of the rectangle remains constant regardless of its size, so the shape of the arc should remain consistent as well, if that makes a difference.
Any ideas on how to go about this?
Parametric equation for axis-aligned ellipse centered at cx, cy with semiaxes a,b against angle Fi is:
t = ArcTan2(a * Sin(Fi), b * Cos(Fi))
x = cx + a * Cos(t)
y = cy + b * Sin(t)
(I used atan2 to get rid off atan range limitation/sign issues)
Note that parameter t runs through the same range 0..2*Pi but differs from true angle Fi (they coincide at angles k*Pi/2).
Picture of Fi/t ratio for b/a=0.6 from Mathworld (near formula 58)
I'm new to opencv and computer vision. I want to find the R and t matrix between two camera pose. So I generally follows the wikipedia:
https://en.wikipedia.org/wiki/Essential_matrix#Determining_R_and_t_from_E
I find a group of the related pixel location of the same point in the two images. I get the essential matrix. Then I run the SVD. And print the 2 possible R and 2 possible t.
[What runs as expected]
If I only change the rotation alone (one of roll, pitch, yaw) or translation alone (one of x, y, z), it works perfect. For example, if I increase pitch to 15 degree, then I would get R and find the delta pitch is +14.9 degree. If I only increase x for 10 cm, then the t matrix is like [0.96, -0.2, -0.2].
[What goes wrong]
However, if I change both rotation and translation, the R and t is non-sense. For example, if I increase x for 10 cm and increase pitch to 15 degree, then the delta degree is like [-23, 8,0.5], and the t matrix is like [0.7, 0.5, 0.5].
[Question]
I'm wondering why I could not get a good result if I change the rotation and translation at the same time. And it is also confusing why the unrelated rotation or translation (roll, yaw, y, z) also changes so much.
Would anyone be willing to figure me out? Thanks.
[Solved and the reason]
OpenCV use a right-hand coordinate system. This is to say that the z-axis is projected from xy plane to the viewer direction. And our system is using a left-hand coordinate system. So as long as the changes are related to the z-axis, the result is non-sense.
This is solved due to the difference of the coordinates using.
OpenCV use a right-hand coordinate system. This is to say that the z-axis is projected from xy plane to the viewer direction. And our system is using a left-hand coordinate system. So as long as the changes are related to the z-axis, the result is non-sense.
In OpenCV, I am using a Charuco board, have calibrated the camera, and use SolvePnP to get rvec and tvec. (similar to the sample code). I am using a stationary board, with a camera on a circular rig which orbits the board. I'm a noob with this, so please bear with me if this is something simple I am missing.
I understand that I can use Rodrigues() to get the 3x3 rotation matrix for the board orientation from rvec, and that I can transform the tvec value into world coordinates using -R.t() * tvec (in c++).
However, as I understand it, this 3x3 rotation R gives the orientation of the board with respect to the camera, so it's not quite what need. I want the rotation of the camera itself, which is offset from R by (I think) the angle between tvec and the z axis in camera space. (because the camera is not always pointing at the board origin, but it is always pointing down the z axis in camera space). Is this correct?
How do I find the additional rotation offset and convert it to a 3x3 rotation matrix which I can combine with R to get the actual camera orientation?
Thanks!
Let's say you capture N frames of the Charuco board from the camera. Then, you have N transformations taking a point in the camera frame to the same point in the Charuco board frame. This is obtained from the Charuco board poses for every frame.
Say we denote a linear transformation from one coordinate frame to another as T4x4 = [R3x3, t3x1; 01x3, 1] If we look at a point P from the board coordinate frame and refer to it as Pboard. Similarly, we look at that point from camera 1 referred to as c1, camera 2 as c2 and so on.
So, we could write:
Pboard = T1Pc1
Pboard = T2Pc2
.
.
.
Pboard = TNPcN
From what I understand, you need camera's rotation say from the starting point (assume that camera is at zero rotation in the frame 1). So, you could express every subsequent frame in terms of Pc1 instead of Pboard.
So, we could say
T2Pc2 = T1Pc1
or, Pc2 = T2-1T1Pc1
Similarly, PcN = TN-1T1Pc1
You could recover RN for taking point from camera position N to camera position 1 by looking at the rotation part of TN-1T1.
I tried determining camera motion from fundamental matrix using opencv. I'm currently using optical flow to track movement of points in every other frame. Essential matrix is being derived from fundamental matrix and camera matrix. My algorithm is as follows
1 . Use goodfeaturestotrack function to detect feature points from frame.
2 . Track the points to next two or three frames(Lk optical flow), during which calculate translation and rotation vectorsusing corresponding points
3 . Refresh points after two or three frame (use goodfeaturestotrack). Once again find translation and rotation vectors.
I understand that i cannot add the translation vectors to find the total movement from the beginning as the axis keep changing when I refresh points and start fresh tracking all over again. Can anyone please suggest me how to calculate the summation of movement from the origin.
You are asking is a typical visual odometry problem. concatenate the transformation matrix SE3 of the Lie-Group.
You just multiply the T_1 T_2 T_3 till you get T_1to3
You can try with this code https://github.com/avisingh599/mono-vo/blob/master/src/visodo.cpp
for(int numFrame=2; numFrame < MAX_FRAME; numFrame++)
if ((scale>0.1)&&(t.at<double>(2) > t.at<double>(0)) && (t.at<double>(2) > t.at<double>(1))) {
t_f = t_f + scale*(R_f*t);
R_f = R*R_f;
}
Its simple math concept. If you feel difficult, just look at robotics forward kinematic for easier understanding. Just the concatenation part, not the DH algo.
https://en.wikipedia.org/wiki/Forward_kinematics
write all of your relative camera position in a 4x4 transformation matrix and then multiply each matrix one after another. For example:
Frame 1 location with respect to origin coordinate system = [R1 T1]
Frame 2 location with respect to Frame 1 coordinate system = [R2 T2]
Frame 3 location with respect to Frame 2 coordinate system = [R3 T3]
Frame 3 location with respect to origin coordinate system =
[R1 T1] * [R2 T2] * [R3 T3]