跳转到内容

Disim 高速公路模拟器/创建新的汽车行为

来自维基教科书,开放世界中的开放书籍

简单示例

[编辑 | 编辑源代码]

Disim 允许创建完全任意的行为,而无需修改其内部代码。为了说明这一点,让我们从一个简单的例子开始:想象一辆汽车应该加速以达到其当前车道的速度限制,并且如果它离前方的汽车太近,应该减速。脚本将如下所示

K = 1.0
safety_distance = 5

function init(self)
  -- Nothing to do here
end

function think(self, dt, neighbors)
  -- Current maximal speed allowed on this lane
  lane_speed = self:getLane():getSpeedLimit()
  lane_acceleration = (lane_speed - self:getSpeed())*K

  -- Get distance to leading car
  lead = neighbors[LEAD].car
  if (lead) then
    f = self:getGeometry()
    phi,r = lead:getGeometry()
    lead_distance = neighbors[LEAD].distance - f - r
    lead_acceleration = (lead:getSpeed()^2 - self:getSpeed()^2)/(lead_distance-safety_distance)
  else
    lead_acceleration = 1000
  end

  return math.min(lane_acceleration, lead_acceleration), 0
end

function destroy(self)
  -- Nothing to do here too
end

什么是脚本语言?

[编辑 | 编辑源代码]

该脚本是使用 LUA (https://lua.ac.cn/manual/5.1/manual.html) 编写的:Lua 是一种扩展编程语言,旨在支持具有数据描述功能的通用过程式编程。它还为面向对象编程、函数式编程和数据驱动编程提供了良好的支持。Lua 旨在用作任何需要脚本语言的程序的强大、轻量级脚本语言。Lua 作为库实现,用干净的 C 语言编写(即,在 ANSI C 和 C++ 的通用子集中)。

Disim 允许任何人使用 LUA 作为脚本语言来创建和重新定义汽车行为。在 LUA 中创建汽车行为有几个优点:不需要编译,提供简化的 API,并且您可以从 LUA 的所有功能中受益(表、匿名函数、字典等)。正如我们在上面的例子中看到的那样,每个脚本都应该提供以下 3 个函数

function init(self, options)

该函数接受两个变量作为输入。self 变量是指向当前正在初始化的汽车的 LuaCar 指针(该汽车刚刚进入高速公路),options 变量是通过 lua-args 命令行选项传递给 Disim 的字符串。请注意,如果脚本需要保存与该汽车相关的特定数据,它应该在外部变量或数组中这样做(例如 vars[self] = { max_speed = 10.0 })。脚本不会针对每辆车单独加载,因此 self 在每次调用此函数时都可能不同。此函数不返回任何值。

function think(self, dt, neighbors)

该函数接受三个变量作为输入

  • self:与输入函数一样,这是一个指向当前正在控制的汽车的指针。
  • dt:这是自上次针对特定汽车调用该函数以来的时间步长持续时间(以秒为单位)。
  • neighbors:此数组至少包含 6 个元素,您可以使用 LEAD、TRAIL、LEFT_LEAD、LEFT_TRAIL、RIGHT_LEAD、RIGHT_TRAIL 键访问它们(例如 neighbors[LEFT_LEAD])。此数组的每个元素都是一个带有 2 个键的数组:cardistance。因此,您可以使用 neighbors[LEAD].car 访问引导车辆的汽车指针,并使用 neighbors[LEAD].distance 访问与该车辆的纵向距离。

此函数需要返回 2 个值:第一个是加速度(将应用于汽车,直到下一个时间步长),第二个是车道变更命令。例如,要让汽车以 2.0 m/s2 的速度加速并变道到左侧车道,您可以执行以下操作:return 2.0, -1。要以 -1.0 m/s2 的速度变道到右侧车道制动,您可以执行以下操作:return -1.0, 1,并且要什么也不做,您可以执行以下操作:return 0, 0。

function destroy(self)

该函数接受一个变量作为输入。此变量是指向当前正在销毁的汽车的指针(该汽车刚刚驶出高速公路)。在此函数中,您应该清理所有由 init 为该车辆初始化的变量。

如上所示,所有提供的函数都将指向当前正在控制的车辆的指针作为参数。此指针描述了 LUA 中的一个对象:LuaCar。要查看您可以使用此对象执行的操作,请查看 Disim 的 LUA API,可在此处获得 此处

下一步是什么?

[编辑 | 编辑源代码]

下一部分中,我们将看到如何创建脚本以控制基础设施。

华夏公益教科书