Threejs路径规划_基于A*算法案例V2

        路径规划算法中有两种算法使用最普遍,第一个是Dijkstr算法,第二个是A*算法,两个算法各有千秋,Dijkstra算法可以保证最优解,但是复杂度较高,尤其当点数量较多时,A*算法是一种启发式搜索算法,它不保证最优解,但成本很低,也是很多机器人移动或者游戏中人物自动寻路场景中常用的算法。

        下面来说下大概得逻辑,假设有30*30的方格,从1,1点要到25,20点,会先从1,1出发,查询1,1能到达的点,假设1,1能够到达(0,1),(1,0),(1,2),(2,1)这四个点,那么求出四个点中哪个点距离目标点(25,20)的曼哈顿距离最近,得到这个这里距离最近的点之后,再找出这个点能够到达的点,从它能够到达的点中再求出四个点中哪个点距离目标点(25,20)的曼哈顿距离最近。依此类推,直到到达目标点。

        ps:曼哈顿距离也就是横向距离加上纵向距离,而不是勾股定理求出的横向距离的平方和纵向距离的平方再开根,因为一般使用A*算法的更多的是街道或者网格状的场景,用曼哈顿距离更加符合实际场景。

        下面可以通过threejs来演示,首先在threejs场景中绘制一个30*30的网格,在绘制网格的时候就正好存储每个网格的点,并用x.y为点的名字,再存储每个点能到达点的路线,另外为了演示更真实可以防止一些障碍物,并在绘制场景的时候去掉能连接到障碍物的路线,

    initTable() {
      const cylinderMaterial = new THREE.MeshLambertMaterial({ color: '#d3d3d3' })
      const table = []
      for (let i = 0; i < 30; i++) {
        for (let j = 0; j < 30; j++) {
          const boxGeometry = new THREE.BoxGeometry(9, 9, 9)
          const box1 = new THREE.Mesh(boxGeometry, cylinderMaterial)
          box1.position.set(i * 10, j * 10, 5)
          // this.scene.add(box1)
          box1.updateMatrix()// 更新模型变换矩阵
          const boxMesh = box1.geometry.applyMatrix4(box1.matrix)// 启动并应用变换矩阵
          table.push(boxMesh)

          const params = { name: i + '.' + j, x: (i * 10), y: (j * 10) }
          this.pointList.push(params)
          if (i > 1) {
            this.roadList.push({ begin: i + '.' + j, end: (i - 1) + '.' + j })
          }
          if (j > 1) {
            this.roadList.push({ begin: i + '.' + j, end: i + '.' + (j - 1) })
          }
          this.roadList.push({ begin: i + '.' + j, end: (i + 1) + '.' + j })
          this.roadList.push({ begin: i + '.' + j, end: i + '.' + (j + 1) })
        }
      }
      const bayGeometry = mergeGeometries(table)// 合并模型数组

      const boxList = new THREE.Mesh(bayGeometry, cylinderMaterial)// 生成一整个新的模型
      this.scene.add(boxList)
      for (let i = 0; i < this.roadList.length; i++) {
        for (let j = 0; j < this.obstacle.length; j++) {
          if (this.roadList[i].begin === (this.obstacle[j].x + '.' + this.obstacle[j].y) ||
          this.roadList[i].end === (this.obstacle[j].x + '.' + this.obstacle[j].y)) {
            console.log(this.obstacle[j].x + '.' + this.obstacle[j].y)
            this.roadList.splice(i, 1)
            j--
          }
        }
      }
    },

        这样一个网格布局就绘制完成,然后可以开始按照刚才的步骤实现具体的寻路过程,在寻路时每次获取到的点都存放到集合中,并用绘制方格的方法绘制路线方格,与网格用不同的颜色来区分。

buildPath() {
      let begin = (parseInt(this.beginPoint.x) - 1) + '.' + (parseInt(this.beginPoint.y) - 1)
      const end = (parseInt(this.endPoint.x) - 1) + '.' + (parseInt(this.endPoint.y) - 1)
      this.removeOnce()
      this.drawPoint(begin)
      while (begin !== end) {
        const result = this.calcDistance(begin, end)
        this.drawPoint(result.point)
        begin = result.point
      }
    },
    calcDistance(begin, end) {
      const tempRoads = []
      for (let i = 0; i < this.roadList.length; i++) {
        if (this.roadList[i].begin === begin) {
          tempRoads.push(this.roadList[i].end)
        }
      }
      let result = { distance: Infinity, point: '' }
      for (let i = 0; i < tempRoads.length; i++) {
        const beginX = tempRoads[i].split('.')[0]
        const beginY = tempRoads[i].split('.')[1]
        const endX = end.split('.')[0]
        const endY = end.split('.')[1]
        const distance = Math.abs(parseInt(endX - beginX)) + Math.abs(parseInt(endY - beginY))
        if (distance < result.distance) {
          result = { distance: distance, point: tempRoads[i] }
        }
      }
      return result
    },
    drawPoint(point) {
      const pointX = point.split('.')[0]
      const pointY = point.split('.')[1]
      const boxGeometry = new THREE.BoxGeometry(10, 10, 10)
      const material = new THREE.MeshPhongMaterial({
        color: '#00FF00', // 设置颜色
        shininess: 20 // 设置高光大小,范围为0到128,默认值为30
      })
      const pointMesh = new THREE.Mesh(boxGeometry, material, 0)
      pointMesh.position.set(parseInt(pointX) * 10, parseInt(pointY) * 10, 6)
      pointMesh.name = 'path'
      this.scene.add(pointMesh)
    },

我们可以先设置默认的起点和结束点看下效果,设置起始点为(1,1),结束点为(20.16),规划后看下效果:

可以同样用上个章节的加入element的输入框来实现动态规划,并在每次规划后清除上一次规划的路线。

我们可以规划试试,效果如下,

A*初級

还可以把距离比较换成两个点之间的直线距离,效果如下:因为两个数相加的和相等的情况下,两个数越接近,直线距离最短,简单的说,周长相等的情况下,正方形的对角线最短。但是在实际地图中,转弯是需要花费成本的,所以还是使用曼哈顿距离更合适。

不过此方式不太适合有障碍物的情况,因为在有复杂障碍物时,并不是距离越接近目标点花费成本越低,直到到达目标点,下面的章节再探讨复杂障碍物的处理方式。

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 无人机路径规划是指在给定的三维环境中寻找一条最优路径,使得无人机从起始点到目标点之间能够避开障碍物,并满足其他约束条件。而A*算法是一种广泛应用于路径规划问题的启发式搜索算法,通过综合考虑每个节点的实际代价和预估代价,来寻找最优路径。 A*算法的具体步骤如下: 1. 初始化一个open列表和一个closed列表,将起始点加入到open列表中; 2. 重复以下步骤直到找到目标点或者open列表为空: a. 在open列表中选择代价最小的节点,将其标记为当前节点,并将其从open列表中移除; b. 将当前节点加入到closed列表中; c. 对当前节点的相邻节点进行遍历,计算它们的实际代价和预估代价(通常使用欧氏距离等启发式函数),并更新它们的父节点; d. 如果相邻节点已经存在于closed列表中,则忽略该节点; e. 如果相邻节点已经存在于open列表中并且新的路径更好(代价更小),则更新该节点的代价和父节点; f. 如果相邻节点不存在于open列表中,则将其加入open列表中; 3. 如果open列表为空,则无法找到路径;否则,从目标点逆向遍历父节点,得到路径。 在无人机三维路径规划中,A*算法需要进行适当的修改以考虑高度或者三维坐标的变化。我们可以使用三维欧氏距离或其他适当的启发式函数来估计节点之间的距离。此外,对于无人机飞行的特殊限制条件,例如最小转弯半径、最大爬升速度等,也需要在评估节点时进行考虑。 总之,基于A*算法的无人机路径规划方法能够通过综合考虑实际代价和预估代价,找到无人机三维环境中的最优路径,有效避开障碍物并满足其他飞行约束条件。 ### 回答2: 无人机路径规划是指根据特定的起点和终点,通过选择合适的路径来实现无人机从起点到终点的导航操作。在三维空间中,无人机的路径规划问题更为复杂,需要考虑高度、避障等因素。 A*算法是一种常用的启发式搜索算法,可以用于无人机三维路径规划。它将搜索空间划分为一个个小区域,每个区域都有一个启发式评估函数来估计该区域到目标的代价。在搜索过程中,根据当前位置和目标位置的启发式评估值,选择代价最小的邻近节点进行扩展,直到找到最优路径。 对于无人机路径规划,A*算法可以按照以下步骤进行求解: 1. 确定无人机的起点和终点,并初始化起点的搜索开销为0。 2. 创建一个开放列表和一个闭合列表。开放列表用于存储待扩展的节点,闭合列表用于存储已经扩展过的节点。 3. 将起点添加到开放列表中,并开始循环搜索。 4. 从开放列表中选取代价最小的节点,作为当前节点。 5. 如果当前节点是终点,则路径规划完成,返回路径。 6. 否则,将当前节点加入闭合列表,并对其邻近节点进行检查。 7. 对于每个邻近节点,计算其到起点的实际代价,并计算到终点的启发式评估值。 8. 如果该邻近节点在闭合列表中,则忽略它。如果不在开放列表中,则将其加入开放列表,并更新其启发式评估值。 9. 如果该邻近节点已经在开放列表中,比较其当前的实际代价,如果新的代价更小,则更新该节点的实际代价和父节点,并重新计算其启发式评估值。 10. 返回步骤4,直到找到最优路径或开放列表为空。 通过以上步骤,A*算法可以找到最优的三维路径规划,实现无人机从起点到终点的导航操作。同时,可以根据具体应用场景的需求,针对性地对A*算法进行改进和优化,提高路径规划的效率和准确性。 ### 回答3: 无人机三维路径规划是指根据目标点和环境条件,找到无人机从起点到目标点的最优路径。A*算法是一种常用的启发式搜索算法,结合了广度优先搜索和迪杰斯特拉算法的特点,适用于解决此类问题。 在使用A*算法进行无人机路径规划时,首先需要定义节点的表示和评估函数。以三维空间中的坐标为节点表示,节点的评估函数一般由两部分组成:启发函数和路径成本函数。 启发函数用于评估当前节点到目标节点的估计距离,可以使用曼哈顿距离、欧几里得距离等方法。路径成本函数用于评估节点到起点的实际路径成本,可根据实际情况定义。 接着,使用一个优先队列来保存待扩展的节点。首先将起点加入队列,并初始化节点的评估值。然后,从队列中取出评估值最小的节点进行扩展,并更新其相邻节点的评估值和路径成本。重复此过程,直到找到目标节点或优先队列为空。 在扩展节点时,需要考虑节点的合法性和可行性。对于无人机来说,需要考虑避开障碍物、避免碰撞等特殊情况。可以使用碰撞检测算法或避障策略来避免不必要的风险。 最后,当找到目标节点时,可以回溯路径,得到无人机从起点到目标点的最优路径。 总之,通过使用A*算法进行无人机三维路径规划,可以高效地找到起点到目标点的最优路径,提高无人机的自主导航能力和任务执行效率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

baker_zhuang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值