boid 模型python实现模拟鸟群运动

本文使用BOIDS三层模型对鸟群运动进行了模拟,可以通过调节不同的参数获取到不同的实验现象,可以在这个基础上修改模型规则,以更好的模拟集群运动,本文提供一个模板。

# -*- coding:utf-8 -*-
import argparse
import math
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from scipy.spatial.distance import squareform, pdist
from numpy.linalg import norm

width, height = 1920, 1080

N = 100             # number of birds
minDist = 100.0      # min dist of approach
maxRuleVel = 0.3    # max magnitude of velocities calculated by "rules"
maxVel = 3.0        # max magnitude of final velocity


class Birds:
    """
    Simulates flock behaviour of birds, using the realistic-looking Boids model (1986)
    """
    def __init__(self):
        self.N = N
        self.minDist = minDist
        self.maxRuleVel = maxRuleVel
        self.maxVel = maxVel

        # Computing initial position and velocity
        self.pos = [width / 2.0, height / 2.0] + 10 * np.random.rand(2 * N).reshape(N, 2)
        # Create an array of N random variable angles in the range [0. 2pi]
        angles = 2 * math.pi * np.random.rand(N)
        # Random velocity vector [x,y] coordinates zip grouped
        self.vel = np.array(list(zip(np.sin(angles), np.cos(angles))))
    def savef(self):
        with open("douban.txt", "a") as f:
            f.write(str(self.pos.reshape(1, N*2)))
            print str(self.pos.reshape(1, N*2))
            f.close()
    def tick(self, frameNum, pts, beak):
        """
        Update the simulation by one time step
        """
        # get pairwise distances
        self.distMatrix = squareform(pdist(self.pos))
        # apply rules:
        self.vel += self.apply_rules()
        self.limit(self.vel, self.maxVel)
        self.pos += self.vel
        self.apply_bc()
        # update data
        pts.set_data(self.pos.reshape(2 * self.N)[::2],
                     self.pos.reshape(2 * self.N)[1::2])
        vec = self.pos + 10 * self.vel / self.maxVel
        beak.set_data(vec.reshape(2 * self.N)[::2],
                      vec.reshape(2 * self.N)[1::2])
        self.savef()
        #print self.pos.reshape(2 * self.N)
        #np.savetxt("x.txt", self.pos.reshape(1, 2*N))
    def limit_vec(self, vec, max_val):
        """ Limit magnitude of 2D vector """
        mag = norm(vec)
        if mag > max_val:
            vec[0], vec[1] = vec[0] * max_val / mag, vec[1] * max_val / mag

    def limit(self, x, max_val):
        """ Limit magnitide of 2D vectors in array X to maxValue """
        for vec in x:
            self.limit_vec(vec, max_val)

    def apply_bc(self):
        """ Apply boundary conditions """
        deltaR = 2.0
        for coord in self.pos:
            if coord[0] > width + deltaR:
                coord[0] = - deltaR
            if coord[0] < - deltaR:
                coord[0] = width + deltaR
            if coord[1] > height + deltaR:
                coord[1] = - deltaR
            if coord[1] < - deltaR:
                coord[1] = height + deltaR

    def apply_rules(self):
        # apply rule #1 - Separation
        D = self.distMatrix < 20.0
        vel = self.pos * D.sum(axis=1).reshape(self.N, 1) - D.dot(self.pos)
        self.limit(vel, self.maxRuleVel)

        # different distance threshold
        D = self.distMatrix < 50.0

        # apply rule #2 - Alignment
        vel2 = D.dot(self.vel)
        self.limit(vel2, self.maxRuleVel)
        vel += vel2

        # apply rule #1 - Cohesion
        vel3 = D.dot(self.pos) - self.pos
        self.limit(vel3, self.maxRuleVel)
        vel += vel3

        return vel


def tick(frameNum, pts, beak, birds):
    """ Update function for animation """
    birds.tick(frameNum, pts, beak)
    return pts, beak


def main():
    print('Starting flock simulation...')

    # Create birds
    birds = Birds()

    # Setup plot
    fig = plt.figure()
    ax = plt.axes(xlim=(0, width), ylim=(0, height))
    pts, = ax.plot([], [], markersize=10, c='k', marker='o', ls='None')
    beak, = ax.plot([], [], markersize=4, c='r', marker='o', ls='None')
    anim = animation.FuncAnimation(fig, tick, fargs=(pts, beak, birds), interval=20)

    # TODO: add a "button press" event handler to scatter birds
    #anim.save('basic_animation.mp4', fps=30, extra_args=['-vcodec', 'libx264'])
    plt.show(anim)
if __name__ == '__main__':
    main()
  

  

posted @ 2017-03-26 09:00  沐雨橙风fire  阅读(1579)  评论(0编辑  收藏  举报