Compare commits

..

73 Commits

Author SHA1 Message Date
p57492168 3e24e286f2 修改 2022-07-03 12:36:58 +08:00
p57492168 6fbd3c65f6 修改 2022-07-03 12:35:47 +08:00
p57492168 900bc64f57 修改 2022-07-03 12:35:18 +08:00
p57492168 0457d6cf8d 修改 2022-07-03 12:34:19 +08:00
p57492168 f92f94eba6 修改 2022-07-03 12:33:41 +08:00
p57492168 e5bedfca38 修改 2022-07-03 12:31:44 +08:00
p57492168 2d75a52ef9 修改 2022-07-02 11:13:50 +08:00
p57492168 2d7c8cf245 修改 2022-07-02 11:12:51 +08:00
p57492168 e465b5123f 修改 2022-07-02 11:09:59 +08:00
p57492168 3776f9c2b8 修改 2022-07-02 11:08:48 +08:00
p57492168 241ac1f9c3 修改 2022-07-02 00:21:43 +08:00
p57492168 f09c3fbb71 修改 2022-07-02 00:20:18 +08:00
p57492168 3b9971c56e 修改 2022-07-02 00:19:44 +08:00
p57492168 0f219cb90a 修改 2022-07-02 00:19:12 +08:00
p57492168 c3d1846720 修改 2022-07-02 00:18:24 +08:00
p57492168 11d80a96cd 修改 2022-07-02 00:17:44 +08:00
p57492168 d16c4dbb45 修改 2022-07-02 00:16:51 +08:00
p57492168 b9cd5f5b0e 修改 2022-07-02 00:15:49 +08:00
p57492168 491444b802 修改 2022-07-02 00:14:18 +08:00
p57492168 c1c1188799 修改 2022-07-02 00:13:25 +08:00
p57492168 74a156d8c1 修改 2022-06-30 20:24:32 +08:00
p57492168 08268e923a 修改 2022-06-30 20:23:58 +08:00
p57492168 49519d6c58 修改 2022-06-30 20:23:13 +08:00
p57492168 f833083c38 修改注释 2022-06-30 20:22:04 +08:00
p57492168 f969d43102 修改注释 2022-06-30 20:21:21 +08:00
p57492168 ca504df41c 修改注释 2022-06-30 20:20:28 +08:00
p57492168 0727015c51 修改注释 2022-06-30 20:19:24 +08:00
p57492168 c9fcdf8c11 修改注释 2022-06-29 22:48:41 +08:00
p57492168 ff28a4690d 修改注释 2022-06-29 22:47:58 +08:00
p57492168 171e95ba18 修改注释 2022-06-29 22:44:44 +08:00
p57492168 03dcf8b594 修改 2022-06-25 15:23:09 +08:00
p57492168 668373a360 readme修改 2022-06-25 15:20:55 +08:00
p57492168 9177dc8154 修改删除 2022-06-25 15:14:35 +08:00
p57492168 d9e42582fb 修改注释 2022-06-25 15:10:58 +08:00
p57492168 e0eb2d4a23 修改注释 2022-06-24 20:25:00 +08:00
p57492168 9778a22753 修改 2022-06-24 20:20:28 +08:00
p57492168 f68044e3cc 修改 2022-06-24 20:17:55 +08:00
p57492168 89652e2ee0 修改 2022-06-23 14:29:03 +08:00
p57492168 d3adaa5643 修改注释 2022-06-23 14:22:00 +08:00
p57492168 858d3f86a0 修改注释 2022-06-23 14:20:34 +08:00
p57492168 b3d65a8b9f 修改注释 2022-06-23 14:18:47 +08:00
p57492168 28395a7985 修改 2022-06-23 14:12:20 +08:00
p57492168 30362c96ea 修改 2022-06-23 14:05:51 +08:00
p57492168 e1516ba2d4 修改 2022-06-23 14:05:03 +08:00
p57492168 c4f6eade52 修改注释 2022-06-23 13:58:06 +08:00
p57492168 b202642c23 修改注释 2022-06-22 23:09:11 +08:00
p57492168 72b451b8ee 修改注释 2022-06-22 23:08:31 +08:00
p57492168 66a4bb1358 修改 2022-06-22 23:02:34 +08:00
p57492168 f0405180f6 修改 2022-06-22 23:01:47 +08:00
p57492168 83d82d86b9 修改 2022-06-22 22:36:13 +08:00
p57492168 aea3558ec1 修改注释 2022-06-22 22:34:00 +08:00
p57492168 40be0b5481 注释删除 2022-06-22 22:32:53 +08:00
p57492168 99d0bcba45 注释修改 2022-06-21 21:56:19 +08:00
p57492168 c84e8cea34 注释删除 2022-06-21 21:54:17 +08:00
p57492168 4f68d89ca6 注释删除 2022-06-21 21:53:24 +08:00
p57492168 9af11c5cc8 删除 2022-06-21 21:51:58 +08:00
p57492168 fa8e41cac8 注释删除 2022-06-21 21:49:43 +08:00
p57492168 f8ca8f1673 注释修改 2022-06-21 21:48:21 +08:00
p57492168 32ee95ada0 界面修改 2022-06-20 22:41:23 +08:00
p57492168 5068ae13ba 修改readme 2022-06-20 22:37:08 +08:00
p57492168 cad3cc3c21 删除注释 2022-06-20 22:34:52 +08:00
p57492168 7156ac8ce6 注释删除 2022-06-20 22:33:28 +08:00
p57492168 3aa201a9c2 修改 2022-06-20 22:31:18 +08:00
p57492168 2d695c79e9 注释删除 2022-06-19 21:08:05 +08:00
p57492168 966fbc74e0 注释添加 2022-06-19 21:06:15 +08:00
p57492168 4d9f7cdc69 字体大小修改 2022-06-19 21:03:59 +08:00
p57492168 8b167cce9b 按钮添加 2022-06-19 21:00:41 +08:00
p57492168 1e59ed6add readme修改内容 2022-06-19 20:58:15 +08:00
p57492168 ee0b753b25 readme添加内容 2022-06-19 20:56:03 +08:00
p57492168 86a71520bd 修改util 2022-06-17 23:44:29 +08:00
p57492168 a2267fd411 修改readme 2022-06-17 23:43:03 +08:00
p57492168 a72ea1c58b 修改main 2022-06-17 23:41:24 +08:00
p57492168 035ce41d9e 修改 2022-06-17 23:39:40 +08:00
42 changed files with 114 additions and 196 deletions

3
.idea/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
# Default ignored files
/shelf/
/workspace.xml

12
.idea/SeAIPalette.iml Normal file
View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
<component name="PyDocumentationSettings">
<option name="format" value="PLAIN" />
<option name="myDocStringFormat" value="Plain" />
</component>
</module>

View File

@ -0,0 +1,13 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="PyUnresolvedReferencesInspection" enabled="true" level="WARNING" enabled_by_default="true">
<option name="ignoredIdentifiers">
<list>
<option value="runtest.ImageEditorPage" />
<option value="ImageEditorPage" />
</list>
</option>
</inspection_tool>
</profile>
</component>

View File

@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<settings>
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>

4
.idea/misc.xml Normal file
View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.7 (Palette)" project-jdk-type="Python SDK" />
</project>

8
.idea/modules.xml Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/SeAIPalette.iml" filepath="$PROJECT_DIR$/.idea/SeAIPalette.iml" />
</modules>
</component>
</project>

6
.idea/vcs.xml Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

View File

@ -2,10 +2,8 @@
# Form implementation generated from reading ui file 'MainWindow_map.ui' # Form implementation generated from reading ui file 'MainWindow_map.ui'
# #
# Created by: PyQt5 UI code generator 5.15.1 # Created by: PyQt5 UI code generator 5.12.3
# # WARNING! All changes made in this file will be lost!
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets from PyQt5 import QtCore, QtGui, QtWidgets
@ -96,6 +94,9 @@ class Ui_MainWindow(object):
self.horizontalLayout.addLayout(self.formLayout_2) self.horizontalLayout.addLayout(self.formLayout_2)
self.verticalLayout_2 = QtWidgets.QVBoxLayout() self.verticalLayout_2 = QtWidgets.QVBoxLayout()
self.verticalLayout_2.setObjectName("verticalLayout_2") self.verticalLayout_2.setObjectName("verticalLayout_2")
self.pushButton_2 = QtWidgets.QPushButton(self.centralwidget)
self.pushButton_2.setObjectName("pushButton_2")
self.verticalLayout_2.addWidget(self.pushButton_2)
self.pushButton_run = QtWidgets.QPushButton(self.centralwidget) self.pushButton_run = QtWidgets.QPushButton(self.centralwidget)
font = QtGui.QFont() font = QtGui.QFont()
font.setFamily("宋体") font.setFamily("宋体")
@ -110,6 +111,13 @@ class Ui_MainWindow(object):
self.pushButton_stop.setFont(font) self.pushButton_stop.setFont(font)
self.pushButton_stop.setObjectName("pushButton_stop") self.pushButton_stop.setObjectName("pushButton_stop")
self.verticalLayout_2.addWidget(self.pushButton_stop) self.verticalLayout_2.addWidget(self.pushButton_stop)
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
font = QtGui.QFont()
font.setFamily("宋体")
font.setPointSize(12)
self.pushButton.setFont(font)
self.pushButton.setObjectName("pushButton")
self.verticalLayout_2.addWidget(self.pushButton)
self.horizontalLayout.addLayout(self.verticalLayout_2) self.horizontalLayout.addLayout(self.verticalLayout_2)
self.horizontalLayout.setStretch(0, 1) self.horizontalLayout.setStretch(0, 1)
self.horizontalLayout.setStretch(1, 1) self.horizontalLayout.setStretch(1, 1)
@ -149,6 +157,8 @@ class Ui_MainWindow(object):
self.label_9.setText(_translate("MainWindow", "移动节点电池容量")) self.label_9.setText(_translate("MainWindow", "移动节点电池容量"))
self.lineEdit_bettery.setText(_translate("MainWindow", "100")) self.lineEdit_bettery.setText(_translate("MainWindow", "100"))
self.label_4.setText(_translate("MainWindow", "算法选择")) self.label_4.setText(_translate("MainWindow", "算法选择"))
self.pushButton_2.setText(_translate("MainWindow", "关于我们"))
self.pushButton_run.setText(_translate("MainWindow", "运行")) self.pushButton_run.setText(_translate("MainWindow", "运行"))
self.pushButton_stop.setText(_translate("MainWindow", "停止")) self.pushButton_stop.setText(_translate("MainWindow", "停止"))
self.pushButton.setText(_translate("MainWindow", "退出程序"))
self.label_show.setText(_translate("MainWindow", "<html><head/><body><p><br/></p></body></html>")) self.label_show.setText(_translate("MainWindow", "<html><head/><body><p><br/></p></body></html>"))

View File

@ -157,6 +157,13 @@
</item> </item>
<item> <item>
<layout class="QVBoxLayout" name="verticalLayout_2"> <layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QPushButton" name="pushButton_2">
<property name="text">
<string>关于我们</string>
</property>
</widget>
</item>
<item> <item>
<widget class="QPushButton" name="pushButton_run"> <widget class="QPushButton" name="pushButton_run">
<property name="font"> <property name="font">
@ -183,6 +190,19 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QPushButton" name="pushButton">
<property name="font">
<font>
<family>宋体</family>
<pointsize>12</pointsize>
</font>
</property>
<property name="text">
<string>退出程序</string>
</property>
</widget>
</item>
</layout> </layout>
</item> </item>
</layout> </layout>

View File

@ -12,7 +12,6 @@ class Charge(WildFire):
def step(self, state, info): def step(self, state, info):
if not self.empty(): if not self.empty():
# if there're actions to do
action = self.actions_to_do[0] action = self.actions_to_do[0]
del self.actions_to_do[0] del self.actions_to_do[0]
return action, None return action, None

View File

@ -23,9 +23,6 @@ class MultiBoustrophedon(Boustrophedon):
self.charges = charges self.charges = charges
self.finished_idx = [False for _ in range(ship_num)] self.finished_idx = [False for _ in range(ship_num)]
#self.ship_energy = ship_energy
#self.current_ship_energy = [ship_energy for _ in range(self.ship_num)]
self.delta_x = (0, 0, 1, -1, ) # 1, 1, -1, -1) self.delta_x = (0, 0, 1, -1, ) # 1, 1, -1, -1)
self.delta_y = (1, -1, 0, 0, ) # 1, -1, 1, -1) self.delta_y = (1, -1, 0, 0, ) # 1, -1, 1, -1)

View File

@ -43,8 +43,6 @@ class MultiGreedy(Boustrophedon):
if self.charges[i].empty(): if self.charges[i].empty():
redecide_directions[i] = True redecide_directions[i] = True
continue continue
# Decide whether charge or not
first_charge_act, charge_len = self.charges.step(state, info, i) first_charge_act, charge_len = self.charges.step(state, info, i)
if first_charge_act == FINISHED: if first_charge_act == FINISHED:
self.finished_idx[i] = True self.finished_idx[i] = True

View File

@ -18,13 +18,10 @@ class MultiSpiral(Spiral):
): ):
super().__init__() super().__init__()
self.ship_num = ship_num self.ship_num = ship_num
# self.dest_direction = [None for _ in range(ship_num)]
self.wildfires = wildfires self.wildfires = wildfires
self.charges = charges self.charges = charges
self.finished_idx = [False for _ in range(ship_num)] self.finished_idx = [False for _ in range(ship_num)]
#self.ship_energy = ship_energy
#self.current_ship_energy = [ship_energy for _ in range(self.ship_num)]
self.delta_x = [0, 0, 1, -1, 1, 1, -1, -1] self.delta_x = [0, 0, 1, -1, 1, 1, -1, -1]
self.delta_y = [1, -1, 0, 0, 1, -1, 1, -1] self.delta_y = [1, -1, 0, 0, 1, -1, 1, -1]

View File

@ -149,7 +149,6 @@ class Spiral(object):
""" """
return _turn(direction) return _turn(direction)
else: else:
# print(f'not turn')
return direction return direction
def step(self, state, info): def step(self, state, info):

View File

@ -7,8 +7,8 @@ class WildFire(object):
def __init__(self): def __init__(self):
super().__init__() super().__init__()
self.actions_to_do = [] self.actions_to_do = []
self.delta_x = (0, 0, 1, -1, ) # 1, 1, -1, -1) self.delta_x = (0, 0, 1, -1, )
self.delta_y = (1, -1, 0, 0, ) # 1, -1, 1, -1) self.delta_y = (1, -1, 0, 0, )
@ staticmethod @ staticmethod
def _is_valid_index(index, an_array): def _is_valid_index(index, an_array):
@ -23,12 +23,9 @@ class WildFire(object):
def step(self, state, info): def step(self, state, info):
if not self.empty(): if not self.empty():
# if there're actions to do
action = self.actions_to_do[0] action = self.actions_to_do[0]
del self.actions_to_do[0] del self.actions_to_do[0]
return [action] return [action]
# print(state)
x, y, _ = state x, y, _ = state
fields = info['fields'] fields = info['fields']
@ -49,7 +46,6 @@ class WildFire(object):
visited[next_x, next_y] = True visited[next_x, next_y] = True
next_node = Node(next_x, next_y, cur_node) next_node = Node(next_x, next_y, cur_node)
if fields[next_x, next_y] == 0: if fields[next_x, next_y] == 0:
# not visited
node = next_node node = next_node
while node.direction is not None: while node.direction is not None:
self.actions_to_do.append(node.direction) self.actions_to_do.append(node.direction)

27
Palette/env/engine.py vendored
View File

@ -29,7 +29,7 @@ class SeaEnvEngine(object):
ship_radius: int, ship_radius: int,
ship_velocity: int, ship_velocity: int,
sonar_spread_times: int, # the number of sonar detection points sonar_spread_times: int,
obstacles: dict, obstacles: dict,
@ -38,7 +38,7 @@ class SeaEnvEngine(object):
show_fields: bool = True, show_fields: bool = True,
init_ships: bool = True, init_ships: bool = True,
start_position=None, # [start_x, start_y] start_position=None,
start_r=None, start_r=None,
time_click: float = 1.0/10.0, time_click: float = 1.0/10.0,
@ -57,8 +57,8 @@ class SeaEnvEngine(object):
self.max_angle, self.min_angle = None, None self.max_angle, self.min_angle = None, None
# basic params
self.crashed = False # whether or not crash into an obstacle or bound self.crashed = False
self.finished = False self.finished = False
self.terminate = False self.terminate = False
@ -100,12 +100,9 @@ class SeaEnvEngine(object):
self.ship_img = pygame.transform.scale( self.ship_img = pygame.transform.scale(
self.ship_img, (self.ship_radius * 4, self.ship_radius * 4)) self.ship_img, (self.ship_radius * 4, self.ship_radius * 4))
""" 2. init gymunk """ """ 2. init gymunk """
# physics stuff
self.space = pymunk.Space() self.space = pymunk.Space()
self.space.gravity = pymunk.Vec2d(0., 0.) self.space.gravity = pymunk.Vec2d(0., 0.)
# create bounds
# self.create_bounds(window_height, window_width)
# create ship
self.finished_idx = None self.finished_idx = None
self.init_ships = init_ships self.init_ships = init_ships
self.battery_capacity = None self.battery_capacity = None
@ -124,7 +121,6 @@ class SeaEnvEngine(object):
self.fields = np.zeros( self.fields = np.zeros(
shape=(self.window_width//field_size[0], self.window_height//field_size[1])) shape=(self.window_width//field_size[0], self.window_height//field_size[1]))
# create obstacles
self.obstacles = [] self.obstacles = []
self.obstacles_w_h = [] self.obstacles_w_h = []
for obstacle_key in obstacles.keys(): for obstacle_key in obstacles.keys():
@ -132,7 +128,6 @@ class SeaEnvEngine(object):
cur_obstacle = self.create_rectangle_obstacle(x, y, width, height) cur_obstacle = self.create_rectangle_obstacle(x, y, width, height)
self.obstacles.append(cur_obstacle) self.obstacles.append(cur_obstacle)
self.obstacles_w_h.append((width, height)) self.obstacles_w_h.append((width, height))
# label the position of obstacles as -1
for i in range(x//self.field_size[0], (x+width)//self.field_size[0]): for i in range(x//self.field_size[0], (x+width)//self.field_size[0]):
for j in range(y//self.field_size[1], (y+height)//self.field_size[1]): for j in range(y//self.field_size[1], (y+height)//self.field_size[1]):
self.fields[i, self.fields.shape[1]-j-1] = -1 self.fields[i, self.fields.shape[1]-j-1] = -1
@ -200,7 +195,6 @@ class SeaEnvEngine(object):
for s in static: for s in static:
s.friction = 1. s.friction = 1.
s.group = 1 s.group = 1
# bound is the same as obstacle for collision
s.collision_type = COLLISION_OBSTACLE s.collision_type = COLLISION_OBSTACLE
s.color = THECOLORS['blue'] s.color = THECOLORS['blue']
self.space.add(*static) self.space.add(*static)
@ -230,10 +224,8 @@ class SeaEnvEngine(object):
self._ship_charging_time_left = [0 for _ in range(self.ship_num)] self._ship_charging_time_left = [0 for _ in range(self.ship_num)]
def create_rectangle_obstacle(self, x, y, width, height): def create_rectangle_obstacle(self, x, y, width, height):
# points = [(0, 0), (0, height), (width, height), (width, 0)]
points = [(-width/2, -height/2), (-width/2, height/2), points = [(-width/2, -height/2), (-width/2, height/2),
(width/2, height/2), (width/2, -height/2)] (width/2, height/2), (width/2, -height/2)]
# points = [(-width, -height), (-width, 0), (0, 0), (0, -height)]
mass = 9999999999 mass = 9999999999
moment = pymunk.moment_for_poly(mass, points, (0, 0)) moment = pymunk.moment_for_poly(mass, points, (0, 0))
obstacle_body = pymunk.Body(mass=mass, moment=moment) obstacle_body = pymunk.Body(mass=mass, moment=moment)
@ -255,7 +247,7 @@ class SeaEnvEngine(object):
return self._ship_batteries[ship_id] return self._ship_batteries[ship_id]
def frame_step(self, actions: List[int]): def frame_step(self, actions: List[int]):
"""frame update for one step """
Args: Args:
action (int): the next direction of the ship action (int): the next direction of the ship
@ -270,11 +262,11 @@ class SeaEnvEngine(object):
raise AssertionError("Cannot continue running after crash!") raise AssertionError("Cannot continue running after crash!")
for ship_id, action in enumerate(actions): for ship_id, action in enumerate(actions):
if action == UP: # up if action == UP:
self._ship_charging[ship_id] = False self._ship_charging[ship_id] = False
self._ship_charging_time_left[ship_id] = 0 self._ship_charging_time_left[ship_id] = 0
self.ship_body[ship_id].angle = 1.5*np.pi self.ship_body[ship_id].angle = 1.5*np.pi
elif action == DOWN: # down elif action == DOWN:
self._ship_charging[ship_id] = False self._ship_charging[ship_id] = False
self._ship_charging_time_left[ship_id] = 0 self._ship_charging_time_left[ship_id] = 0
self.ship_body[ship_id].angle = 0.5*np.pi self.ship_body[ship_id].angle = 0.5*np.pi
@ -362,7 +354,6 @@ class SeaEnvEngine(object):
self.ship_body[ship_id].angle = process_angle( self.ship_body[ship_id].angle = process_angle(
self.ship_body[ship_id].angle) self.ship_body[ship_id].angle)
# calculate velocity with direction
driving_direction = Vec2d(1, 0).rotated( driving_direction = Vec2d(1, 0).rotated(
self.ship_body[ship_id].angle) self.ship_body[ship_id].angle)
@ -372,7 +363,7 @@ class SeaEnvEngine(object):
else: else:
self.ship_body[ship_id].velocity = 0.0 * driving_direction self.ship_body[ship_id].velocity = 0.0 * driving_direction
# Update the screen and stuff. # Update the screen and stuff
if self.draw_screen: if self.draw_screen:
# self.screen.fill(THECOLORS["black"]) # self.screen.fill(THECOLORS["black"])
self.screen.blit(self.ss_img, (0, 0)) self.screen.blit(self.ss_img, (0, 0))

View File

@ -109,13 +109,7 @@ def make(
filling_time: int = 1, filling_time: int = 1,
cover_ratio: float = 1.0 cover_ratio: float = 1.0
): ):
"""
if not render:
os.environ["SDL_VIDEODRIVER"] = "dummy"
else:
os.environ["DISPLAY"] = os.popen(
'printenv grep DISPLAY').read().strip()
"""
with open(os.path.join('Palette', 'maps', f'{env_config}.yaml'), 'r') as f: with open(os.path.join('Palette', 'maps', f'{env_config}.yaml'), 'r') as f:
config = yaml.safe_load(f) config = yaml.safe_load(f)
@ -160,5 +154,5 @@ if __name__ == '__main__':
if t: if t:
break break
# sea_env.reset()
print(steps) print(steps)

View File

@ -1,5 +1,4 @@
import numpy as np import numpy as np
import random
from math import acos, asin from math import acos, asin
@ -18,12 +17,9 @@ def process_angle(_angle):
def asincos(sin_value, cos_value): def asincos(sin_value, cos_value):
if sin_value >= 0: if sin_value >= 0:
# 第一象限和第二象限
return acos(cos_value) return acos(cos_value)
else: else:
if cos_value >= 0: if cos_value >= 0:
# 第四象限
return asin(sin_value) return asin(sin_value)
else: else:
# 第三象限
return 2*np.pi - acos(cos_value) return 2*np.pi - acos(cos_value)

View File

@ -17,7 +17,6 @@ def generate_agent_fields(fields, ship_num, splited_areas):
for _ in range(ship_num)], axis=0) for _ in range(ship_num)], axis=0)
for ship_id in range(1, ship_num+1): for ship_id in range(1, ship_num+1):
cur_fields = agents_fields[ship_id-1] cur_fields = agents_fields[ship_id-1]
# print((splited_areas != ship_id) * (splited_areas != -1))
cur_fields[(splited_areas != ship_id) * (splited_areas != -1)] += 1 cur_fields[(splited_areas != ship_id) * (splited_areas != -1)] += 1
return agents_fields return agents_fields

View File

@ -17,7 +17,6 @@ def generate_agent_fields(fields, ship_num, splited_areas):
for _ in range(ship_num)], axis=0) for _ in range(ship_num)], axis=0)
for ship_id in range(1, ship_num+1): for ship_id in range(1, ship_num+1):
cur_fields = agents_fields[ship_id-1] cur_fields = agents_fields[ship_id-1]
# print((splited_areas != ship_id) * (splited_areas != -1))
cur_fields[(splited_areas != ship_id) * (splited_areas != -1)] += 1 cur_fields[(splited_areas != ship_id) * (splited_areas != -1)] += 1
return agents_fields return agents_fields
@ -29,7 +28,6 @@ def main(env: SeaEnv, agent: MultiGreedy):
while True: while True:
steps += 1 steps += 1
info['redecide_direction'] = redecide_direction info['redecide_direction'] = redecide_direction
# print(np.sum(info['fields'] == 0))
agents_fields = generate_agent_fields( agents_fields = generate_agent_fields(
info['fields'], env.ship_num, env.splited_areas) info['fields'], env.ship_num, env.splited_areas)
agent_info = deepcopy(info) agent_info = deepcopy(info)

View File

@ -17,7 +17,6 @@ def generate_agent_fields(fields, ship_num, splited_areas):
for _ in range(ship_num)], axis=0) for _ in range(ship_num)], axis=0)
for ship_id in range(1, ship_num+1): for ship_id in range(1, ship_num+1):
cur_fields = agents_fields[ship_id-1] cur_fields = agents_fields[ship_id-1]
# print((splited_areas != ship_id) * (splited_areas != -1))
cur_fields[(splited_areas != ship_id) * (splited_areas != -1)] += 1 cur_fields[(splited_areas != ship_id) * (splited_areas != -1)] += 1
return agents_fields return agents_fields

View File

@ -18,7 +18,6 @@ def generate_agent_fields(fields, ship_num, splited_areas):
for _ in range(ship_num)], axis=0) for _ in range(ship_num)], axis=0)
for ship_id in range(1, ship_num+1): for ship_id in range(1, ship_num+1):
cur_fields = agents_fields[ship_id-1] cur_fields = agents_fields[ship_id-1]
# print((splited_areas != ship_id) * (splited_areas != -1))
cur_fields[(splited_areas != ship_id) * (splited_areas != -1)] += 1 cur_fields[(splited_areas != ship_id) * (splited_areas != -1)] += 1
return agents_fields return agents_fields

View File

@ -25,8 +25,6 @@ def main(env: SeaEnv, agent: Union[Boustrophedon, Spiral], wildfire: WildFire):
redecide_direction = True redecide_direction = True
cur_area_terminate = False cur_area_terminate = False
while True: while True:
# for _ in range(9999999):
# continue
info['redecide_direction'] = redecide_direction info['redecide_direction'] = redecide_direction
modified_fields = deepcopy(info['fields']) modified_fields = deepcopy(info['fields'])
modified_fields += ((splited_area != area_id) modified_fields += ((splited_area != area_id)

View File

@ -7,7 +7,7 @@ env:
ship_radius: !!int 5 ship_radius: !!int 5
ship_velocity: 200 ship_velocity: 200
sonar_spread_times: !!int 40 sonar_spread_times: !!int 40
obstacles: # name: [x of the left bottom, y of the left bottom, width, height] obstacles:
obstacle0: [100, 100, 100, 200] obstacle0: [100, 100, 100, 200]
obstacle1: [300, 160, 120, 120] obstacle1: [300, 160, 120, 120]
obstacle2: [460, 460, 120, 120] obstacle2: [460, 460, 120, 120]

View File

@ -7,7 +7,7 @@ env:
ship_radius: !!int 5 ship_radius: !!int 5
ship_velocity: 200 ship_velocity: 200
sonar_spread_times: !!int 40 sonar_spread_times: !!int 40
obstacles: # name: [x of the left bottom, y of the left bottom, width, height] obstacles:
obstacle0: [100, 600, 100, 200] obstacle0: [100, 600, 100, 200]
obstacle1: [300, 360, 120, 120] obstacle1: [300, 360, 120, 120]
obstacle2: [660, 460, 120, 120] obstacle2: [660, 460, 120, 120]

View File

@ -7,7 +7,7 @@ env:
ship_radius: !!int 5 ship_radius: !!int 5
ship_velocity: 200 ship_velocity: 200
sonar_spread_times: !!int 40 sonar_spread_times: !!int 40
obstacles: # name: [x of the left bottom, y of the left bottom, width, height] obstacles:
obstacle0: [100, 600, 100, 200] obstacle0: [100, 600, 100, 200]
obstacle1: [300, 260, 120, 320] obstacle1: [300, 260, 120, 320]
obstacle2: [660, 460, 120, 120] obstacle2: [660, 460, 120, 120]

View File

@ -7,7 +7,7 @@ env:
ship_radius: !!int 1 ship_radius: !!int 1
ship_velocity: 40 ship_velocity: 40
sonar_spread_times: !!int 40 sonar_spread_times: !!int 40
obstacles: # name: [x of the left bottom, y of the left bottom, width, height] obstacles:
obstacle0: [40, 440, 340, 220] obstacle0: [40, 440, 340, 220]
obstacle1: [100, 160, 300, 180] obstacle1: [100, 160, 300, 180]
obstacle2: [300, 40, 100, 60] obstacle2: [300, 40, 100, 60]

View File

@ -7,7 +7,7 @@ env:
ship_radius: !!int 5 ship_radius: !!int 5
ship_velocity: 200 ship_velocity: 200
sonar_spread_times: !!int 40 sonar_spread_times: !!int 40
obstacles: # name: [x of the left bottom, y of the left bottom, width, height] obstacles:
obstacle0: [40, 440, 340, 220] obstacle0: [40, 440, 340, 220]
obstacle1: [100, 160, 300, 180] obstacle1: [100, 160, 300, 180]
obstacle2: [300, 40, 100, 60] obstacle2: [300, 40, 100, 60]

View File

@ -7,7 +7,7 @@ env:
ship_radius: !!int 1 ship_radius: !!int 1
ship_velocity: 40 ship_velocity: 40
sonar_spread_times: !!int 40 sonar_spread_times: !!int 40
obstacles: # name: [x of the left bottom, y of the left bottom, width, height] obstacles:
obstacle0: [40, 440, 340, 220] obstacle0: [40, 440, 340, 220]
obstacle1: [100, 160, 300, 180] obstacle1: [100, 160, 300, 180]
obstacle2: [300, 40, 100, 60] obstacle2: [300, 40, 100, 60]

View File

@ -7,7 +7,7 @@ env:
ship_radius: !!int 5 ship_radius: !!int 5
ship_velocity: 200 ship_velocity: 200
sonar_spread_times: !!int 40 sonar_spread_times: !!int 40
obstacles: # name: [x of the left bottom, y of the left bottom, width, height] obstacles:
obstacle0: [40, 440, 340, 220] obstacle0: [40, 440, 340, 220]
obstacle1: [100, 160, 300, 180] obstacle1: [100, 160, 300, 180]
obstacle2: [300, 40, 100, 60] obstacle2: [300, 40, 100, 60]

View File

@ -3,16 +3,11 @@ env:
window_width: !!int 1000 window_width: !!int 1000
window_height: !!int 1000 window_height: !!int 1000
field_size: [20, 20] field_size: [20, 20]
#start_position:
# ship0: [10, 10]
# ship1: [990, 990]
#start_r:
# ship0: !!float 0.0 # pi
# ship1: !!float 1.0 # pi
ship_radius: !!int 5 ship_radius: !!int 5
ship_velocity: 200 ship_velocity: 200
sonar_spread_times: !!int 40 sonar_spread_times: !!int 40
obstacles: # name: [x of the left bottom, y of the left bottom, width, height] obstacles:
obstacle0: [100, 100, 100, 200] obstacle0: [100, 100, 100, 200]
obstacle1: [300, 160, 120, 120] obstacle1: [300, 160, 120, 120]
obstacle2: [460, 460, 120, 120] obstacle2: [460, 460, 120, 120]

129
README.md
View File

@ -4,16 +4,16 @@ SeAI Palette集智调色板是面向集群网络的多节点智能协同路径
集智调色板软件设计了参数输入模块、算法运行模块及信息输出模块,在不同节点数量要求的前提下划分区域方向,按区域进行算法的运行。并可以综合考虑固定节点、覆盖率、电池容量等条件下,给出运行步数、重复步数和重复率等等性能指标。 集智调色板软件设计了参数输入模块、算法运行模块及信息输出模块,在不同节点数量要求的前提下划分区域方向,按区域进行算法的运行。并可以综合考虑固定节点、覆盖率、电池容量等条件下,给出运行步数、重复步数和重复率等等性能指标。
软件界面简单,易学用,包含参数的输入选择,程序的运行,算法结果的展示等,源代码公开,算法可修改。 软件界面简单,易学用,包含参数的输入选择,程序的运行,算法结果的展示等,源代码公开,算法可修改。
开发人员:H.P. Yu、K. Wang、J. Li、H.T. Li、Z.Q. Wang、Z.Y. Zhao、L.F. Zhang、G. Chen 开发人员:王凯、于化鹏、李晶、王兆琦、李慧涛、赵志允、张乐飞、陈光
## 1. 开发环境配置 ## 1. 开发环境配置
运行以下命令: 运行以下命令:
```bash ```bash
conda env create -f create_env.yaml conda env create -f create_env.yaml
``` ```
该命令会创建一个名为`Palette`的conda虚拟环境`conda activate Palette`即可激活该虚拟环境。 该命令会根据create_env.yaml配置文件创建一个名为`Palette`的conda虚拟环境继续输入`conda activate Palette`即可激活该虚拟环境。
## 2. 软件运行 ## 2. 软件运行
@ -21,125 +21,8 @@ conda env create -f create_env.yaml
```python ```python
python main_tt.py python main_tt.py
``` ```
## 3. 问题定义和仿真设计 ## 3. 一些说明
1环境设计 1. 关于程序输出的说明
环境依赖方面仿真平台主要基于Python平台实现。具体地物理仿真引擎使用的是Pymunk并将物理仿真结果Pygame渲染成可视化结果。此外在数值计算方面主要使用了Numpy工具包。
为保证实验结果综合客观,仿真平台包含了三张虚构的海图。
2方案设计
主要考虑了三种方案:
单AUV全覆盖路径规划即只规划单个AUV的全覆盖路径
多AUV全覆盖路径规划即需要同时规划多个AUV相互配合情况下的全覆盖路径
需要充电的单/多AUV路径规划即在上面两种方案的基础上额外考虑AUV的充电的需要AUV可根据能量情况自行前往充电桩进行充电降低人工打捞充电带来的巨大运维成本。
针对以上三种方案分别设计了仿真实验测试在不同目标覆盖率下AUV使用不同算法巡航海域所需的总时间以及重复航行区域的大小。
## 4. 使用算法
* 栅格法
* 牛耕法
* 内螺旋法
* 贪心法
## 5. 软硬件运行平台
1配置要求
<table>
<tr>
<th>组件</th>
<th>配置</th>
<th>备注</th>
</tr>
<tr>
<td>系统 </td>
<td>Windows 10 家庭中文版 20H2 64位</td>
<td>扩展支持Linux和Mac系统</td>
</tr>
<tr>
<td>处理器</td>
<td>处理器类型:
酷睿i3兼容处理器或速度更快的处理器
处理器速度:
最低1.0GHz
建议2.0GHz或更快
</td>
<td>不支持ARM、IA64等芯片处理器</td>
</tr>
<tr>
<td>内存</td>
<td>RAM 16.0 GB (15.7 GB 可用)</td>
<td></td>
</tr>
<tr>
<td>显卡</td>
<td>最小:核心显卡
推荐GTX1060或同类型显卡
</td>
<td></td>
</tr>
<tr>
<td>硬盘</td>
<td>500G</td>
<td></td>
</tr>
<td>显示器</td>
<td>3840×2160像素高分屏</td>
<td></td>
</tr>
<tr>
</tr>
<td>软件</td>
<td>Anaconda3 2020及以上</td>
<td>Python3.7及以上,需手动安装包</td>
</tr>
</table>
2手动部署搭建及运行
推荐的安装步骤如下:
安装Anaconda3-2020.02-Windows-x86_64或以上版本
手动安装pygame、pymunk、pyyaml、numpy、easydict和pyqt安装方式推荐参考如下
```
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pygame==2.0.1
```
将软件模块文件夹拷贝到电脑中以D盘为例路径为D:\island-multi_ships
## 6. 模块详细设计
1界面设计
界面总体设计如下:
![主界面展示](https://osredm.com/repo/SeAIPalette/SeAIPalette/raw/branch/master/pic2/3.png)
为了操作简便主界面只分为功能选择区和信息输出区以及“运行”、“停止”按钮。功能选择区涵盖“地图选择”、“最低覆盖率”、“AUV数量”、“区域划分方向”、“算法选择”、“是否渲染”、“考虑固定节点”、“是否需要充电”和与之相关联的“AUV电池容量”。
信息输出区主要包含当前运行的相关信息,包括状态标志、运行完成标志、步数、重复步数、重复率等。
2地图0演示
采用“牛耕法”最低覆盖率100%AUV数量为1运行结果如下步数2373重复步数60重复率2.40%。
![D:\pic](https://osredm.com/repo/SeAIPalette/SeAIPalette/raw/branch/master/pic2/40.png)
当“是否渲染”选择“否”时,物理引擎图形不展示,程序后台静默运行后自动输出相关状态及结果信息。
![D:\pic](https://osredm.com/repo/SeAIPalette/SeAIPalette/raw/branch/master/pic2/4.jpg)
当AUV数量为3时使用的步数大大减少仅需要706步重复步数为38重复率1.52%。
![D:\pic](https://osredm.com/repo/SeAIPalette/SeAIPalette/raw/branch/master/pic2/7.jpg)
![D:\pic](https://osredm.com/repo/SeAIPalette/SeAIPalette/raw/branch/master/pic2/8.jpg)
算法选择“贪心法”使用的步数705重复步数33重复率1.32%,和“牛耕法”相同。
当考虑充电时设置电池容量为100使用的步数964重复步数709重复率28.36%。
## 7. 其他说明
* 程序输出的说明
程序运行结束后会在命令行输出类似于下面的结果: 程序运行结束后会在命令行输出类似于下面的结果:
``` ```
@ -151,7 +34,7 @@ pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pygame==2.0.1
``` ```
分别为使用的步数,重复的步数和重复率。 分别为使用的步数,重复的步数和重复率。
* 关于渲染结果的说明 2. 关于渲染结果的说明
渲染中不同移动节点负责的区域用不同颜色标记,每个区域颜色越深表示该区域被重复走的次数越多。 渲染中不同移动节点负责的区域用不同颜色标记,每个区域颜色越深表示该区域被重复走的次数越多。

View File

@ -3,7 +3,6 @@ from MainWindow_map import Ui_MainWindow
from PyQt5 import QtWidgets, QtCore, QtSql, QtGui from PyQt5 import QtWidgets, QtCore, QtSql, QtGui
from PyQt5.QtWidgets import * from PyQt5.QtWidgets import *
from PyQt5.QtCore import * from PyQt5.QtCore import *
from PyQt5.QtGui import QPixmap
import threading, time, subprocess import threading, time, subprocess
@ -122,6 +121,5 @@ class mywindow(QtWidgets.QMainWindow, Ui_MainWindow):
if __name__ == '__main__': if __name__ == '__main__':
app = QApplication(sys.argv) app = QApplication(sys.argv)
window = mywindow() window = mywindow()
# window.showMaximized()
window.show() window.show()
sys.exit(app.exec_()) sys.exit(app.exec_())

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB