How to prevent plane fitting of plane on xz and yz axes? - point-cloud-library

I have this code:
SACSegmentation<PointXYZ> seg;
seg.setAxis(Vector3f(0, 0, 1));
seg.setEpsAngle(0.5 * M_PI / 180.0);
seg.setModelType(SACMODEL_PLANE);
seg.setMethodType(SAC_RANSAC);
seg.setDistanceThreshold(0.2);
// then set the input cloud and filter..
The axis and epsAngle seem to do nothing at all-- the point cloud still picks up walls when the sensor gets close enough to them that the wall has more points than the ground. I construct the point cloud explicitly from xyz point data, and so PointCloud member variables like sensor_origin_ and sensor_orientation_ are likely not set (unless PointCloud defaults them to something). Could this be the root of my problem? Or am I doing something else wrong?
Other posts I've seen on this problem all suggest setting the eps angle, which I'm already doing. I appreciate your help!

I sniffed around on the PCL docs and found the answer. They don't make it abundantly clear in the documentation, but only SOME of the models are affected by setAxis() and setEpsAngle(). For my application, that model was SACMODEL_PARALLEL_PLANE. You can find the others here: http://docs.pointclouds.org/1.7.0/group__sample__consensus.html.

Related

Project 3D velocity values from vector field around a sphere to create flow lines

I just cannot figure out how to make an a point with a given velocity move around in cartesian space in my visualization while staying around a sphere (planet).
The input:
Many points with:
A Vector3 position in XYZ (lat/lon coordinates transformed with spherical function below).
A Vector3 velocity (eg. 1.0 m/s eastward, 0.0 m/s elevation change, 2.0 m/s northward).
Note these are not degrees, just meters/second which are similar to my world space units.
Just adding the velocities to the point location will make the points fly of the sphere, which makes sense. Therefore the velocities need to be transformed so stay around the sphere.
Goal: The goal is to create some flowlines around a sphere, for example like this:
Example image of vectors around a globe
So, I have been trying variations on the basic idea of: Taking the normal to center of my sphere, get a perpendicular vector and multiply that again to get a tangent:
// Sphere is always at (0,0,0); but just to indicate for completeness:
float3 normal = objectposition - float3(0,0,0);
// Get perpendicular vector of our velocity.
float3 tangent = cross(normal,velocity);
// Calculate final vector by multiplying this with our original normal
float3 newVector = cross(normal, tangent);
// And then multiplying this with length (magnitude) of the velocity such that the speed is part of the velocity again.
float final_velocity = normalize(newVector) * length(velocity);
However, this only works for an area of the data, it looks like it only works on the half of the western hemisphere (say, USA). To get it (partially) working at the east-southern area (say, South-Africa) I had to switch U and V components.
The XYZ coordinates of the sphere are created using spherical coordinates:
x = radius * Math.Cos(lat) * Math.Cos(lon);
y = radius * Math.Sin(lat);
z = radius * Math.Cos(lat) * Math.Sin(lon);
Of course I have also tried all kinds of variations with multiplying different "Up/Right" vectors like float3(0,1,0) or float3(0,0,1), switching around U/V/W components, etc. to transform the velocity in something that works well. But after about 30 hours of making no progress, I hope that someone can help me with this and point me in the right direction. The problem is basically that only a part of the sphere is correct.
Considering that a part of the data visualizes just fine, I think it should be possible by cross and dot products. As performance is really important here I am trying to stay away from 'expensive' trigonometry operations - if possible.
I have tried switching the velocity components, and in all cases one area/hemisphere works fine, and others don't. For example, switching U and V around (ignoring W for a while) makes both Africa and the US work well. But starting halfway the US, things go wrong again.
To illustrate the issue a bit better, a couple of images. The large purple image has been generated using QGIS3, and shows how it should be:
Unfortunately I have a new SO account and cannot post images yet. Therefore a link, sorry.
Correct: Good result
Incorrect: Bad result
Really hope that someone can shed some light on this issue. Do I need a rotation matrix to rotate the velocity vector? Or multiplying with (a correct) normal/tangent is enough? It looks like that to me, except for these strange oddities and somehow I have the feeling I am overlooking something trivial.
However, math is really not my thing and deciphering formula's are quite a challenge for me. So please bear with me and try to keep the language relative simple (Vector function names are much easier for me than scientific math notation). That I got this far is already quite an achievement for myself.
I tried to be as clear as possible, but if things are unclear, I am happy to elaborate them more.
After quite some frustration I managed to get it done, and just posting the key information that was needed to solve this, after weeks of reading and trying things.
The most important thing is to convert the velocity using rotation matrix no. 6 from ECEF to ENU coordinates. I tried to copy the matrix from the site; but it does not really paste well. So, some code instead:
Matrix3x3:
-sinLon, cosLon, 0,
-cosLon * sinLat, -sinLon * sinLat, cosLat,
cosLon * cosLat, sinLon * cosLat, sinLat
Lon/Lat has to be acquired through a Cartesian to polar coordinate conversion function for the given location where your velocity applies.
Would have preferred a method which required no sin/cos functions but I am not sure if that is possible after all.

GKObstacleGraph How to Find Closest Valid point?

In a scenario where user wants to navigate via mouse or touch to some are of the map that is not passable. When sending the point to GKObstacleGRpah FindPath it just returns an empty array.
I want the unit to go to closest (or close enough) passable point.
What would be an appropriate way to find a closest valid point in GKObstacleGraph.
I understand that I can get the GKObstacle so I can enumerate it's vertices, and I know my unit's position...
But well... what is the next step ?
NOTE: I am not using GKAgengts.
Here was my thinking as I worked through this problem. There may be an easier answer, but I haven’t found it.
1. Figure out if a point is valid or not.
To do this, I actually have a CGPath representation of each obstacle. I export paths from PhysicsEditor and then load them in through a custom script that converts them to CGPath. I always store that CGPath along with the GKObstacle I created from the path. Finally, I can call CGPathContainsPoint to determine the the obstacle contains the point. If true, I know the point is invalid.
2. Once the point is invalid, find out which obstacle was clicked.
With my approach in #1, I already have a handle on the CGPath and obstacle it belongs to.
3. Find closest vertex
Now that I know the obstacle, find the vertex closest to the unit that is moving. I wouldn’t find the closet vertex to the point clicked because that could be around a corner. Instead, figure out the vector between the desired position and the unit. Then, draw an invisible line from the desired position through the vertex. I used this equation to find out where the lines would cross.
// http://stackoverflow.com/questions/1811549/perpendicular-on-a-line-from-a-given-point
let k = ((end.y - start.y) * (hitPoint.x - start.x) - (end.x - start.x) * (hitPoint.y - start.y)) / ((end.y - start.y) * (end.y - start.y) + (end.x - start.x) * (end.x - start.x))
let x4 = hitPoint.x - k * (end.y - start.y)
let y4 = hitPoint.y + k * (end.x - start.x)
let ret = float2(x: x4, y: y4)
4. Offset intersection by unit size towards moving unit
Knowing where the paths intersect along with the vector towards the unit, we can just move to intersection point + (the vector * unit size).
5. Edge cases
This gets tricky when you have two obstacles touching each other, or if you have very large obstacles. The user may think they are moving to the far side of the map, but this script will follow back to the closet valid point which could be nearby. Because of that, I scrapped all of the code and I just don’t allow you to move to invalid positions. A red X and a buzz sound happens prompting the user to select a new, valid position on the map.
6. DemoBots
I could be wrong, but I vaguely recall DemoBots from Apple having similar logic — they may be a good reference too.
7. Debug Layer
This took forever for me to get a proof of concept together. I’d highly recommend drawing lines on a debug layer to verify your logic.

How to implement KdTree using PCLPointCloud2 used in loadOBJfile in point cloud library?

Okay, so I have one OBJ file which I read into PCLpointcloud2. Now I want to feed it into a K-dTree. Which is not taking PCLPointCloud2 as input. I want to query any general point if it lies on the surface of my OBJ file.
I am finding it hard to understand their documentation. So how can it be done?
Plus, kindly point me to a good reference easily interpretable. And what is "PointT" BTW? Is it custom build type defined by us? please elaborate.
Look at the code in the provided tool pcl_mesh_sampling (in the PCL code directory under tools/mesh_sampling.cpp). It is relatively simple. It loads a model from PLY or OBJ then for each triangle it samples random points from the triangle. The final point cloud then undergoes a voxel-grid sample to make the points relatively uniform. Alternatively, you can just run the pcl_mesh_sampling program on your obj file to get an output PCD which you can then visualise with pcl_viewer before loading the PCD file into your own code.
Once you have the final point cloud, you can build and use a KD-Tree as per http://pointclouds.org/documentation/tutorials/kdtree_search.php
PointT is the template argument. The point cloud library can handle a variety of point types, from simple PointXYZ (having just x,y,z) to more complicated points like PointXYZRGBNormal (having x,y,z,normal_x,normal_y,normal_z, curvature, r, g, and b channels). Each algorithm is templated on the point type that you want to use. It would probably be easier if you used PointXYZ with your OBJ file, so use pcl::PointXYZ for all your template arguments. For more on templates see http://www.tutorialspoint.com/cplusplus/cpp_templates.htm and http://pointclouds.org/documentation/tutorials/adding_custom_ptype.php.
Update (reply to latest comment)
Added here because this reply is too long for a comment.
I think I see what you are getting at. So when you sample points from the point cloud & build a KD-tree of the object surface, and for each point you keep track which faces are nearby that point (probably all the faces adjacent to the face from which the point was sampled should be sufficient? Just one face is definitely insufficient). Then when the query point is given, you find the nearest point in the KD-tree and check whether the query point is on the "outside" or inside of the full list of nearby faces associated with that point in the KD-tree. If it's on the "inside" of all of them perhaps it is an interior point. But I cannot guarantee that this is true. That is my thinking on that question at the moment. But I do wonder if you want a mesh-based approach really. By the way, if you break your mesh up into convex parts then you can have nice guarantees when processing each convex part.

Three.JS Object following a spline path - rotation / tanget issues & constant speed issue

I think my issue is similar to: Orient object's rotation to a spline point tangent in THREE.JS but I can't access the jsfiddle's properly and I struggled with the second part of the explanation.
Basically, I have created this jsfiddle: http://jsfiddle.net/jayfield1979/qGPTT/2/ which demonstrates a simple cube following the path created by a spline using SplineCurve3. Use standard TrackBall mouse interaction to navigate.
Positioning the cube along the path is simple. However I have two questions.
First, I am using the spline.getTanget( t ) where t is the position along the path in order to have the cube rotate (Y axis as UP only). I think I am missing something because even if I extract the .y property of the resulting tangent provided, the rotations still seem off. Is there some nomalizing that needs doing?
Second, the speed is very varied along the path, obviously a lot more points stacked in creating the tighter curves, but I was wondering is there a way to refactor the path to more evenly distribute the spaces between points? I came across the reparametrizeByArcLength function but struggled to find an explanation how to use it.
Any help or explanation for a bit of a maths dummy, would be gratefully received.
To maintain a constant speed, you use .getPointAt( t ) instead of .getPoint( t ).
To get the box to remain tangent to the curve, you follow the same logic as explained in the answer to Orient object's rotation to a spline point tangent in THREE.JS.
box.position.copy( spline.getPointAt( counter ) );
tangent = spline.getTangentAt( counter ).normalize();
axis.crossVectors( up, tangent ).normalize();
var radians = Math.acos( up.dot( tangent ) );
box.quaternion.setFromAxisAngle( axis, radians );
three.js r.144

rayPlaneIntersection (like) exemple or similar function

I'm working with bots in Call Of Duty and their vision is calculated with a bulletTracePassed  function, there's no other way to calculate that, since there's not really bot functions, so this will return true if a bullet can pass from point A to point B returning true/false, which works great MOST of the times, but causes a chaos in those 2 cases mainly:
When the mapper didn't put any kind iDFLAGS_PENETRATION on the walls (means the wall have no resistance to bullets, so there's not contact/hit, and the bullets pass through like was nothing.
When we have Trees, Plants, etc in the middle
In those 2 cases the bots will see the other players when shoudn't, and in jungle like maps it's a complete hell to play.
Ok, the right way to do these fixes are just fix the maps, adding the right penetration in those walls and dense vegetation, but is not possible do that because are SEVERAL maps by SEVERAL modders, and even official releases with the same problems, and of course, we don't have their sources to apply these fixes.
So the only way to do that is via script, and I'm thinking in doing something like this:
I have the position of the eye of the attacker bot in 3D like (x,y,z) for exemple (1000,500,22), and also the position which hit the other players like (2000,1200,60), which is returned by the function bulletTracePassed.
But for exemple, in a wall I have part of it without any collision, so the bots can see through them, so would like to set the middle of the wall with position (1600,800,50) and angles (10,-40,-90) and a square radius of the size to of the square/plane, for exemple, 500.
So I want to test if the ray passed through this square/plane, then returning false/true to let me use it to make the bots decide to aim to shoot or not this player behind the "bad" wall.
Looking around I found the function rayPlaneIntersection, which by the name seams what I want, but didn't get right yet how it works in my solution, since I can't see any kind of angles of even a square radius to determine their size... or are doing to a single point only?
rayPlaneIntersectionrayPlaneIntersection(ray0: vec3, ray1: vec3, origin?: vec3 | number[], normal?: vec3 | number[]): vec3 | undefined
Defined in raymath.ts:130
Computes the intersection point of a given ray and a given plane (rooted at [ 0, 0, 0 ]). t = -(dot(plane.xyz, origin) + plane.w) / dot(plane.xyz, ray); The ray intersects when (t > 0.0) && (t < tm) is true.
Parameters
ray0: vec3 Start point of a ray.
ray1: vec3Far point of a ray, used to derive the ray direction.
Default value origin: vec3 | number[] = [0.0, 0.0, 0.0]
Point on a plane with origin [ 0, 0, 0 ].
Default value normal: vec3 | number[] = [0.0, 1.0, 0.0]
Normal of the plane with origin [ 0, 0, 0 ].
Returns vec3 | undefined
If ray intersects, the intersection point on the plane if the plane was hit.
Anyone could point an exemple of this use in my exemple? Or any other function that might give me the same (or even similar) result to let me at least start to fix this problem?
I know it's not an easy task, that's why I'm posting here, after many lost hours trying to do it alone without success yet.
thank you very much.

Resources