I have a map of individual trees from a forest stored as x,y points in a matrix. I call it fixedPositions. It's cartesian and (0,0) is the origin.
Given a velocity and a heading, i.e. .5 m/s and 60 degrees (2 o'clock equivalent on a watch), how do I rotate the x,y points, so that the new origin is centered at (.5cos(60),.5sin(60)) and 60 degrees is now at the top of the screen?
Then if I were to give you another heading and speed, i.e. 0 degrees and 2m/s, it should calculate it from the last point, not the original fixedPositions origin.
I've wasted my day trying to figure this out. I wish I took matrix algebra but I'm at a loss.
I tried doing cos(30) and even those wouldn't compute correctly, which after an hour I realize were in radians.
I'd try the following: In your object, you already have a property heading. Now you add another property, currentPosition (an maybe rename them to heading_robot and currentPos_robot). heading as well as currentPosition should always be relative to the original coordinate system
Then you add a new method, updatePosition that takes (newHeading, distance) as input. This method will update both heading and currentPosition, by first adding the angle in newHeading to the angle in heading, after which you update currentPosition by adding [distance*cos(heading),distance*sin(heading)] (check for signs of sin/cos here!) to the old value of currentPosition.
Finally, to get the view of the landscape (i.e. apparentPositions), you run bsxfun(#minus,fixedPositions,currentPosition) to move the origin to where the robot is at this moment, and then you multiply with the 2D rotation matrix using the angle stored in heading.
You just first translate the coordinates (-0.5cos(60),-0.5sin(60)) to take the origin to your target point.
Then rotate by multiplying the coordinates by a rotation matrix.
Of course, most programming languages use radians as angle units, so that instead of 60 you must enter 60 * PI / 180
Related
So I want to have my projectiles travel to a targeted position with in a certain amount of time and have a curve trajectory with a max height. I have watchh a couple youtube tutorials but they're just simply not want I need right now is there a way for me to do this ?
I followed this tutorial as first but I can't increase the speed and reduce the time and the height to my liking:
https://www.youtube.com/watch?v=Qxs3GrhcZI8
You have a targeted position implies that the distance between the user and the target is r (say). Now, you want the projectile to hit the target in a certain time t. Let's say the projectile was thrown at a velocity v. Below are the calculations that yield the result of how much velocity and angle of projection are required to achieve the hit in the given time t
The question says
have a curve trajectory with a max height.
Theoretically, the maximum height is achieved when the angle of projection is 90 degrees with respect to the ground and the cosine of 90 is 0. Substituting the value of cos(theta) in the resultant equation results in the value of velocity being infinity, which is practically impossible.
Hence, with the given range and time of flight, two variables, the velocity, and angle of projection can be configured. If the maximum height that you want to achieve is specified, the angle of projection is calculated accordingly.
Unity Slerp will be a good fit for you. You can specify the start, end point and also
control the time. You won't be able to control the height as its dependent on the Vectors.
Here is the Link to Unity Docs
https://docs.unity3d.com/ScriptReference/Vector3.Slerp.html
I've got a 3d sphere which I've been able to plot a point on using longitude and latitude thanks to some work of another developer I've found online. I think I understand what its doing.
What I need to do now is rotate my planet so the point is always at the top most point (ie the north pole) but I'm not sure how to do this. I'm probably missing some important fundamentals here so I'm hoping the answer can assist in my future learning.
Here's an image showing what I have - The blue line is a line coming from the longitude and latitude I have plotted and I need to rotate the planet so that line is basically pointing directly upwards.
https://ibb.co/2y24FxS
If anyone is able to advise it'd be very much appreciated.
If I'm not mistaken, Unity uses a coordinate system where the y-axis points up.
If the point on your sphere was in the xy-plane, you'd just have to determine the angle between the radius-vector (starts in the center of the sphere, ends on the point in question) and the y-axis, and than rotate by that amount around the z-axis, so that the radius vector becomes vertical. But your point is at an arbitrary location in 3D space - see the image below. So one way to go about it is to first bring the point to the xy-plane, then continue from there.
Calculate the radius vector, which is just r = x-sphereCenter. Make a copy of it, set y to zero, so that you have (x, 0, z) - which is just the projection of the vector r on the horizontal xz-plane - let's call the copy rXZ.
Determine the signed angle between the x-axis and rXZ (use Vector3.SignedAngle(xAxis, rXZ, yAxis), see docs), and create a rotation matrix M1 that rotates the sphere in the opposite direction around the vertical (negate the angle). This should place your point in the xy-plane.
Now determine the angle between r and the y-axis (Vector3.SignedAngle(r, yAxis, zAxis)), and create a new rotation matrix M2 that rotates by that angle around the zAxis. (I think for this second one, the simpler Vector3.Angle will work as well.)
So, what you want now is to combine the two matrices (by multiplying them) into a single transform (I'm assuming this is a transformation in the local coordinate system of the sphere, where (0, 0, 0) is the sphere's center). If I'm not mistaken, Unity uses column-major matrices, so the multiplication order should be M = M2 * M1 (the rightmost matrix is applied first).
Reorient your globe using M as a local transform, and it should bring your point to the top. You can also create M3 = M1.inverse, and then do M = M3 * M2 * M1, to preserve the original angular offset from the xy-plane.
Check for edge cases, such as r already being vertical (pointing straight up, or straight down).
Background: I am creating an AR treasure hunt app. It is simple, it has a locator that tells you where the treasure is relative to you. I have the camera being the origin and the treasure being an object in AR world.
Question: I would like to rotate my arrow according to where in space the treasure is at. but in 2d. Basically, I would ignore the relative forward plane that is camera.forward.
Example: If the camera rotation is default, the angle can be calculated as atan2(dy,dx). If the camera is looking straight down, the angle is atan2(dz,dx).
What I have tried:
Quaternion lookRot = Quaternion.LookRotation(target.transform.position - origin.transform.position);
Quaternion relativeRot = Quaternion.Inverse(origin.transform.rotation) * lookRot;
Relative rotation is correct in 3d space but I would like to convert that into 2d ignoring the camera.forward plane. So even if the treasure is in front or behind the camera, it should not change the angle.
Okay so I’m hoping this makes sense. You’re going to need some sort of if statement to determine if your character is looking along the x, y or z plane. Hopefully the diagram is clear as to what those parameters are but if not. To be looking in the “x” plane for example, the y rotation would have to be between 45° and -45° or 135° and -135° AND the z rotation would have to be between 45° and -45° or between 135° and -135°.
Essentially what you’ve got is a sphere split into six parts, two parts for each plane along which the character could look. Once you’ve determined which plane the character is looking in you can determine the direction by finding the difference in position between the character and the treasure along the two planes the character isn’t looking along. Then use trig to calculate the angle
Replying to an old thread, but I was struggling with the same problem and found a relatively simple solution:
Project the position of the target (relative to the origin) on a plane defined by the forward vector of the camera. Then just rotate towards the projected point:
Vector3 diff = target.transform.position - origin.transform.position;
Vector3 projected = Vector3.ProjectOnPlane(diff, Camera.main.transform.forward);
origin.transform.rotation = Quaternion.LookRotation(projected);
Calculate the difference in x and y coordinates simply by subtracting transform.x for one object by transform.x of another object and the same process for y coordinates and then use Mathf.atan(difference in y/difference in x) to calculate the angle. Then put the z rotation to this angle and assign the x and y rotation to what they already were.
Turns out there is a very simple way to get relative X and Y of the target.
Vector2 ExtractRelativeXY(Transform origin, Transform target) {
// Get the absolute look rotation from origin to target.
Quaternion lookRot = Quaternion.LookRotation(target.transform.position - origin.transform.position);
// Create a relative look rotation with respect to origin's forward.
Quaternion relativeRot = Quaternion.Inverse(origin.transform.rotation) * lookRot;
// Obtain Matrix 4x4 from the rotation.
Matrix4x4 m = Matrix4x4.Rotate(relativeRot);
// Get the 3rd column (which is the forward vector of the rotation).
Vector4 mForward = m.GetColumn(2);
// Simply extract the x and y.
return new Vector2(mForward.x, mForward.y);
}
Once obtained x and y, turn it into angle using angle = atan2(y,x) as suggested by both MBo and Tom.
This works because of the matrix components of the quaternion can be demonstrated in multiple vectors. Better illustration is found here https://stackoverflow.com/a/26724912.
I'm trying to make a character jump between two points. The two points are varying distances apart, and at different heights.
I have the character moving from point to point using Vector3.MoveTowards in a IEnumerator. But how can I make modify the Y axis so that the character moves in a curved path to appear as if jumping?
The character needs to land exactly at each point, so I cannot use physics.
Thanks! :-)
Image Example
Extra bonus points if you can adjust where you want the peak of the jump to occur (so the curve isn't perfectly circular, but more like an arc) E.g. so that the peak of the jump is closer to destination.
Looking at your given image, I would suggest using a projectile motion's equation to calculate the path between the source and destination in a given time with a given start velocity(Vo) and given angle (theta).
In case you are not familiar with projectile equation, have a look at here:
https://en.wikipedia.org/wiki/Projectile_motion
In the Displacement section you'll find 2 equations like this:
x = Vo * T * cos(theta)
y = Vo * T * sin(theta) - 0.5 * g * pow(T,2)
So, in Update function don't move the object directly towards the target, rather take temporary targets along the projectile motion, which you can calculate using the above two equations. You can then use,
Vector3.MoveTowards(curPosition,new Vector3(x,y,0),step);
Considering, the z value is 0.
I have two moving objects with position and orientation data (Euler Angles, Quaternions) relative to ECI coordinate frame. I would like to calculate AZ/EL from what I'm guessing is the "body frame" of the first object. I have attempted to convert both objects into the body frame through rotation matrices (X-Y-Z and Z-Y-X rotation sequence) and calculate a target vector AZ/EL this way but have not had success. I've also tried to get body frame positions and calculate the body axis/angles and convert back to Eulers (relative to body frame). I'm never sure how the coordinate system axes I'm supposedly creating are aligned along my object.
I have found a couple other questions like this answered with Quaternion solutions so that may be the best path to take, however my Quaternion background is weak at best and I fail to see how the computations given result in a target vector.
Any advice would be much appreciated and I'm happy to share my progress/experiences going forward.
get the current NEH transform matrix for the moving object
you must know position and at least two directions from North,East,Height(Up or Altitude) of the moving object otherwise is your problem unsolvable no matter what. This matrix/frame is called NEH (X=North,Y=East,Z=Height) or sometimes also ENU (X=East,Y=North,Z=Up). Look here transform matrix anatomy and here Earth's NEH construction and change the position and radius to match your moving object.
convert point P0 from GCS (global coordinate system) to NEH
simply: P1=Inverse(NEH)*P0 where P1 is now in NEH LCS (Local coordinate system). Both P0,P1 are in homogenous coordinates { x,y,z,w=1 } to allow multiplications with 4x4 matrix so you can compute azimut and elevation directly from it:
Azimut=atanxy(P1.x,P1.y);
Elevation=atan(P1.z/sqrt((P1.x*P1.x)+(P1.y*P1.y)));
where atanxy is mine atan2 (4 quadrant atan) first is dx then dy. I think atan2 in matlab has it in reverse.
[Notes]
Always visually check all frames (especially NEH). Just draw the 3 axises as lines of some length to validate if the result is correct. It should look like on image, just different color for each axis. You can move to next point only if NEH is OK !!!
Check atan2/atanxy operands order and also check goniometric functions units (rad,deg) to avoid confusions.