How to get axis aligned bounding box of convex bodies - drake

I'd like to set the position of some convex bodies such that the body is flush against a ground plane.
To do so, I want to calculate the axis aligned bounding box so I can use the lowest point on the body.
I am adding convex bodies like this:
cv_shape = Convex(str(ROOT_PATH / mesh_path_list[body_idx]), scale=scale_factors[body_idx])
name = f"polytope_{body_idx}"
instance =self.plant.AddModelInstance(name)
H = RigidTransform(RotationMatrix(np.eye(3)), np.zeros(3))
body = self.plant.AddRigidBody(
name, instance,
SpatialInertia(mass=m,
p_PScm_E=np.array([0., 0., 0.]),
G_SP_E=inertia))
geom_id = self.plant.RegisterCollisionGeometry(
body, H,
cv_shape, name,
pydrake.multibody.plant.CoulombFriction(mu, mu))
How to get the AABB?

This is related to Drake issue #18421. A user had specifically requested an Obb for the mesh in place of the Aabb. I believe that user had obtained the Aabb by directly reading the obj in as a SurfaceTriangleMesh and then asking the mesh for its axis-aligned box. That issue will be resolved soon and we'll provide access for Aabb and Obb for shapes more generally via more public APIs.

Related

Finding vertexes for construction of minimum size bounding box / convex hull

I have an array of data from a grayscale image that I have segmented sets of contiguous points of a certain intensity value from.
Currently I am doing a naive bounding box routine where I find the minimum and maximum (x,y) [row, col] points. This obviously does not provide the smallest possible box that contains the set of points which is demonstrable by simply rotating a rectangle so the longest axis is no longer aligned with a principal axis.
What I wish to do is find the minimum sized oriented bounding box. This seems to be possible using an algorithm known as rotating calipers, however the implementations of this algorithm seem to rely on the idea that you have a set of vertices to begin with. Some details on this algorithm: https://www.geometrictools.com/Documentation/MinimumAreaRectangle.pdf
My main issue is in finding the vertices within the data that I currently have. I believe I need to at least find candidate vertices in order to reduce the amount of iterations I am performing, since the amount of points is relatively large and treating the interior points as if they are vertices is unnecessary if I can figure out a way to not include them.
Here is some example data that I am working with:
Here's the segmented scene using the naive algorithm, where it segments out the central objects relatively well due to the objects mostly being aligned with the image axes:
.
In red, you can see the current bounding boxes that I am drawing utilizing 2 vertices: top-left and bottom-right corners of the groups of points I have found.
The rotation part is where my current approach fails, as I am only defining the bounding box using two points, anything that is rotated and not axis-aligned will occupy much more area than necessary to encapsulate the points.
Here's an example with rotated objects in the scene:
Here's the current naive segmentation's performance on that scene, which is drawing larger than necessary boxes around the rotated objects:
Ideally the result would be bounding boxes aligned with the longest axis of the points that are being segmented, which is what I am having trouble implementing.
Here's an image roughly showing what I am really looking to accomplish:
You can also notice unnecessary segmentation done in the image around the borders as well as some small segments, which should be removed with some further heuristics that I have yet to develop. I would also be open to alternative segmentation algorithm suggestions that provide a more robust detection of the objects I am interested in.
I am not sure if this question will be completely clear, therefore I will try my best to clarify if it is not obvious what I am asking.
It's late, but that might still help. This is what you need to do:
expand pixels to make small segments connect larger bodies
find connected bodies
select a sample of pixels from each body
find the MBR ([oriented] minimum bounding rectangle) for selected set
For first step you can perform dilation. It's somehow like DBSCAN clustering. For step 3 you can simply select random pixels from a uniform distribution. Obviously the more pixels you keep, the more accurate the MBR will be. I tested this in MATLAB:
% import image as a matrix of 0s and 1s
oI = ~im2bw(rgb2gray(imread('vSb2r.png'))); % original image
% expand pixels
dI = imdilate(oI,strel('disk',4)); % dilated
% find connected bodies of pixels
CC = bwconncomp(dI);
L = labelmatrix(CC) .* uint8(oI); % labeled
% mark some random pixels
rI = rand(size(oI))<0.3;
sI = L.* uint8(rI) .* uint8(oI); % sampled
% find MBR for a set of connected pixels
for i=1:CC.NumObjects
[Y,X] = find(sI == i);
mbr(i) = getMBR( X, Y );
end
You can also remove some ineffective pixels using some more processing and morphological operations:
remove holes
find boundaries
find skeleton
In MATLAB:
I = imfill(I, 'holes');
I = bwmorph(I,'remove');
I = bwmorph(I,'skel');

Controlling an object orbiting a sphere

I want to let the user control an object moving over the surface of a static sphere. Using two buttons to rotate the direction of the object clockwise and anti-clockwise as it constantly moves forward similar to asteroids.
In scene kit there are three different orientation properties for an SCNNode and I really don't know where to start. I understand how to execute everything except the rotation around the sphere.
You're looking for a parameterization of the surface of the sphere. You can find this online (but it can be tricky if you don't know the magic words to enter for your searches). Check out the entry on MathWorld.
The surface of the sphere is parameterized by two angle variables, call them s and t. Note that one variable will run from zero to 2 pi, and the other will run only from zero to pi. This is a gotcha that can be easy to miss. To convert these angles to rectangular (x, y, z) coordinates, you use the formula:
x = r cos(s) sin(t)
y = r sin(s) sin(t) // Yes it's sin(t) twice, that's not a typo.
z = r cos(t)
I find the following visualization helpful. A curve in a plane (the xy-plane, for example) sweeps out an angle from zero to pi, half a rotation and corresponds to the parameter s. If you set t equal to pi/2, so sin(t) = 1, then you can see how x and y turn into standard rectangular coordinates for a circular section. After the s parameter sweeps out half a circle, you can rotate that half circle all the way around from zero to 2 pi, to form a full sphere, and that full sweep corresponds to the parameter t.
If you represent your object's position by coordinates (s, t) then you can, for the most part, safely convert to rectangular coordinates using the formula above without worrying about the domain of either parameter; however if s or t grow without bound (say, because your object orbits continuously for a long time) it might be worth the small extra effort to normalize the parameters. I'm not sure how sin or cos behave for very large inputs.

Anchor Points in Image Processing

I want to use filter functions in Intel IPP or OpenCV. There is an argument about the position of anchor points, and I don't know what they are or how I can use them.
What is an anchor point, and what is it for?
Say you use a filter with a kernel (or mask size or something similar). The anchor point defines how your kernel is positioned with respect to the pixel currently processed during the filter operation.
The anchor point is an IppiPoint, i.e. a struct with members x and y. This is the coordinate in the kernel of the currently processed pixel. Typically, it is set to the center, i.e. kernelWidth/2 and kernelHeight/2.
Originally, I claimed that the anchor point is a linear index. Sorry, that was wrong.

Creating a BoundingFrustum from 8 corners

XNA contains a BoundingFrustum class which defines a frustum and facilitates collisions with Rays and other objects. However, the Frustum can only be constructed with a Matrix. I have a certain object which is created in a frustum shape using 8 vertices; what kind of Matrix should I create from these vertices in order to create a Frustum to represent it?
The object in question is a chunk of a sphere-- 4 points on the sphere's surface in the form of a square, extending downward into the origin of the sphere.
Normally to use a BoundingFrustum you pass it a Matrix that is a view matrix multiplied by a projection matrix:
BoundingFrustum frustum = new BoundingFrustum(this.viewMatrix * this.projectionMatrix);
There is no easy way to use that class to do what you describe unless you're particularly skilled in creating a Matrix by hand that combines what would normally be in a view matrix and projection matrix into something that represents your 8 corners.
What I would recommend is writing an algorithm to solve your problem.
// Do something like this for all 8 sides of the frustum, if the sphere lies outside
// of any of the 8 sides then it isn't in the frustum.
// Each plane will have a normal direction (the direction the inside is facing)
Vector3 normal = Vector3.UnitY;
// Creates a plane
Plane plane = new Plane(normal, 20.0f);
BoundingSphere sphere = new BoundingSphere(Vector3.Zero, 10.0f);
// This type is an enum that will tell you which side the intersection is on
PlaneIntersectionType type = sphere.Intersects(plane);
Thanks to Nic's inspiration and the help of a friend, I was able to write this class which represents a region defined by 8 points which has flat sides, such as a frustum or cube.
Here is the class.
It's important to note that, when passing in the constructor parameters, you choose a vantage point from which to view your region and stick with it.
Hope this helps anyone else who may run into this (obscure) problem to solve.

Given a set of points to define a shape, how can I contract this shape like Photoshop's Selection>Contract

I have a set of points to define a shape. These points are in order and essentially are my "selection".
I want to be able to contract this selection by an arbitrary amount to get a smaller version of my original shape.
In a basic example with a triangle, the points are simply moved along their normal which is defined by the points to the left and the right of the points in question.
Eventually all 3 points will meet and form one point but until that point they will make a smaller and smaller triangle.
For more complex shapes, when moving the individual points inward, they may pass through the outer edge of the shape resulting in weird artifacts. Obviously I'll need to cull these points and remove them from the array.
Any help in exactly how I can do that would be greatly appreciated.
Thanks!
This is just an idea but couldn't you find the center of mass of the object, create a vector from the center to each point, and move each point along this vector?
To find the center of mass would of course involve averaging each x and y coordinate. Getting a vector is as simple a subtracting the point in question with the center point. Normalizing and scaling are common vector operations that can be found with the Google.
EDIT
Another way to interpret what you're asking is you want to erode your collection of points. As in morphology erosion. This is typically applied to binary images but you can slightly modify the concept to work with a collection of points. Essentially, you need to write a function that, given a point, will return true (black) or false (white) depending on if that point is inside or outside the shape defined by your points. You'd have to look up how to do that for shapes that aren't always concave (it's harder but not impossible).
Now, obviously, every single one of your actual points will return false because they're all on the border (by definition). However, you now have a matrix of points around your point of interest that define where is "inside" and where is "outside". Average all of the "inside" points and move your actual point along the vector between itself and towards this average. You could play with different erosion kernels to see what works best.
You could even work with a kernel with floating point weights instead of either/or values which will affect your average calculation proportional to their weights. With this, you could approximate a circular kernel with a low number of points. Try the simpler method first.
Find the selection center (as suggested by colithium)
Map the selection points to the coordinate system with the selection center at (0,0). For example, if the selection center is at (150,150), and a given selection point is at (125,75), the mapped position of the point becomes (-25,-75).
Scale the mapped points (multiply X and Y by something in the range of 0.0..1.0)
Remap the points back to the original coordinate system
Only simple maths required, no need to muck about normalizing vectors.

Resources