type
status
date
Oct 24, 2024 06:44 AM
slug
summary
tags
category
icon
password
VDA5050是什么
VDA5050 是 自动导引车 (AGV) 和主控制器之间通信接口的定义。
主控制器可以在本地,也可以在云计算中心。
沟通流程及内容
AGV运行流程至少有以下部分:
- AGV的系统提供基本信息
- 主控组织管理运行
- AGV执行指令
在实施阶段,建立了由主控和AGV组成的无人驾驶运输系统(DTS)。必要的框架条件由操作员定义,所需的信息要么由操作员手动输入,要么通过从其他系统导入来存储在主控制器中。本质上,这涉及以下内容:
- 线路定义:使用CAD导入,可以将线路导入到主控中。或者,也可以由操作员在主控制器中手动实施路线。路线可以是单向街道,限制某些车辆组(基于尺寸比例)等。
- 路线网络配置:路线内定义装卸站、充电站、周边环境(闸机、电梯、道闸)、候车位、缓冲站等。
- 车辆配置:AGV 的物理属性(尺寸、可用的负载载体安装座等)由操作员存储。 AGV 应以文档主题“情况说明书”中定义的特定方式通过主题情况
factsheet
传达此信息。
上述路由配置和路由网络不属于本文档的内容。它们构成了主控制器基于此信息和要完成的运输要求实现订单控制和驾驶路线分配的基础。然后,AGV 的最终订单通过 MQTT 消息代理传输到车辆。然后,在执行作业的同时,不断向主控制器报告其状态。这也是使用 MQTT 消息代理完成的。
主控的功能
- Assignment of orders to the AGVs
将订单分配给 AGV
- Route calculation and guidance of the AGVs (taking into account the limitations of the individual physical properties of each AGV, e.g., size, maneuverability, etc.)
AGV 的路线计算和引导(考虑到每个 AGV 个体物理特性的限制,例如尺寸、机动性等)
- Detection and resolution of blockages ("deadlocks")
阻塞(“死锁”)的检测和解决
- Energy management: Charging orders can interrupt transfer orders
能源管理:充电指令可以中断转移指令
- Traffic control: Buffer routes and waiting positions
交通管制:缓冲路线和等候位置
- (Temporary) changes in the environment, such as freeing certain areas or changing the maximum speed
(临时)环境变化,例如释放某些区域或更改最大速度
- Communication with peripheral systems such as doors, gates, elevators, etc.
与门、大门、电梯等外围系统通信
- Detection and resolution of communication errors
通信错误的检测和解决
AGV的功能
- Localization
定位
- Navigation along associated routes (guided or autonomous)
沿着相关路线导航(引导或自主)
- Execution of actions
行动的执行
- Continuous transmission of vehicle status
车辆状态持续传输
协议规范
协议规定了主控与AGV之间的通信。不同的消息显示在描述作为指令、状态等发送的 JSON 字段内容的表格中。
此外,JSON 架构可在公共 git 存储库 ( https://github.com/VDA5050/VDA5050 ) 中进行验证。
表格符号及格式含义
Identification | Description |
standard | Variable is an elementary data type |
bold | Variable is a non-elementary data type (e.g., JSON object or array) and defined separately |
italic | Variable is optional |
italic and bold | Variable is optional and a non-elementary data type |
arrayName[arrayDataType] | Variable (here arrayName) is an array of the data type included in the square brackets (here the data type is arrayDataType) |
Optional
如果一个变量被标记为可选,则意味着它对于发送者来说是可选的,因为该变量在某些情况下可能不适用(例如,当主控向 AGV 发送命令时,一些 AGV 会自行规划其轨迹和场地)
edge
对象内的trajectory
顺序可以省略)。主控只发送AGV支持的可选信息。
示例:轨迹是可选的。如果AGV无法处理轨迹,主控不得向车辆发送轨迹。
AGV 应通过 AGV
factsheet
消息传达其需要的可选参数。允许的字符和字段长度
所有通信均以 UTF-8 编码,以实现描述的国际适应。建议 ID 应仅使用以下字符:
A-Z a-z 0-9 _ - . :
最大消息长度没有定义,但受到 MQTT 协议规范的限制,并且可能受到情况说明书中定义的技术约束的限制。如果 AGV 内存不足以处理传入订单,则会拒绝该订单。最大字段长度、字符串长度或值范围的匹配由积分器决定。为了便于集成,AGV 供应商应提供 AGV 资料表,详细信息请参阅资料表部分。
字段、主题和枚举的表示法
本文档中的主题和字段以以下样式突出显示:
exampleField
和exampleTopic
。枚举应以大写字母书写。这些值在文档中用单引号引起来。这包括诸如actionStatus
字段中的关键字(“WAITING”、“FINISHED”等)。JSON 数据类型
如果可能,应使用 JSON 数据类型。因此,布尔值由“true”或“false”编码,而不是用枚举(“TRUE”、“FALSE”)或幻数编码。
数值数据类型用类型和精度指定,例如float64 或uint32。不支持 IEEE 754 中的特殊数值,例如 NaN 和无穷大。
MQTT 连接处理、安全性和 QoS
MQTT 协议提供为客户端设置最后遗嘱消息的选项。如果客户端因任何原因意外断开连接,最后的遗嘱将由代理分发给其他订阅的客户端。该功能的使用在第6.14 节主题“连接”中描述。
如果 AGV 与代理断开连接,它会保留所有指令信息并履行直到最后发布的节点为止的指令。
代理配置需要考虑协议安全性。
为了减少通信开销,MQTT QoS 级别 0(尽力而为)将用于主题
order
、 instantActions
、 state
、 factsheet
和visualization
。主题connection
应使用 QoS 级别 1(至少一次)。MQTT 主题级别
以下部分中定义的主题名称是强制性的。
对于本地broker,建议的 MQTT 主题级别如下:
interfaceName/majorVersion/manufacturer/serialNumber/topic
Example:
MQTT Topic Level | Data type | Description |
interfaceName | string | Name of the used interface |
majorVersion | string | Major version number of the VDA 5050 recommendation, preceded by "v" |
manufacturer | string | Manufacturer of the AGV. |
serialNumber | string | Unique AGV serial number consisting of the following characters:A-Za-z0-9_.:- |
topic | string | Topic (e.g., order or state) see Section 6.5 Topics for Communication |
注意:由于
/
字符用于定义主题层次结构,因此不得在上述任何字段中使用它。 $
字符也在一些 MQTT 代理中用于特殊的内部主题,因此也不应该使用它。Protocol header
每个 JSON 消息都以header开头。在以下部分中,为了便于阅读,以下字段将被引用为header。header由以下各个元素组成。header不是 JSON 对象。
Object structure/Identifier | Data type | Description |
headerId | uint32 | Header ID of the message.The headerId is defined per topic and incremented by 1 with each sent (but not necessarily received) message. |
timestamp | string | Timestamp (ISO 8601, UTC); YYYY-MM-DDTHH:mm:ss.ffZ (e.g., "2017-04-15T11:40:03.12Z"). |
version | string | Version of the protocol [Major].[Minor].[Patch] (e.g., 1.3.2). |
manufacturer | string | Manufacturer of the AGV. |
serialNumber | string | Serial number of the AGV. |
Topics for communication
AGV协议使用以下主题进行主控与AGV之间的信息交换。
Topic name | Published by | Subscribed by | Used for | Implementation | Schema |
order | master control | AGV | Communication of driving orders from master control to the AGV | mandatory | order.schema |
instantActions | master control | AGV | Communication of the actions that are to be executed immediately | mandatory | instantActions.schema |
state | AGV | master control | Communication of the AGV state | mandatory | state.schema |
visualization | AGV | Visualization systems | Higher frequency of position topic for visualization purposes only | optional | visualization.schema |
connection | Broker/AGV | master control | Indicates when AGV connection is lost, not to be used by master control for checking the vehicle health, added for an MQTT protocol level check of connection | mandatory | connection.schema |
factsheet | AGV | master control | Parameters or vendor-specific information to assist set-up of the AGV in master control | mandatory | factsheet.schema |
Topic内容
Topic: "order" (from master control to AGV)
概念与逻辑
主题“order”是 MQTT 主题,AGV 通过该主题接收 JSON 封装的order。
order的基本结构是节点和边的图。 AGV 预计会遍历节点和边来完成order。所有连接的节点和边的完整图由主控制保存。
Graph representation in master control and graph transmitted in orders
- 节点和边作为order消息中的两个列表进行传递。这些列表中的节点和边的顺序也决定了节点和边的遍历顺序。
- 对于有效的order,至少应有一个节点,并且边的数量应等于节点数减一。
- AGV 应该能够轻松到达订单的第一个节点。这意味着要么AGV已经站在节点上,要么AGV处于节点的偏差范围内。
- 节点和边都有一个布尔属性
released
。如果某个节点或边被释放,AGV 就会穿过它。如果节点或边未被释放,AGV 不得遍历它。
- 只有当一条边的起始节点和结束节点都被释放时,该边才能被释放。
- 在未释放的边之后,序列中不能跟随任何已释放的节点或边。
- 释放的节点和边的集合称为“base”。未释放的节点和边的集合称为“horizon”。
- 发送没有horison的order是合法的。
- order消息不一定描述完整的运输订单。为了进行交通控制并容纳资源受限的车辆,完整的运输order(可能由许多节点和边组成)可以分为许多子order,这些子order通过其
orderId
和orderUpdateId
连接。更新order的过程将在下一节中描述。
Orders and order update
为了支持流量管理,主控可以将通过命令通信的路径分为两部分:
- “Base” :这是允许 AGV 行驶的定义路线。基本路线的所有节点和边缘均已被车辆主控释放。基的最后一个节点称为decision point。
- “horizon” :这是主控当前规划的AGV在决策点之后行驶的路线。horizon路径尚未被主控释放。
如果没有进一步的节点和边添加到基础上,AGV 将停止在决策点。为了保证运动流畅,在交通情况允许的情况下,主控应在AGV到达决策点之前扩展base。
由于 MQTT 是异步协议,通过无线网络传输不可靠,因此base无法更改。因此,主控应假定base已被 AGV 执行。后面的部分描述了取消order的过程,但由于上述通信限制,这也被认为是不可靠的。
主控制器可以通过向 AGV 发送更新的路线来改变horizon,其中包括更改的节点和边列表。改变horizon路径的流程如图4所示。
图4 更改行驶路线“Horizon”的流程
在图 4 中,控制面板首先在时间 t = 1 时发送初始作业。图 5 显示了可能作业的伪代码。为了便于阅读,这里省略了完整的 JSON 示例。
图 5 order的伪代码。
在时间 t = 3 时,通过发送order扩展来更新order(参见图 6 中的示例)。请注意,
orderUpdateId
会递增,并且order更新的第一个节点对应于前一个order消息的最后一个共享base节点。这确保了AGV也可以执行order更新,即通过执行AGV已知的边可以到达作业更新的第一个节点。
图 6 order更新的伪代码。请注意orderUpdateId
的更改。
这在order update丢失的情况下也有帮助(例如,由于无线网络不可靠)。 AGV 始终可以检查最后一个已知的基本节点是否与第一个新的基本节点具有相同的
nodeId
(以及nodeSequenceId
,稍后会详细介绍)。另请注意,节点 g 是唯一再次发送的基节点。由于基数无法更改,因此节点 f 和 d 的重传无效。
重要的是,拼接节点(示例中的节点 g)的内容不会改变。对于动作、偏差范围等,AGV应使用第一条order中提供的指令(图5,orderUpdateId 0)。
图7 定期更新流程-order extension。
图 7 描述了如何延长order。它显示 AGV 当前可用的信息。
orderId
保持不变, orderUpdateId
递增。前一个基节点的最后一个节点是更新顺序中的第一个基节点。通过该节点,AGV 可以将更新的order添加到当前order上(缝合)。来自前一个基的其他节点和边不会重新发送。
主控制可以选择通过发送完全不同的节点作为新base来更改horizon。horizon也可以删除。
为了允许按顺序循环(例如从节点 a 到 b,然后再返回到 a),将
sequenceId
分配给节点和边对象。该sequenceId
在节点和边上运行(订单的第一个节点接收0,第一个边然后获取1,第二个节点然后获取2,依此类推)。这样可以更轻松地跟踪order进度。一旦分配了
sequenceId
,它就不会随着order更新而改变(参见图7)。这对于AGV侧确定主控指的是哪个节点是必要的。图8描述了接受order或order更新的过程。
图8 接受order或order update的流程。
Order cancellation
如果基本节点发生意外更改,则应使用 instantAction
cancelOrder
取消order。图 9cancelOrder
后的预期行为。
取消order后,车辆应处于接受新order的状态。
如果 AGV 通过标签将自身定位在节点上,则新order必须从 AGV 现在所在的节点开始(另请参见图 5)。
如果 AGV 可以在节点之间停止,则选择由主控制如何启动下一个order。 AGV 应接受这两种方法。
两种选择:
- 发送一个order,其中第一个节点是临时节点,位于AGV当前所在的位置。然后,AGV 应意识到该节点是可轻松到达的并接受order。
- 发送一个order,其中第一个节点是上一个订单的最后一个遍历的节点,但将偏差范围设置得足够大,使 AGV 在此范围内。因此,AGV 应意识到该节点应被计为已遍历并接受order。
如果 AGV 收到
cancelOrder
操作,但 AGV 当前没有order,或者先前的order已取消,则cancelOrder
操作应报告为“FAILED”。AGV 应报告“noOrderToCancel”错误,并将
errorLevel
设置为“警告”。 instantAction
的actionId
应作为errorReference
传递。Order rejection
‣
Corridors
可选的
corridor
边缘属性允许车辆偏离边缘轨迹以避障,并定义允许车辆运行的边界。要使用corridor
属性,需要一个预定义的轨迹,如果未定义corridor
属性,车辆将遵循该轨迹。这可以是主控制器已知的在车辆上定义的轨迹,也可以是按order发送的轨迹。使用corridor
属性的车辆的行为仍然是线路引导车辆的行为,只不过它允许暂时偏离轨迹以避开障碍物。备注:order内的边定义两个节点之间的逻辑连接,而不一定是车辆从起始节点行驶到结束节点时遵循的(真实)轨迹。根据车辆类型,车辆在起始节点和结束节点之间采取的轨迹要么由主控制通过轨迹边缘属性定义,要么作为预定义轨迹分配给车辆。根据车辆的内部状态,选择的轨迹可能会有所不同。
图 10 具有corridor
属性的边缘,定义了允许车辆偏离其预定义轨迹以避开障碍物的左右边界。左侧,运动中心定义了允许的偏差,而右侧,车辆的轮廓(可能因负载而延伸)定义了允许的偏差。这是由corridorRefPoint
参数定义的。
允许车辆独立导航(并偏离原始边缘轨迹)的区域由左边界和右边界定义。可选的
corridorRefPoint
字段指定车辆控制点或车辆轮廓是否应位于定义的边界内。边缘的边界应以这样的方式定义:车辆一经过节点就位于新的当前边缘的边界内。如果车辆不偏离轨迹,主控不应使用corridor
属性,而不是将走廊边界设置为零。车辆的运动控制软件应不断检查车辆是否在定义的边界内。否则,车辆应因超出允许的导航空间而停车并报告错误。主控制器可以通过取消当前命令并向车辆发送带有允许车辆再次移动的走廊信息的新命令来决定是否需要用户交互或者车辆是否可以继续。
备注:允许车辆偏离轨迹会增加车辆在行驶过程中可能的足迹。在初始运行时,如果主控根据车辆的足迹做出交通控制决策,则应考虑这种情况。
另请参阅遍历节点和进入/离开边缘以获取更多信息。
Implementation of the order message
Object structure | Unit | Data type | Description |
headerId | ㅤ | uint32 | Header ID of the message.The header ID is defined per topic and incremented by 1 with each sent (but not necessarily received) message. |
timestamp | ㅤ | string | Timestamp (ISO 8601, UTC); YYYY-MM-DDTHH:mm:ss.ffZ (e.g., "2017-04-15T11:40:03.12Z") |
version | ㅤ | string | Version of the protocol [Major].[Minor].[Patch] (e.g., 1.3.2) |
manufacturer | ㅤ | string | Manufacturer of the AGV |
serialNumber | ㅤ | string | Serial number of the AGV |
orderId | ㅤ | string | Order identification.This is to be used to identify multiple order messages that belong to the same order. |
orderUpdateId | ㅤ | uint32 | Order update identification.Is unique per orderId.If an order update is rejected, this field is to be passed in the rejection message. |
zoneSetId | ㅤ | string | Unique identifier of the zone set, that the AGV has to use for navigation or that was used by master control for planning.Optional: Some master control systems do not use zones.Some AGVs do not understand zones.Do not add to message, if no zones are used. |
nodes [node] | ㅤ | array | Array of node objects to be traversed for fulfilling the order.One node is enough for a valid order.Leave edge array empty in that case. |
edges [edge] | ㅤ | array | Array of edge objects to be traversed for fulfilling the order.One node is enough for a valid order.Leave edge array empty in that case. |
Object structure | Unit | Data type | Description |
node { | ㅤ | JSON object | ㅤ |
nodeId | ㅤ | string | Unique node identification |
sequenceId | ㅤ | uint32 | Number to track the sequence of nodes and edges in an order and to simplify order updates.The main purpose is to distinguish between a node, which is passed more than once within one orderId.The variable sequenceId runs across all nodes and edges of the same order and is reset when a new orderId is issued. |
nodeDescription | ㅤ | string | Additional information on the node |
released | ㅤ | boolean | "true" indicates that the node is part of the base."false" indicates that the node is part of the horizon. |
nodePosition | ㅤ | JSON object | Node position.Optional for vehicle types that do not require the node position (e.g., line-guided vehicles). |
actions [action]} | ㅤ | array | Array of actions to be executed on a node.Empty array, if no actions required. |
Object structure | Unit | Data type | Description |
nodePosition { | ㅤ | JSON object | Defines the position on a map in a global project-specific world coordinate system.Each floor has its own map.All maps shall use the same project-specific global origin. |
x | m | float64 | X-position on the map in reference to the map coordinate system.Precision is up to the specific implementation. |
y | m | float64 | Y-position on the map in reference to the map coordinate system.Precision is up to the specific implementation. |
theta | rad | float64 | Range: [-Pi ... Pi]Absolute orientation of the AGV on the node.Optional: vehicle can plan the path by itself.If defined, the AGV has to assume the theta angle on this node.If previous edge disallows rotation, the AGV shall rotate on the node.If following edge has a differing orientation defined but disallows rotation, the AGV is to rotate on the node to the edges desired rotation before entering the edge. |
allowedDeviationXY | m | float64 | Indicates how precisely an AGV shall match the position of a node for it to be considered traversed.If = 0.0: no deviation is allowed (no deviation means within the normal tolerance of the AGV manufacturer).If > 0.0: allowed deviation radius in meters.If the AGV passes a node within the deviation radius, the node can be considered traversed. |
allowedDeviationTheta | rad | float64 | Range: [0.0 ... Pi]Indicates how precise the orientation defined in theta has to be met on the node by the AGV.The lowest acceptable angle is theta - allowedDeviationTheta and the highest acceptable angle is theta + allowedDeviationTheta. |
mapId | ㅤ | string | Unique identification of the map on which the position is referenced.Each map has the same project-specific global origin of coordinates.When an AGV uses an elevator, e.g., leading from a departure floor to a target floor, it will disappear off the map of the departure floor and spawn in the related lift node on the map of the target floor. |
mapDescription} | ㅤ | string | Additional information on the map. |
Object structure | Unit | Data type | Description |
action { | ㅤ | JSON object | Describes an action that the AGV can perform. |
actionType | ㅤ | string | Name of action as described in the first column of "Actions and Parameters".Identifies the function of the action. |
actionId | ㅤ | string | Unique ID to identify the action and map them to the actionState in the state.Suggestion: Use UUIDs. |
actionDescription | ㅤ | string | Additional information on the action |
blockingType | ㅤ | string | Enum {'NONE', 'SOFT', 'HARD'}:'NONE': allows driving and other actions;'SOFT': allows other actions but not driving;'HARD': is the only allowed action at that time. |
actionParameters [actionParameter]} | ㅤ | array | Array of actionParameter objects for the indicated action, e.g., "deviceId", "loadId", "external triggers".An example implementation can be found in 7.2 Format of parameters. |
Object structure | Unit | Data type | Description |
edge { | ㅤ | JSON object | Directional connection between two nodes. |
edgeId | ㅤ | string | Unique edge identification. |
sequenceId | ㅤ | uint32 | Number to track the sequence of nodes and edges in an order and to simplify order updates.The variable sequenceId runs across all nodes and edges of the same order and is reset when a new orderId is issued. |
edgeDescription | ㅤ | string | Additional information on the edge. |
released | ㅤ | boolean | "true" indicates that the edge is part of the base."false" indicates that the edge is part of the horizon. |
startNodeId | ㅤ | string | nodeId of first node within the order. |
endNodeId | ㅤ | string | nodeId of the last node within the order. |
maxSpeed | m/s | float64 | Permitted maximum speed on the edge.Speed is defined by the fastest measurement of the vehicle. |
maxHeight | m | float64 | Permitted maximum height of the vehicle, including the load, on the edge. |
minHeight | m | float64 | Permitted minimal height of the load handling device on the edge. |
orientation | rad | float64 | Orientation of the AGV on the edge. The value orientationType defines if it has to be interpreted relative to the global project-specific map coordinate system or tangential to the edge. In case of interpreted tangential to the edge, 0.0 denotes driving forwards and PI denotes driving backwards.Example: orientation Pi/2 rad will lead to a rotation of 90 degrees.If the AGV starts in a different orientation, rotate the vehicle on the edge to the desired orientation, if rotationAllowed is set to "true".If rotationAllowed is "false", rotate before entering the edge.If that is not possible, reject the order.If no trajectory is defined, apply the rotation to the direct path between the two connecting nodes of the edge.If a trajectory is defined for the edge, apply the orientation to the trajectory. |
orientationType | ㅤ | string | Enum {'GLOBAL', 'TANGENTIAL'}:'GLOBAL': relative to the global project-specific map coordinate system;'TANGENTIAL': tangential to the edge.If not defined, the default value is 'TANGENTIAL'. |
direction | ㅤ | string | Sets direction at junctions for line-guided or wire-guided vehicles, to be defined initially (vehicle-individual).Examples: "left", "right", "straight". |
rotationAllowed | ㅤ | boolean | "true": rotation is allowed on the edge."false": rotation is not allowed on the edge.Optional:No limit, if not set. |
maxRotationSpeed | rad/s | float64 | Maximum rotation speedOptional:No limit, if not set. |
trajectory | ㅤ | JSON object | Trajectory JSON object for this edge as NURBS.Defines the path, on which the AGV should move between the start node and the end node of the edge.Optional:Can be omitted, if the AGV cannot process trajectories or if the AGV plans its own trajectory. |
length | m | float64 | Length of the path from the start node to the end nodeOptional:This value is used by line-guided AGVs to decrease their speed before reaching a stop position. |
corridor | ㅤ | JSON object | Definition of boundaries in which a vehicle can deviate from its trajectory, e.g., to avoid obstacles. |
action [action]} | ㅤ | array | Array of actions to be executed on the edge.Empty array, if no actions required.An action triggered by an edge will only be active for the time that the AGV is traversing the edge which triggered the action.When the AGV leaves the edge, the action will stop and the state before entering the edge will be restored. |
Object structure | Unit | Data type | Description |
trajectory { | ㅤ | JSON object | ㅤ |
degree | ㅤ | float64 | Range: [1.0 ... float64.max]Degree of the NURBS curve defining the trajectory.If not defined, the default value is 1. |
knotVector [float64] | ㅤ | array | Range: [0.0 ... 1.0]Array of knot values of the NURBS.knotVector has size of number of control points + degree + 1. |
controlPoints [controlPoint]} | ㅤ | array | Array of controlPoint objects defining the control points of the NURBS, explicitly including the start and end point. |
Object structure | Unit | Data type | Description |
controlPoint { | ㅤ | JSON object | ㅤ |
x | ㅤ | float64 | X-coordinate described in the world coordinate system. |
y | ㅤ | float64 | Y-coordinate described in the world coordinate system. |
weight | ㅤ | float64 | Range: [0.0 ... float64.max]The weight of the control point on the curve.When not defined, the default will be 1.0. |
} | ㅤ | ㅤ | ㅤ |
Object structure | Unit | Data type | Description |
corridor { | ㅤ | JSON object | ㅤ |
leftWidth | m | float64 | Range: [0.0 ... float64.max]Defines the width of the corridor in meters to the left related to the trajectory of the vehicle (see Figure 13). |
rightWidth | m | float64 | Range: [0.0 ... float64.max]Defines the width of the corridor in meters to the right related to the trajectory of the vehicle (see Figure 13). |
corridorRefPoint} | ㅤ | string | Defines whether the boundaries are valid for the kinematic center or the contour of the vehicle. If not specified the boundaries are valid to the vehicles kinematic center.Enum { 'KINEMATICCENTER' , 'CONTOUR' } |
- Author:NotionNext
- URL:https://tangly1024.com/article/1299b391-226a-8079-97f3-f737a263c71e
- Copyright:All articles in this blog, except for special statements, adopt BY-NC-SA agreement. Please indicate the source!
Relate Posts