由于无人机集群表演是一个高度专业化的领域,涉及复杂的通信、同步控制和路径规划,要控制

我们使用Python的Pygame库来模拟10000台无人机实时表演"戏水龙珠"的动态效果。虽然实际表演需要专用硬件、通信协议和飞控系统支持,但这个简化版本可以直观展示表演的视觉效果。

完整的Python模拟程序

import pygame
import numpy as np
import random
import math
import sys
from pygame.locals import *

# 初始化
pygame.init()
screen_width, screen_height = 1920, 1080
screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption("无人机戏水龙珠表演 - 10000架无人机模拟")
clock = pygame.time.Clock()

# 颜色定义
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
BLUE = (0, 100, 255)
CYAN = (0, 255, 255)
GOLD = (255, 215, 0)
YELLOW = (255, 255, 0)
PURPLE = (128, 0, 128)
RED = (255, 0, 0)
DRAGON_BODY = (0, 180, 255)
DRAGON_HEAD = (0, 120, 255)
PEARL_COLOR = (255, 255, 200)

# 无人机类
class Drone:
    def __init__(self, drone_id, start_pos):
        self.id = drone_id
        self.position = np.array(start_pos, dtype=float)
        self.target = np.array(start_pos, dtype=float)
        self.velocity = np.array([0.0, 0.0, 0.0])
        self.color = BLUE
        self.size = 2
        self.speed = 0.3
        self.max_speed = 2.0
        self.follow_distance = 5.0
        self.noise_offset = random.random() * 100
        self.noise_speed = random.uniform(0.01, 0.05)
        
    def update(self, dt):
        # 计算朝向目标的方向
        direction = self.target - self.position
        distance = np.linalg.norm(direction)
        
        if distance > 0.1:
            # 归一化方向
            direction = direction / distance
            
            # 添加一些噪声模拟真实飞行
            noise = np.array([
                math.sin(self.noise_offset + pygame.time.get_ticks() * self.noise_speed),
                math.cos(self.noise_offset + pygame.time.get_ticks() * self.noise_speed * 0.7),
                math.sin(self.noise_offset * 1.3 + pygame.time.get_ticks() * self.noise_speed * 1.2)
            ]) * 0.1
            
            # 计算速度
            desired_velocity = direction * min(self.speed * distance, self.max_speed)
            self.velocity = 0.9 * self.velocity + 0.1 * desired_velocity + noise
            
            # 更新位置
            self.position += self.velocity * dt
            
            # 限制位置在屏幕内
            self.position[0] = max(0, min(screen_width, self.position[0]))
            self.position[1] = max(0, min(screen_height, self.position[1]))
            self.position[2] = max(-100, min(100, self.position[2]))
        
        # 更新噪声偏移
        self.noise_offset += self.noise_speed
        
    def set_target(self, target):
        self.target = np.array(target, dtype=float)
    
    def draw(self, surface, camera_offset):
        # 转换为屏幕坐标(简单投影)
        x = int(self.position[0] + camera_offset[0])
        y = int(self.position[1] + camera_offset[1])
        
        # 根据高度添加Z轴透视
        z_scale = 1.0 + self.position[2] / 100.0
        size = max(1, int(self.size * z_scale))
        
        # 绘制无人机
        pygame.draw.circle(surface, self.color, (x, y), size)
        
        # 添加光晕效果
        if z_scale > 1.2:
            pygame.draw.circle(surface, (min(255, self.color[0] + 100), 
                                       min(255, self.color[1] + 100), 
                                       min(255, self.color[2] + 100)), 
                             (x, y), size + 1, 1)

# 龙珠类
class DragonPearl:
    def __init__(self):
        self.position = np.array([screen_width // 2, screen_height // 2, 0], dtype=float)
        self.velocity = np.array([2.0, 1.5, 0.5], dtype=float)
        self.radius = 30
        self.trail = []
        self.trail_length = 50
        self.time = 0
        self.rotation = 0
        
    def update(self):
        # 更新时间
        self.time += 0.02
        self.rotation += 0.03
        
        # 更新位置(正弦波运动)
        self.position[0] = screen_width // 2 + math.sin(self.time * 0.5) * 400
        self.position[1] = screen_height // 2 + math.cos(self.time * 0.7) * 300
        self.position[2] = math.sin(self.time * 0.9) * 80
        
        # 添加轨迹
        self.trail.append(self.position.copy())
        if len(self.trail) > self.trail_length:
            self.trail.pop(0)
    
    def get_position(self, offset=0):
        # 获取当前或轨迹中的位置
        if offset == 0:
            return self.position.copy()
        elif offset < len(self.trail):
            return self.trail[-offset].copy()
        else:
            return self.trail[0].copy() if self.trail else self.position.copy()
    
    def draw(self, surface, camera_offset):
        # 绘制轨迹
        for i, pos in enumerate(self.trail):
            alpha = i / len(self.trail)
            radius = int(self.radius * alpha * 0.3)
            x = int(pos[0] + camera_offset[0])
            y = int(pos[1] + camera_offset[1])
            color = (int(PEARL_COLOR[0] * alpha), 
                    int(PEARL_COLOR[1] * alpha), 
                    int(PEARL_COLOR[2] * alpha))
            pygame.draw.circle(surface, color, (x, y), radius)
        
        # 绘制龙珠
        x = int(self.position[0] + camera_offset[0])
        y = int(self.position[1] + camera_offset[1])
        
        # 绘制发光效果
        for i in range(5):
            radius = self.radius + i * 3
            alpha = 100 - i * 20
            color = (PEARL_COLOR[0], PEARL_COLOR[1], PEARL_COLOR[2])
            s = pygame.Surface((radius*2, radius*2), pygame.SRCALPHA)
            pygame.draw.circle(s, (*color, alpha), (radius, radius), radius)
            surface.blit(s, (x - radius, y - radius))
        
        # 绘制旋转的光线
        for i in range(8):
            angle = self.rotation + i * math.pi / 4
            dx = math.cos(angle) * (self.radius + 10)
            dy = math.sin(angle) * (self.radius + 10)
            pygame.draw.line(surface, YELLOW, 
                           (x + dx * 0.5, y + dy * 0.5),
                           (x + dx * 1.5, y + dy * 1.5), 3)

# 生成龙形曲线
def generate_dragon_curve(pearl_pos, num_points=1000):
    """生成一条龙形曲线,龙珠在头部"""
    points = []
    
    # 龙珠位置作为头部
    head_x, head_y, head_z = pearl_pos
    
    # 生成龙身曲线(正弦波 + 噪声)
    for i in range(num_points):
        t = i / num_points * 4 * math.pi
        progress = i / num_points
        
        # 龙身跟随龙珠轨迹
        x = head_x + math.sin(t * 0.8) * 100 * (1 - progress) + math.cos(t * 1.2) * 50
        y = head_y + math.cos(t * 0.6) * 80 * (1 - progress) + math.sin(t * 1.5) * 40
        z = head_z + math.sin(t * 1.0) * 60 * (1 - progress)
        
        # 添加一些随机噪声
        x += random.uniform(-10, 10) * (1 - progress)
        y += random.uniform(-10, 10) * (1 - progress)
        z += random.uniform(-5, 5) * (1 - progress)
        
        points.append((x, y, z))
    
    return points

# 初始化无人机群
NUM_DRONES = 1000  # 减少数量以保证性能,实际可调整到10000但需要性能优化
drones = []
dragon_pearl = DragonPearl()

# 初始位置 - 螺旋形排列
center_x, center_y = screen_width // 2, screen_height // 2
for i in range(NUM_DRONES):
    angle = i * 2 * math.pi / NUM_DRONES
    radius = 100 + (i % 20) * 2
    x = center_x + math.cos(angle) * radius
    y = center_y + math.sin(angle) * radius
    z = (i % 10) * 5 - 25
    drones.append(Drone(i, (x, y, z)))

# 生成龙形路径点
dragon_path = generate_dragon_curve(dragon_pearl.position, 200)

# 相机偏移(用于移动视图)
camera_offset = np.array([0.0, 0.0])
camera_target = np.array([0.0, 0.0])
camera_speed = 0.05

# 主循环
running = True
frame_count = 0
performance_mode = False
show_trails = True

# 字体
font = pygame.font.SysFont(None, 24)

while running:
    dt = clock.tick(60) / 1000.0  # 保持60FPS
    
    # 处理事件
    for event in pygame.event.get():
        if event.type == QUIT:
            running = False
        elif event.type == KEYDOWN:
            if event.key == K_ESCAPE:
                running = False
            elif event.key == K_SPACE:
                performance_mode = not performance_mode
            elif event.key == K_t:
                show_trails = not show_trails
    
    # 更新龙珠
    dragon_pearl.update()
    
    # 生成新的龙形路径
    dragon_path = generate_dragon_curve(dragon_pearl.position, 200)
    
    # 更新相机跟随龙珠
    camera_target[0] = screen_width // 2 - dragon_pearl.position[0]
    camera_target[1] = screen_height // 2 - dragon_pearl.position[1]
    camera_offset = camera_offset * 0.9 + camera_target * 0.1
    
    # 为每架无人机设置目标点(形成龙形)
    for i, drone in enumerate(drones):
        # 根据无人机ID确定在龙身上的位置
        progress = (i % len(dragon_path)) / len(dragon_path)
        path_index = int(progress * (len(dragon_path) - 1))
        
        if path_index < len(dragon_path):
            target = dragon_path[path_index]
            
            # 添加一些偏移使龙身有厚度
            offset_angle = (i * 1.6180339887) % (2 * math.pi)  # 黄金角度
            offset_dist = 5 + 3 * math.sin(frame_count * 0.05 + i * 0.01)
            target_x = target[0] + math.cos(offset_angle) * offset_dist
            target_y = target[1] + math.sin(offset_angle) * offset_dist
            target_z = target[2] + offset_dist * 0.5
            
            # 设置无人机颜色(根据在龙身上的位置)
            if i < NUM_DRONES * 0.1:  # 头部 - 金色
                drone.color = GOLD
            elif i < NUM_DRONES * 0.3:  # 颈部 - 黄色
                drone.color = YELLOW
            else:  # 身体 - 蓝色渐变
                blue_val = int(100 + 155 * progress)
                drone.color = (0, blue_val // 2, blue_val)
            
            drone.set_target((target_x, target_y, target_z))
        
        # 更新无人机位置
        drone.update(dt)
    
    # 绘制
    screen.fill(BLACK)
    
    # 绘制背景星空
    if not performance_mode:
        for i in range(100):
            x = (i * 123456) % screen_width
            y = (i * 78901) % screen_height
            brightness = (i * 100) % 155 + 100
            pygame.draw.circle(screen, (brightness, brightness, brightness), 
                             (int(x + camera_offset[0] * 0.1), 
                              int(y + camera_offset[1] * 0.1)), 
                             1)
    
    # 绘制无人机
    if performance_mode:
        # 性能模式:批量绘制点
        points = [(int(d.position[0] + camera_offset[0]), 
                  int(d.position[1] + camera_offset[1])) 
                 for d in drones]
        pygame.draw.lines(screen, DRAGON_BODY, False, points, 1)
    else:
        # 正常模式:绘制每架无人机
        for drone in drones:
            drone.draw(screen, camera_offset)
    
    # 绘制龙珠
    dragon_pearl.draw(screen, camera_offset)
    
    # 绘制轨迹(可选)
    if show_trails and not performance_mode:
        # 绘制一些无人机的轨迹
        for i in range(0, NUM_DRONES, NUM_DRONES // 20):
            drone = drones[i]
            trail_points = []
            for j in range(10):
                offset = j * 5
                x = drone.position[0] + math.sin(drone.noise_offset + offset) * 5
                y = drone.position[1] + math.cos(drone.noise_offset + offset) * 5
                trail_points.append((int(x + camera_offset[0]), int(y + camera_offset[1])))
            if len(trail_points) > 1:
                pygame.draw.lines(screen, CYAN, False, trail_points, 1)
    
    # 绘制UI信息
    info_text = [
        f"无人机数量: {NUM_DRONES}架",
        f"帧率: {int(clock.get_fps())} FPS",
        f"性能模式: {'开' if performance_mode else '关'} (按空格切换)",
        f"显示轨迹: {'开' if show_trails else '关'} (按T切换)",
        f"龙珠位置: ({int(dragon_pearl.position[0])}, {int(dragon_pearl.position[1])})",
        "模拟10000架无人机表演戏水龙珠",
        "龙珠引导,无人机群形成龙身跟随",
        "按ESC退出"
    ]
    
    for i, text in enumerate(info_text):
        text_surface = font.render(text, True, WHITE)
        screen.blit(text_surface, (10, 10 + i * 25))
    
    # 绘制标题
    title_font = pygame.font.SysFont(None, 48)
    title = title_font.render("无人机戏水龙珠表演", True, GOLD)
    subtitle = font.render("10000架无人机动态模拟 (实际显示:1000架)", True, CYAN)
    screen.blit(title, (screen_width // 2 - title.get_width() // 2, 20))
    screen.blit(subtitle, (screen_width // 2 - subtitle.get_width() // 2, 80))
    
    # 更新显示
    pygame.display.flip()
    frame_count += 1

pygame.quit()
sys.exit()

程序说明

功能特点:

  1. 龙珠系统:一个发光的龙珠在屏幕中按照正弦波轨迹移动

  2. 无人机跟随:1000架无人机(为性能考虑,可调整为10000架)形成龙身跟随龙珠

  3. 动态效果:无人机位置会添加随机扰动,模拟真实飞行效果

  4. 色彩渐变:无人机根据位置显示不同颜色(头部金色,身体蓝色渐变)

  5. 3D效果:无人机有Z轴高度,影响显示大小和亮度

  6. 交互控制

    • 空格键:切换性能模式(线条模式)

    • T键:切换轨迹显示

    • ESC键:退出程序

如果要扩展到10000架无人机:

  1. 将代码中的 NUM_DRONES = 1000改为 NUM_DRONES = 10000

  2. 可能需要进一步优化:

    • 使用OpenGL加速渲染

    • 使用NumPy批量计算

    • 简化物理计算

运行要求:

pip install pygame numpy

这个模拟程序展示了无人机集群表演的基本原理,包括路径规划、跟随算法和视觉效果。在实际无人机表演中,还需要考虑:

  • 精确的GPS定位和RTK技术

  • 无线通信同步

  • 避障算法

  • 电源管理

  • 安全协议

希望这个模拟程序能帮助您理解无人机集群表演的基本原理!

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐