Related
In a 2D plane, I have 2 objects (A and B) with 2 coordinates. Their centers are A(xA, yA) and B(xB, yB) (and C(xC, yC)=C(xB, yA) as AC parallel to the OX line and BC is perpendicular on AC). I can manipulate the rotation of an object and I have access to all usual math operations and can use degrees and radians.
I researched but I couldn't find anything explained in detail.
I also tried using the math formula with arccos formula as follows:
I tried to calculate the distance from A to B (AB) using the Pythagoras theorem, then calculate A to C (AC), then calculate cos(angle)=AC/AB, so the final angle to which I would need to rotate object A towards B is arccos(AC/AB).
Problem is this sounds insanely buggy as you can probably get a lot of digits and ruin everything.
So how can I do this? Please explain mathematically. Thanks!
The simplest way to find the angle between two points is to take their arctangent (a.k.a. inverse tangent). You were on the right track with using cosine, but tangent simplifies the process by not requiring the distance between the points to be known.
As such, you'll want to use an atan2 function in your choice of language. The C# Math.Atan2, for example:
double angle = Math.Atan2(B.Y - A.Y, B.X - A.X);
Note: This particular function returns the angle in radians.
Do you want to rotate object A towards B with C like center of the rotation ?
If it's the case you have only to rotate with an angle of 90 degrees because your triangle is special. But if you want to apply a rotation with a specific angle around a specific center you have to use a transformation TRT.
You will find more explanation here.
I'm trying to take a static list of vertices and, using a matrix, bend them about a circle as shown in the image below. I can find the new vertices using basic geometry, but I'm unsure how to implement it with a matrix, or if it is even possible. I believe, calling the center of the circle 'C' and calling the distance from the vertex to C 'd', that x' = Cx + d*cos(theta) and y' = Cy + d*sin(theta). (Cx and Cy are components of C). However, I don't think that that, in itself, can be converted to a matrix.
The Transformation
For context, I'm making a 3D Snake game. The Snake is made up of segments, and each segment should connect to the next. I have a direction and position for each connection between the segments, so I figured that I could build the segment by connecting each part as shown. However, it would be inefficient to calculate the vertices for each segment on each frame. If I could have the vertices statically listed and then transform it in the model-world matrix, that would be faster, and fit into the method I'm currently using. I included a simple drawing of the Snake (ignore the head) below.
The Snake
If it's not possible, are there any alternatives that can be done using a matrix while giving a similar result?
Yes, it is possible.
Skeleton Animation:
You can actually add a series of bones to the object and just apply rotation to the bones equally to get a perfect curve. This is the easiest way to achieve this. However, not necessarily the fastest way for your case.
Just Matrix & Weights:
If the bending is always in this proportion, you have to add weight information to each vertex and then multiply with a matrix with transformation/rotation/scale combination. This will give you better performance compared to Skeleton animation, as every vertex is multiplied using only one matrix and there is no hierarchy.
From an PNG Image containing a transparent region and a colored region, I would like to generate a polygon with N sides (N being configurable) approximating the best possible edge of the image. I want this polygon to be defined by a series of vector.
For example, let consider the following image: + link to plus. I can manage to detect the edges of the image by counting, for each pixel, the number of transparent pixels around it. I get the following matrix:
0000000000000000
0000053335000000
0000030003000000
0000030003000000
0000020002000000
0533210001233500
0300000000000300
0300000000000300
0300000000000300
0533210001233500
0000020002000000
0000030003000000
0000030003000000
0000053335000000
0000000000000000
0000000000000000
I think, based on this matrix, I should be able to get the coordinate of all the corners and therefore get the vectors, but I cannot figure out how. In this case, I would like my program to return:
[7,2]->[11,2]
[11,2]->[11,6]
[11,6]->[15,6]
...
Do any of you have a suggestion or a link to do that?
Ultimately, I would also like the approximate angle other than 90 and 0, but that's really for a second stage.
I think you will find a number of tools in the CV toolkit can be of use to you. You'll do best to leverage these resources rather than roll your own solution.
The two features I think you'd be interested in extracting are edges and corners.
Edges, like what you were going for, can get you toward the outline of the shape. What you're probably not interested in right now are Edge Detection techniques. These will transform your image into a binary image of edge/space. Instead, you'll want to look into the Hough Transform which can give you end points for each of the lines in your image. If you are dealing with well defined, solid, straight lines as you seem to be, this should work quite well. You've tagged your question as Ruby so maybe you can take a look into OpenCV (OpenCV is written in C but there are ruby-opencv and javacv projects to bind). Here is the Hough Transform documentation for OpenCV. One thing you may find, however, is that the Hough transform doesn't give you lines which connect. This depends on the regularity/irregularity of the actual lines in your image. Because of this, you may need to manually connect the end points of the lines into a structure.
Corners, may work quite well for images such as the one you provided. The standard algorithm is Harris corner detection. Similar to the Hough transform, you can use this technique to return the 'most significant' features in the image. This technique is known for giving consistent results, even for different images of the same thing. As such, it's often used for pattern recognition and the like. However, if your images are as simple as the one provided, you may well be able to extract all of the shape's corners in this manner. Getting the shape of the image would then just be a matter of connecting the points in a meaningful way given your predefined N sides.
You should definitely play with both of these feature spaces and see how they work, and you could probably use both in concert for better results.
As an aside, if your image really is color/intensity on transparent you can convert your image to a 'binary image'. Note that this is not just binary data. Instead, it means you are only representing two colors, one represented by 0 and the other represented by 1. Doing so opens up a whole suite of tools that work on grayscale and binary images. For example, the matrix of numbers you calculated manually above is known as a distance transformation and can be done quite easily and efficiently using tools like OpenCV.
The Hough transform is a standard technique for finding lines, polygons, and other shapes given a set of points. It might exactly what you're looking for here. You could use the Hough transform to find all possible line segments in the image, then group nearby line segments together to get a set of polygons approximating the image.
Hope this helps!
In such a simple situation you can do the following three steps: find the centroid of your shape, sort the points of interest based on the angle between the x axis and the line formed by the current point and the centroid, walk through the sorted points.
Given the situation, the x coordinate of the centroid is the sum of the x coordinates of each point of interest divided by the total number of points of interest (respectively for the y coord of centroid). To calculate the angles, it is a simple matter of using atan2 available in virtually any language. Your points of interest are those that are either presented as 1 or 5, otherwise it is not a corner (based on your input).
Do not be fooled that Hough will solve your question, i.e., it won't give the sorted coordinates you are after. It is also an expensive method. Also, given your matrix, you already have such perfect information that no other method will beat (the problem, of course, is repeating such good result as you presented -- in those occasions, Hough might prove useful).
My Ruby is quite bad, so take the following code as a guideline to your problem:
include Math
data = ["0000000000000000",
"0000053335000000",
"0000030003000000",
"0000030003000000",
"0000020002000000",
"0533210001233500",
"0300000000000300",
"0300000000000300",
"0300000000000300",
"0533210001233500",
"0000020002000000",
"0000030003000000",
"0000030003000000",
"0000053335000000",
"0000000000000000",
"0000000000000000"]
corner_x = []
corner_y = []
data.each_with_index{|line, i|
line.split(//).each_with_index{|col, j|
if col == "1" || col == "5"
# Cartesian coords.
corner_x.push(j + 1)
corner_y.push(data.length - i)
end
}
}
centroid_y = corner_y.reduce(:+)/corner_y.length.to_f
centroid_x = corner_x.reduce(:+)/corner_x.length.to_f
corner = []
corner_x.zip(corner_y).each{|c|
dy = c[1] - centroid_y
dx = c[0] - centroid_x
theta = Math.atan2(dy, dx)
corner.push([theta, c])
}
corner.sort!
corner.each_cons(2) {|c|
puts "%s->%s" % [c[0][1].inspect, c[1][1].inspect]
}
This results in:
[2, 7]->[6, 7]
[6, 7]->[6, 3]
[6, 3]->[10, 3]
[10, 3]->[10, 7]
[10, 7]->[14, 7]
[14, 7]->[14, 11]
[14, 11]->[10, 11]
[10, 11]->[10, 15]
[10, 15]->[6, 15]
[6, 15]->[6, 11]
[6, 11]->[2, 11]
Which are your vertices in anti-clock-wise order starting with the bottom leftmost point (in cartesian coords starting in (1, 1) at left-bottom most position).
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Circle line collision detection
I'm trying to do collision testing between a finite line segment, and an arc segment. I have a collision test which does line segment vs. line segment, so I was going to approximate these arc segments with line segments and run my existing test.
The data I have defining the arc segment(s) are three points. Two of which are endpoints that lie on the circumference of a circle, and the third point is the center of that circle.
So far this is what I've got:
Let (a,b) be the center point of the circle, let 'r' be the radius of the circle, and (x1, y1), (x2, y2) be the endpoints of the arc segment which lies on the circumference of the circle.
The following parametric equations give the x, and y locations of an arc. 't' is the parametric variable.
x = a + r * cos(t)
y = b + r * sin(t)
To create the line segments from the arc, I wanted to walk the arc for some fixed ratio of 't' creating line segments along the way, until I've reached the end of the arc. To do this I figured I'd have to find the start and end angle. I'd start walking the arc from the start angle, and end at the end angle. Since I know the start and end points I figured I could use these equations to solve for these angles. The following are my equations for this:
t = arccos((x-a)/r)
or
t = acrcsin((y-b)/r)
The problem I'm having is that the range of values returned by these functions (http://en.wikipedia.org/wiki/Inverse_trigonometric_function) is limited, so there is a high probability that the angle I'm looking for will not be returned because these functions are multivalued: arcsin(0) = 0, but also arcsin(0) = π, arcsin(0) = 2π, etc
How do I get the exact angle(s) I'm looking for? Or, can you think of a better/different way of achieving my goal?
Take a look at the atan2 function, which should exist in whatever programming language or math library you're using. It takes two arguments, the x and y coordinates of a point (for you: (x-a)/r and (y-b)/r) and returns the angle in the range -π to +π.
At least IMO, you're going at this the wrong way. A line has an equation y=mx+b. A circle has an equation x2 + y2 = r2. You're looking for a point at which the x and y of the circle equals the x and y of the line. You can do that by substituting the mx+b equation for the line for the y equation in the circle, and then solve using the quadratic equation.
The equations involved do get a bit long, but quite a few web pages (e.g., http://www.sonoma.edu/users/w/wilsonst/papers/geometry/circles/default.html) have them, at which point it's simple matter of implementing the equations as a couple of functions and plugging in the values for your particular circle/line. A solution based on these equations complete avoids the ambiguity from using an arg tangent.
Your pseudo-code looks a lot like Python. If you don't mind using Python I would recommend the Shapely Library. If you just want the algorithm, check the source.
Shapely objects have the 'simplify' and 'intersection' methods.
I am trying to implement Inverse Kinematics on a 2D arm(made up of three sticks with joints). I am able to rotate the lowest arm to the desired position. Now, I have some questions:
How can I make the upper arm move alongwith the third so the end point of the arm reaches the desired point. Do I need to use the rotation matrices for both and if yes can someone give me some example or an help and is there any other possibl;e way to do this without rotation matrices???
The lowest arm only moves in one direction. I tried google it, they are saying that cross product of two vectors give the direction for the arm but this is for 3D. I am using 2D and cross product of two 2D vectors give a scalar. So, how can I determine its direction???
Plz guys any help would be appreciated....
Thanks in advance
Vikram
I'll give it a shot, but since my Robotics are two decades in the past, take it with a grain of salt.
The way I learned it, every joint was described by its own rotation matrix, defined relative to its current position and orientation. The coordinate of the whole arm's endpoint was then calculated by combining the rotation matrices together.
This achieved exactly the effect you are looking for: you could move only one joint (change its orientation), and all the other joints followed automatically.
You won't have much chance in getting around matrices here - in fact, if you use homogeneous coordinates, all joint calculations (rotations as well as translations) can be modeled with matrix multiplications. The advantage is that the full arm position can then be described with a single matrix (plus the arm's origin).
With this transformation matrix, you can tackle the inverse kinematic problem: since the transformation matrix' elements will depend on the angles of the joints, you can treat the whole calculation 'endpoint = startpoint x transformation' as a system of equations, and with startpoint and endpoint known, you can solve this system to determine the unknown angles. The difficulty herein lies that the equation may not be solvable, or that there are multiple solutions.
I don't quite understand your second question, though - what are you looking for?
Instead of a rotation matrix, the rotation can be represented by its angle or by a complex number of the unit circle, but it's the same thing really. More importantly, you need a representation T of rigid body transformations, so that you can write stuff like t1 * t2 * t3 to compute the position and orientation of the third link.
Use atan2 to compute the angle between the vectors.
As the following Python example shows, those two things are enough to build a small IK solver.
from gameobjects.vector2 import Vector2 as V
from matrix33 import Matrix33 as T
from math import sin, cos, atan2, pi
import random
The gameobjects library does not have 2D transformations, so you have to write matrix33 yourself. Its interface is just like gameobjects.matrix44.
Define the forward kinematics function for the transformation from one joint to the next. We assume the joint rotates by angle and is followed by a fixed transformation joint:
def fk_joint(joint, angle): return T.rotation(angle) * joint
The transformation of the tool is tool == fk(joints, q) where joints are the fixed transformations and q are the joint angles:
def fk(joints, q):
prev = T.identity()
for i, joint in enumerate(joints):
prev = prev * fk_joint(joint, q[i])
return prev
If the base of the arm has an offset, replace the T.identity() transformation.
The OP is solving the IK problem for position by cyclic coordinate descent. The idea is to move the tool closer to the goal position by adjusting one joint variable at a time. Let q be the angle of a joint and prev be the transformation of the base of the joint. The joint should be rotated by the angle between the vectors to the tool and goal positions:
def ccd_step(q, prev, tool, goal):
a = tool.get_position() - prev.get_position()
b = goal - prev.get_position()
return q + atan2(b.get_y(), b.get_x()) - atan2(a.get_y(), a.get_x())
Traverse the joints and update the tool configuration for every change of a joint value:
def ccd_sweep(joints, tool, q, goal):
prev = T.identity()
for i, joint in enumerate(joints):
next = prev * fk_joint(joint, q[i])
q[i] = ccd_step(q[i], prev, tool, goal)
prev = prev * fk_joint(joint, q[i])
tool = prev * next.get_inverse() * tool
return prev
Note that fk() and ccd_sweep() are the same for 3D; you just have to rewrite fk_joint() and ccd_step().
Construct an arm with n identical links and run cnt iterations of the CCD sweep, starting from a random arm configuration q:
def ccd_demo(n, cnt):
q = [random.uniform(-pi, pi) for i in range(n)]
joints = [T.translation(0, 1)] * n
tool = fk(joints, q)
goal = V(0.9, 0.75) # Some arbitrary goal.
print "i Error"
for i in range(cnt):
tool = ccd_sweep(joints, tool, q, goal)
error = (tool.get_position() - goal).get_length()
print "%d %e" % (i, error)
We can try out the solver and compare the rate of convergence for different numbers of links:
>>> ccd_demo(3, 7)
i Error
0 1.671521e-03
1 8.849190e-05
2 4.704854e-06
3 2.500868e-07
4 1.329354e-08
5 7.066271e-10
6 3.756145e-11
>>> ccd_demo(20, 7)
i Error
0 1.504538e-01
1 1.189107e-04
2 8.508951e-08
3 6.089372e-11
4 4.485040e-14
5 2.601336e-15
6 2.504777e-15
In robotics we most often use DH parameters for the forward and reverse kinematics. Wikipedia has a nice introduction.
The DH (Denavit-Hartenberg) notation is part of the solution. It helps you collect a succinct set of values that describe the mechanics of your robot such as link length and joint type.
From there it becomes easier to calculate forward kinematics. The first think you have to understand is how to translate a coordinate frame from one place to another coordinate frame. For example, given your robot (or the DH table of it), what is the set of rotations and translations you have to apply to one coordinate frame (the world for example) to know the location of a point (or vector) in the robot's wrist coordinate frame.
As you may already know, homogeneous transform matrices are very useful for such transformations. They are 4x4 matrices that encapsulate rotation and translation. Another very useful property of those matrices is that if you have two coordinate frames linked and defined by some rotation and translation, if you multiply the two matrices together, then you just need to multiply your transformation target by the product of that multiplication.
So the DH table will help you build that matrix.
Inverse kinematics is a bit more complicated though and depends on your application. The complication arises from having multiple solutions for the same problem. The greater the number of DOF, the greater the number of solutions.
Think about your arm. Pinch something solid around you. You can move your arm to several locations in the space and still keep your pinching vector unchanged. Solving the inverse kinematics problem involves deciding which solution to choose as well.