小的无人机仿真代码

无人机仿真代码,至少能飞

改善转弯函数应该可以得到好的仿真
图就是这样

上代码吧

import math
import matplotlib.pyplot as plt
import random
pi = math.pi

class Fly:
    def __init__(self, vec, rad, x, y):
        self.vec = vec  # 速度
        self.rad = rad  # 方向
        self.x = x  # 坐标
        self.y = y
        self.trace_x = []
        self.trace_y = []   # 移动记录
        self.trace_x.append(int(self.x))
        self.trace_y.append(int(self.y))
        self.sn = -1
        self.old_x=0
        self.old_y=0

    def move(self):
        self.x += self.vec * math.cos(self.rad)
        self.y += self.vec * math.sin(self.rad)
        # print(self.x, ' , ', self.y)
        self.trace_x.append(int(self.x))
        self.trace_y.append(int(self.y))

    def try_move(self, rad):
        self.old_x = self.x
        self.old_y = self.y
        self.x += self.vec * math.cos(rad)
        self.y += self.vec * math.sin(rad)
        # self.trace_x.append(int(self.x))
        # self.trace_y.append(int(self.y))


    def back(self):
        self.x = self.old_x
        self.y = self.old_y
        # self.trace_x.pop()
        # self.trace_y.pop()

    def red_cul_sn(self, blue, r):

        weight = 0
        where = 0
        for b in blue:
            d = distance(self, b)
            if self.x - b.x > 30000:
                self.rad = pi
                return
            sn = blue_k * norlize(math.pow(d/100, -2))
            dir = (math.atan2(b.y -self.y, b.x -self.x) + 2 * pi) % (2 * pi)

            # if dir > b.rad:
            #     if dir - b.rad > pi:
            #         dir = beta * (b.rad + 2 * pi) + dir * (1 - alpha)
            #     else:
            #         dir = dir * (1 - alpha) + beta * b.rad
            # else:
            #     if b.rad - dir > pi:
            #         dir = (dir + 2 * pi) * (1 - beta) + beta * b.rad
            #     else:
            #         dir = beta * b.rad + dir * (1 - beta)
            # if d > 5000:
            #     if dir > b.rad:
            #         if dir - b.rad > pi:
            #             dir = alpha * (b.rad + 2 * pi) + dir * (1 - alpha)
            #         else:
            #             dir = dir * (1 - alpha) + alpha * b.rad
            #     else:
            #         if b.rad - dir > pi:
            #             dir = (dir + 2 *pi) * (1 - alpha) + alpha * b.rad
            #         else:
            #             dir = alpha * b.rad + dir * (1 - alpha)
            # else:
            #     if dir > b.rad:
            #         if dir - b.rad > pi:
            #             dir = beta * (b.rad + 2 * pi) + dir * (1 - alpha)
            #         else:
            #             dir = dir * (1 - alpha) + beta * b.rad
            #     else:
            #         if b.rad - dir > pi:
            #             dir = (dir + 2 * pi) * (1 - beta) + beta * b.rad
            #         else:
            #             dir = beta * b.rad + dir * (1 - beta)
            dir = (dir + 2*pi + pi/4) % (2*pi)
            if weight == 0:
                weight = sn
                where = dir
                # print(where)
                continue
            weight, where = cal_where(weight, where, sn, dir)

        flag = 0
        # if self.rad > where:
        #     if self.rad - where > pi:
        #         if (min(self.rad, 2 * pi - self.rad) + min(where, 2 * pi - where)) > red_turn_rad:
        #             # print('1')
        #             self.rad = self.rad + red_turn_rad
        #             flag = 1
        #     else:
        #         if self.rad - where > red_turn_rad:
        #             # print('2')
        #             self.rad = self.rad - red_turn_rad
        #             flag = 1
        # else:
        #     if where - self.rad > pi:
        #         # print('3')
        #         if min(self.rad, 2 * pi - self.rad) + min(where, 2 * pi - where) > red_turn_rad:
        #             self.rad = self.rad - red_turn_rad
        #             flag = 1
        #     else:
        #         # print('4')
        #         if where - self.rad > red_turn_rad:
        #             self.rad = self.rad + red_turn_rad
        #             flag = 1
        # if flag == 0:
        self.rad = where
        self.rad = (self.rad +2 * pi) % (2 * pi)

        # cc = 0
        # while (1):
        #     print(cc)
        #     cc += 1
        #     rad = (self.rad + (random.random() - 0.5) % (0.0001 * pi) + 2 * pi) % (2 * pi)
        #     self.try_move(rad)
        #     if self.constrain(r):
        #         self.back()
        #         self.rad = rad
        #         break
        #     self.back()


    def blue_cul_sn(self, red):
        self.rad = 0
        return
        weight = 1
        where = self.rad
        for r in red:
            for rr in r:
                d = distance(self, rr)
                dir = rr.rad
                sn = red_k * (math.pow(d/100, -2)) * math.fabs(dir - self.rad)
                if weight == 1:
                    weight = sn
                    where = dir
                    continue
                weight, where = cal_where(weight, where, sn, dir)
                # print(where)

        # 对于上边界
        up_dir = math.pi * 3 / 2
        if y_up[1] - self.y <= 1000:
            up_sn = up_k * norlize(math.pow((y_up[1] - self.y)/100, -2))
            weight, where = cal_where(weight, where, up_sn, up_dir)

        # 对于下边界
        down_dir = math.pi / 2
        if 0< self.y <= 1000:
            down_sn = down_k * norlize(math.pow(self.y/100, -2))
            weight, where = cal_where(weight, where, down_sn, down_dir)

        # 对于右边界(目的地)
        right_dir = 0
        right_sn = right_k
        # print(where)
        weight, where = cal_where(weight, where, right_sn, right_dir)

        # print(where)

        # 完成角度计算
        flag = 0
        if self.rad > where:
            if self.rad - where > pi:
                if min(self.rad, 2*pi - self.rad) + min(where, 2*pi - where) > blue_turn_rad:
                    # print('1')
                    self.rad = self.rad + blue_turn_rad
                    flag = 1
            else:
                if self.rad - where > blue_turn_rad:
                    # print('2')
                    self.rad = self.rad - blue_turn_rad
                    flag = 1
        else:
            if where - self.rad > pi:
                # print('3')
                if min(self.rad, 2*pi - self.rad) + min(where, 2*pi - where) > blue_turn_rad:
                    self.rad = self.rad - blue_turn_rad
                    flag = 1
            else:
                # print('4')
                if where - self.rad > blue_turn_rad:
                    self.rad = self.rad + blue_turn_rad
                    flag = 1
        if flag == 0:
            self.rad = where
        self.rad = (self.rad + 2 * pi) % (2 * pi)

    def constrain(self, r):
        min_count = 0
        for rr in r:
            if distance(self, rr) < 30:
                min_count +=1
            if min_count > 1:
                return False
        max_count = 0
        for rr in r:
            if distance(self, rr) < 200:
                max_count += 1
        if max_count < 3:
            return False
        return True


def draw(blue, red, x_up, y_up):
    # plt.ion()
    plt.ylim(y_up[0], y_up[1])
    plt.xlim(x_up[0], x_up[1])
    # llen = len(blue[0].trace_x)
    point = range(len(blue[0].trace_x))
    for b in blue:
        plt.scatter(b.trace_x, b.trace_y, c=point, cmap=plt.cm.Blues, s=5)
        # plt.pause(0.2)

    for r in red:
        for rr in r:
            plt.scatter(rr.trace_x, rr.trace_y, c=point, cmap=plt.cm.Reds, s=5)
    plt.show()



def cal_where(v1_w, v1_d, v2_w, v2_d):
    v1_x = v1_w * math.cos(v1_d)
    v1_y = v1_w * math.sin(v1_d)
    v2_x = v2_w * math.cos(v2_d)
    v2_y = v2_w * math.sin(v2_d)
    new_w = math.sqrt(math.pow(v1_x + v2_x, 2) + math.pow(v1_y + v2_y, 2))
    new_d = (math.atan2(v1_y + v2_y, v1_x + v2_x) + 2 * math.pi) % (2 * math.pi)
    return new_w, new_d

def blue_success(blue):
    # 判断蓝色方是否逃脱了
    count = 0
    for i in range(len(blue)):
        if blue[i].x >= x_up[1]:
            print('蓝色飞机- ', i + 1, ' -逃脱成功!')
            count += 1
    return count == len(blue)

def distance(f1, f2):
    # 判断任意两个飞机的距离
    return math.sqrt(math.pow((f1.x - f2.x), 2) + math.pow((f1.y - f2.y), 2))

def distance1(f1, f2):
    # 判断任意两个飞机的距离
    return math.sqrt(math.pow((f1.x - f2.x), 2) + math.pow((f1.y - f2.y), 2))

def red_success(red, blue):
    # 判断红色方是否捕捉了 蓝色
    for i in range(len(blue)):
        count = 0
        for r in red:
            for rr in r:
                if distance1(rr, blue[i]) <= cap_distance:
                    count += 1
                if count > 1:
                    print('红色飞机捕获了蓝色飞机- ', )
                    return True
    return False

def red_distance(f1, f2):
    # 判断红色小飞机是否满足约束 30
    return distance(f1, f2) >= red_min_distance

def cal_sn(red, blue):
    # 计算方向操作
    for b in blue:
        b.blue_cul_sn(red)

    for r in red:
        for rr in r:
            rr.red_cul_sn(blue, r)

def all_move(red, blue):
    # 移动操作
    for b in blue:
        b.move()

    for r in red:
        for rr in r:
            rr.move()

def initial_red(red_num, cycle_x, cycle_y):
    avg = 2 * math.pi / red_num
    angles = []
    for i in range(red_num):
        angles.append(i * avg)
    FY = []
    for a in angles:
        x = red_radius * math.cos(a) + cycle_x
        y = red_radius * math.sin(a) + cycle_y
        fy = Fly(vec=rr_vec, rad=math.pi, x=x, y=y)
        FY.append(fy)
    return FY

def beyond(blue):
    count = 0
    for i in range(len(blue)):
        if blue[i].x < x_up[0] or blue[i].y > y_up[1] or blue[i].y < y_up[0]:
            print('蓝色飞机- ', i + 1, ' -撞墙!')
            count += 1
    return count == len(blue)

def norlize(s):
    return (s - nor_min) / (nor_max - nor_min)

x_up = [0, 50000]  # x为 0 ~ 50 km
y_up = [0, 70000]
cap_distance = 300.
blue_turn_rad = 0.0795774
red_turn_rad = 0.09094568
red_min_distance = 30.
red_radius = 100.
rr_vec = 200
blue_vec = 250
red_k = 0.05      # 红色飞机排斥系数
blue_k = 1      # 蓝色飞机吸引系数
up_k = 10      # 上界的排斥系数
down_k = 10      # 下界的排斥系数
right_k = 0.0005   # 目标的吸引系数
epochs = 360
alpha = 0.3
beta = 0.7
nor_max, nor_min = 1, 1 / 10000


# 初始化个数以及出生位置
blue1 = Fly(vec=blue_vec, rad=0., x=x_up[0], y=y_up[1] /2)
# blue2 = Fly(vec=blue_vec, rad=0., x=x_up[0], y=y_up[1] /2)
# blue3 = Fly(vec=blue_vec, rad=0., x=x_up[0], y=y_up[1] *3/4)
blue = [blue1]
red1 = initial_red(5, x_up[1], y_up[1]-20000)
red2 = initial_red(5, x_up[1], y_up[0]+20000)
# red3 = initial_red(5, x_up[1], y_up[1] * 2/3)
# red4 = initial_red(5, x_up[1], y_up[1] /3)
# red5 = initial_red(5, x_up[1], y_up[1] /6)
red = [red1, red2]
x_history = []
y_history = []
# for i in range(1, x_up[1] - 1, 250):
#     for j in range(1, y_up[1]-1, 250):
#         blue1 = Fly(vec=blue_vec, rad=0., x=i, y=j)
#         blue = [blue1]
for i in range(1, epochs + 1):
    '''
    每个东西 都计算势能
    然后根据势能计算下一步的位置
    '''
    cal_sn(red, blue)

    all_move(red, blue)


    if blue_success(blue):
        # x_history.append(i)
        # y_history.append(j)
        print('当前 ', i, ' 秒')
        print('蓝色飞机 1 成功逃脱')
        break

    if red_success(red, blue):
        print('当前 ', i, ' 秒')
        print('红色飞机成功捕获 蓝色飞机 1')
        break

    if beyond(blue):
        print('当前 ', i, ' 秒')
        print('蓝色飞机 1 撞墙失败')
        break

def ddraw(x, y):
    plt.ylim(y_up[0], y_up[1])
    plt.xlim(x_up[0], x_up[1])
    plt.scatter(x, y, s=5)
    plt.show()

draw(blue, red, x_up, y_up)
# ddraw(x_history,y_history)
  • 1
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值