I don't know how to find the third point that I have said.
However, I try to write code write this:
float extraX; // x of the third point
float extraY; // y of the third point
float extraZ; // z of the third point
void CalculateExtraPoint(float x1, float y1, float z1, float x2, float y2, float z2){
float range = extraRange; //range from the first point to third point
float d_x = x1-x2;
float d_y = y1-y2;
float d_z = z1-z2;
distance1_2 = sqrt(pow(d_x,2)+pow(d_y,2)+pow(d_z,2));
float temp = (range/distance1_2)+1;
extraX = x2 + (temp*d_x);
extraY = y2 + (temp*d_y);
extraZ = z2 + (temp*d_z);
}
It come from vector equation, r=(x2,y2,z2) + (lambda)[x1-x2,y1-y2,z1-z2]. r is any point.
Is it correct? Thanks in advance.
Yes, it is correct.
Slightly simpler, more convenient variant. Here it is more clear that we consider range from the first point:
float temp = range/distance1_2;
extraX = x1 + (temp*d_x);
extraY = y1 + (temp*d_y);
extraZ = z1 + (temp*d_z);
My first post on Stack Overflow, be gentle. I wrote a code to follow the position on the x,y plane of a particle of mass M on a potential V(r) described by a four-dimensional system of equations of motion
M(dv/dt)=-grad V(r), dr/dt=v,
Which are solved by using the Runge Kutta 4th Order method, where r=(x,y) and v=(vx,vy); now the state of the particle is defined by x, y and the angle theta between the vector v and the positive x-axis where the magnitude of the velocity is given by
|v|=sqrt(2(E-V(r))/M)
where E is the energy in the plane and the potential V(r) is given by
V(r)=x^2y^2exp[-(x^2+y^2)],
now here is the code I made for the initial values
x(0)=3,
y(0)=0.3905,
vx(0)=0,
vy(0)=-sqrt(2*(E-V(x(0), y(0)))),
where E=0.260*(1/exp(2))
// RK4
#include <iostream>
#include <cmath>
// constant global variables
const double M = 1.0;
const double DeltaT = 1.0;
// function declaration
double f0(double t, double y0, double y1, double y2, double y3); // derivative of y0
double f1(double t, double y0, double y1, double y2, double y3); // derivative of y1
double f2(double t, double y0, double y1, double y2, double y3); // derivative of y2
double f3(double t, double y0, double y1, double y2, double y3); // derivative of y3
void rk4(double t, double h, double &y0, double &y1, double &y2, double &y3); // method of runge kutta 4th order
double f(double y0, double y1); //function to use
int main(void)
{
double y0, y1, y2, y3, time, E, Em;
Em = (1.0/(exp(2.0)));
E = 0.260*Em;
y0 = 3.0; //x
y1 = 0.3905; //y
y2 = 0.0; //vx
y3 = -(std::sqrt((2.0*(E-f(3.0, 0.0)))/M)); //vy
for(time = 0.0; time <= 400.0; time += DeltaT)
{
std::cout << time << "\t\t" << y0 << "\t\t" << y1 << "\t\t" << y2 << "\t\t" << y3 << std::endl;
rk4(time, DeltaT, y0, y1, y2, y3);
}
return 0;
}
double f(double y0, double y1)
{
return y0*y0*y1*y1*(exp(-(y0*y0)-(y1*y1)));
}
double f0(double t, double y0, double y1, double y2, double y3)
{
return y2;
}
double f1(double t, double y0, double y1, double y2, double y3)
{
return y3;
}
double f2(double t, double y0, double y1, double y2, double y3)
{
return 2*y0*((y0*y0)-1)*(y1*y1)*(exp(-(y0*y0)-(y1*y1)))/M;
}
double f3(double t, double y0, double y1, double y2, double y3)
{
return 2*(y0*y0)*y1*((y1*y1)-1)*(exp(-(y0*y0)-(y1*y1)))/M;
}
void rk4(double t, double h, double &y0, double &y1, double &y2, double &y3) // method of runge kutta 4th order
{
double k10, k11, k12, k13, k20, k21, k22, k23, k30, k31, k32, k33, k40, k41, k42, k43;
k10 = h*f0(t, y0, y1, y2, y3);
k11 = h*f1(t, y0, y1, y2, y3);
k12 = h*f2(t, y0, y1, y2, y3);
k13 = h*f3(t, y0, y1, y2, y3);
k20 = h*f0(t+h/2, y0 + k10/2, y1 + k11/2, y2 + k12/2, y3 + k13/2);
k21 = h*f1(t+h/2, y0 + k10/2, y1 + k11/2, y2 + k12/2, y3 + k13/2);
k22 = h*f2(t+h/2, y0 + k10/2, y1 + k11/2, y2 + k12/2, y3 + k13/2);
k23 = h*f3(t+h/2, y0 + k10/2, y1 + k11/2, y2 + k12/2, y3 + k13/2);
k30 = h*f0(t+h/2, y0 + k20/2, y1 + k21/2, y2 + k22/2, y3 + k23/2);
k31 = h*f1(t+h/2, y0 + k20/2, y1 + k21/2, y2 + k22/2, y3 + k23/2);
k32 = h*f2(t+h/2, y0 + k20/2, y1 + k21/2, y2 + k22/2, y3 + k23/2);
k33 = h*f3(t+h/2, y0 + k20/2, y1 + k21/2, y2 + k22/2, y3 + k23/2);
k40 = h*f0(t + h, y0 + k30, y1 + k31, y2 + k32, y3 + k33);
k41 = h*f1(t + h, y0 + k30, y1 + k31, y2 + k32, y3 + k33);
k42 = h*f2(t + h, y0 + k30, y1 + k31, y2 + k32, y3 + k33);
k43 = h*f3(t + h, y0 + k30, y1 + k31, y2 + k32, y3 + k33);
y0 = y0 + (1.0/6.0)*(k10 + 2*k20 + 2*k30 + k40);
y1 = y1 + (1.0/6.0)*(k11 + 2*k21 + 2*k31 + k41);
y2 = y2 + (1.0/6.0)*(k12 + 2*k22 + 2*k32 + k42);
y3 = y3 + (1.0/6.0)*(k13 + 2*k23 + 2*k33 + k43);
}
The problem here is that when I run the code with the initial conditions given, the values do not match with what it is supposed to according to the case given by the problem
what the graphic should look like with the initial conditions given
now, I think i got right the implementation of the method but i do not know why the graphs do not match because when i run the code the particle goes away from the potential.
Any help will be appreciated.
The paths look chaotic with sharp turns. This requires an adaptive step size, you will need to implement some step size control. Either by comparing each step with two steps of half the step length or by using a method with embedded methods of higher order like Fehlberg or Dormand-Price.
More immediate errors:
define Em as V(1,1) to avoid unnecessary magic numbers
your initial position is, if you read the chart right,
y0 = 3.0;
y1 = -0.3905+k*0.0010;
with k=-1,0,1, note the minus sign.
your initial velocity is horizontal, and the kinetic energy is computed to complement the potential energy at that position. Thus
y2 = v0 = -(std::sqrt((2.0*(E-V(y0, y1)))/M));
y3 = v1 = 0.0;
With these changes and an adaptive solver I get (in python) the plot
import numpy as np
from scipy.integrate import odeint
import matplotlib.pyplot as plt
# capture the structure of the potential
f = lambda r : r*np.exp(-r);
df = lambda r : (1-r)*np.exp(-r);
V = lambda y1,y2 : f(y1*y1)*f(y2*y2);
M= 1.0
Em = V(1.0,1.0);
E = 0.260*Em;
def prime(t,y):
x1,x2,v1,v2 = y
dV_dx1 = 2*x1*df(x1*x1)*f(x2*x2);
dV_dx2 = 2*x2*df(x2*x2)*f(x1*x1);
return [ v1, v2, -dV_dx1/M, -dV_dx2/M ];
# prepare and draw the contour plot
X1,X0=np.ogrid[-4:3:100j,-4:3:100j]
plt.contour(X0.ravel(), X1.ravel(), V(X0,X1), Em*np.arange(0,1,0.1), colors='k', linewidths=0.3)
# display grid and fix the coordinate ranges
plt.grid();plt.autoscale(False)
for k in range(-1,1+1):
x01 = 3.0;
x02 = b = -0.3905 + 0.0010*k;
v01 = -( ( E-V(x01,x02) )*2.0/M )**0.5;
v02 = 0.0;
print "initial position (%.4f, %.4f), initial velocity (%.4f, %.4f)" % ( x01, x02, v01, v02 )
t0 = 0.0
tf = 50.0
tol = 1e-10
y0 = [ x01, x02, v01, v02 ]
t = np.linspace(t0,tf,501); y = odeint(lambda y,t: prime(t,y) , y0, t)
plt.plot(y[:,0], y[:,1], label="b=%.4f" % b, linewidth=2)
plt.legend(loc='best')
plt.show()
I have the Razer Hydra SDK here, and I want to transform the rotation matrix I get from the hardware, into pitch, yaw and roll.
The documentation states:
rot_mat - A 3x3 matrix describing the rotation of the controller.
My code is currently:
roll = atan2(rot_mat[2][0], rot_mat[2][1]);
pitch = acos(rot_mat[2][2]);
yaw = -atan2(rot_mat[0][2], rot_mat[1][2]);
Yet this seems to give me wrong results.
Would somebody know how I can easily translate this, and what I am doing wrong?
You can calculate pitch, roll and yaw like this.
Based on that:
#include <array>
#include <limits>
typedef std::array<float, 3> float3;
typedef std::array<float3, 3> float3x3;
const float PI = 3.14159265358979323846264f;
bool closeEnough(const float& a, const float& b, const float& epsilon = std::numeric_limits<float>::epsilon()) {
return (epsilon > std::abs(a - b));
}
float3 eulerAngles(const float3x3& R) {
//check for gimbal lock
if (closeEnough(R[0][2], -1.0f)) {
float x = 0; //gimbal lock, value of x doesn't matter
float y = PI / 2;
float z = x + atan2(R[1][0], R[2][0]);
return { x, y, z };
} else if (closeEnough(R[0][2], 1.0f)) {
float x = 0;
float y = -PI / 2;
float z = -x + atan2(-R[1][0], -R[2][0]);
return { x, y, z };
} else { //two solutions exist
float x1 = -asin(R[0][2]);
float x2 = PI - x1;
float y1 = atan2(R[1][2] / cos(x1), R[2][2] / cos(x1));
float y2 = atan2(R[1][2] / cos(x2), R[2][2] / cos(x2));
float z1 = atan2(R[0][1] / cos(x1), R[0][0] / cos(x1));
float z2 = atan2(R[0][1] / cos(x2), R[0][0] / cos(x2));
//choose one solution to return
//for example the "shortest" rotation
if ((std::abs(x1) + std::abs(y1) + std::abs(z1)) <= (std::abs(x2) + std::abs(y2) + std::abs(z2))) {
return { x1, y1, z1 };
} else {
return { x2, y2, z2 };
}
}
}
If you still get wrong angles with this, you may be using a row-major matrix as opposed to column-major, or vice versa - in that case you'll need to flip all R[i][j] instances to R[j][i].
Depending on the coordinate system used (left handed, right handed) x,y,z may not correspond to the same axes, but once you start getting the right numbers, figuring out which axis is which should be easy :)
Alternatively, to convert from a Quaternion to euler angles like shown here:
float3 eulerAngles(float q0, float q1, float q2, float q3)
{
return
{
atan2(2 * (q0*q1 + q2*q3), 1 - 2 * (q1*q1 + q2*q2)),
asin( 2 * (q0*q2 - q3*q1)),
atan2(2 * (q0*q3 + q1*q2), 1 - 2 * (q2*q2 + q3*q3))
};
}
This is the an formula that will do, keep in mind that the higher the precision the more variables in the rotation matrix are important:
roll = atan2(rot_mat[2][1], rot_mat[2][2]);
pitch = asin(rot_mat[2][0]);
yaw = -atan2(rot_mat[1][0], rot_mat[0][0]);
http://nghiaho.com/?page_id=846
This is also used in the point cloud library, function : pcl::getEulerAngles
I have a small question about 3D.
What follows is an example of my problem.
I have two points:
A: 12 4 5
B: 6 8 -10
I have another point:
C: 5 6 7
I need to transform(?) point C so that the angle ABC is 48 degrees.
How do I do this? I would appreciate if someone can help me with the formulas or maybe even make the above example into a working one.
Another way to put it: How do I transform C.x, C.y, and C.z so that the angle ABC is 48 degrees?
I would really appreciate some help on this as I am stuck at the moment.
Side note:
I already implemented a method for finding the angle:
float Angle( float x1, float y1, float z1,
float x2, float y2, float z2 )
{
float x, y, z;
CrossProduct( x1, y1, z1, x2, y2, z2, &x, &y, &z );
float result = atan2 ( L2Norm( x, y, z ),
DotProduct( x1, y1, z1, x2, y2, z2 ) );
return result;
}
You use it:
Angle( B.x - A.x, B.y - A.y, B.z - A.z,
C.x - B.x, C.y - B.y, C.z - B.z );
A------C
|
c'' | c'
B
As three point in 3D define a plane, there are only 2 possible candidates for a transform C-->c' or C-->c'' at that plane.
c' would be then c' = A+t*(B-A) + u*(C-A) with constraint Normalize(c'-A) dot Normalize(B-A) == cos (48 / 180 * pi).
I'd first suggest normalizing D=(B-A), after that:
D dot D+u*(C-A) = 1 * |D+u(C-A)| * cos (48 degrees)
Dx*(Dx+u*(Cx-Ax))+ Dy*(Dy+u*(Cy-Ay))+Dz*(Dz+u*(Cz-Az)) ==
0.669 * sqrt ((Dx+u*(Cx-Ax))^2+(Dy+u*(Cy-Ay))^2+(Dz+u*(Cz-Az))^2)
This is of form a+u*b == 0.669*sqrt(c+du+e*u^2), which will be simplified to a second degree polynomial in u by squaring both sides.
The track of point C is actually a cone, you can imagine, B is the vertex and line AB is the central line of the cone, means the 3D cone is symmetric on AB.
Looking for the quickest way to calculate a point that lies on a line
a given distance away from the end point of the line:
void calculate_line_point(int x1, int y1, int x2, int y2, int distance, int *px, int *py)
{
//calculate a point on the line x1-y1 to x2-y2 that is distance from x2-y2
*px = ???
*py = ???
}
Thanks for the responses, no this is not homework, just some hacking out of
my normal area of expertise.
This is the function suggested below. It's not close to working. If I
calculate points every 5 degrees on the upper right 90 degree portion of
a circle as starting points and call the function below with the center of the circle as x2,y2 with a distance of 4 the end points are totally wrong. They lie below and to the right of the center and the length is as long as the center point. Anyone have any suggestions?
void calculate_line_point(int x1, int y1, int x2, int y2, int distance)
{
//calculate a point on the line x1-y1 to x2-y2 that is distance from x2-y2
double vx = x2 - x1; // x vector
double vy = y2 - y1; // y vector
double mag = sqrt(vx*vx + vy*vy); // length
vx /= mag;
vy /= mag;
// calculate the new vector, which is x2y2 + vxvy * (mag + distance).
px = (int) ( (double) x2 + vx * (mag + (double)distance) );
py = (int) ( (double) y2 + vy * (mag + (double)distance) );
}
I've found this solution on stackoverflow but don't understand it completely, can anyone clarify?
I think this belongs on MathOverflow, but I'll answer since this is your first post.
First you calculate the vector from x1y1 to x2y2:
float vx = x2 - x1;
float vy = y2 - y1;
Then calculate the length:
float mag = sqrt(vx*vx + vy*vy);
Normalize the vector to unit length:
vx /= mag;
vy /= mag;
Finally calculate the new vector, which is x2y2 + vxvy * (mag + distance).
*px = (int)((float)x1 + vx * (mag + distance));
*py = (int)((float)y1 + vy * (mag + distance));
You can omit some of the calculations multiplying with distance / mag instead.
These equations are wrong:
px = (int) ( (double) x2 + vx * (mag + (double)distance) );
py = (int) ( (double) y2 + vy * (mag + (double)distance) );
The correct equations are:
px = (int) ( (double) x2 + vx * (double)distance );
py = (int) ( (double) y2 + vy * (double)distance );
Tom