I am trying to calculate the moment of inertia around the center of mass of a 2D capsule which I divided into a rectangle and two semicircles. C is the center of mass and the axis of rotation passes through this point.
I know that the moment of inertia for a semicircle around an axis perpendicular to its plane passing through the center of its full circle is 1/2 MR² where M is the mass of the semicircle and R is the radius (correct me if I am wrong). Here, for the two semicircles, it is points A and B. For a rectangle, the moment of inertia passing through its centroid is 1/12 M(L² + W²) where M is mass of the rectangle and L and W are its dimensions. Here, the centroid is the same as center of mass C.
According to the Parallel Axis Theorem, the moment of inertia around an axis parallel to the existing axis is the existing moment of inertia added to the mass multiplied with the squared perpendicular distance between the two axes. Here, for the semicircles, around C it would be 1/2 MR² + M(AC² or BC²).
The total moment of inertia for the capsule would be the sum of its constituent moments of inertia, so it would be Rectangle's + 2 * (Semicircle's). Based on this, this is what I did, but I don't think I got it right because my capsule is jittering all over the place and not rotating as intended.
float momentOfInertiaOfRectangle = (massOfRectangle / 12.0f) * ((extentLength * extentLength) + (extentWidth * extentWidth));
float momentOfInertiaOfSemiCircle = massOfSemicircle * ((0.5f * m_CapsuleRadius * m_CapsuleRadius) + (extentLength * extentLength * 0.25f));
float totalMomentOfInertia = momentOfInertiaOfRectangle + (momentOfInertiaOfSemiCircle * 2.0f);
Please tell me if I did anything wrong and clarify this for me. Thank you.
Related
My question is about calculating points coordinates in 2D space.
I have two circles - outer and inner, that are centered between them (the inner is in the middle of the outer).
What I know:
-the two circles' radiuses (R1,R2)
-the 2D coordinates of a random point (x) in space always outside of the inner circle
What I want to find out:
-The 2D coordinates of the two points (y,z) that are lying on the outer circle following the two tangent lines from the random point (x)
Here is an illustration of what I need
Let's circles' center is coordinate origin (0,0) (shift other coordinates by true center ones), random point is P, point at big circle is Q, small radius is r, larger one is R.
We could build a system of equations for distance from center to tangent point and for intersection point, but it requires solving of quartic equation with rather long coefficients.
So at first find equation of tangent from point P to small circle with trigonometry:
Dist = Sqrt(px^2+py^2)
tan_angle = ArcSin(r / Dist)
rot_angle = ArcTan2(py, px)
ta1 = rot_angle - tan_angle
ta2 = rot_angle + tan_angle
and tangent points are
t1x = r * sin(ta1)
t1y = - r * cos(ta1)
t2x = - r * sin(ta2)
t2y = r * cos(ta2)
Now for both tangent points solve quadratic equation like
(px + s * (t1x - px))^2 + (py + s * (t1y - py))^2 = R^2
for unknown parameter s, get two solutions s1,s2 and find points of intersections
q11x = px + s1 * (t1x - px)
and so on
Note that solution consists of four points - two tangents, two intersection points for every tangent.
I'm looking for an algorithm that can generate points within a cone with a flat bottom (a disk).
I have the normalized axis along which the cone is being created (for our purposes let's just say it is the y-axis so (0, 1, 0) and the angle of the cone (let's say it is 45 degrees).
The only resources I could find online generate vectors within a cone, but they are based on sampling a sphere, so at the bottom you get a kind of "snow-cone" effect instead of a disk at the bottom.
That is done with the following pseudocode:
// Sample phi uniformly on [0, 2PI]
float phi = rand(0, 1) * 2 * PI
// Sample u uniformly from [cos(angle), 1]
float u = rand(0, 1) * (1 - cos(angle * PI/180)) + cos(angle * PI/180)
vec3 = vec3(sqrt(1 - u^2) * cos(phi), u, sqrt(1 - u^2) * sin(phi)))
The below picture is what I am going for. Having the ability to generate samples either on the surface or inside would be nice as well:
I could explain my solution in detail using integrals and probability distributions, but the lack of MathJax on this site makes that difficult. I'll keep my explanation at a simple level, but it should be clear. I'll also make the solution a little more general than you ask: we want a random point inside a right circular cone of height a and radius of base b, and we want the point with uniform sampling over the volume of that cone. This method directly chooses a random point in the cone without any rejection testing.
First let's consider the small cone of height h inside that larger cone, both cones with the same apex and parallel bases. The two cones are of course similar figures, and the square-cube law says that the volume of the smaller cone varies as the cube of its height. That height varies from 0 to a and we want its cube to be uniform over that range. Therefore we choose h to vary with the cube root of a uniform random variable, and we get (in Python 3 code),
h = a * (random()) ** (1/3)
We next consider the circular region that is the base of that smaller cone of height h. The radius of that base is (b / a) * h, by similar triangles. Now think of a smaller circular region of radius r inside that larger circular region, both circles in the same plane and with the same center. The area of the smaller circle varies with the square of its radius, so to get a uniform area over its range we take the square root of a uniform random variable. We get
r = (b / a) * h * sqrt(random())
We now want the angle t (for theta) of a point on the circumference of that smaller circle of radius r. The angle in radians obviously does not depend on the other factors, so we just use a uniform random variable to get
t = 2 * pi * random()
We now use those three random variables h, r, and t to choose our point inside the starting cone. If the apex of the cone is at the origin and the axis of the cone is along the positive y-axis, so that the center of the base is (0, a, 0) and a point on the circumference of the base is (b, a, 0), you can choose
x = r * cos(t)
y = h
z = r * sin(t)
When you asked about generating samples "on the surface" you did not clarify if you mean just the side (or is it "sides"?) of the cone, just the base, or the entire surface. Your second graphic appears to mean just the side, but I'll give code for all three.
The side only
Again we use a smaller cone of height h inside the larger cone. Its surface area varies as the square of its height, so we take the square root of a uniform random variable. The circle in its base is fixed, if our point is to be on the surface, and again the angle is just uniform. So we get
h = a * sqrt(random())
r = (b / a) * h
t = 2 * pi * random()
Use the same code for x, y, and z I used above for the interior of the cone to get the final random point on the side surface of the cone.
The base only
This is much like choosing a point in the interior, except the height is predetermined to equal the height of the entire cone. We get the following, somewhat simplified code:
h = a
r = b * sqrt(random())
t = 2 * pi * random()
Again, use the previous code for the final x, y, and z.
The entire surface
Here we can first decide, at random, whether to place our point on the base or on the surface, then place the point in one of the two ways above. The area of the base of a cone of height a and base radius b is pi * b * b while the surface area of the cone's side is pi * b * sqrt(a*a + b*b). We use the ratio of the base to the total of those areas to choose which subsurface to use for our point:
if random() < b / (b + sqrt(a*a + b*b)):
return point_on_base(a, b)
else:
return point_on_side(a, b)
Use my codes above for the side and base to complete that code.
Here are simple matplotlib 3D scatter plots of 10,000 random points, first inside the cone then on its side surface. Note that I made the apex angle 45°, as your text states but unlike your pictures. Viewing these from other angles seems to confirm that they are uniform in volume or area.
i have an image and 3 points with following datas for each point:
x and y 2d-world coordinates
x image coordinate
how can i calculate the camera orientation (only left/right) and the 2d-world position?
thanks.
edit: the image is a normal photography (so perspective projection). The world coordinate is a top view of a map, so Orthographic projection).
Given a point in world space, the projection can be expressed as
(x - cx) * cos(phi) - (y - cy) * sin(phi)
proj(x, y) = -----------------------------------------
(x - cx) * sin(phi) + (y - cy) * cos(phi)
cx and cy are the camera position and phi is the camera rotation. The projection will result in a value in camera coordinates (not image coordinates). To transform image coordinates to camera coordinates, usw
cameraX(imageX) = (2 * imageX / W - 1) * tan(fovy / 2) * ratio
W is the pixel width of the image, fovy is the vertical field of view, ratio is the image's aspect ratio.
Then you want to solve the system of equations formed by the three given points. There is an analytic solution, but it is quite complex. So you're left with numerical (probably least-squares) solvers. Pick one, plug in the formula and get your result. Since you optimize for both a position and an angle, you may want to normalize the values so that they have a similar range. I got quite good results with levmar for similar problems if you're unsure what optimizer to use.
This all assumes that the camera does not distort the image.
How to calculate 3D vector position after some time of movement at given angle and speed?
I have these variables available: current position, horizontal angle, vertical angle and speed.
I want to calculate position in the future.
Speed is defined as:
float distMade = this->Position().GetDistanceTo(lastPosition);
float speed = (distMade / timeFromLastCheck) * 1000; // result per sec
// checking every 100ms
Vertical angle coordinate system:
Facing 100% down -PI/2 (-1.57)
Facing 100% up PI/2 (1.57)
Horizontal angle:
Radian system, facing north = PI/2
Facing west = PI
Position 3d vector: x, y, z where z is height level.
It looks like you are trying to predict a future position based on current position and previous position, and know the duration between them.
In this case, it seems like you don't need the angular directions at all. Just keep your "speed" as a vector.
speed = (position() - lastPosition) / (time-last_time);
future_position = position()+(future_time-time)*speed;
If your vector objects don't have operators overloaded, look for some that do or perform the calculation on each x,y,z component independently.
This is, of course, does not take into account any acceleration, just predicts based on current velocity. You could also smooth it out by averaging over the last 5-10 speeds to get a slightly less jittery prediction. If you want to account for acceleration, then you'll have to track last_speed in the same fashion you are tracking last_position currently, and acceleration is just speed-last_speed. And you'd likely want to do an average over that as well.
in that case your speed is cartesian speed
so:
get point positions in cartesian space in different time
P0=(x0,y0,z0); - last position [units]
P1=(x1,y1,z1); - actual position [units]
dt=0.1; - time difference between obtaining P0,P1
compute new position in time pasted from obtaining P1
P(t)=P1+(P1-P0)*t/dt
expand:
x=x1+(x1-x0)*t/dt
y=y1+(y1-y0)*t/dt
z=z1+(z1-z0)*t/dt
if you need angh,angv,dist (and origin of your coordinate system is (0,0,0)
then you use this or modify it to your coordinate system:
dist = |P|=sqrt(x*x+y*y+z*z)
angv=asin(z/dist)
angh=atan2(y,x)
this is for: Z axis = UP, Y axis = North, X axis = East
if origin is not (0,0,0) then just substract it from P before conversion
If your horizontal angle is azimuthal angle, and vertical angle is elevation,
then
X = X0 + V * t * Cos(Azimuth) * Cos(Elevation)
Y = Y0 + V * t * Sin(Azimuth) * Cos(Elevation)
Z = Z0 + V * t * Sin(Elevation)
Please see the image below for a visual clue to my problem:
I have the coordinates for points 1 and 2. They were derived by a formula that uses the other information available (see question: How to calculate a point on a circle knowing the radius and center point).
What I need to do now (separately from the track construction) is plot the points in green between point 1 and 2.
What is the best way of doing so? My Maths skills are not the best I have to admit and I'm sure there's a really simple formula I just can't work out (from my research) which to use or how to implement.
In the notation of my answer to your linked question (i.e. x,y is the current location, fx,fy is the current 'forward vector', and lx,ly is the current 'left vector')
for (i=0; i<=10; i++)
{
sub_angle=(i/10)*deg2rad(22.5);
xi=x+285.206*(sin(sub_angle)*fx + (1-cos(sub_angle))*(-lx))
yi=y+285.206*(sin(sub_angle)*fy + (1-cos(sub_angle))*(-ly))
// now plot green point at (xi, yi)
}
would generate eleven green points equally spaced along the arc.
The equation of a circle with center (h,k) and radius r is
(x - h)² + (y - k)² = r² if that helps
check out this link for points http://www.analyzemath.com/Calculators/CircleInterCalc.html
The parametric equation for a circle is
x = cx + r * cos(a)
y = cy + r * sin(a)
Where r is the radius, cx,cy the origin, and a the angle from 0..2PI radians or 0..360 degrees.