insertObservation method in COccupancyGridMap2D is producing warped results - mobile-robot-toolkit
The function insertObservation in COccupancyGridMap2D takes in two parameters which are the CPose3D and CObservation2DRangeScan values, even though both of these values are accurate with no noise, the grid is producing warped boundaries. The only thing I can think of is the scan.aperture settings might be producing this effect but these are correct with a range of 2*PI and other visual aides for point clouds show no warpage at all. Below is an illustration of this.
On the right the occupancy grid is warped compared to the ground truth square boundary. The left points look fine and are using the same aperture and load FromVectors settings.
Here is example code to try to verify the warp effect your self.
COccupancyGridMap2D gridmap;
gridmap.setSize(-4.0,4.0,-4.0,4.0,0.025f);
#define SCANS_SIZE 100
char SCAN_VALID[] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
CPose3D transform = CPose3D(0,0,0,0,0,0);
CObservation2DRangeScan read_scan;
read_scan.aperture = 2*M_PIf;
read_scan.rightToLeft = true;
vector<float> landmark = {2.9f,2.906f,2.924f,2.953f,2.996f,3.052f,3.124f,3.212f,3.319f,3.447f,3.601f,3.786f,4.007f,3.948f,3.736f,3.560f,3.413f,3.290f,3.188f,3.104f,3.037f,2.984f,2.945f,2.918f,2.903f,2.900f,2.909f,2.930f,2.963f,3.009f,3.069f,3.144f,3.237f,3.349f,3.483f,3.644f,3.837f,4.069f,3.891f,3.689f,3.521f,3.380f,3.263f,3.166f,3.086f,3.022f,2.973f,2.937f,2.913f,2.901f,2.901f,2.913f,2.937f,2.973f,3.022f,3.086f,3.166f,3.263f,3.380f,3.521f,3.689f,3.891f,4.069f,3.837f,3.644f,3.483f,3.349f,3.237f,3.144f,3.069f,3.009f,2.963f,2.930f,2.909f,2.900f,2.903f,2.918f,2.945f,2.984f,3.037f,3.104f,3.188f,3.290f,3.413f,3.560f,3.736f,3.948f,4.007f,3.786f,3.601f,3.447f,3.319f,3.212f,3.124f,3.052f,2.996f,2.953f,2.924f,2.906f,2.900f};
float *SCAN_RANGES = &landmark[0];
read_scan.loadFromVectors(SCANS_SIZE, SCAN_RANGES,SCAN_VALID);
gridmap.insertObservation(&read_scan,&transform);
CSimplePointsMap m3;
m3.insertObservation(&read_scan);
m3.getAllPoints(map_xs,map_ys,map_zs);
Here is a image of the simplePointsMap plot (red points) vs the OccupanyGrid
The angles being casted from the occupany grid look correct, with a consistent interval, but the angle is still off from simplepoints map, length looks ok and it seems each ray could be rotated to match with one of the red points. Possibly what could be happening is a mapping issue, and since we try to make the angles into discrete horizontal and vertical steps this causes the misalignment. I've tried increasing the resolution but this does not help, I guess that makes sense since scaling a horizontal/vertical ratio would still result in the same ratio and mismatch. I might be missing something though, what else could be causing this distortion, is this expected and the best we can do? Thank you for any help.
It seems to me that the problem is in the assumption of which are the angles of each scan "ray".
Take a look at the class mrpt::obs::CSinCosLookUpTableFor2DScans, generate one such sin/cos LUT for your specific scan object, and double check if the sin/cos values coincide with yours, as used to generate the scan.
By the way, COccupancyGridMap2D has one method to simulate a 2D scan from a gridmap image, give it a try, and if that one generates warped results, please fill up a bug report (!) ;-)
Cheers.
I just realized what was going on, CSimplePointsMap and COccupancyGridMap2D use two slightly different references for point angles. CSimplePointsMap is expecting an overlap between the first and last point while COccupancyGridMap2D is not. The simple fix to all of this then is to read in one less scan for the COccupancyGridMap2D and then everything lines up. This is if your angles are being defined as so, which is fine for CSimplePointsMap.
for (int i = 0; i < Raysize; i++)
{
float angle = -angle_range / 2 + i * (angle_range) / (Raysize-1);
Here is the fix for OccupancyGridMap2D insertObservation using SCANS_SIZE-1 instead and CSimplePointsMap can still use SCANS_SIZE.
read_scan.loadFromVectors(SCANS_SIZE-1, SCAN_RANGES,SCAN_VALID);
gridmap.insertObservation(&read_scan,&transform);
Related
Determing the direction of face normals consistently?
I'm a newbie to computer graphics so I apologize if some of my language is inexact or the question misses something basic. Is it possible to calculate face normals correctly, given a list of vertices, and a list of faces like this: v1: x_1, y_1, z_1 v2: x_2, y_2, z_2 ... v_n: x_n, y_n, z_n f1: v1,v2,v3 f2: v4,v2,v5 ... f_m: v_j, v_k, v_l Each x_i, y_i , z_i specifies the vertices position in 3d space (but isn't neccesarily a vector) Each f_i contains the indices of the three vertices specifying it. I understand that you can use the cross product of two sides of a face to get a normal, but the direction of that normal depends on the order and choice of sides (from what I understand). Given this is the only data I have is it possible to correctly determine the direction of the normals? or is it possible to determine them consistently atleast? (all normals may be pointing in the wrong direction?)
In general there is no way to assign normal "consistently" all over a set of 3d faces... consider as an example the famous Möbius strip... You will notice that if you start walking on it after one loop you get to the same point but on the opposite side. In other words this strip doesn't have two faces, but only one. If you build such a shape with a strip of triangles of course there's no way to assign normals in a consistent way and you'll necessarily end up having two adjacent triangles with normals pointing in opposite directions. That said, if your collection of triangles is indeed orientable (i.e. there actually exist a consistent normal assignment) a solution is to start from one triangle and then propagate to neighbors like in a flood-fill algorithm. For example in Python it would look something like: active = [triangles[0]] oriented = set([triangles[0]]) while active: next_active = [] for tri in active: for other in neighbors(tri): if other not in oriented: if not agree(tri, other): flip(other) oriented.add(other) next_active.append(other) active = next_active
In CG its done by polygon winding rule. That means all the faces are defined so the points are in CW (or CCW) order when looked on the face directly. Then using cross product will lead to consistent normals. However many meshes out there does not comply the winding rule (some faces are CW others CCW not all the same) and for those its a problem. There are two approaches I know of: for simple shapes (not too much concave) the sign of dot product of your face_normal and face_center-cube_center will tell you if the normal points inside or outside of the object. if ( dot( face_normal , face_center-cube_center ) >= 0.0 ) normal_points_out You can even use any point of face instead of the face center too. Anyway for more complex concave shapes this will not work correctly. test if point above face is inside or not simply displace center of face by some small distance (not too big) in normal direction and then test if the point is inside polygonal mesh or not: if ( !inside( face_center+0.001*face_normal ) ) normal_points_out to check if point is inside or not you can use hit test. However if the normal is used just for lighting computations then its usage is usually inside a dot product. So we can use its abs value instead and that will solve all lighting problems regardless of the normal side. For example: output_color = face_color * abs(dot(face_normal,light_direction)) some gfx apis have implemented this already (look for double sided materials or normals, turning them on usually use the abs value ...) For example in OpenGL: glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
Three.js ParticleSystem flickering with large data
Back story: I'm creating a Three.js based 3D graphing library. Similar to sigma.js, but 3D. It's called graphosaurus and the source can be found here. I'm using Three.js and using a single particle representing a single node in the graph. This was the first task I had to deal with: given an arbitrary set of points (that each contain X,Y,Z coordinates), determine the optimal camera position (X,Y,Z) that can view all the points in the graph. My initial solution (which we'll call Solution 1) involved calculating the bounding sphere of all the points and then scale the sphere to be a sphere of radius 5 around the point 0,0,0. Since the points will be guaranteed to always fall in that area, I can set a static position for the camera (assuming the FOV is static) and the data will always be visible. This works well, but it either requires changing the point coordinates the user specified, or duplicating all the points, neither of which are great. My new solution (which we'll call Solution 2) involves not touching the coordinates of the inputted data, but instead just positioning the camera to match the data. I encountered a problem with this solution. For some reason, when dealing with really large data, the particles seem to flicker when positioned in front/behind of other particles. Here are examples of both solutions. Make sure to move the graph around to see the effects: Solution 1 Solution 2 You can see the diff for the code here Let me know if you have any insight on how to get rid of the flickering. Thanks!
It turns out that my near value for the camera was too low and the far value was too high, resulting in "z-fighting". By narrowing these values on my dataset, the problem went away. Since my dataset is user dependent, I need to determine an algorithm to generate these values dynamically.
I noticed that in the sol#2 the flickering only occurs when the camera is moving. One possible reason can be that, when the camera position is changing rapidly, different transforms get applied to different particles. So if a camera moves from X to X + DELTAX during a time step, one set of particles get the camera transform for X while the others get the transform for X + DELTAX. If you separate your rendering from the user interaction, that should fix the issue, assuming this is the issue. That means that you should apply the same transform to all the particles and the edges connecting them, by locking (not updating ) the transform matrix until the rendering loop is done.
Preventing pixelshader overdraw for a single ERG
Background Using gluTess to build a triangle list in Direct3D9 from a GDI+ DrawString(..) path: A pixel shader (v3.0) is then used to fill in the shape. When painting with opaque values, everything looks fine: The problem At certain font sizes, if the color has an alpha component (ie Argb #55FFFFFF) we begin to see these nasty tessellation artifacts where triangles may overlap ever so slightly: At larger font sizes the problem is sometimes not present: Using Intel's excellent GPA Frame Analyzer Pixel History tool, we can see in areas where the artifacts occur, the pixel has been "touched" 3 times from the single Erg. I'm trying to figure out how I can stop my pixel shader from touching the same pixel more than once. Other solutions relating to overdraw prevention seem to be all about zbuffer strategies, however this problem is more to do with painting of a single 2D triangle list within a single pixel shader pass. I'm at a bit of a loss trying to come up with a solution on this one. I was hoping that HLSL might have some sort of "touch each pixel only once" flag, but I've been unable to find anything like that. The closest I've found was to set the BLENDOP to MAX instead of ADD. But the output is not correct when blending over other colors in the scene. I also have SRCBLEND = ONE, DSTBLEND = INVSRCALPHA. The only combination of flags which produce correct output (albeit with overdraw artifacts.) I have played with SEPARATEALPHABLENDENABLE in the GPA frame analyzer, which sounded like almost exactly what I need here -- set blending to MAX but only on the "alpha" channel, however from what I can determine, that setting (and corresponding BLENDOPALPHA) affects nothing at all. One final thing I thought of was to bake text as opaque onto a texture, and then repaint that texture into the scene with the appropriate alpha value applied, however this doesn't actually work in this project because I also support gradient brushes, where stop values may contain alpha, meaning either the artifacts would still be seen, or the final output just plain wrong if we stripped the alpha away from the stop values prior to baking to a texture. Also the whole endeavor would be hideously expensive. Any hints or pointers would be appreciated. Thanks for reading.
The problem you're seeing shouldn't happen. If two of your triangles are overlapping it's because you've placed the vertices in such a way that when the adjacent triangles are drawn, they overlap. What's probably happening is that these two adjacent triangles share two vertices, but each triangle has its own copy of each vertex that's been calculated to be in a very, very slightly different position. The solution to the problem isn't to try and make the pixel shader touch the pixel only once it's to use an index buffer (if you aren't already) and have the shared vertices between each triangle actually share the same vertex and not use one that's ever-so-slightly not in the same place as the one used by the adjacent triangle. If you aren't in control of the tessellation algorithm being used you may have to run a pass over the vertex buffer after its been generated to detect and merge vertices that are within some very small tolerance of one another. Even without an index buffer, a naive solution would be this: For each vertex in the vertex buffer, compare its position to every other vertex in the rest of the vertex buffer. If two vertices are within some small tolerance of another, replace the second vertex's position with the position of the one you are comparing it against. This should have the effect of pairing up the positions of two vertices if they are close enough that you deem them to be the same. You now shouldn't have any problem with overlapping triangles. In everyday rendering two triangles share edges with each other all the time and you won't ever get the effect where they appear to every-so-slightly overlap. The hardware guarantees that a sample point is either on one side of the line or the other, but never both at the same time, no matter how close the point is to the line (even if it's mathematically on the line, it still fails on one side or the other).
Intersecting points with a polygon in OpenCV
My inputs I have a vector<Point2f> that contains the contours of a polygon. I also have a list of points that need to be intersected with this polygon. The problem I want to calculate how much of these points intersect with the polygon. I want to repeat this calculation on a number of polygons to see which one contains the highest number of points. Does OpenCV implement such intersection functionality of its own or will I need to implement an intersection function myself? I'm worried that if I try to implement it myself, the result will be unnecessarily slow. If OpenCV can't do it, are there other free graphics libraries that can perform this task?
pointPolygonTest does exactly what you're looking for, and it's pretty well optimized. The parameter is a Mat which you can make with the constructor that takes your vector of points. The function determines whether the point is inside a contour, outside, or lies on an edge (or coincides with a vertex). It returns positive (inside), negative (outside) or zero (on an edge) value, correspondingly. When measureDist=false , the return value is +1, -1 and 0, respectively. Otherwise, the return value it is a signed distance between the point and the nearest contour edge. Your problem seems easily parallelizable, though, i.e. each batch of candidate polygons could run on a different thread, so I'd definitely look into that if you're concerned about performance.
why different Mandelbrot zooming values yields same results?
what gives one the ability to define how deep the zooming process would be? what i mean is that i tried earlier to run mandelbrot set with 200 iteration and then compared the results with a 1000 iterations run. the results were kinda surprising because i got the same zooming level.the iterations were constant the entire process and the mandelbrot set was defined with 512X512 pixels constant. what should i change in order to get a deeper zooming level? thanks! edit : i would also like to mention that from nice looking picture, after i get to the 2nd-3rd level of mandelbrot the entire set is viewed as a giant pixel. why is that? 2d edit : after an extensive research i've just noticed that what makes the entire set to look like a big pixel is because all points get same iterations count,in my case they are all 60...
This may be too abstract, or too concrete, or incomprehensible. Like I said in the comment, it would be easier to discuss with your code at hand. If you mean what I think you mean by zooming, you'd change the boundaries of c (in the formula z[n+1] = z[n]^2 + c). To explain, the full Mandelbrot set is contained within a circle with radius 2 around a center [0;0]. The c in the formula is a complex number, i.e. [r;i] (real;imaginary), which, on the computer screen, corresponds to x and y. In other words, if we place that radius 2 circle so that it is exactly contained within our image, then [-2;2] will be the upper left corner of our image, and [2;-2] is the lower right corner. We then take each point of our image, calculate what its pixel coordinates [x;y] correspond to in terms of the smaller, "actual" coordinate system [r;i]. Then we have our c and can send it through our iterations. So, to "zoom", you'd pick other boundaries [r;i] than the full [-2;2],[2:-2], e.g. [-1;1],[1:-1]. With 512x512 pixels, and an "actual" coordinate system that's now 2 by 2, that would mean each pixel corresponds to 2/512 units of the "actual" coordinate system. So your first r value would be -1, the next would be -1 + 2/512 = -0.99609375 etc. The number of iterations only decide how accurate your rendering will be. Generally, the further you "zoom" in, the more accurate they'll need to be, so the more iterations you'll need in order to capture the details.