如何在仿真中动态计算以正交割草机模式测量的连接 2-UAV 的节点(USV)路径?

How to dynamically calculate path for Node (USV) for connected 2-UAV which are surveying in orthogonal lawnmower pattern in simulation?

我正在编写一个涉及2-UUV 和1-USV 的模拟脚本。两种水下航行器都在正交割草机运动模型中进行测量。我想留在两辆车的范围内,所以他们从同一个起点开始。我想知道如何定义 USV 运动模型,使其在大多数情况下始终处于两个 UUV 的通信范围内。

  1. 基本上我如何手动为 USV 提供动态路径规划/运动模型,以便我可以在大多数时间与 UUV 进行通信?有可能吗?有人可以提供一个基本示例或为我指明正确的方向吗?

这是我的模拟脚本:

import org.arl.fjage.RealTimePlatform
import org.arl.unet.sim.MotionModel

///////////////////////////////////////////////////////////////////////////////
// display documentation

println '''
Bedford Basin AUV node network
------------------------------

Node USV-1: tcp://localhost:1101, http://localhost:8081/
Node UUV-1: tcp://localhost:1102, http://localhost:8082/
Node UUV-2: tcp://localhost:1103, http://localhost:8083/

------------------------------
------------------------------
'''

///////////////////////////////////////////////////////////////////////////////
// simulator configuration

platform = RealTimePlatform   // use real-time mode
// origin = [44.696178,-63.632992] // Bedford basin GPS co-ordinates 
origin = [44.434153,-63.251702]

simulate{
  def n1 = node 'USV', location: [0.m, -100.m,  1.8.m], heading: 45.deg, mobility: true, web: 8081, api: 1101, stack: "$home/etc/setup"
    n1.motionModel = MotionModel.lawnmower(speed: 0.5.mps, leg: 200.m, spacing: 50.m, legs: 17) 
                      
  def n2 = node 'UUV-1', location: [0.m,  0.m,  30.m], heading: 90.deg, mobility: true, web: 8082, api: 1102, stack: "$home/etc/setup"
    // n2.motionModel = MotionModel.lawnmower(speed: 3.3554.mps, leg: 6000.m, spacing: 40.m, legs: 150)
    n2.motionModel = MotionModel.lawnmower(speed: 0.3.mps, leg: 1000.m, spacing: 50.m, legs: 20)
  def n3 = node 'UUV-2', location: [0.m,  0.m,  30.m], heading: 180.deg, mobility: true, web: 8083, api: 1103, stack: "$home/etc/setup"
    //  n3.motionModel = MotionModel.lawnmower(speed: 3.3554.mps, leg: 6000.m, spacing: -40.m, heading:90.deg, legs: 150)
     n3.motionModel = MotionModel.lawnmower(speed: 0.3.mps, leg: 1000.m, spacing: -50.m, heading:90.deg, legs: 20)
}
  1. 如何将 platform = DiscreteEventSimulator 与运动模型一起使用?如果我想在更短的时间内模拟几个小时的模拟?

参考:

  1. “使用单个信标的合作水下范围导航路径规划”,M.Chitre

Unet 模拟器支持多级运动模型,具体取决于模拟中所需的复杂性。

每个模拟节点中的NodeInfo代理实现了一个基本的动力学模型。使用可以在模拟脚本中或直接在 NodeInfo 代理上设置的 mobility 标志打开模型。启用 mobility 时,代理会使用简单动力学模型根据 speedheading 等运动参数自动更新 location。这可以方便地模拟节点的运动,例如,AUV 游离水下调制解调器。

我们可以通过在模拟中手动更新其中一个节点的参数来轻松地做到这一点。使用来自 Unet IDE 的 2-node-network 示例。 IDE 的“地图”视图可以方便地可视化节点的运动。连接到节点A的WebShell,设置mobilityheadingspeed参数。随着模拟的继续,节点 A 的位置将根据 speedheading.

继续更新
// On Node A's shell, set heading to 45deg and speed to 10m/s
node.mobility = true
node.heading = 45
node.speed = 10

对于更高级的用例,Unet 模拟脚本允许在节点上设置一系列运动参数设定值。这是使用模拟脚本中 node 对象上的 motionModel 参数完成的。 Unet Handbook has a few examples of this in Chapter 30.

motionModel设置为MapsList,每个设置点具有各种运动属性,将自动将属性设置到特定模拟的NodeInfo代理上节点 at/for 适当 time/duration。这反过来驱动 NodeInfo 中的动力学模型,给出设定点之间的内插位置。例如,可以使用这个使用 4 个设定点的模拟脚本来模拟在正方形中移动的节点。请注意,运动会在最后一个设定点后自动停止。

def n = node 'B', location: [ 1.km, 0.km, -15.m], web: 8082, api: 1102, stack: "$home/etc/setup", mobility: true
n.motionModel = [
  [time:     0.minutes, heading:  0.deg, speed:   1.mps],
  [time:     1.minutes, heading:  -90.deg, speed: 1.mps],
  [time:     2.minutes, heading:  180.deg, speed: 1.mps],
  [time:     3.minutes, heading:  90.deg, speed:  1.mps],
]

实用方法 MotionModel.lawnmower 有助于为割草机运动模式的一组属性设置点 Map 生成此 List

最后,如果需要更细粒度的运动控制,可以将模拟节点的属性 motionModel设置为Groovy Closure. The Closure is called by the simulator with the current simulation timestamp and is expected to return a single Setpoint in form of a Groovy Map。例如,可以通过将此 Closure 分配给 motionModel.

来实现与方形图案类似的逻辑
def n = node 'B', location: [ 1.km, 0.km, -15.m], web: 8082, api: 1102, stack: "$home/etc/setup", mobility: true
startTime = -1
n.motionModel = { ts -> 
  def setpoint = [speed: 10.mps, duration: 1.minutes]
  if (startTime < 0) startTime = ts
  if (ts <= startTime+1.minutes){
    setpoint["heading"] = 0.deg
  } else if (ts <= startTime+2.minutes){
    setpoint["heading"] = -90.deg
  } else if (ts <= startTime+3.minutes){
    setpoint["heading"] = 180.deg
  } else if (ts <= startTime+4.minutes){
    setpoint["heading"] = 90.deg
  } else {
    setpoint = [speed:0.mps]
  }
  return setpoint
}

更复杂的逻辑也可以在这样的内部实现 Closures 包括与其他代理甚至其他节点通信。

最后,基于 Closure 的方法还可以允许通过简单地返回带有 location 属性 的设定值来覆盖 NodeInfo 代理中的内置动力学模型这将允许直接从 Closure 更新节点的位置,而不是通过动态模型。