快速入门

无人车-注册示例代码

  1#!/usr/bin/env python
  2
  3import argparse
  4import time
  5from time import sleep
  6
  7# 刹车需要的秒数
  8BRAKE_V = 0.05
  9
 10
 11def main():
 12    argparser = argparse.ArgumentParser(
 13        description=__doc__)
 14    argparser.add_argument(
 15        '-i', '--address',
 16        default='127.0.0.1')
 17    argparser.add_argument(
 18        '-p', '--port',
 19        type=int,
 20        default=2000)
 21    argparser.add_argument(
 22        '-n', '--number',
 23        type=int,
 24        default=5)
 25    argparser.add_argument(
 26        '-s', '--subject',
 27        type=int,
 28        default=1
 29    )
 30    args = argparser.parse_args()
 31    ue_ip = args.address.strip()
 32    ue_port = args.port
 33    num = args.number
 34    try:
 35        # 列表,用于后续控制
 36        nodes = []
 37
 38        # 1. 首先引入sdk
 39        from swarmae.SwarmAEClient import SwarmAEClient
 40        # 2. 连接UE
 41        client = SwarmAEClient(ue_ip=ue_ip, ue_port=ue_port)
 42        timestamp, world, code = client.get_world()
 43        objects = world.get_environment_objects()
 44
 45        # 注册车辆
 46        for id in range(num):
 47            # node_no 从1开始编号
 48            timestamp, node, code = client.register_node(
 49                node_type="四轮车", node_name="节点" + str(id+1), node_no=id+1, frame_timestamp=int(round(time.time() * 1000))
 50            )
 51            if code == 200:
 52                # 获取信息
 53                node_name, node_no, _, node_type, node_model, color = node.get_node_info()
 54                nodes.append(node)
 55
 56
 57        # 获取第一阶段障碍物信息
 58        BP_Barricade = list(filter(lambda x: (x.name.startswith('BP_Barricade')), objects))
 59        # 获取武器库
 60        BP_WeaponCache = list(filter(lambda x: (x.name.startswith('BP_WeaponCache')), objects))
 61        # 获取弹箱
 62        BP_AmmoCrat = list(filter(lambda x: (x.name.startswith('BP_AmmoCrat')), objects))
 63        # 获取每条线
 64        lines = list(filter(lambda x: (x.name.startswith('SM_SpeedBump')), objects))
 65        # print(lines[1].bounding_box.location.x)
 66
 67
 68        # 第 3、4 辆车把第一阶段目标打击
 69        nodes[2].set_vehicle_steer(0.0005)
 70        time.sleep(0.05)
 71        nodes[2].control_vehicle(0.15)
 72
 73
 74        time.sleep(1)
 75        nodes[3].set_vehicle_steer(-0.0015)
 76        time.sleep(0.05)
 77        nodes[3].control_vehicle(0.15)
 78
 79        three_flag = 0  # 检查是否开过火了
 80        four_flag = 0
 81        while 1:
 82            # 3 开火
 83            if nodes[2].get_location()[0] > BP_Barricade[1].bounding_box.location.x - 50:
 84                nodes[2].gun_fire(1)
 85                time.sleep(0.05)
 86                three_flag = 1
 87
 88            # 4 开火
 89            if nodes[3].get_location()[0] > BP_Barricade[0].bounding_box.location.x - 30:
 90                nodes[3].gun_fire(5)
 91                time.sleep(0.05)
 92                four_flag = 1
 93
 94            if three_flag==1 and four_flag==1:
 95                # nodes[2].gun_fire(0)
 96                break
 97
 98        v = 0.1
 99        nodes[0].control_vehicle(v)
100        nodes[1].control_vehicle(v)
101
102        count = 0
103        flag = [0,0,0,0]
104        while 1:
105            for i in range(4):
106                print(i)
107                if nodes[i].get_location()[0] > lines[1].bounding_box.location.x and flag[i]==0:
108                    nodes[i].set_vehicle_brake(1)
109                    nodes[i].set_vehicle_handle_brake(True)
110                    time.sleep(BRAKE_V)
111                    nodes[i].control_vehicle(0)
112                    time.sleep(BRAKE_V)
113                    count += 1
114                    flag[i] = 1
115
116            if count == 4:
117                break
118        i = 0
119        for node in nodes:
120            print(i)
121            i += 1
122            print(node.get_vehicle_status())
123            print("=========================")
124
125
126
127
128    finally:
129        print('main() end')
130
131if __name__ == '__main__':
132    try:
133        main()
134    except KeyboardInterrupt:
135        pass
136    finally:
137        print('__main__ end')

无人机-注册示例代码

 1#!/usr/bin/env python
 2
 3import argparse
 4import time
 5
 6
 7def main():
 8    argparser = argparse.ArgumentParser(
 9        description=__doc__)
10    argparser.add_argument(
11        '-i', '--address',
12        default='127.0.0.1')
13    argparser.add_argument(
14        '-p', '--port',
15        type=int,
16        default=2000)
17    argparser.add_argument(
18        '-n', '--number',
19        type=int,
20        default=10)
21    argparser.add_argument(
22        '-s', '--subject',
23        type=int,
24        default=1
25    )
26    args = argparser.parse_args()
27    ue_ip = args.address.strip()
28    ue_port = args.port
29    num = args.number
30    try:
31        # 列表,用于后续控制
32        nodes = []
33
34        # 1. 首先引入sdk
35        from swarmae.SwarmAEClient import SwarmAEClient
36        # 2. 连接UE
37        client = SwarmAEClient(ue_ip=ue_ip, ue_port=ue_port)
38
39        # 注册车辆
40        for id in range(num):
41            # node_no 从1开始编号
42            timestamp, node, code = client.register_node(
43                node_type="四旋翼", node_name="节点" + str(id+1), node_no=id+1, frame_timestamp=int(round(time.time() * 1000))
44            )
45            if code == 200:
46                # 获取信息
47                node_name, node_no, _, node_type, node_model, color = node.get_node_info()
48                nodes.append(node)
49
50
51
52        print(nodes[0].get_weapon()[1].get_weapon_ammo())
53
54
55
56
57    finally:
58        print('main() end')
59
60if __name__ == '__main__':
61    try:
62        main()
63    except KeyboardInterrupt:
64        pass
65    finally:
66        print('__main__ end')

地图信息读取

方式一:通过读取fbx获取

fbx读取依赖 python 3.6 的 FBX PYTHON SDK(已提供下载), 将fbx的三个文件解压到读取fbx的py同目录即可。目录文件如下:

  • fbx.pyd (SDK文件)

  • FbxCommon.py (SDK文件)

  • sip.pyd (SDK文件)

  • scenario.fbx (地图fbx)

  • fbx_reader.py (读取fbx封装类,一般不调整)

  • get_node_xyz.py (示例代码)

fbx_reader.py
  1import pdb
  2import sys
  3
  4import fbx
  5from FbxCommon import *
  6from timeit import timeit
  7from re import compile
  8import pdb
  9
 10
 11class NodeWrapper:
 12    def __init__(self, fbx_node, fbx_type, father):
 13        self.cur_node = fbx_node
 14        self.cur_type = fbx_type
 15        self.father = father
 16        self.children = []
 17
 18    def is_mesh(self):
 19        attr = self.cur_node.GetNodeAttribute()
 20        if attr is None:
 21            return False
 22        elif attr.GetAttributeType() == fbx.FbxNodeAttribute.eMesh:
 23            return True
 24        else:
 25            return False
 26
 27    def add_child(self, child):
 28        self.children.append(child)
 29
 30    def get_vertices(self):
 31        if self.cur_type is None \
 32           or self.cur_type != fbx.FbxNodeAttribute.eMesh:
 33            return None
 34        else:
 35            return self.cur_node.GetMesh().GetControlPoints()
 36
 37    def get_transform_info(self):
 38        print("/--------------------------------------------------------------")
 39        T = self.cur_node.GetGeometricTranslation(fbx.FbxNode.eDestinationPivot)
 40        print("| ", "GeometricTranslation-Destination", T)
 41        R = self.cur_node.GetGeometricRotation(fbx.FbxNode.eDestinationPivot)
 42        print("| ", "GetGeometricRotation-Destination", R)
 43        S = self.cur_node.GetGeometricScaling(fbx.FbxNode.eDestinationPivot)
 44        print("| ", "GetGeometricScaling-Destination", S)
 45
 46        print("|")
 47        
 48        T = self.cur_node.GetGeometricTranslation(fbx.FbxNode.eSourcePivot)
 49        print("| ", "GeometricTranslation-Source", T)
 50        R = self.cur_node.GetGeometricRotation(fbx.FbxNode.eSourcePivot)
 51        print("| ", "GetGeometricRotation-Source", R)
 52        S = self.cur_node.GetGeometricScaling(fbx.FbxNode.eSourcePivot)
 53        print("| ", "GetGeometricScaling-Source", S)
 54        
 55        print("|")
 56
 57        x = self.cur_node.LclTranslation.Get()
 58        print("| ", "LclTranslation", list(x))
 59
 60        x = self.cur_node.LclRotation.Get()
 61        print("| ", "LclRotation", list(x))
 62
 63        x = self.cur_node.LclScaling.Get()
 64        print("| ", "LclScaling", list(x))
 65
 66        x = self.cur_node.ScalingOffset.Get()
 67        print("| ", "ScalingOffset", list(x))
 68        
 69        print("|")
 70
 71        x = self.cur_node.EvaluateGlobalTransform()
 72        print("| ", "EvaluateGlobalTransform")
 73        for s in x:
 74            print("| ", s[0], s[1], s[2], s[3])
 75        print("|")
 76
 77        x = self.cur_node.EvaluateLocalTransform()
 78        print("| ", "EvaluateLocalTransform")
 79        for s in x:
 80            print("| ", s[0], s[1], s[2], s[3])
 81        print("\\______________________________________________________________")
 82
 83
 84    def get_global_transform_matrix(self):
 85        return self.cur_node.EvaluateGlobalTransform()
 86        
 87        
 88
 89class Scenario:
 90    def __init__(self, map_name = "scenario.fbx"):
 91        self.manager, self.scene = InitializeSdkObjects()
 92        self.res = LoadScene(self.manager, self.scene, map_name)
 93
 94        self.root = None
 95        self.elements = {}
 96
 97        self.traversal()
 98
 99
100    def traversal(self, a_node=None):
101        if a_node is None:
102            fbx_node = self.scene.GetRootNode()
103            attr = fbx_node.GetNodeAttribute()
104            a_type = None
105            if attr is not None:
106                a_type = attr.GetAttributeType()
107
108            a_node = NodeWrapper(fbx_node, attr, None)
109            self.root = a_node
110            self.elements[fbx_node.GetName()] = a_node
111
112        for each in range(a_node.cur_node.GetChildCount()):
113            child = a_node.cur_node.GetChild(each)
114            attr = child.GetNodeAttribute()
115            c_type = None
116            if attr is not None:
117                c_type = attr.GetAttributeType()
118            c_node = NodeWrapper(child, c_type, a_node)
119            a_node.add_child(c_node)
120            self.elements[child.GetName()] = c_node
121            if c_type is not None and c_type == fbx.FbxNodeAttribute.eMesh:
122                pass
123            else:
124                self.traversal(c_node)
125
126    def get_nodes_by_regex(self, regex:str):
127        node_list = {}
128        reg = compile(regex)
129        for name, node in self.elements.items():
130            if reg.match(name) is not None:
131                node_list[name] = node
132        return node_list
133
134    def get_vertices_by_name(self, obj_name):
135        obj = None
136        if obj_name in self.elements.keys():
137            obj = self.elements[obj_name]
138        else:
139            return None
140        return obj.get_vertices()
141
142
143def ProcessMesh(pMesh):
144    if (pMesh == None):
145        return
146
147    #获得mesh的构成顶点 = polygonVertices
148    #获得三角面的数量 = triangleCount
149
150    lNormals = pMesh.GetElementNormal()
151    triangleCount = pMesh.GetPolygonCount()
152    polygonVertices = pMesh.GetPolygonVertices()
153    vertexCounter = 0
154
155    #逐顶点去遍历
156    for i in range(triangleCount):
157        for j in range(3):
158            ctrlPointIndex = polygonVertices[i * 3 + j]
159            vertex = pMesh.GetControlPointAt(ctrlPointIndex)
160            vertexCounter = vertexCounter + 1

警告

fbx_reader.py 默认读取当前目录的 scenario.fbx 文件。提交的算法必须配置为读取 scenario.fbx 文件。

get_node_xyz.py
 1from fbx_reader import Scenario
 2
 3scenario = Scenario()
 4
 5# 以名字筛选静态资源
 6nodes = scenario.get_nodes_by_regex(r'SM_Bridges*')
 7
 8for name in nodes.keys():
 9    node = nodes[name]
10    if not node.is_mesh():
11        continue
12    # door.get_transform_info()
13    vertices = node.get_vertices()
14    trans = node.get_global_transform_matrix()
15    v_g = []
16    if len(vertices) == 0:
17        continue
18    for v in vertices:
19        # print(v[0], v[1], v[2])
20        v_g.append(trans.MultT(v))
21        ## print(v_g[-1][0], v_g[-1][1], v_g[-1][2])
22        ## print()
23
24    xmin = v_g[0][0]
25    xmax = v_g[0][0]
26    ymin = v_g[0][1]
27    ymax = v_g[0][1]
28    zmin = v_g[0][2]
29    zmax = v_g[0][2]
30
31    for v in v_g:
32        xmin = xmin if v[0] > xmin else v[0]
33        xmax = xmax if v[0] < xmax else v[0]
34        ymin = ymin if v[1] > ymin else v[1]
35        ymax = ymax if v[1] < ymax else v[1]
36        zmin = zmin if v[2] > zmin else v[2]
37        zmax = zmax if v[2] < zmax else v[2]
38
39    # 节点的中心点坐标(已换算成UE中单位)
40    x = (xmax + xmin) / 2 / 100
41    y = (ymin + ymax) / 2 / 100
42    z = (zmin + zmax) / 2 / 100
43    print(f"{name}: {[xmin, xmax, ymin, ymax, zmin, zmax]}, vertices len: {len(vertices)}\n"
44          f"x: {x}, y: {y}, z: {z}")
45

示例输出:

NODE_AddSplineMeshComponent-4_3: [-48349.26806640625, -47532.067138671875, -44948.359619140625, -44483.18731689453, 48958.85232543945, 49166.15264892578], vertices len: 200
x: -479.40667602539065, y: 447.1577346801758, z: 490.62502487182616
NODE_AddSplineMeshComponent-4_5: [-46728.33251953125, -45914.85400390625, -44948.359619140625, -44483.18731689453, 49048.88885498047, 49200.847412109375], vertices len: 200
x: -463.2159326171875, y: 447.1577346801758, z: 491.2486813354492
NODE_AddSplineMeshComponent-4_8: [-44326.49658203125, -43509.57080078125, -44948.359619140625, -44483.18731689453, 48676.22117614746, 48938.067474365234], vertices len: 200
x: -439.1803369140625, y: 447.1577346801758, z: 488.0714432525635
NODE_AddSplineMeshComponent-4_7: [-45123.880859375, -44306.19140625, -44948.359619140625, -44483.18731689453, 48824.69805908203, 49069.222412109375], vertices len: 200
x: -447.150361328125, y: 447.1577346801758, z: 489.469602355957
NODE_AddSplineMeshComponent-4_6: [-45924.66796875, -45107.42529296875, -44948.359619140625, -44483.18731689453, 48955.23065185547, 49163.64343261719], vertices len: 200
x: -455.16046630859375, y: 447.1577346801758, z: 490.5943704223633
NODE_AddSplineMeshComponent-4_2: [-49150.487060546875, -48332.87109375, -44948.359619140625, -44483.18731689453, 48828.154205322266, 49072.852600097656], vertices len: 200
x: -487.4167907714844, y: 447.1577346801758, z: 489.5050340270996
NODE_AddSplineMeshComponent-4_4: [-47541.6171875, -46728.11669921875, -44948.359619140625, -44483.18731689453, 49051.37585449219, 49200.847412109375], vertices len: 200
x: -471.3486694335937, y: 447.1577346801758, z: 491.2611163330078
NODE_AddSplineMeshComponent-4_1: [-49946.930908203125, -49130.080322265625, -44948.359619140625, -44483.18731689453, 48678.63131713867, 48941.505310058594], vertices len: 200
x: -495.38505615234374, y: 447.1577346801758, z: 488.10068313598634
NODE_AddSplineMeshComponent-4_0: [-50742.195251464844, -49925.20788574219, -44948.359619140625, -44483.18731689453, 48528.83069610596, 48791.737548828125], vertices len: 200
x: -503.33701568603516, y: 447.1577346801758, z: 486.6028412246704
NODE_AddSplineMeshComponent-4: [-51539.103446006775, -50721.786560058594, -44948.359619140625, -44483.18731689453, 48397.506313323975, 48642.18147277832], vertices len: 200
x: -511.30445003032685, y: 447.1577346801758, z: 485.1984389305115
NODE_AddSplineMeshComponent-4_10: [-42734.2412109375, -41916.9345703125, -44948.359619140625, -44483.18731689453, 48397.49868774414, 48641.13966369629], vertices len: 200
x: -423.25587890625, y: 447.1577346801758, z: 485.19319175720216
NODE_AddSplineMeshComponent-4_9: [-43531.10888671875, -42714.015625, -44948.359619140625, -44483.18731689453, 48527.75614929199, 48789.36279296875], vertices len: 200
x: -431.2256225585937, y: 447.1577346801758, z: 486.5855947113037

科目的名称列表参考

方式二:通过 SDK 读取

警告

需要 SDK 1.0.1 及以上版本

0-sdk读取环境信息.py
 1#!/usr/bin/env python
 2
 3import argparse
 4import time
 5
 6
 7def main():
 8    argparser = argparse.ArgumentParser(
 9        description=__doc__)
10    argparser.add_argument(
11        '-i', '--address',
12        default='127.0.0.1')
13    argparser.add_argument(
14        '-p', '--port',
15        type=int,
16        default=2000)
17    argparser.add_argument(
18        '-n', '--number',
19        type=int,
20        default=5)
21    argparser.add_argument(
22        '-s', '--subject',
23        type=int,
24        default=1
25    )
26    args = argparser.parse_args()
27    ue_ip = args.address.strip()
28    ue_port = args.port
29    num = args.number
30    try:
31        # 1. 首先引入sdk
32        from swarmae.SwarmAEClient import SwarmAEClient
33        # 2. 连接UE
34        client = SwarmAEClient(ue_ip=ue_ip, ue_port=ue_port)
35
36        # sdk读取环境信息,需要 1.0.1 sdk 才支持
37        timestamp, world, code = client.get_world()
38        objects = world.get_environment_objects()
39        # 桥信息
40        bridges = list(filter(lambda x: (x.name.startswith('BP_Bridge')), objects))
41        print(f"bridges len: {len(bridges)}")
42    finally:
43        print('main() end')
44
45if __name__ == '__main__':
46    try:
47        main()
48    except KeyboardInterrupt:
49        pass
50    finally:
51        print('__main__ end')

通过sdk仅能读取到地图静态资源的坐标信息、角度和包围盒信息,**不能读取**打所有顶点信息。 如需读取顶点信息,需要使用 方式一 读取。

地形信息读取

  • 地形信息 仅支持fbx方式 读取,需要读取名称为 Landscape,由于该地形复杂(千万+个顶点),建议缩小范围进行地形信息的获取。

  • 这里提供demo用法,选手根据自身实际情况进行调整, 注意:比较占用电脑性能,测试发现最大可占用8GB内存 选手可根据实际情况优化重构

  • demo以科目二为例,检测坑洼路段的坑洼点(低于地平面1米的坑)

terrain.py
 1from fbx_reader import Scenario
 2
 3
 4
 5
 6class TerrainAnalyzer:
 7    def __init__(self, scenario):
 8        self.scenario = scenario
 9
10    def analyze_terrain(self, terrain_name="Landscape", x_min=1616, x_max=2116, y_min=-470, y_max=-410):
11        # 使用正则表达式获取与地形名称匹配的节点
12        nodes = self.scenario.get_nodes_by_regex(terrain_name)
13
14        if not nodes:
15            print(f"无法找到名为 {terrain_name} 的地形对象")
16            return None
17
18        # 精确获取名称为 'Landscape' 的节点
19        if terrain_name not in nodes:
20            print(f"未找到精确匹配的节点: {terrain_name}")
21            return None
22
23        node = nodes[terrain_name]
24
25        # 判断该节点是否是网格(地形模型)
26        if not node.is_mesh():
27            print(f"节点 {terrain_name} 不是网格模型")
28            return None
29
30        # 获取顶点数据
31        vertices = node.get_vertices()
32
33        # 获取全局变换矩阵
34        trans = node.get_global_transform_matrix()
35
36        # 将UE坐标转换为FBX坐标范围(UE坐标是厘米,FBX坐标是米,需要乘以100)
37        x_min_fbx = x_min * 100
38        x_max_fbx = x_max * 100
39        y_min_fbx = y_min * 100
40        y_max_fbx = y_max * 100
41
42        # 定义一个生成器来逐个处理顶点
43        def generate_global_vertices(vertices, trans, x_min_fbx, x_max_fbx, y_min_fbx, y_max_fbx):
44            for v in vertices:
45                v_global = trans.MultT(v)  # 将局部坐标转换为全局坐标
46                # 筛选在给定 FBX x 和 y 范围内的顶点
47                if x_min_fbx <= v_global[0] <= x_max_fbx and y_min_fbx <= v_global[1] <= y_max_fbx:
48                    yield v_global
49
50        # 使用生成器逐个处理顶点,减少内存消耗
51        vertex_generator = generate_global_vertices(vertices, trans, x_min_fbx, x_max_fbx, y_min_fbx, y_max_fbx)
52
53        total_height = 0
54        vertex_count = 0
55        low_points = []
56
57        # 计算总高度并筛选出低于阈值的顶点
58        for v in vertex_generator:
59            total_height += v[2]
60            vertex_count += 1
61
62        if vertex_count == 0:
63            print("没有符合条件的顶点数据")
64            return None
65
66        # 计算平均高度
67        average_height = total_height / vertex_count
68        # 阈值 低于平均高度1米,选手可根据自己情况设定
69        threshold = 48500
70
71        # 重新生成顶点,筛选低于阈值的点
72        vertex_generator = generate_global_vertices(vertices, trans, x_min_fbx, x_max_fbx, y_min_fbx, y_max_fbx)
73        for v in vertex_generator:
74            if v[2] < threshold:
75                low_points.append(v)
76
77        print(f"地形 {terrain_name} 的平均高度为: {average_height}")
78        print(f"低于阈值 {threshold} 且位于给定范围内的坑洼点数量为: {len(low_points)}")
79
80        # 根据 z 值从低到高对低点排序
81        low_points_sorted = sorted(low_points, key=lambda v: v[2])
82
83        # 输出按 z 值排序的低点坐标
84        for i, low_point in enumerate(low_points_sorted[:len(low_points) ]):  # 仅输出前10个低点
85            low_point_ue = [coord / 100 for coord in low_point]  # 将FBX坐标转换回UE坐标
86            print(f"低点 {i + 1}: {low_point_ue}")
87
88        return low_points_sorted
89
90scenario = Scenario()
91# 使用实例:
92analyzer = TerrainAnalyzer(scenario)
93low_points = analyzer.analyze_terrain("Landscape", x_min=1616, x_max=2116, y_min=-470, y_max=-410)

各科目地图信息

警告

示例坐标仅供参考,请勿在算法中写死坐标,否则提交后的算法在新的地图坐标中将可能无法正常完成比赛。

科目一

警告

新地图的桥 名称前缀 与 旧地图不一致。

科目一地图信息

静态资源名

地图信息 名称前缀

坐标信息示例(SDK方式)

坐标信息示例(fbx方式)

备注

BP_Bridge

第一段:(x=-515.309021, y=447.157715)

x: -511.30445003032685, y: 447.1577346801758, z: 485.1984389305115

整座桥由12部分组成

区域线

SM_SpeedBump

第一条:x = -1072.7。第二条:x = -1062.7

x: -1072.72, y: 439.79998779296875, z: 486.4460653877258

一共五条

科目二

科目二地图信息

静态资源名

地图信息 名称前缀

坐标信息示例(SDK方式)

坐标信息示例(fbx方式)

备注

火力掩护区域

SM_Wall_Single

x=1286.280029, y=423.690002, z=486.449982

x: 1286.2800677490218, y: 423.69001159667823, z: 487.70000022888183

x = 1286.28是掩护区前侧墙壁的最大x值,y = 437 是掩护区右侧墙壁的最大y值

路障

SM_Obstacle

x=1761.797974, y=450.703613, z=487.442017

x: 1761.797890625, y: 450.7036328125, z: 487.44203125

路障有四个

科目三

科目三地图信息

静态资源名

地图信息 名称前缀

坐标信息示例(SDK方式)

坐标信息示例(fbx方式)

备注

待清除路障

BP_Barricade

x=3087.445801, y=446.928894, z=486.205109

x: 3087.7848975372312, y: 447.07353057861326, z: 486.9671220779419

两个待清除路障

掩护区域信息

SM_Wall

x=3528.699951, y=424.399994, z=487.669983

x: 3528.700119045008, y: 424.4000122070286, z: 487.67000022888186

两个掩护区域

打击目标

BP_WeaponCache、BP_AmmoCrat

x=4160.653809, y=460.942810, z=486.262787

BP_WeaponCache_0: x: 4160.616912260056, y: 461.1040254211426, z: 487.07110996246337, BP_AmmoCrat_0: x: 4034.23685546875, y: 450.861875, z: 487.0463818359375

目标分为WeaponCache(武器库)和AmmoCrat(弹药箱两种)

固定障碍

SM_Obstacle

SM_Obstacle10_SM_0: x=3083.403076, y=461.315063, z=486.758392

同左

红白相间的固定障碍,每个区域均有。

科目四

科目四地图信息

静态资源名

地图信息 名称前缀

坐标信息示例(SDK方式)

坐标信息示例(fbx方式)

备注

航路点信息

Waypoint

第一个:x=504.899994, y=89.610001

x: 504.89998046875, y: 89.6099609375, z: 490.92625

一共两个航路点。

起始线及停止线

BP_Trees

起始线及停止线各有一排树来标识,获取所有树的位置,筛选x轴最大值及最小值

科目五

科目五地图信息

静态资源名

地图信息 名称前缀

坐标信息示例(SDK方式)

坐标信息示例(fbx方式)

备注

外门框

SM_DoorFrame

第一个:(x=780.000000, y=937.599976, z=490.551331)门的转向:Rotation(pitch=0.000000, yaw=0.000000, roll=0.000000)

一共两个门。 fbx方式读取缺少一个门框信息,可直接查询内门框信息实现穿越。

内门框(需要穿越的门框)

BP_DoorInst

这两个的 X,Y相同,Z 不同,绝对值|Z1 - Z2|是门的高度

x: 780.0, y: 937.6, z: 502.2

一共两个门。

起始线及停止线

BP_Trees

起始线及停止线各有一排树来标识,获取所有树的位置,筛选x轴最大值及最小值

科目六

科目六地图信息

静态资源名

地图信息 名称前缀

坐标信息示例(SDK方式)

坐标信息示例(fbx方式)

备注

禁飞区

BP_No_FlyZone

x=554.745300, y=661.802185, z=486.599976

x: 554.7453125, y: 661.8021940102539, z: 536.6

五个禁飞区,每个禁飞区直径为400

打击目标

Dynamic_BP_WaterTower、Dynamic_BP_Pillbox、Dynamic_BP_RadarDish

x=806.907471, y=625.588257, z=486.000000

Dynamic_BP_WaterTower: x: 806.9075003051757, y: 626.0299639892578, z: 496.678145134151, Dynamic_BP_Pillbox: x: 677.3367694091797, y: 1293.5023559570313, z: 489.4137258148193, Dynamic_BP_RadarDish: x: 447.39156612144063, y: 1006.3265622024043, z: 506.2

三种类型打击目标:依次为3个普通目标(WaterTower)、四个坚固目标(Pillbox)、三个重点目标(RadarDish)

起始线及停止线

BP_Trees

起始线及停止线各有一排树来标识,获取所有树的位置,筛选x轴最大值及最小值

各科目sdk使用说明

科目一

科目二

(1)编队容错保持:队形规定格式为5*5的矩形,在此基础上摄动不超过两米

(2)重新编队规划:①需要获取掩体位置信息,通过``get_environment_objects()``获取,具体信息通过wall = list(filter(lambda x: (x.name.startswith(‘SM_Wall_Single’)), objects))获取

②离开掩体区域时,需要进行倒车操作,将油门设置为负值即可实现

(3)编队自主避障:①需要获取障碍位置信息,通过``get_environment_objects()``获取,具体信息的关键字为 SM_Obstacle

②此阶段除了障碍之外,注意坑洼,速度过小容易陷入坑内

科目三

最后一个区域,需要获取敌方目标信息,需要通过 get_targets() 获取。

科目四

队形编队密度:①需要获取航路点信息,通过``get_environment_objects()``获取,具体信息关键字为 Waypoint

②起飞时需注意周围树木,规划航线

科目五

一开始需要获取门框信息,需要通过 get_environment_objects() 获取环境物体信息,并过滤出门框。

科目六

一开始需要获取可打击目标信息,需要通过 get_environment_objects() 获取环境物体信息,并过滤出可打击目标。

weapon调用Demo

无人车

 1# node为注册的无人车
 2# 获取车辆武器
 3weapon = node.get_weapon()[1]
 4# 设置开火角度
 5# 参数为(yaw角度,pitch俯仰,时间戳)
 6#         yaw角度是水平方向的角度,正北顺时针方向,范围是-90到90度,负数表示逆时针
 7#         yaw角度值需要更新模型后才能支持设置
 8#         目前pitch设置生效
 9#         但是这个代码可以先写好
10weapon.set_weapon_angle(yaw, pitch, time.time())
11# 无人机开火
12node.gun_fire(1)

无人机

 1# node为注册的无人机
 2# 获取车辆武器
 3weapon = node.get_weapon()[1]
 4# 瞄准目标
 5weapon.set_weapon_angle(yaw, pitch, time.time())
 6# 无人机开火
 7# 获取打击目标id,具体坐标信息等可查看具体get_targets方法,这里仅展示id获取部分
 8world = client.get_world()[1]
 9targets = world.get_targets()
10ids = []
11for target in targets:
12    ids.append(target["id"])
13#weapon类方法missle_fire负责瞄准打击目标,参数为打击目标的id(通过get_targets方法获得)
14weapon.missile_fire(ids[0])
15#node类方法gun_fire负责开火,参数为开火次数,注意规则中荷载武器上限
16node.gun_fire(1)