快速入门¶
无人车-注册示例代码¶
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 (示例代码)
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 文件。
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 及以上版本
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米的坑)
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方式) |
备注 |
---|---|---|---|---|
桥 |
|
第一段: |
|
整座桥由12部分组成 |
区域线 |
|
第一条: |
|
一共五条 |
科目二¶
静态资源名 |
地图信息 名称前缀 |
坐标信息示例(SDK方式) |
坐标信息示例(fbx方式) |
备注 |
---|---|---|---|---|
火力掩护区域 |
|
|
|
x = 1286.28是掩护区前侧墙壁的最大x值,y = 437 是掩护区右侧墙壁的最大y值 |
路障 |
|
|
|
路障有四个 |
科目三¶
静态资源名 |
地图信息 名称前缀 |
坐标信息示例(SDK方式) |
坐标信息示例(fbx方式) |
备注 |
---|---|---|---|---|
待清除路障 |
|
|
|
两个待清除路障 |
掩护区域信息 |
|
|
|
两个掩护区域 |
打击目标 |
|
|
BP_WeaponCache_0: |
目标分为WeaponCache(武器库)和AmmoCrat(弹药箱两种) |
固定障碍 |
|
SM_Obstacle10_SM_0: |
同左 |
红白相间的固定障碍,每个区域均有。 |
科目四¶
静态资源名 |
地图信息 名称前缀 |
坐标信息示例(SDK方式) |
坐标信息示例(fbx方式) |
备注 |
---|---|---|---|---|
航路点信息 |
|
第一个: |
|
一共两个航路点。 |
起始线及停止线 |
|
起始线及停止线各有一排树来标识,获取所有树的位置,筛选x轴最大值及最小值 |
科目五¶
静态资源名 |
地图信息 名称前缀 |
坐标信息示例(SDK方式) |
坐标信息示例(fbx方式) |
备注 |
---|---|---|---|---|
外门框 |
|
第一个: |
一共两个门。 fbx方式读取缺少一个门框信息,可直接查询内门框信息实现穿越。 |
|
内门框(需要穿越的门框) |
|
这两个的 X,Y相同,Z 不同,绝对值|Z1 - Z2|是门的高度 |
|
一共两个门。 |
起始线及停止线 |
|
起始线及停止线各有一排树来标识,获取所有树的位置,筛选x轴最大值及最小值 |
科目六¶
静态资源名 |
地图信息 名称前缀 |
坐标信息示例(SDK方式) |
坐标信息示例(fbx方式) |
备注 |
---|---|---|---|---|
禁飞区 |
|
|
|
五个禁飞区,每个禁飞区直径为400 |
打击目标 |
|
|
Dynamic_BP_WaterTower: |
三种类型打击目标:依次为3个普通目标(WaterTower)、四个坚固目标(Pillbox)、三个重点目标(RadarDish) |
起始线及停止线 |
|
起始线及停止线各有一排树来标识,获取所有树的位置,筛选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)