684 lines
21 KiB
Python
684 lines
21 KiB
Python
"""
|
|
群体智能插件完整实现
|
|
包含插件主类、群体管理器、Boids算法、配置管理、GUI界面和示例
|
|
"""
|
|
|
|
# plugin.py
|
|
plugin_code = '''
|
|
"""
|
|
群体智能插件
|
|
实现Boids群体智能算法
|
|
"""
|
|
|
|
from plugins.plugin_manager import BasePlugin
|
|
from .swarm_manager import SwarmManager
|
|
|
|
class Plugin(BasePlugin):
|
|
"""
|
|
群体智能插件
|
|
"""
|
|
|
|
def __init__(self, plugin_manager, name):
|
|
super().__init__(plugin_manager, name)
|
|
# 设置插件配置
|
|
self.config = {
|
|
"version": "1.0.0",
|
|
"author": "AI Assistant",
|
|
"description": "实现Boids群体智能算法的插件"
|
|
}
|
|
self.swarm_manager = None
|
|
|
|
def initialize(self) -> bool:
|
|
"""
|
|
初始化插件
|
|
"""
|
|
print(f"初始化插件: {self.name}")
|
|
# 在这里执行插件初始化逻辑
|
|
return True
|
|
|
|
def enable(self) -> bool:
|
|
"""
|
|
启用插件
|
|
"""
|
|
if not super().enable():
|
|
return False
|
|
|
|
print(f"启用插件: {self.name}")
|
|
|
|
# 初始化群体管理器
|
|
self.swarm_manager = SwarmManager(self.plugin_manager.world)
|
|
|
|
# 创建示例群体
|
|
self.swarm_manager.create_example_swarm()
|
|
|
|
# 注册事件处理器
|
|
self.plugin_manager.world.accept("f1", self._on_f1_pressed)
|
|
|
|
return True
|
|
|
|
def disable(self) -> bool:
|
|
"""
|
|
禁用插件
|
|
"""
|
|
if not super().disable():
|
|
return False
|
|
|
|
print(f"禁用插件: {self.name}")
|
|
|
|
# 清理群体
|
|
if self.swarm_manager:
|
|
self.swarm_manager.cleanup()
|
|
|
|
# 移除事件处理器
|
|
self.plugin_manager.world.ignore("f1")
|
|
|
|
return True
|
|
|
|
def finalize(self):
|
|
"""
|
|
清理插件资源
|
|
"""
|
|
print(f"清理插件资源: {self.name}")
|
|
# 在这里执行最终清理逻辑
|
|
|
|
def get_info(self) -> dict:
|
|
"""
|
|
获取插件信息
|
|
"""
|
|
info = super().get_info()
|
|
info.update({
|
|
"version": self.config.get("version", "1.0.0"),
|
|
"author": self.config.get("author", "Unknown"),
|
|
"description": self.config.get("description", "Base plugin class")
|
|
})
|
|
return info
|
|
|
|
def _on_f1_pressed(self):
|
|
"""
|
|
F1按键处理函数
|
|
"""
|
|
print("群体智能插件: F1按键被按下")
|
|
if self.swarm_manager:
|
|
self.swarm_manager.toggle_pause()
|
|
'''
|
|
|
|
# swarm_manager.py
|
|
swarm_manager_code = '''
|
|
"""
|
|
群体管理器
|
|
负责创建和管理群体成员
|
|
"""
|
|
|
|
from panda3d.core import Vec3, Point3
|
|
import random
|
|
|
|
class SwarmManager:
|
|
"""
|
|
群体管理器
|
|
负责创建和管理群体成员
|
|
"""
|
|
|
|
def __init__(self, world):
|
|
self.world = world
|
|
self.members = []
|
|
self.paused = False
|
|
self.task = None
|
|
|
|
# 群体参数
|
|
self.cohesion_weight = 1.0
|
|
self.separation_weight = 1.5
|
|
self.alignment_weight = 1.0
|
|
self.max_speed = 5.0
|
|
self.perception_radius = 10.0
|
|
|
|
# 启动更新任务
|
|
self.task = self.world.taskMgr.add(self._update_task, "swarm_update_task")
|
|
|
|
def create_example_swarm(self):
|
|
"""
|
|
创建示例群体
|
|
"""
|
|
# 创建20个群体成员
|
|
for i in range(20):
|
|
# 随机位置
|
|
pos = Vec3(
|
|
random.uniform(-20, 20),
|
|
random.uniform(-20, 20),
|
|
random.uniform(5, 15)
|
|
)
|
|
|
|
# 创建简单的球体代表群体成员
|
|
member = self.world.loader.loadModel("models/misc/sphere")
|
|
member.reparentTo(self.world.render)
|
|
member.setPos(pos)
|
|
member.setScale(0.5)
|
|
|
|
# 随机初始速度
|
|
velocity = Vec3(
|
|
random.uniform(-1, 1),
|
|
random.uniform(-1, 1),
|
|
random.uniform(-1, 1)
|
|
)
|
|
|
|
# 添加到群体成员列表
|
|
self.members.append({
|
|
'node': member,
|
|
'position': pos,
|
|
'velocity': velocity
|
|
})
|
|
|
|
def _update_task(self, task):
|
|
"""
|
|
更新任务
|
|
"""
|
|
if not self.paused:
|
|
self._update_swarm()
|
|
return task.cont
|
|
|
|
def _update_swarm(self):
|
|
"""
|
|
更新群体行为
|
|
"""
|
|
for i, member in enumerate(self.members):
|
|
# 计算邻居
|
|
neighbors = self._find_neighbors(member, i)
|
|
|
|
# 计算三个基本力
|
|
cohesion_force = self._calculate_cohesion(member, neighbors)
|
|
separation_force = self._calculate_separation(member, neighbors)
|
|
alignment_force = self._calculate_alignment(member, neighbors)
|
|
|
|
# 应用权重
|
|
cohesion_force *= self.cohesion_weight
|
|
separation_force *= self.separation_weight
|
|
alignment_force *= self.alignment_weight
|
|
|
|
# 计算总加速度
|
|
acceleration = cohesion_force + separation_force + alignment_force
|
|
|
|
# 更新速度和位置
|
|
member['velocity'] += acceleration
|
|
# 限制最大速度
|
|
if member['velocity'].length() > self.max_speed:
|
|
member['velocity'].normalize()
|
|
member['velocity'] *= self.max_speed
|
|
|
|
member['position'] += member['velocity']
|
|
member['node'].setPos(member['position'])
|
|
|
|
def _find_neighbors(self, member, index):
|
|
"""
|
|
查找邻居
|
|
"""
|
|
neighbors = []
|
|
for i, other in enumerate(self.members):
|
|
if i != index: # 排除自己
|
|
distance = (member['position'] - other['position']).length()
|
|
if distance < self.perception_radius:
|
|
neighbors.append(other)
|
|
return neighbors
|
|
|
|
def _calculate_cohesion(self, member, neighbors):
|
|
"""
|
|
计算聚集力
|
|
"""
|
|
if not neighbors:
|
|
return Vec3(0, 0, 0)
|
|
|
|
# 计算邻居的中心位置
|
|
center = Vec3(0, 0, 0)
|
|
for neighbor in neighbors:
|
|
center += neighbor['position']
|
|
center /= len(neighbors)
|
|
|
|
# 返回指向中心的向量
|
|
return (center - member['position']).normalized()
|
|
|
|
def _calculate_separation(self, member, neighbors):
|
|
"""
|
|
计算分离力
|
|
"""
|
|
if not neighbors:
|
|
return Vec3(0, 0, 0)
|
|
|
|
separation = Vec3(0, 0, 0)
|
|
for neighbor in neighbors:
|
|
diff = member['position'] - neighbor['position']
|
|
distance = diff.length()
|
|
if distance > 0: # 避免除零
|
|
# 距离越近,分离力越大
|
|
separation += diff.normalized() / distance
|
|
|
|
if len(neighbors) > 0:
|
|
separation /= len(neighbors)
|
|
|
|
return separation.normalized() if separation.length() > 0 else separation
|
|
|
|
def _calculate_alignment(self, member, neighbors):
|
|
"""
|
|
计算对齐力
|
|
"""
|
|
if not neighbors:
|
|
return Vec3(0, 0, 0)
|
|
|
|
# 计算邻居的平均速度方向
|
|
avg_velocity = Vec3(0, 0, 0)
|
|
for neighbor in neighbors:
|
|
avg_velocity += neighbor['velocity']
|
|
avg_velocity /= len(neighbors)
|
|
|
|
return avg_velocity.normalized()
|
|
|
|
def toggle_pause(self):
|
|
"""
|
|
切换暂停状态
|
|
"""
|
|
self.paused = not self.paused
|
|
print(f"群体模拟{'已暂停' if self.paused else '已恢复'}")
|
|
|
|
def cleanup(self):
|
|
"""
|
|
清理资源
|
|
"""
|
|
# 移除任务
|
|
if self.task:
|
|
self.world.taskMgr.remove(self.task)
|
|
|
|
# 移除所有群体成员
|
|
for member in self.members:
|
|
member['node'].removeNode()
|
|
|
|
self.members.clear()
|
|
'''
|
|
|
|
# config.py
|
|
config_code = '''
|
|
"""
|
|
群体智能插件配置
|
|
"""
|
|
|
|
class Config:
|
|
"""
|
|
配置管理类
|
|
"""
|
|
|
|
def __init__(self):
|
|
# 默认配置
|
|
self.default_settings = {
|
|
"cohesion_weight": 1.0,
|
|
"separation_weight": 1.5,
|
|
"alignment_weight": 1.0,
|
|
"max_speed": 5.0,
|
|
"perception_radius": 10.0,
|
|
"member_count": 20
|
|
}
|
|
|
|
# 当前配置
|
|
self.settings = self.default_settings.copy()
|
|
|
|
def get(self, key, default=None):
|
|
"""
|
|
获取配置值
|
|
"""
|
|
return self.settings.get(key, default)
|
|
|
|
def set(self, key, value):
|
|
"""
|
|
设置配置值
|
|
"""
|
|
self.settings[key] = value
|
|
|
|
def reset_to_default(self):
|
|
"""
|
|
重置为默认配置
|
|
"""
|
|
self.settings = self.default_settings.copy()
|
|
|
|
def load_from_dict(self, config_dict):
|
|
"""
|
|
从字典加载配置
|
|
"""
|
|
self.settings.update(config_dict)
|
|
|
|
def to_dict(self):
|
|
"""
|
|
导出配置为字典
|
|
"""
|
|
return self.settings.copy()
|
|
'''
|
|
|
|
# boids_algorithm.py
|
|
boids_algorithm_code = '''
|
|
"""
|
|
Boids算法实现
|
|
"""
|
|
|
|
from panda3d.core import Vec3
|
|
|
|
class BoidsAlgorithm:
|
|
"""
|
|
Boids算法实现类
|
|
"""
|
|
|
|
def __init__(self, config):
|
|
self.config = config
|
|
|
|
def calculate_cohesion(self, member, neighbors):
|
|
"""
|
|
计算聚集力
|
|
"""
|
|
if not neighbors:
|
|
return Vec3(0, 0, 0)
|
|
|
|
# 计算邻居的中心位置
|
|
center = Vec3(0, 0, 0)
|
|
for neighbor in neighbors:
|
|
center += neighbor['position']
|
|
center /= len(neighbors)
|
|
|
|
# 返回指向中心的向量
|
|
return (center - member['position']).normalized()
|
|
|
|
def calculate_separation(self, member, neighbors):
|
|
"""
|
|
计算分离力
|
|
"""
|
|
if not neighbors:
|
|
return Vec3(0, 0, 0)
|
|
|
|
separation = Vec3(0, 0, 0)
|
|
for neighbor in neighbors:
|
|
diff = member['position'] - neighbor['position']
|
|
distance = diff.length()
|
|
if distance > 0: # 避免除零
|
|
# 距离越近,分离力越大
|
|
separation += diff.normalized() / distance
|
|
|
|
if len(neighbors) > 0:
|
|
separation /= len(neighbors)
|
|
|
|
return separation.normalized() if separation.length() > 0 else separation
|
|
|
|
def calculate_alignment(self, member, neighbors):
|
|
"""
|
|
计算对齐力
|
|
"""
|
|
if not neighbors:
|
|
return Vec3(0, 0, 0)
|
|
|
|
# 计算邻居的平均速度方向
|
|
avg_velocity = Vec3(0, 0, 0)
|
|
for neighbor in neighbors:
|
|
avg_velocity += neighbor['velocity']
|
|
avg_velocity /= len(neighbors)
|
|
|
|
return avg_velocity.normalized()
|
|
|
|
def calculate_obstacle_avoidance(self, member, obstacles):
|
|
"""
|
|
计算避障力
|
|
"""
|
|
# 简单实现,实际应用中可以更复杂
|
|
avoidance = Vec3(0, 0, 0)
|
|
for obstacle in obstacles:
|
|
diff = member['position'] - obstacle['position']
|
|
distance = diff.length()
|
|
if distance < obstacle['radius']:
|
|
avoidance += diff.normalized() / distance
|
|
|
|
return avoidance.normalized() if avoidance.length() > 0 else avoidance
|
|
|
|
def update_member(self, member, neighbors, obstacles=[]):
|
|
"""
|
|
更新群体成员状态
|
|
"""
|
|
# 计算三个基本力
|
|
cohesion_force = self.calculate_cohesion(member, neighbors)
|
|
separation_force = self.calculate_separation(member, neighbors)
|
|
alignment_force = self.calculate_alignment(member, neighbors)
|
|
|
|
# 计算避障力
|
|
obstacle_force = self.calculate_obstacle_avoidance(member, obstacles)
|
|
|
|
# 应用权重
|
|
cohesion_force *= self.config.get("cohesion_weight", 1.0)
|
|
separation_force *= self.config.get("separation_weight", 1.5)
|
|
alignment_force *= self.config.get("alignment_weight", 1.0)
|
|
obstacle_force *= self.config.get("obstacle_weight", 2.0)
|
|
|
|
# 计算总加速度
|
|
acceleration = cohesion_force + separation_force + alignment_force + obstacle_force
|
|
|
|
# 更新速度和位置
|
|
member['velocity'] += acceleration
|
|
# 限制最大速度
|
|
max_speed = self.config.get("max_speed", 5.0)
|
|
if member['velocity'].length() > max_speed:
|
|
member['velocity'].normalize()
|
|
member['velocity'] *= max_speed
|
|
|
|
member['position'] += member['velocity']
|
|
'''
|
|
|
|
# gui.py
|
|
gui_code = '''
|
|
"""
|
|
群体智能插件GUI界面
|
|
"""
|
|
|
|
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QSlider, QLabel, QGroupBox
|
|
from PyQt5.QtCore import Qt
|
|
|
|
class SwarmGUI(QWidget):
|
|
"""
|
|
群体智能插件GUI界面
|
|
"""
|
|
|
|
def __init__(self, swarm_manager, config):
|
|
super().__init__()
|
|
self.swarm_manager = swarm_manager
|
|
self.config = config
|
|
self.init_ui()
|
|
|
|
def init_ui(self):
|
|
"""
|
|
初始化UI界面
|
|
"""
|
|
self.setWindowTitle('群体智能控制面板')
|
|
self.setGeometry(100, 100, 300, 400)
|
|
|
|
layout = QVBoxLayout()
|
|
|
|
# 控制按钮组
|
|
control_group = QGroupBox("控制")
|
|
control_layout = QHBoxLayout()
|
|
|
|
self.pause_button = QPushButton("暂停/继续")
|
|
self.pause_button.clicked.connect(self.toggle_pause)
|
|
control_layout.addWidget(self.pause_button)
|
|
|
|
reset_button = QPushButton("重置")
|
|
reset_button.clicked.connect(self.reset_swarm)
|
|
control_layout.addWidget(reset_button)
|
|
|
|
control_group.setLayout(control_layout)
|
|
layout.addWidget(control_group)
|
|
|
|
# 参数调节组
|
|
params_group = QGroupBox("参数调节")
|
|
params_layout = QVBoxLayout()
|
|
|
|
# 聚集权重
|
|
cohesion_layout = QHBoxLayout()
|
|
cohesion_layout.addWidget(QLabel("聚集权重:"))
|
|
self.cohesion_slider = QSlider(Qt.Horizontal)
|
|
self.cohesion_slider.setRange(0, 50)
|
|
self.cohesion_slider.setValue(int(self.config.get("cohesion_weight", 1.0) * 10))
|
|
self.cohesion_slider.valueChanged.connect(self.update_cohesion_weight)
|
|
cohesion_layout.addWidget(self.cohesion_slider)
|
|
|
|
# 分离权重
|
|
separation_layout = QHBoxLayout()
|
|
separation_layout.addWidget(QLabel("分离权重:"))
|
|
self.separation_slider = QSlider(Qt.Horizontal)
|
|
self.separation_slider.setRange(0, 50)
|
|
self.separation_slider.setValue(int(self.config.get("separation_weight", 1.5) * 10))
|
|
self.separation_slider.valueChanged.connect(self.update_separation_weight)
|
|
separation_layout.addWidget(self.separation_slider)
|
|
|
|
# 对齐权重
|
|
alignment_layout = QHBoxLayout()
|
|
alignment_layout.addWidget(QLabel("对齐权重:"))
|
|
self.alignment_slider = QSlider(Qt.Horizontal)
|
|
self.alignment_slider.setRange(0, 50)
|
|
self.alignment_slider.setValue(int(self.config.get("alignment_weight", 1.0) * 10))
|
|
self.alignment_slider.valueChanged.connect(self.update_alignment_weight)
|
|
alignment_layout.addWidget(self.alignment_slider)
|
|
|
|
# 最大速度
|
|
speed_layout = QHBoxLayout()
|
|
speed_layout.addWidget(QLabel("最大速度:"))
|
|
self.speed_slider = QSlider(Qt.Horizontal)
|
|
self.speed_slider.setRange(1, 20)
|
|
self.speed_slider.setValue(int(self.config.get("max_speed", 5.0)))
|
|
self.speed_slider.valueChanged.connect(self.update_max_speed)
|
|
speed_layout.addWidget(self.speed_slider)
|
|
|
|
# 感知半径
|
|
radius_layout = QHBoxLayout()
|
|
radius_layout.addWidget(QLabel("感知半径:"))
|
|
self.radius_slider = QSlider(Qt.Horizontal)
|
|
self.radius_slider.setRange(1, 50)
|
|
self.radius_slider.setValue(int(self.config.get("perception_radius", 10.0)))
|
|
self.radius_slider.valueChanged.connect(self.update_perception_radius)
|
|
radius_layout.addWidget(self.radius_slider)
|
|
|
|
params_group.setLayout(params_layout)
|
|
layout.addWidget(params_group)
|
|
|
|
# 状态信息组
|
|
status_group = QGroupBox("状态信息")
|
|
status_layout = QVBoxLayout()
|
|
self.status_label = QLabel("群体成员数量: 0")
|
|
status_layout.addWidget(self.status_label)
|
|
status_group.setLayout(status_layout)
|
|
layout.addWidget(status_group)
|
|
|
|
self.setLayout(layout)
|
|
|
|
def toggle_pause(self):
|
|
"""
|
|
切换暂停状态
|
|
"""
|
|
if self.swarm_manager:
|
|
self.swarm_manager.toggle_pause()
|
|
|
|
def reset_swarm(self):
|
|
"""
|
|
重置群体
|
|
"""
|
|
if self.swarm_manager:
|
|
self.swarm_manager.cleanup()
|
|
self.swarm_manager.create_example_swarm()
|
|
self.update_status()
|
|
|
|
def update_cohesion_weight(self, value):
|
|
"""
|
|
更新聚集权重
|
|
"""
|
|
weight = value / 10.0
|
|
self.config.set("cohesion_weight", weight)
|
|
if self.swarm_manager:
|
|
self.swarm_manager.cohesion_weight = weight
|
|
|
|
def update_separation_weight(self, value):
|
|
"""
|
|
更新分离权重
|
|
"""
|
|
weight = value / 10.0
|
|
self.config.set("separation_weight", weight)
|
|
if self.swarm_manager:
|
|
self.swarm_manager.separation_weight = weight
|
|
|
|
def update_alignment_weight(self, value):
|
|
"""
|
|
更新对齐权重
|
|
"""
|
|
weight = value / 10.0
|
|
self.config.set("alignment_weight", weight)
|
|
if self.swarm_manager:
|
|
self.swarm_manager.alignment_weight = weight
|
|
|
|
def update_max_speed(self, value):
|
|
"""
|
|
更新最大速度
|
|
"""
|
|
self.config.set("max_speed", float(value))
|
|
if self.swarm_manager:
|
|
self.swarm_manager.max_speed = float(value)
|
|
|
|
def update_perception_radius(self, value):
|
|
"""
|
|
更新感知半径
|
|
"""
|
|
self.config.set("perception_radius", float(value))
|
|
if self.swarm_manager:
|
|
self.swarm_manager.perception_radius = float(value)
|
|
|
|
def update_status(self):
|
|
"""
|
|
更新状态信息
|
|
"""
|
|
if self.swarm_manager:
|
|
count = len(self.swarm_manager.members)
|
|
self.status_label.setText(f"群体成员数量: {count}")
|
|
'''
|
|
|
|
# __init__.py
|
|
init_code = '''
|
|
"""
|
|
群体智能插件初始化
|
|
"""
|
|
|
|
from .plugin import Plugin
|
|
from .swarm_manager import SwarmManager
|
|
from .boids_algorithm import BoidsAlgorithm
|
|
from .config import Config
|
|
from .gui import SwarmGUI
|
|
|
|
__all__ = ['Plugin', 'SwarmManager', 'BoidsAlgorithm', 'Config', 'SwarmGUI']
|
|
'''
|
|
|
|
# Create the plugin directory and files
|
|
import os
|
|
plugin_dir = "/home/hello/EG/plugins/user/swarm_intelligence"
|
|
os.makedirs(plugin_dir, exist_ok=True)
|
|
|
|
# Write the files
|
|
with open(os.path.join(plugin_dir, "plugin.py"), "w", encoding="utf-8") as f:
|
|
f.write(plugin_code)
|
|
|
|
with open(os.path.join(plugin_dir, "swarm_manager.py"), "w", encoding="utf-8") as f:
|
|
f.write(swarm_manager_code)
|
|
|
|
with open(os.path.join(plugin_dir, "config.py"), "w", encoding="utf-8") as f:
|
|
f.write(config_code)
|
|
|
|
with open(os.path.join(plugin_dir, "boids_algorithm.py"), "w", encoding="utf-8") as f:
|
|
f.write(boids_algorithm_code)
|
|
|
|
with open(os.path.join(plugin_dir, "gui.py"), "w", encoding="utf-8") as f:
|
|
f.write(gui_code)
|
|
|
|
with open(os.path.join(plugin_dir, "__init__.py"), "w", encoding="utf-8") as f:
|
|
f.write(init_code)
|
|
|
|
print("群体智能插件已成功创建!")
|
|
print("插件包含以下功能:")
|
|
print("1. Boids群体智能算法实现")
|
|
print("2. 可调节的群体行为参数")
|
|
print("3. 可视化控制面板")
|
|
print("4. 实时参数调节")
|
|
print("5. 暂停/继续控制")
|
|
print("6. 示例场景")
|
|
print("7. 完整的插件生命周期管理") |