选择矩阵中距离另一个点 30m 以内的所有点
因此,如果您查看我的其他帖子,您就会发现我正在构建一个可以在森林中收集数据并将其粘贴在地图上的机器人,这并不奇怪。我们的算法可以检测树中心和树干直径,并将它们粘贴在笛卡尔 XY 平面上。
我们计划使用某些“关键”树作为定位机器人的自然地标,使用三角测量和三边测量等方法,但仅使用 Matlab 对其进行编程并保持数据的直接和高效变得困难。
是否有一种技术可以对点数组或矩阵进行子设置?假设我有 1000 棵树存储在 1km (1000m) 范围内,有没有办法说,仅选择当前位置 30m 半径内的点并仅处理这些点?
我只会使用 GIS,但我在 Matlab 中执行此操作,我不知道有任何适用于 Matlab 的 GIS 插件。
我忘了提及,这段代码正在上线,这意味着它正在机器人上实时执行。我不知道当地图增长到几英里时,使用不同的数据结构是否会有帮助,或者计算到随机点的每个距离是否是空间数据库要做的事情。
我正在考虑将树数组镜像为两个数组,一个按 X 排序,另一个按 Y 排序。然后冒泡排序以确定其中的 30m 范围。我对两个数组 X 和 Y 执行相同的操作,然后使用第三个交叉链接表来选择各个值。但我不知道这叫什么,如何编程,而且我确信有人已经知道了,所以我不想重新发明轮子。
So if you look at my other posts, it's no surprise I'm building a robot that can collect data in a forest, and stick it on a map. We have algorithms that can detect tree centers and trunk diameters and can stick them on a cartesian XY plane.
We're planning to use certain 'key' trees as natural landmarks for localizing the robot, using triangulation and trilateration among other methods, but programming this and keeping data straight and efficient is getting difficult using just Matlab.
Is there a technique for sub-setting an array or matrix of points? Say I have 1000 trees stored over 1km (1000m), is there a way to say, select only points within 30m radius of my current location and work only with those?
I would just use a GIS, but I'm doing this in Matlab and I'm unaware of any GIS plugins for Matlab.
I forgot to mention, this code is going online, meaning it's going on a robot for real-time execution. I don't know if, as the map grows to several miles, using a different data structure will help or if calculating every distance to a random point is what a spatial database is going to do anyway.
I'm thinking of mirroring the array of trees, into two arrays, one sorted by X and the other by Y. Then bubble sorting to determine the 30m range in that. I do the same for both arrays, X and Y, and then have a third cross link table that will select the individual values. But I don't know, what that's called, how to program that and I'm sure someone already has so I don't want to reinvent the wheel.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
您正在寻找一个空间数据库,例如 quadtree 或 kd-tree。我在此处和此处,但没有找到任何 Matlab 的四叉树实现。
You are looking for a spatial database like a quadtree or a kd-tree. I found two kd-tree implementations here and here, but didn't find any quadtree implementations for Matlab.
计算所有距离并扫描的简单解决方案似乎几乎可以立即运行:
在 1.2 GHz 机器上,我可以在 <100 万棵树(1 MTree?)中处理 100 万棵树(1 MTree?)。 0.4秒。
您是否直接在机器人上运行 Matlab 代码?你在使用实时工作室之类的吗?如果您需要将其转换为 C,可以将
hypot
替换为sqr(trees[i].x - pos.x) + sqr(trees[i].y - pos.y) )
,并将限制检查替换为< lim^2
。如果你真的只需要处理 1 个 KTree,我不知道是否值得你花时间去实现一个更复杂的数据结构。The simple solution of calculating all the distances and scanning through seems to run almost instantaneously:
On a 1.2 GHz machine, I can process 1 million trees (1 MTree?) in < 0.4 seconds.
Are you running the Matlab code directly on the robot? Are you using the Real-Time Workshop or something? If you need to translate this to C, you can replace
hypot
withsqr(trees[i].x - pos.x) + sqr(trees[i].y - pos.y)
, and replace the limit check with< lim^2
. If you really only need to deal with 1 KTree, I don't know that it's worth your while to implement a more complicated data structure.您可以使用 CART2POL。然后在一定半径内选择点将是直接的。
其中X0,Y0是当前位置的坐标。
You can transform you cartesian coordinates into polar coordinates with CART2POL. Then selecting points inside certain radius will be strait-forward.
where X0, Y0 are coordinates of the current location.
我的猜测是,树木在森林中的分布大致均匀。如果是这种情况,只需使用 30x30(或 15x15)网格块作为 封闭哈希的哈希键表。查找与搜索圈相交的所有块的键,并检查从该键开始的所有哈希条目,直到一个被标记为其“桶”中的最后一个。
例如,要获取 (0,0)…(30,30) 中的树,请将 (0,0) 映射到地址
0
并读取条目 (1,3)、(10,15 ),拒绝(3,46),因为它超出范围,读取(24,9),并停止,因为它被标记为该扇区中的最后一棵树。要获取 (0,60)…(30,90) 中的树,请将 (0,60) 映射到地址 20。跳过 (24, 9),读取 (23, 65),然后停止。
这将非常节省内存,因为它避免存储指针,否则指针相对于实际数据来说将具有相当大的大小。然而,封闭散列需要留一些空白空间。
该插图并非“按比例”,因为实际上哈希键标记之间会有多个条目的空间。因此,除非本地先前扇区中的树木数量多于平均水平,否则您不必跳过任何条目。
这确实利用了哈希冲突,因此它不像哈希函数通常那样随机。 (并非每个条目都对应一个不同的哈希值。)但是,由于森林的密集部分通常是相邻的,因此您应该将扇区映射到“存储桶”随机化,因此给定的密集扇区有望溢出到密度较低的扇区,或下一个,或下一个。
此外,还存在空扇区和终止迭代的问题。您可以在每个扇区中插入一棵虚拟树以将其标记为空,或者进行其他一些简单的修改。
抱歉这么长的解释。这种事情实施起来比记录起来更简单。但性能和占用空间都非常出色。
My guess is that trees are distributed roughly evenly through the forest. If that is the case, simply use 30x30 (or 15x15) grid blocks as hash keys into an closed hash table. Look up the keys for all blocks intersecting the search circle, and check all hash entries starting at that key until one is flagged as the last in its "bucket."
For example, to get the trees in (0,0)…(30,30), map (0,0) to the address
0
and read entries (1,3), (10,15), reject (3,46) because it's out of bounds, read (24,9), and stop because it's flagged as the last tree in that sector.To get trees in (0,60)…(30,90), map (0,60) to address 20. Skip (24, 9), read (23, 65), and stop as it's last.
This will be quite memory efficient as it avoids storing pointers, which would otherwise be of considerable size relative to the actual data. Nevertheless, closed hashing requires leaving some empty space.
The illustration isn't "to scale" as in reality there would be space for several entries between the hash key markers. So you shouldn't have to skip any entries unless there are more trees than average in a local preceding sector.
This does use hash collisions to your advantage, so it's not as random as a hash function typically is. (Not every entry corresponds to a distinct hash value.) However, as dense sections of forest will often be adjacent, you should randomize the mapping of sectors to "buckets," so a given dense sector will hopefully overflow into a less dense one, or the next, or the next.
Additionally, there is the issue of empty sectors and terminating iteration. You could insert a dummy tree into each sector to mark it as empty, or some other simple hack.
Sorry for the long explanation. This kind of thing is simpler to implement than to document. But the performance and the footprint can be excellent.
使用某种空间分区的数据结构。一个简单的解决方案是简单地创建一个包含 30m x 30m 区域内所有对象的二维列表数组。最坏的情况是您只需要与其中四个列表中的对象进行比较。
还可以使用大量更复杂(并且可能有益)的解决方案 - 像双树这样的解决方案实现起来有点复杂(虽然不是很多),但可以获得更优化的性能(特别是在对象密度变化的情况下)相当)。
Use some sort of spatially partitioned data structure. A simple solution would be to simply create a 2d array of lists containing all objects within a 30m x 30m region. Worst case is then that you only need to compare against the objects in four of those lists.
Plenty of more complex (and potentially beneficial) solutions could also be used - something like bi-trees are a bit more complex to implement (not by much though), but could get more optimum performance (especially in cases where the density of objects varies considerably).
您可以查看 matlab 中的 voronoi 图支持:
http:// /www.mathworks.com/access/helpdesk/help/techdoc/ref/voronoi.html
如果您将 voronoi 多边形基于关键树,并将相邻树聚集到这些多边形中,这将分割您的搜索空间通过接近度(找到给定非关键点的封闭多边形很快),但最终您将通过毕达哥拉斯或三角函数计算关键到非关键距离并进行比较。
对于几千个点(树)来说,如果你有一个合理的处理器,那么暴力破解可能就足够快了。计算每棵树与 n 棵树的距离,然后选择 30 英尺以内的树。这与将所有树放在同一个 voronoi 多边形中是一样的。
我从事 GIS 工作已经有几年了,但我发现以下内容很有用:《C 语言计算几何》Joseph O Rourke,ISBN 0-521-44592-2 平装本。
You could look at the voronoi diagram support in matlab:
http://www.mathworks.com/access/helpdesk/help/techdoc/ref/voronoi.html
If you base the voronoi polygons on your key trees, and cluster the neighbouring trees into those polygons, that would partition your search space by proximity (finding the enclosing polygon for a given non-key point is fast), but ultimately you're going to get down to computing key to non-key distances by pythagoras or trig and comparing them.
For a few thousand points (trees) brute force might be fast enough if you have a reasonable processor on board. Compute the distance of every other tree from tree n, then select those within 30'. This is the same as having all trees in the same voronoi polygon.
Its been a few years since I worked in GIS but I found the following useful: 'Computational Geometry In C' Joseph O Rourke, ISBN 0-521-44592-2 Paperback.