#1 添加 'rrt.java'

Merged
DemonKing merged 1 commits from demonking-patch-2 into master 1 year ago
  1. +209
    -0
      rrt.java

+ 209
- 0
rrt.java View File

@@ -0,0 +1,209 @@
package DemonKing;

/**
* <p>

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;

public class RRTStar {

private List<Point> nodes;
private static final double step = 20.0;
private static final double goalTolerance = 5;
private static final double obstacleRadius = 1.0;
private static final double expandDistance = 5.0;
private static final int maxIter = 10000;

public static void main(String[] args) {
// 设置起点和终点
Point start = new Point(0, 0);
Point goal = new Point(90, 80);
// 设置障碍
Point[] obstacles = new Point[]{new Point(40, 30), new Point(70, 50), new Point(30, 70)};
RRTStar rrt = new RRTStar();
List<Point> path = rrt.plan(start, goal, obstacles);
// 输出路径
for (Point p : path) {
System.out.println(p);
}
}

public List<Point> plan(Point start, Point goal, Point[] obstacles) {
// 创建节点列表,将起点加入列表
nodes = new ArrayList<>();
nodes.add(start);
// 开始迭代
for (int i = 0; i < maxIter; i++) {
// 随机生成一个点
Point randomPoint = getRandomPoint(goal);
// 找到距离该点最近的节点
int closestPointIndex = getClosestPointIndex(randomPoint);
Point closestPoint = nodes.get(closestPointIndex);
// 获取朝该点移动的向量
Point newPoint = getNewPoint(closestPoint, randomPoint);
// 判断是否有障碍物
if(!detectObstacle(closestPoint, newPoint, obstacles)){
// 查找距离新点最近的一些点
List<Point> nearbyPoints = getNearbyPoints(newPoint);
// 找到距离新点最优的父节点
int parentIndex = getBestParent(nearbyPoints, newPoint);
Point parentNode = nodes.get(parentIndex);
// 把新节点加入树中
nodes.add(newPoint);
// 设置新节点的父节点
newPoint.parent = parentNode;
newPoint.cost = parentNode.cost + newPoint.distance(parentNode);
// 重新排序nearbyPoints
nearbyPoints.remove(newPoint.parent);
for(Point nearbyPoint : nearbyPoints) {
double distance = nearbyPoint.distance(newPoint);
double cost = newPoint.cost + distance;
if(cost < nearbyPoint.cost && !detectObstacle(nearbyPoint, newPoint, obstacles)){
nearbyPoint.parent = newPoint;
nearbyPoint.cost = cost;
}
}
}
// 判断是否接近终点
if (newPoint.distance(goal) < goalTolerance) {
goal.parent = newPoint;
nodes.add(goal);
return getPath(goal);
}
}
// 未找到路径,返回空
return null;
}

// 随机生成一个点
private Point getRandomPoint(Point goal) {
Random random = new Random();
if (random.nextDouble() < 0.1) {
return goal;
} else {
Point p = new Point(random.nextDouble()*100, random.nextDouble()*100);
return p;
}
}

// 获取距离该点最近的节点
private int getClosestPointIndex(Point point) {
int index = 0;
double minDistance = point.distance(nodes.get(0));
for (int i = 1; i < nodes.size(); i++) {
double distance = point.distance(nodes.get(i));
if (distance < minDistance) {
minDistance = distance;
index = i;
}
}
return index;
}

// 获取朝该点移动的向量
private Point getNewPoint(Point start, Point end) {
if(start.distance(end) < step){
return end;
} else {
double theta = Math.atan2(end.y - start.y, end.x - start.x);
double x = start.x + step * Math.cos(theta);
double y = start.y + step * Math.sin(theta);
return new Point(x, y);
}
}

// 判断是否有障碍物
private boolean detectObstacle(Point start, Point end, Point[] obstacles) {
double distance = start.distance(end);
for(Point obstacle : obstacles){
if(obstacle.distance(start) < obstacleRadius || obstacle.distance(end) < obstacleRadius){
return true;
}
Point v1 = new Point(end.x - start.x, end.y - start.y);
Point v2 = new Point(obstacle.x - start.x, obstacle.y - start.y);
double cosTheta = v1.dotProduct(v2) / (v1.length() * v2.length());
double theta = Math.acos(cosTheta);
double distToLine = Math.sin(theta) * v2.length();
if(distToLine < obstacleRadius && distance > v1.length()){
return true;
}
}
return false;
}

// 查找距离新点最近的一些点
private List<Point> getNearbyPoints(Point point){
List<Point> nearbyPoints = new ArrayList<>();
for(Point p : nodes){
if(p.distance(point) < expandDistance){
nearbyPoints.add(p);
}
}
return nearbyPoints;
}

// 找到距离新点最优的父节点
private int getBestParent(List<Point> nearbyPoints, Point point) {
int bestParent = nodes.size() - 1;
double bestCost = Double.POSITIVE_INFINITY;
for (int i = 0; i < nearbyPoints.size(); i++) {
Point p = nearbyPoints.get(i);
if (!detectObstacle(p, point, new Point[0])) {
double cost = p.cost + point.distance(p);
if (cost < bestCost) {
bestCost = cost;
bestParent = nodes.indexOf(p);
}
}
}
return bestParent;
}

// 获取路径
private List<Point> getPath(Point goal) {
List<Point> path = new ArrayList<>();
path.add(goal);
Point p = goal.parent;
while (p != null) {
path.add(p);
p = p.parent;
}
Collections.reverse(path);
return path;
}
}

class Point {
public double x;
public double y;
public double cost;
public Point parent;

public Point(double x, double y) {
this.x = x;
this.y = y;
this.cost = 0;
this.parent = null;
}

public double distance(Point other){
double dx = this.x - other.x;
double dy = this.y - other.y;
return Math.sqrt(dx*dx + dy*dy);
}

public double dotProduct(Point other){
return this.x * other.x + this.y * other.y;
}

public double length(){
return Math.sqrt(this.x * this.x + this.y * this.y);
}

public String toString(){
return "(" + x + "," + y + ")";
}
}

Loading…
Cancel
Save