예제 #1
0
    def __init__(self, IP, AIPort, scenario_name, simulate_compression):
        self.control_noise = True
        self.SERVER_PLAT = "linux"
        self.SERVER_IP = IP
        self.SERVER_PORT = AIPort
        self.connect_mode = 1
        self.DURATION_INTERVAL = etc.DURATION_INTERVAL
        self.simulate_compression = simulate_compression
        self.scenario_name = scenario_name
        self.mozi_service = MoziService(IP,
                                        AIPort,
                                        self.scenario_name,
                                        connect_mode=self.connect_mode)

        self.action_space = 4
        self.action_max = 1
        self.element_item_count = 7
        self.observation_space = 7 * 2

        self.last_situation_time = None
        self.red_unit_list = None
        self.blue_unit_list = None
        self.observation = None
        self.red_side_name = "红方"
        self.blue_side_name = "蓝方"
예제 #2
0
 def connect_mozi_server(self, websocket_Ip, websocket_port):
     """
     连接墨子服务器
     param :
     websocket_server 要连接的服务器的ip
     websocket_port 要连接的服务器的端口
     :return:
     """
     pylog.info("connect_mozi_server")
     if self.connect_mode == 1:
         self.mozi_service = MoziService(websocket_Ip, websocket_port,
                                         self.scenario_name)
         return True
     # server_address = r"ws://%s:%d/websocket" % ('60.205.207.206', 9998)
     server_address = r"ws://%s:%d/websocket" % (websocket_Ip,
                                                 websocket_port)
     pylog.info(server_address)
     for i in range(10):
         try:
             self.websocket_connect = create_connection(server_address)
             break
         except:
             pylog.info("can not connect to %s." % server_address)
             time.sleep(2)
             self.websocket_connect = None
     #
     if self.websocket_connect is None:
         pylog.warning("Interrupted, can not connect to %s." %
                       server_address)
         return False
     #
     self.websocket_connect.send("{\"RequestType\":\"StartServer\"}")
     result = self.websocket_connect.recv()
     print("connect server result:%s" % result)
     jsons = json.loads(result)
     self.ai_server = jsons['IP']
     self.ai_port = jsons['AIPort']
     self.mozi_task = MoziService(self.server_ip, self.aiPort,
                                  self.scenario_name)
     return True
예제 #3
0
class MoziEnv():
    def __init__(self, IP, AIPort, scenario_name, simulate_compression):
        self.control_noise = True
        self.SERVER_PLAT = "linux"
        self.SERVER_IP = IP
        self.SERVER_PORT = AIPort
        self.connect_mode = 1
        self.DURATION_INTERVAL = etc.DURATION_INTERVAL
        self.simulate_compression = simulate_compression
        self.scenario_name = scenario_name
        self.mozi_service = MoziService(IP,
                                        AIPort,
                                        self.scenario_name,
                                        connect_mode=self.connect_mode)

        self.action_space = 2
        self.action_max = 1
        self.observation_space = 3

        self.last_situation_time = None
        self.red_unit_list = None
        self.blue_unit_list = None
        self.observation = None
        self.red_side_name = "美国海军"
        self.blue_side_name = "俄罗斯海军"

    def _init_red_unit_list(self):
        side_name = self.red_side_name

        ret_lt = []
        side_guid = get_side_guid_from_side_name(
            side_name, self.mozi_service.all_info_dict)
        side_dic = get_a_side_dic(side_guid, self.mozi_service.all_info_dict)
        aircraft_list_dic = get_units_from_side(
            side_guid, "CAircraft", self.mozi_service.all_info_dict)
        for key in aircraft_list_dic:
            ret_lt.append(key)
        return ret_lt

    def _init_blue_unit_list(self):
        side_name = self.blue_side_name

        ret_lt = []
        side_guid = get_side_guid_from_side_name(
            side_name, self.mozi_service.all_info_dict)
        submarine_list_dic = get_units_from_side(
            side_guid, "CSubmarine", self.mozi_service.all_info_dict)

        return ret_lt

    def _init_unit_list(self):
        self.red_unit_list = self._init_red_unit_list()
        self.blue_unit_list = self._init_blue_unit_list()

    def _get_a_side_observation(self, unit_list):
        obs_lt = []
        for key in unit_list:
            unit = self.mozi_service.all_info_dict.get(key, "")
            if unit:
                obs_lt.append(unit["dLongitude"])
                obs_lt.append(unit["dLatitude"])
                obs_lt.append(unit["fCurrentHeading"])
            else:
                pylog.info("unit do not exist")
                obs_lt.append(0.0)
                obs_lt.append(0.0)
                obs_lt.append(0.0)

        return obs_lt

    def _get_blue_observation(self):
        unit_list = self.blue_unit_list
        obs_lt = self._get_a_side_observation(unit_list)
        return obs_lt

    def _get_red_observation(self):
        unit_list = self.red_unit_list
        obs_lt = self._get_a_side_observation(unit_list)
        return obs_lt

    def _get_observation(self):
        red_obs_lt = self._get_red_observation()
        self.observation = red_obs_lt

        if self._check_aircraft_exist():
            if etc.TRANS_DATA:
                lt = []
                lt.append(red_obs_lt[0] - etc.task_end_point["longitude"])
                lt.append(red_obs_lt[1] - etc.task_end_point["latitude"])
                lt.append(red_obs_lt[2] / 360)
                return lt

        return red_obs_lt

    def _set_duration_interval(self):
        self.mozi_service.mozi_task.sendAndRecv("Hs_OneTimeStop('Stop', %d)" %
                                                self.DURATION_INTERVAL)

    def _reset(self):
        ret = self.mozi_service.suspend_simulate()
        self.mozi_service.all_info_dict = {}
        self.scenario = self.mozi_service.load_scenario(plat=self.SERVER_PLAT)
        self._set_duration_interval()

        ret = self.mozi_service.set_run_mode()
        ret = self.mozi_service.set_simulate_compression(
            self.simulate_compression)
        ret = self.mozi_service.set_compression_mode(False)

        self._run_simulate()

    def _run_simulate(self):
        pylog.info("run simulation")
        return self.mozi_service.run_simulate()

    def _check_duration(self):
        update_situation_time = self.mozi_service.mozi_task.getCurrentTime()
        if self.last_situation_time != None:
            duration_time = float(update_situation_time) - float(
                self.last_situation_time)
            if int(duration_time) != self.DURATION_INTERVAL:
                pylog.error(
                    "duration_time:%s is differet from etc.DURATION_INTERVAL:%s"
                    % (duration_time, self.DURATION_INTERVAL))

        self.last_situation_time = update_situation_time

    def _run_with_situation_data(self):
        self.mozi_service.update_situation(self.scenario)
        # self._check_duration()

    def _get_waypoint_heading(self, last_heading, action_value):
        current_heading = last_heading + action_value
        if current_heading < 0:
            current_heading += 360
        if current_heading > 360:
            current_heading -= 360
        return current_heading

    def _get_new_waypoint(self, heading, lat, lon, distance=20.0):
        dic = get_point_with_point_bearing_distance(lat, lon, heading,
                                                    distance)
        return dic

    def _deal_point_data(self, waypoint):
        if self.control_noise:
            lon = str(
                float(waypoint["longitude"]) + random.random() / 10.0 - 0.05)
            lat = str(
                float(waypoint["latitude"]) + random.random() / 10.0 - 0.05)
        else:
            lon = str(waypoint["longitude"]),
            lat = str(waypoint["latitude"]),
        return lon, lat

    def _check_is_drop_sonobuoy(self, action_value):
        if action_value[1].item() > 0:
            return True
        return False

    def _get_aircraft_waypoint(self, action_value):
        obs = self.observation
        # pylog.info(obs)

        longitude = obs[0]
        latitude = obs[1]
        heading = obs[2]

        waypoint_heading = self._get_waypoint_heading(
            heading, action_value[0].item() * 90)
        waypoint = self._get_new_waypoint(waypoint_heading, latitude,
                                          longitude)
        distance = get_target_distance(latitude, longitude)
        return waypoint, distance

    def _execute_action(self, action_value):
        waypoint, distance = self._get_aircraft_waypoint(action_value)
        guid = self.red_unit_list[0]
        aircraft = self.mozi_service.get_entity(guid)

        if self._check_is_find_target():
            target_guid = self._get_target_guid()
            # aircraft.autoattack_target(target_guid, self.mozi_service.mozi_task)
            aircraft.autoattack_target(target_guid)
        else:
            if distance < etc.target_radius:
                if self._check_is_drop_sonobuoy(action_value):
                    # aircraft.drop_sonobuoy(self.red_side_name, "shallow", "active", self.mozi_service.mozi_task)
                    aircraft.drop_sonobuoy(self.red_side_name, "shallow",
                                           "active")

            lon, lat = self._deal_point_data(waypoint)
            # aircraft.set_waypoint(self.red_side_name, guid, lon, lat, self.mozi_service.mozi_task)
            aircraft.set_waypoint(self.red_side_name, guid, lon, lat)

    def _check_done(self):
        if not self._check_aircraft_exist():
            return True
        if not self._check_target_exist():
            return True
        return False

    def _check_aircraft_exist(self):
        obs = self.observation
        for i in range(len(obs)):
            if obs[i] != 0.0:
                return True
        return False

    def _check_target_exist(self):
        if not check_is_exist_target(etc.target_name,
                                     self.mozi_service.all_info_dict):
            return False
        return True

    def _get_target_guid(self):
        target_name = etc.target_name
        target_guid = get_target_contact_guid_from_target_name(
            self.red_side_name, target_name, self.mozi_service.all_info_dict)
        return target_guid

    def _check_is_find_target(self):
        target_guid = self._get_target_guid()

        if target_guid:
            pylog.info("find target_guid:%s" % target_guid)
            return True
        return False

    def _get_distance_reward(self, action_value):
        obs = self.observation
        longitude = obs[0]
        latitude = obs[1]
        heading = obs[2]

        distance = get_target_distance(latitude, longitude)
        action_change_heading = action_value[0].item() * 90
        reward = get_distance_reward(latitude, longitude, heading,
                                     action_change_heading)
        return reward, distance

    def _get_reward(self, action_value):
        reward = 0.0
        distance_reward, distance = self._get_distance_reward(action_value)
        reward += distance_reward

        if distance < etc.target_radius:
            if self._check_is_drop_sonobuoy(action_value):
                # pylog.info("target area drop sonobuoy get 10.0 reward")
                reward += 10.0
        else:
            if not self._check_aircraft_exist():
                # pylog.info("aircraft is not exist get -100.0 reward")
                reward += -100.0

        if self._check_is_find_target():
            # pylog.info("find target get 10.0 reward")
            reward += 10.0

        if not self._check_target_exist():
            pylog.info("destroy target get 150.0 reward")
            reward += 150.0

        return reward

    def reset(self):
        self._reset()
        self.mozi_service.init_situation(self.scenario)
        self._init_unit_list()
        obs = self._get_observation()
        return np.array(obs)

    def step(self, action):
        self._execute_action(action)
        self._run_with_situation_data()
        obs = self._get_observation()

        reward = self._get_reward(action)
        done = self._check_done()
        info = ""
        return np.array(obs), reward, done, info

    def connect_server(self):
        if not self.mozi_service.connect_mozi_server(self.SERVER_IP,
                                                     self.SERVER_PORT):
            return False
        else:
            return True
예제 #4
0
파일: env.py 프로젝트: doublestar90/Course
class Environment():
    '''
    环境
    '''
    def __init__(self, IP, AIPort, scenario_name, simulate_compression):
        self.server_ip = IP
        self.aiPort = AIPort
        self.scenario_name = scenario_name
        self.websocker_conn = None
        self.mozi_server = None
        self.scenario = None
        self.connect_mode = 1
        self.num = 1
        self.simulate_compression = simulate_compression
        #self.agent = CAgent()
    
    def step(self):
        '''
        步长
        主要用途:
        单步决策的方法
        根据环境态势数据改变战场环境
        '''
        time.sleep(1/3)
        self.mozi_server.suspend_simulate()
        self.mozi_server.update_situation(self.scenario)#数据更新
        self.redside.static_update()#数据组合
        self.blueside.static_update()
        #写了一个my_step函数,用来执行动作
        self.my_step(self.blueside)
        self.mozi_server.run_simulate()
        return self.scenario
    
    def reset(self):
        '''
        重置函数
        主要用途:
        加载想定,
        '''
        self.mozi_server.suspend_simulate() 
        self.mozi_server.load_scenario("linux")
        self.create_scenario() 
        self.mozi_server.init_situation(self.scenario)
        self.redside = self.scenario.get_side_by_name('红方')# 获得红方的主对象
        self.redside.static_construct() # 结构化平台返回数据,存入相应的实体属性中,
        self.blueside = self.scenario.get_side_by_name('蓝方')# 获得蓝方的主对象
        self.blueside.static_construct()
        self.mozi_server.run_simulate()
        self.mozi_server.set_simulate_compression(4) #设定推演步长
        
        
        #为了便于区分,定义了一个新的函数my_prepeo,以实例化的推演方对象作为参数输入,对推演前的任务进行设置

        self.my_prepro(self.blueside)


    def create_scenario(self):
        '''
        建立一个想定对象
        '''
        self.scenario = CScenario(self.mozi_server)

    def connect_mozi_server(self, websocket_Ip, websocket_port):
        """
        连接墨子服务器
        param :
        websocket_server 要连接的服务器的ip
        websocket_port 要连接的服务器的端口
        :return:
        """
        pylog.info("connect_mozi_server")
        if self.connect_mode == 1:
            self.mozi_server = MoziService(self.server_ip ,self.aiPort,self.scenario_name)
            return True
        # server_address = r"ws://%s:%d/websocket" % ('60.205.207.206', 9998)
        server_address = r"ws://%s:%d/websocket" % (websocket_Ip, websocket_port)
        pylog.info(server_address)
        for i in range(10):
            try:
                self.websocket_connect = create_connection(server_address)
                break
            except:
                pylog.info("can not connect to %s." % server_address)
                time.sleep(2)
                self.websocket_connect = None
        #
        if self.websocket_connect is None:
            pylog.warning("Interrupted, can not connect to %s." % server_address)
            return False
        #
        self.websocket_connect.send("{\"RequestType\":\"StartServer\"}")
        result = self.websocket_connect.recv()
        print("connect server result:%s" % result)
        jsons = json.loads(result)
        self.ai_server = jsons['IP']
        self.ai_port = jsons['AIPort']
        self.mozi_task = MoziService(self.server_ip ,self.aiPort,self.scenario_name)
        return True

    def start(self):
        '''
        开始函数
        主要用途:
        1.连接服务器端
        2.设置决策时间
        3.设置智能体决策想定是否暂停
        '''
        self.connect_mozi_server(self.server_ip,self.aiPort)
        self.mozi_server.set_run_mode()
        self.mozi_server.one_time_stop(10)
        
    def my_prepro(self,side):
        '''
        设置预先设定的任务
        '''
        #清空原本的想定任务
        mission_keys=list(self.blueside.missions.keys())
        for k in mission_keys:
            self.blueside.delete_mission(k)
        
        
        #记录信息,这部分是用来做条件判断
        self.enm_miss=[]
        
        
        #设置推演方条令,对水面自由开火,对空自由开火,电磁管控开
        doctrine=side.get_doctrine()
        doctrine.set_weapon_control_status_surface(0)
        doctrine.set_weapon_control_status_air(0)
        doctrine.set_em_control_status('Radar','Active')
        
        #设置武器打击距离
        #51
        doctrine.set_weapon_release_authority(weapon_dbid='51',target_type='1999', quantity_salvo='1', shooter_salvo='1',firing_range='45')
        doctrine.set_weapon_release_authority(weapon_dbid='51',target_type='2000', quantity_salvo='1', shooter_salvo='1',firing_range='45')
        doctrine.set_weapon_release_authority(weapon_dbid='51',target_type='2001', quantity_salvo='1', shooter_salvo='1',firing_range='45')
        
        #15
        doctrine.set_weapon_release_authority(weapon_dbid='15',target_type='2200', quantity_salvo='1', shooter_salvo='1',firing_range='25')
        doctrine.set_weapon_release_authority(weapon_dbid='15',target_type='2201', quantity_salvo='1', shooter_salvo='1',firing_range='25')
        doctrine.set_weapon_release_authority(weapon_dbid='15',target_type='2202', quantity_salvo='1', shooter_salvo='1',firing_range='25')        
        doctrine.set_weapon_release_authority(weapon_dbid='15',target_type='2203', quantity_salvo='1', shooter_salvo='1',firing_range='25')
        doctrine.set_weapon_release_authority(weapon_dbid='15',target_type='2204', quantity_salvo='1', shooter_salvo='1',firing_range='25')        
        doctrine.set_weapon_release_authority(weapon_dbid='15',target_type='1999', quantity_salvo='1', shooter_salvo='1',firing_range='20')
        

        #第一个是空战巡逻任务,主要是执行对空作战的歼击机,进行空中巡逻。第二个是空战等待任务,
        #创建空战任务飞机的巡逻区(以驱逐舰为中心的八边形,内径长80km)
        a=0
        ship=side.ships['6d829dba-2092-4b9d-a824-05ae1cb74c9b']
        point_list='{type="AAW",Zone={'
        for i in range(8):
            temp=get_geopoint_from_distance(geo_point=(ship.dLatitude,ship.dLongitude), azimuth=22.5+i*45, distance_m=80*1000)
            side.addReferencePoint('AAW_Attack'+str(i),temp[0],temp[1])
            if i!=7:
                point_list+=('"AAW_Attack'+str(i)+'",')
            else:
                point_list+=('"AAW_Attack'+str(i)+'"}}')
        print(point_list)
        side.add_mission('空战巡逻','Patrol',point_list)
        
        
        #创建突击任务飞机的巡逻区(以驱逐舰为中心的八边形,内径长30km)
        a=0
        point_list='{type="AAW",Zone={'
        for i in range(8):
            temp=get_geopoint_from_distance(geo_point=(ship.dLatitude,ship.dLongitude), azimuth=22.5+i*45, distance_m=30*1000)
            side.addReferencePoint('AAW_Wait'+str(i),temp[0],temp[1])
            if i!=7:
                point_list+=('"AAW_Wait'+str(i)+'",')
            else:
                point_list+=('"AAW_Wait'+str(i)+'"}}')
        
        side.add_mission('空战等待','Patrol',point_list)
        
        #创建突击任务
        side.add_mission('对水攻击','STRIKE',"{type='LAND'}")
        
        #对每类飞机设置标签,记录当前信息。
        self.AAW_Attack={}
        self.AAW_Wait={}
        
        for k,v in side.aircrafts.items():
            temp=v.strName.split('#')
            if int(temp[1])>8:
                self.AAW_Attack[k]={'空战巡逻':True}
            else:
                self.AAW_Wait[k]={'空战等待':True, '对水攻击':False}
        
        #最后一行代码,是用来标记任务是否进行了设置,在step中会用到。
        self.mission_setting=False    
        
    def get_enmInfo(self, side):
        '''
        获取探测信息
        '''
        #print(side.contacts)
        airs=dict()
        air_missiles=dict()
        ship_missiles=dict()
        defense_missiles=dict()
        ships=dict()
        for k,v in side.contacts.items():
            
            temp=v.get_contact_info()
            if temp['typed']==2:
                ships[k]={'name':temp['name'],'fg':temp['fg'],'longitude':temp['longitude'],'latitude':temp['latitude'],
                          'alt':temp['altitude'],'heading':temp['heading'],'speed':temp['speed']}
            if temp['typed']==1 and '导弹' in temp['name']:
                air_missiles[k]={'name':temp['name'],'fg':temp['fg'],'longitude':temp['longitude'],'latitude':temp['latitude'],
                          'alt':temp['altitude'],'heading':temp['heading'],'speed':temp['speed']}
            if temp['typed']==0:
                airs[k]={'name':temp['name'],'fg':temp['fg'],'longitude':temp['longitude'],'latitude':temp['latitude'],
                          'alt':temp['altitude'],'heading':temp['heading'],'speed':temp['speed']}
            if temp['typed']==1 and ('VAMPIRE' in temp['name'] or 'GuidedWeapon' in temp['name']):
                ship_missiles[k]={'name':temp['name'],'fg':temp['fg'],'longitude':temp['longitude'],'latitude':temp['latitude'],
                          'alt':temp['altitude'],'heading':temp['heading'],'speed':temp['speed']}
            if temp['typed']==1 and '防空' in temp['name'] :
                defense_missiles[k]={'name':temp['name'],'fg':temp['fg'],'longitude':temp['longitude'],'latitude':temp['latitude'],
                          'alt':temp['altitude'],'heading':temp['heading'],'speed':temp['speed']}
        #敌方飞机,舰船,空空弹,空地弹,地空弹    
        return  airs,ships,air_missiles,ship_missiles,defense_missiles     
    
    def my_step(self,side):
        '''
        实现自身的规则设计
        '''
        #获得己方任务对象,根据我们之前定义的名字,拿到被对象化的任务实例
        for k,v in side.missions.items():
            if '巡逻' in v.strName:
                AAW_Attack=v
            elif '等待' in v.strName:
                AAW_Wait=v
            else:
                LAND_Attack=v
        
        #获取敌方实体信息,接下来是我自己写的一个函数,用来对敌方的信息进行抽取,我将其分为飞机、舰船,空空弹,反舰弹,防空弹五类。
        airs,ships,air_missiles,ship_missiles,defense_missiles=self.get_enmInfo(side)
        
        #记录敌方发射的空空弹
        for k,v in air_missiles.items():
            if k not in self.enm_miss:
                self.enm_miss.append(k)
        
        #获取敌方驱逐舰信息,我这里获取敌方的舰船guid,这个值是要传给打击任务的。
        ship_target=None
        for k,v in ships.items():
            if '驱逐舰' in v['name']:
                ship_target=k
        
        #首次进入对任务的规则进行设置
        if not self.mission_setting:
            #巡逻任务:关闭三分之一,关闭防区外探测,设置单机编队,设置出航、阵位、攻击速度;设置高度。
            AAW_Attack.set_one_third_rule('false')
            AAW_Attack.set_OPA_check(False)
            AAW_Attack.set_flight_size(FlightSize.One)
            AAW_Attack.set_throttle_transit(Throttle.Cruise)
            AAW_Attack.set_throttle_station(Throttle.Loiter)
            AAW_Attack.set_throttle_attack(Throttle.Loiter)
            AAW_Attack.set_transit_altitude(8000)
            AAW_Attack.set_station_altitude(8000)
            AAW_Attack.set_attack_altitude(8000)
            
            AAW_Wait.set_one_third_rule('false')
            AAW_Wait.set_OPA_check(False)
            AAW_Wait.set_flight_size(FlightSize.One)
            AAW_Wait.set_throttle_transit(Throttle.Cruise)
            AAW_Wait.set_throttle_station(Throttle.Loiter)
            AAW_Wait.set_throttle_attack(Throttle.Loiter)
            AAW_Wait.set_transit_altitude(8000)
            AAW_Wait.set_station_altitude(8000)
            AAW_Wait.set_attack_altitude(8000)            
            
            #打击任务:设置单机编队,设置预先规划,添加打击目标,设置最小打击半径,设置多扇面攻击
            LAND_Attack.set_flight_size(FlightSize.One)
            LAND_Attack.set_preplan(True)
            LAND_Attack.add_target([k])
            LAND_Attack.set_min_strike_radius(30)
            LAND_Attack.set_auto_planner(True)

            self.mission_setting=True
        
                
        #规则实现,根据敌方的空中防御力量,判断是否发起对水攻击任务

        if len(self.enm_miss)>60 or len(airs)<3:
            for k,v in self.AAW_Wait.items():
                self.AAW_Wait[k]['对水攻击']=True
                self.AAW_Wait[k]['空战等待']=False
        else:
            for k,v in self.AAW_Wait.items():
                self.AAW_Wait[k]['对水攻击']=False
                self.AAW_Wait[k]['空战等待']=True
        

        #获取任务的分配单元
        AAW_Attack_list=AAW_Attack.get_assigned_mission()
        AAW_Wait_list=AAW_Wait.get_assigned_mission()
        LAND_Attack_target=LAND_Attack.get_targets()
        LAND_Attack_list=LAND_Attack.get_assigned_mission()

        #根据存储标识,将飞机分向指定任务
        for k,v in self.AAW_Attack.items():
            if k not in AAW_Attack_list and self.AAW_Attack[k]['空战巡逻']:
                #先清空出之前的任务
                if k  in LAND_Attack_list:
                    LAND_Attack.scenEdit_unAssignUnitFromMission(k)
                #在分配至新任务
                AAW_Attack.assignUnitToMission(k)
                
        
        for k,v in self.AAW_Wait.items():
            if k not in AAW_Wait_list and self.AAW_Wait[k]['空战等待']:
                side.aircrafts[k].delete_coursed_point(clear=True)
                #先清空出之前的任务
                if k  in LAND_Attack_list:
                    LAND_Attack.scenEdit_unAssignUnitFromMission(k)
                
                AAW_Wait.assignUnitToMission(k)
                
            if k not in LAND_Attack_list and self.AAW_Wait[k]['对水攻击']:
                #先清空出之前的任务
                if k  in AAW_Wait_list:
                    AAW_Wait.scenEdit_unAssignUnitFromMission(k)
                
                LAND_Attack.assignUnitToMission(k)
                
        
    def get_mysideInfo(self, side):
        '''
        传入推演方
        输出:
        {
         'ships':{guid:{}},
         'airs':{guid:{}},
         'ship_missiles':{guid:{}},
         'air_missiles': {guid:{}}
         }
        '''
        ships=dict()
        airs=dict()
        missiles=dict()
    
        
        for k,v in side.ships.items():
            ships[k]={'latitude':v.dLatitude,'longitude':v.dLongitude,'name':v.strName}
    
                
        for k,v in side.aircrafts.items():
            airs[k]={'latitude':v.dLatitude,'longitude':v.dLongitude,'alt':v.fCurrentAlt,
                      'speed':v.fDesiredSpeed,'name':v.strName}
            
            
        for k,v in side.weapons.items():
            missiles[k]={'latitude':v.dLatitude,'longitude':v.dLongitude,'alt':v.fCurrentAlt,
                      'speed':v.fDesiredSpeed,'target':v.m_PrimaryTargetGuid,'from':v.m_FiringUnitGuid,'name':v.strName}
    
        return ships,airs, missiles
예제 #5
0
파일: env.py 프로젝트: sx1616039/moziai
class MoziEnv():
    def __init__(self, IP, AIPort, scenario_name, simulate_compression):
        self.control_noise = True
        self.SERVER_PLAT = "linux"
        self.SERVER_IP = IP
        self.SERVER_PORT = AIPort
        self.connect_mode = 1
        self.DURATION_INTERVAL = etc.DURATION_INTERVAL
        self.simulate_compression = simulate_compression
        self.scenario_name = scenario_name
        self.mozi_service = MoziService(IP,
                                        AIPort,
                                        self.scenario_name,
                                        connect_mode=self.connect_mode)

        self.action_space = 4
        self.action_max = 1
        self.element_item_count = 8
        self.observation_space = self.element_item_count * 4  # two red aircraft, two blue aircraft

        self.last_situation_time = None
        self.red_unit_list = None
        self.blue_unit_list = None
        self.observation = None
        self.red_side_name = "红方"
        self.blue_side_name = "蓝方"

        self.last_red_aircraft_num = 0
        self.last_blue_aircraft_num = 0
        self.red_aircraft_num = 0
        self.blue_aircraft_num = 0

    def _get_mounts_guid_lt(self, item_dic):
        mounts_str = item_dic["m_Mounts"]
        guid_lt = mounts_str.split("@")
        #pylog.info("%s mounts guid:%s" %(item_dic["strUnitClass"], guid_lt))
        return guid_lt

    def _get_loadout_guid_lt(self, item_dic):
        mounts_str = item_dic["m_LoadoutGuid"]
        guid_lt = mounts_str.split("@")
        #pylog.info("%s loadout guid:%s" %(item_dic["strUnitClass"], guid_lt))
        return guid_lt

    def _show_mounts_info(self, mounts_guid_lt):
        for mounts_guid in mounts_guid_lt:
            pylog.info("mount guid:%s" % mounts_guid)
            item = self.mozi_service.all_info_dict[mounts_guid]
            for key in item:
                pylog.info("%s:%s" % (key, item[key]))

    def _show_loadout_info(self, guid_lt):
        for loadout_guid in guid_lt:
            pylog.info("loadout guid:%s" % loadout_guid)
            item = self.mozi_service.all_info_dict[loadout_guid]
            pylog.info("strName:%s" % item["strName"])
            pylog.info("m_AircraftGuid:%s" % item["m_AircraftGuid"])
            pylog.info("strLoadWeaponCount:%s" % item["strLoadWeaponCount"])
            pylog.info("m_LoadRatio:%s" % item["m_LoadRatio"])
            #for key in item:
        #    pylog.info("%s:%s" % (key, item[key]))

    def _init_red_unit_list(self):
        side_name = self.red_side_name

        ret_lt = []
        side_guid = get_side_guid_from_side_name(
            side_name, self.mozi_service.all_info_dict)
        side_dic = get_a_side_dic(side_guid, self.mozi_service.all_info_dict)
        aircraft_list_dic = get_units_from_side(
            side_guid, "CAircraft", self.mozi_service.all_info_dict)
        for key in aircraft_list_dic:
            item = aircraft_list_dic[key]
            if item["strUnitClass"] == '苏-35S型“超级侧卫”战斗机':
                ret_lt.append(key)
        return ret_lt

    def _init_blue_unit_list(self):
        side_name = self.blue_side_name

        ret_lt = []
        side_guid = get_side_guid_from_side_name(
            side_name, self.mozi_service.all_info_dict)
        side_dic = get_a_side_dic(side_guid, self.mozi_service.all_info_dict)
        aircraft_list_dic = get_units_from_side(
            side_guid, "CAircraft", self.mozi_service.all_info_dict)
        for key in aircraft_list_dic:
            item = aircraft_list_dic[key]
            if item["strUnitClass"] == 'F-15E型“攻击鹰式”战斗机':
                ret_lt.append(key)
        return ret_lt

    def _show_mounts_and_loadout(self):
        for guid in self.blue_unit_list:
            item = self.mozi_service.all_info_dict.get(guid, "")
            if item != "":
                mounts_guid_lt = self._get_mounts_guid_lt(item)
                #self._show_mounts_info(mounts_guid_lt)
                loadout_guid_lt = self._get_loadout_guid_lt(item)
                self._show_loadout_info(loadout_guid_lt)

        for guid in self.red_unit_list:
            item = self.mozi_service.all_info_dict.get(guid, "")
            if item != "":
                mounts_guid_lt = self._get_mounts_guid_lt(item)
                #self._show_mounts_info(mounts_guid_lt)
                loadout_guid_lt = self._get_loadout_guid_lt(item)
                self._show_loadout_info(loadout_guid_lt)

    def _init_unit_list(self):
        self.red_unit_list = self._init_red_unit_list()
        #pylog.info(len(self.red_unit_list))
        self.last_red_aircraft_num = len(self.red_unit_list)
        self.blue_unit_list = self._init_blue_unit_list()
        #pylog.info(len(self.blue_unit_list))
        self.last_blue_aircraft_num = len(self.blue_unit_list)

    def _get_a_side_observation(self, unit_list):
        obs_lt = []
        num = 0
        for key in unit_list:
            unit = self.mozi_service.all_info_dict.get(key, "")
            if unit:
                obs_lt.append(unit["fFuelConsumptionCruise"])
                obs_lt.append(unit["dLongitude"])
                obs_lt.append(unit["dLatitude"])
                obs_lt.append(unit["fCurrentHeading"])
                obs_lt.append(unit["fCurrentSpeed"])
                obs_lt.append(unit["fCurrentAlt"])
                obs_lt.append(unit["fPitch"])
                obs_lt.append(unit["fRoll"])
                num += 1
            else:
                obs_lt.append(0.0)
                obs_lt.append(0.0)
                obs_lt.append(0.0)
                obs_lt.append(0.0)
                obs_lt.append(0.0)
                obs_lt.append(0.0)
                obs_lt.append(0.0)
                obs_lt.append(0.0)

        return obs_lt, num

    def _get_blue_observation(self):
        unit_list = self.blue_unit_list
        obs_lt, num = self._get_a_side_observation(unit_list)
        self.blue_aircraft_num = num
        return obs_lt

    def _get_red_observation(self):
        unit_list = self.red_unit_list
        obs_lt, num = self._get_a_side_observation(unit_list)
        self.red_aircraft_num = num
        return obs_lt

    def _get_observation(self):
        red_obs_lt = self._get_red_observation()
        #pylog.info(red_obs_lt)
        blue_obs_lt = self._get_blue_observation()
        #pylog.info(blue_obs_lt)
        red_obs_lt.extend(blue_obs_lt)
        #pylog.info(red_obs_lt)
        self.observation = red_obs_lt

        return red_obs_lt

    def _set_duration_interval(self):
        self.mozi_service.mozi_task.sendAndRecv("Hs_OneTimeStop('Stop', %d)" %
                                                self.DURATION_INTERVAL)

    def _reset(self):
        ret = self.mozi_service.suspend_simulate()
        self.mozi_service.all_info_dict = {}
        self.scenario = self.mozi_service.load_scenario(plat=self.SERVER_PLAT)
        self._set_duration_interval()

        ret = self.mozi_service.set_run_mode()
        ret = self.mozi_service.set_simulate_compression(
            self.simulate_compression)
        ret = self.mozi_service.set_compression_mode(False)

        self._run_simulate()

    def _run_simulate(self):
        pylog.info("run simulation")
        return self.mozi_service.run_simulate()

    def _check_duration(self):
        update_situation_time = self.mozi_service.mozi_task.getCurrentTime()
        if self.last_situation_time != None:
            duration_time = float(update_situation_time) - float(
                self.last_situation_time)
            if int(duration_time) != self.DURATION_INTERVAL:
                pylog.error(
                    "duration_time:%s is differet from etc.DURATION_INTERVAL:%s"
                    % (duration_time, self.DURATION_INTERVAL))

        self.last_situation_time = update_situation_time

    def _run_with_situation_data(self):
        self.mozi_service.update_situation(self.scenario)
        #self._check_duration()

    def _get_waypoint_heading(self, last_heading, action_value):
        current_heading = last_heading + action_value
        if current_heading < 0:
            current_heading += 360
        if current_heading > 360:
            current_heading -= 360
        return current_heading

    def _get_new_waypoint(self, heading, lat, lon, distance=20.0):
        dic = get_point_with_point_bearing_distance(lat, lon, heading,
                                                    distance)
        return dic

    def _deal_point_data(self, waypoint):
        if self.control_noise:
            lon = str(
                float(waypoint["longitude"]) + random.random() / 10.0 - 0.05)
            lat = str(
                float(waypoint["latitude"]) + random.random() / 10.0 - 0.05)
        else:
            lon = str(waypoint["longitude"]),
            lat = str(waypoint["latitude"]),
        return lon, lat

    def _check_is_drop_sonobuoy(self, action_value):
        if action_value[1].item() > 0:
            return True
        return False

    def _get_aircraft_waypoint(self, action_value):
        obs = self.observation
        #pylog.info(obs)

        longitude = obs[0]
        latitude = obs[1]
        heading = obs[2]

        #waypoint_heading = self._get_waypoint_heading(heading, action_value[0].item() * 90)
        waypoint_heading = self._get_waypoint_heading(heading,
                                                      action_value * 90)
        waypoint = self._get_new_waypoint(waypoint_heading, latitude,
                                          longitude)
        distance = get_target_distance(latitude, longitude)
        return waypoint, distance

    def _get_a_aircraft_waypoint(self, obs_item, action_value):

        longitude = obs_item[0]
        latitude = obs_item[1]
        heading = obs_item[2]

        waypoint_heading = self._get_waypoint_heading(heading,
                                                      action_value * 90)
        #pylog.info("waypoint_heading:%s" % waypoint_heading)

        waypoint = self._get_new_waypoint(waypoint_heading, latitude,
                                          longitude)
        #pylog.info("waypoint:%s" % waypoint)

        return waypoint

    def _execute_action(self, action_value):
        count = 0
        for guid in self.red_unit_list:
            #pylog.info(guid)
            #pylog.info("observation:%s" % self.observation)
            obs_item = self.observation[count *
                                        self.element_item_count:(count + 1) *
                                        self.element_item_count]
            #pylog.info("obs_item:%s" % obs_item)
            waypoint = self._get_a_aircraft_waypoint(
                obs_item, action_value[count].item())
            #pylog.info(waypoint)
            aircraft = self.mozi_service.get_entity(guid)
            if aircraft:
                lon, lat = self._deal_point_data(waypoint)
                aircraft.set_waypoint(self.red_side_name, guid, lon, lat)
                #if True:
                #aircraft.set_up_throttleI(self.mozi_service.mozi_task)
                #    aircraft.set_up_throttleI()
                #else:
                #aircraft.set_down_throttleI(self.mozi_service.mozi_task)
                #    aircraft.set_down_throttleI()

#               if True:
#                   aircraft.set_up_Alt(self.mozi_service.mozi_task)
#               else:
#                   aircraft.set_down_Alt(self.mozi_service.mozi_task)
            else:
                pylog.debug("aircraft:%s has been destroyed" % guid)
            count += 1

#       if self._check_is_find_target():
#           target_guid = self._get_target_guid()
#           aircraft.autoattack_target(target_guid, self.mozi_service.mozi_task)
#       else:
#           if distance < etc.target_radius:
#               if self._check_is_drop_sonobuoy(action_value):
#                   aircraft.drop_sonobuoy(self.red_side_name, "shallow", "active", self.mozi_service.mozi_task)

#           lon, lat = self._deal_point_data(waypoint)
#           aircraft.set_waypoint(self.red_side_name, guid, lon, lat, self.mozi_service.mozi_task)

    def _check_done(self):
        if not self._check_red_aircraft_exist():
            #pylog.info("do not has any red aircraft exit")
            if not self._check_red_missile_exist():
                #pylog.info("do not has any red missile exit")
                return True

        if not self._check_blue_aircraft_exist():
            #pylog.info("do not has any blue aircraft exit")
            if not self._check_blue_missile_exist():
                #pylog.info("do not has any blue missile exit")
                return True
        return False

    def _check_red_missile_exist(self):
        if self._get_red_missile_num() != 0:
            return True
        return False

    def _check_blue_missile_exist(self):
        if self._get_blue_missile_num() != 0:
            return True
        return False

    def _check_red_aircraft_exist(self):
        obs = self.observation
        for i in range(2 * self.element_item_count):
            if obs[i] != 0.0:
                return True
        return False

    def _check_blue_aircraft_exist(self):
        obs = self.observation
        for i in range(2 * self.element_item_count,
                       4 * self.element_item_count):
            if obs[i] != 0.0:
                return True
        return False

    def _check_target_exist(self):
        if not check_is_exist_target(etc.target_name,
                                     self.mozi_service.all_info_dict):
            return False
        return True

    def _get_target_guid(self):
        target_name = etc.target_name
        target_guid = get_target_contact_guid_from_target_name(
            self.red_side_name, target_name, self.mozi_service.all_info_dict)
        return target_guid

    def _get_reward(self, action_value):
        reward = 0.0
        # get reward -1 when loss an aircraft
        reward += -(self.last_red_aircraft_num - self.red_aircraft_num) * 1
        # get reward 1 when destroy an aircraft
        reward += (self.last_blue_aircraft_num - self.blue_aircraft_num) * 1

        self.last_red_aircraft_num = self.red_aircraft_num
        self.last_blue_aircraft_num = self.blue_aircraft_num

        if reward != 0.0:
            pylog.info("reward:%s" % reward)
            pylog.info(
                "cur red aircraft num:%s cur blue aircraft num:%s" %
                (self.last_red_aircraft_num, self.last_blue_aircraft_num))
            pylog.info(
                "cur red missile num:%s cur blue missile num:%s" %
                (self._get_red_missile_num(), self._get_blue_missile_num()))

        #self._show_mounts_and_loadout()

        return reward

    def _get_red_missile_num(self):
        side_name = self.red_side_name
        return self._get_missile_num(side_name)

    def _get_missile_num(self, side_name):
        missile_count = 0
        side_guid = get_side_guid_from_side_name(
            side_name, self.mozi_service.all_info_dict)
        side_dic = get_a_side_dic(side_guid, self.mozi_service.all_info_dict)
        for key in side_dic:
            if side_dic[key]["ClassName"] == "CWeapon":
                missile_count += 1
                #pylog.info(side_dic[key])
                pylog.info("m_PrimaryTargetGuid:%s" %
                           side_dic[key]["m_PrimaryTargetGuid"])
                pylog.info("m_FiringUnitGuid:%s" %
                           side_dic[key]["m_FiringUnitGuid"])
                #for k in side_dic[key]:
                #    pylog.info("%s:%s" % (k, side_dic[key][k]))

        return missile_count

    def _get_blue_missile_num(self):
        side_name = self.blue_side_name
        return self._get_missile_num(side_name)

    def reset(self):
        self._reset()
        self.mozi_service.init_situation(self.scenario)
        self._init_unit_list()
        obs = self._get_observation()
        return np.array(obs)

    def step(self, action):
        self._execute_action(action)
        self._run_with_situation_data()
        obs = self._get_observation()

        reward = self._get_reward(action)
        done = self._check_done()
        info = ""
        return np.array(obs), reward, done, info

    def connect_server(self):
        if not self.mozi_service.connect_mozi_server(self.SERVER_IP,
                                                     self.SERVER_PORT):
            return False
        else:
            return True
예제 #6
0
파일: env.py 프로젝트: sx1616039/moziai
class MoziEnv():
    def __init__(self, IP, AIPort, scenario_name, simulate_compression):
        self.control_noise = True
        self.SERVER_PLAT = "linux"
        self.SERVER_IP = IP
        self.SERVER_PORT = AIPort
        self.connect_mode = 1
        self.DURATION_INTERVAL = etc.DURATION_INTERVAL
        self.simulate_compression = simulate_compression
        self.scenario_name = scenario_name
        self.mozi_service = MoziService(IP,
                                        AIPort,
                                        self.scenario_name,
                                        connect_mode=self.connect_mode)

        self.action_space = 4
        self.action_max = 1
        self.observation_space = 4 * 3
        self.element_item_count = 4

        self.last_situation_time = None
        self.red_unit_list = None
        self.blue_unit_list = None
        self.observation = None
        self.red_side_name = "红方"
        self.blue_side_name = "蓝方"

    def connect_server(self):
        if not self.mozi_service.connect_mozi_server(self.SERVER_IP,
                                                     self.SERVER_PORT):
            return False
        else:
            return True

    def _init_red_unit_list(self):
        side_name = self.red_side_name

        ret_lt = []
        side_guid = get_side_guid_from_side_name(
            side_name, self.mozi_service.all_info_dict)
        side_dic = get_a_side_dic(side_guid, self.mozi_service.all_info_dict)
        redfacility_list_dic = get_units_from_side(
            side_guid, "CFacility", self.mozi_service.all_info_dict)
        for key in redfacility_list_dic:
            ret_lt.append(key)
        return ret_lt

    def _init_blue_unit_list(self):
        side_name = self.blue_side_name

        ret_lt = []
        side_guid = get_side_guid_from_side_name(
            side_name, self.mozi_service.all_info_dict)
        blufacility_list_dic = get_units_from_side(
            side_guid, "CFacility", self.mozi_service.all_info_dict)

        for key in blufacility_list_dic:
            ret_lt.append(key)
        return ret_lt

    def _init_unit_list(self):  # 方法生成属性
        self.red_unit_list = self._init_red_unit_list()
        self.blue_unit_list = self._init_blue_unit_list()

    def _get_a_side_observation(self, unit_list):
        obs_lt = []
        for key in unit_list:
            unit = self.mozi_service.all_info_dict.get(key, "")
            if unit:
                obs_lt.append(unit["dLongitude"])
                obs_lt.append(unit["dLatitude"])
                obs_lt.append(unit["fCurrentSpeed"])
                obs_lt.append(unit["fCurrentHeading"])
            else:
                pylog.info("unit do not exist")
                obs_lt.append(0.0)
                obs_lt.append(0.0)
                obs_lt.append(0.0)
                obs_lt.append(0.0)

        return obs_lt

    def _get_blue_observation(self):
        unit_list = self.blue_unit_list
        obs_lt = self._get_a_side_observation(unit_list)
        return obs_lt

    def _get_red_observation(self):
        unit_list = self.red_unit_list
        obs_lt = self._get_a_side_observation(unit_list)
        return obs_lt

    def _get_observation(self):
        red_obs_lt = self._get_red_observation()
        self.observation = red_obs_lt

        if not self._check_tank_exist():
            if etc.TRANS_DATA:
                lt = []
                lt.append(red_obs_lt[0] - etc.task_end_point["longitude"])
                lt.append(red_obs_lt[1] - etc.task_end_point["latitude"])
                lt.append(red_obs_lt[2] / 360)
                return lt

        return red_obs_lt

    def _set_duration_interval(self):
        self.mozi_service.mozi_task.sendAndRecv("Hs_OneTimeStop('Stop', %d)" %
                                                self.DURATION_INTERVAL)

    def _reset(self):
        ret = self.mozi_service.suspend_simulate()
        self.mozi_service.all_info_dict = {}
        self.scenario = self.mozi_service.load_scenario(plat=self.SERVER_PLAT)
        self._set_duration_interval()

        ret = self.mozi_service.set_run_mode()
        ret = self.mozi_service.set_simulate_compression(
            self.simulate_compression)
        ret = self.mozi_service.set_compression_mode(False)

        self._run_simulate()

    def _run_simulate(self):
        pylog.info("run simulation")
        return self.mozi_service.run_simulate()

    def _check_duration(self):
        update_situation_time = self.mozi_service.mozi_task.getCurrentTime()
        if self.last_situation_time != None:
            duration_time = float(update_situation_time) - float(
                self.last_situation_time)
            if int(duration_time) != self.DURATION_INTERVAL:
                pylog.error(
                    "duration_time:%s is differet from etc.DURATION_INTERVAL:%s"
                    % (duration_time, self.DURATION_INTERVAL))

        self.last_situation_time = update_situation_time

    def _run_with_situation_data(self):
        self.mozi_service.update_situation(self.scenario)
        # self._check_duration()

    def _get_waypoint_heading(self, last_heading, action_value):
        current_heading = last_heading + action_value
        if current_heading < 0:
            current_heading += 360
        if current_heading > 360:
            current_heading -= 360
        return current_heading

    def _get_new_waypoint(self, heading, lat, lon, distance=20.0):
        dic = get_point_with_point_bearing_distance(lat, lon, heading,
                                                    distance)
        return dic

    def _deal_point_data(self, waypoint):
        if self.control_noise:
            lon = str(
                float(waypoint["longitude"]) + random.random() / 10.0 - 0.05)
            lat = str(
                float(waypoint["latitude"]) + random.random() / 10.0 - 0.05)
        else:
            lon = str(waypoint["longitude"]),
            lat = str(waypoint["latitude"]),
        return lon, lat

    def _get_tank_waypoint(self, obs, action_value):
        longitude = obs[0]
        latitude = obs[1]
        heading = obs[2]

        waypoint_heading = self._get_waypoint_heading(heading,
                                                      action_value * 90)
        waypoint = self._get_new_waypoint(waypoint_heading, latitude,
                                          longitude)
        distance = get_target_distance(latitude, longitude)
        return waypoint, distance

    def _execute_action(self, action_value):
        pylog.info(action_value)
        count = 0
        for guid in self.red_unit_list:
            obs_item = self.observation[count *
                                        self.element_item_count:(count + 1) *
                                        self.element_item_count]
            waypoint, distance = self._get_tank_waypoint(
                obs_item, action_value[count].item())
            tank = self.mozi_service.get_entity(guid)

            if distance < etc.target_radius:
                target_guid = self._get_target_guid(
                )  # 只有1个,如果一个red, 可以检测到多个怎么办?
                tank.fac_attack_auto(target_guid)
            else:
                if tank:
                    lon, lat = self._deal_point_data(waypoint)
                    tank.set_waypoint(self.red_side_name, guid, lon, lat)
            count += 1

    def _check_done(self):
        if not self._check_tank_exist():
            return True
        if not self._check_target_exist():
            return True
        return False

    def _check_tank_exist(self):
        obs = self.observation
        for i in range(len(obs)):
            if obs[i] != 0.0:
                return True
        return False

    def _check_target_exist(self):
        if not check_is_exist_target(etc.target_name,
                                     self.mozi_service.all_info_dict):
            return False
        return True

    def _get_target_guid(self):
        target_name = etc.target_name
        target_guid = get_target_contact_guid_from_target_name(
            self.red_side_name, target_name, self.mozi_service.all_info_dict)
        return target_guid

    def _check_is_find_target(self):
        target_guid = self._get_target_guid()

        if target_guid:
            pylog.info("find target_guid:%s" % target_guid)
            return True
        return False

    def _get_distance_reward(self, num, action_value):
        obs = self.observation
        longitude = obs[0]
        latitude = obs[1]
        heading = obs[2]

        distance = get_target_distance(latitude, longitude)
        # action_change_heading = action_value[0].item() * 90
        action_change_heading = action_value[num].item() * 90
        reward = get_distance_reward(latitude, longitude, heading,
                                     action_change_heading)
        return reward, distance

    def _get_reward(self, action_value):
        # reward = 0
        sum_reward = []
        count = 0
        for i in range(len(self.red_unit_list)):  # 一直是3个?,应该用更新后的。
            reward = 0
            distance_reward, distance = self._get_distance_reward(
                i, action_value)
            reward += distance_reward
            if self._check_is_find_target():
                reward += 10.0
                if distance < etc.target_radius:
                    reward += 10.0
                    if not self._check_tank_exist():
                        reward += -100.0
                # 红方打掉蓝方坦克, 加100

            # if distance < etc.target_radius:  # 其实就是距离的奖赏值。只不过在距离范围内,值增加的更多。保留。
            #     reward += 10.0
            # # else:
            # #     if not self._check_tank_exist():
            # #         # pylog.info("tank is not exist get -100.0 reward")
            # #         reward += -100.0
            # elif not self._check_tank_exist():
            #     reward += -100.0
            # elif self._check_is_find_target():
            #     reward += 10.0
            #
            # elif not self._check_target_exist():
            #     pylog.info("destroy target get 150.0 reward")
            #     reward += 150.0
            # else:
            #     print('没有用的else语句')
            sum_reward.append(reward)
            count += 1
        return sum(sum_reward)

    def reset(self):
        self._reset()
        self.mozi_service.init_situation(self.scenario)
        self._init_unit_list()
        obs = self._get_observation()
        return np.array(obs)

    def step(self, action):
        self._execute_action(action)
        self._run_with_situation_data()  # 更新,update
        obs = self._get_observation()

        reward = self._get_reward(action)
        done = self._check_done()
        info = ""
        return np.array(obs), reward, done, info
예제 #7
0
class MoziEnv():
    def __init__(self, IP, AIPort, scenario_name, simulate_compression):
        self.control_noise = True
        self.SERVER_PLAT = "linux"
        self.SERVER_IP = IP
        self.SERVER_PORT = AIPort
        self.connect_mode = 1
        self.DURATION_INTERVAL = etc.DURATION_INTERVAL
        self.simulate_compression = simulate_compression
        self.scenario_name = scenario_name
        self.mozi_service = None

        self.action_space = 4
        self.action_max = 1
        self.observation_space = 4 * 3
        self.element_item_count = 4

        self.last_situation_time = None
        self.red_unit_list = None
        self.blue_unit_list = None
        self.observation = None
        self.red_side_name = "红方"
        self.blue_side_name = "蓝方"

    def connect_mozi_server(self, websocket_Ip, websocket_port):
        """
        连接墨子服务器
        param :
        websocket_server 要连接的服务器的ip
        websocket_port 要连接的服务器的端口
        :return:
        """
        pylog.info("connect_mozi_server")
        if self.connect_mode == 1:
            self.mozi_service = MoziService(websocket_Ip, websocket_port,
                                            self.scenario_name)
            return True
        # server_address = r"ws://%s:%d/websocket" % ('60.205.207.206', 9998)
        server_address = r"ws://%s:%d/websocket" % (websocket_Ip,
                                                    websocket_port)
        pylog.info(server_address)
        for i in range(10):
            try:
                self.websocket_connect = create_connection(server_address)
                break
            except:
                pylog.info("can not connect to %s." % server_address)
                time.sleep(2)
                self.websocket_connect = None
        #
        if self.websocket_connect is None:
            pylog.warning("Interrupted, can not connect to %s." %
                          server_address)
            return False
        #
        self.websocket_connect.send("{\"RequestType\":\"StartServer\"}")
        result = self.websocket_connect.recv()
        print("connect server result:%s" % result)
        jsons = json.loads(result)
        self.ai_server = jsons['IP']
        self.ai_port = jsons['AIPort']
        self.mozi_task = MoziService(self.server_ip, self.aiPort,
                                     self.scenario_name)
        return True

    #def connect_server(self):
    #if not self.mozi_service.connect_mozi_server(self.SERVER_IP, self.SERVER_PORT):
    #return False
    #else:
    #return True

    def _init_red_unit_list(self):
        side_name = self.red_side_name

        ret_lt = []
        side_guid = get_side_guid_from_side_name(
            side_name, self.mozi_service.all_info_dict)
        side_dic = get_a_side_dic(side_guid, self.mozi_service.all_info_dict)
        redaircraft_list_dic = get_units_from_side(
            side_guid, "CAircraft", self.mozi_service.all_info_dict)
        for key in redaircraft_list_dic:
            ret_lt.append(key)
        return ret_lt

    def _init_blue_unit_list(self):
        side_name = self.blue_side_name

        ret_lt = []
        side_guid = get_side_guid_from_side_name(
            side_name, self.mozi_service.all_info_dict)
        blufacility_list_dic = get_units_from_side(
            side_guid, "CFacility", self.mozi_service.all_info_dict)

        for key in blufacility_list_dic:
            ret_lt.append(key)
        return ret_lt

    def _init_unit_list(self):  # 方法生成属性
        self.red_unit_list = self._init_red_unit_list()
        self.blue_unit_list = self._init_blue_unit_list()

    def _get_a_side_observation(self, unit_list):
        obs_lt = []
        for key, unit in unit_list.items():
            if unit:
                obs_lt.append(unit.dLongitude)
                obs_lt.append(unit.dLatitude)
                obs_lt.append(unit.fCurrentSpeed)
                obs_lt.append(unit.fCurrentHeading)
            else:
                pylog.info("unit do not exist")
                obs_lt.append(0.0)
                obs_lt.append(0.0)
                obs_lt.append(0.0)
                obs_lt.append(0.0)

        return obs_lt

    def _get_blue_observation(self):
        unit_list = self.blue_unit_list
        obs_lt = self._get_a_side_observation(unit_list)
        return obs_lt

    def _get_red_observation(self):
        '''
        获取红方得态势信息
        '''
        side_dic = self.scenario.situation.side_dic

        for key, side in side_dic.items():
            if side.strName == '红方':
                unit_list = side.get_all_unitinfo()
                break
        obs_lt = self._get_a_side_observation(unit_list)
        return obs_lt

    def _get_observation(self):
        red_obs_lt = self._get_red_observation()
        self.observation = red_obs_lt

        if not self._check_tank_exist():
            if etc.TRANS_DATA:
                lt = []
                lt.append(red_obs_lt[0] - etc.task_end_point["longitude"])
                lt.append(red_obs_lt[1] - etc.task_end_point["latitude"])
                lt.append(red_obs_lt[2] / 360)
                return lt

        return red_obs_lt

    def _set_duration_interval(self):
        self.mozi_service.sendAndRecv("Hs_OneTimeStop('Stop', %d)" %
                                      self.DURATION_INTERVAL)

    def _reset(self):
        ret = self.mozi_service.suspend_simulate()
        self.mozi_service.all_info_dict = {}
        self.scenario = self.mozi_service.load_scenario(plat=self.SERVER_PLAT)
        self._set_duration_interval()

        ret = self.mozi_service.set_run_mode()
        ret = self.mozi_service.set_simulate_compression(
            self.simulate_compression)
        ret = self.mozi_service.set_compression_mode(False)

        self._run_simulate()

    def _run_simulate(self):
        pylog.info("run simulation")
        return self.mozi_service.run_simulate()

    def _check_duration(self):
        update_situation_time = self.mozi_service.mozi_task.getCurrentTime()
        if self.last_situation_time != None:
            duration_time = float(update_situation_time) - float(
                self.last_situation_time)
            if int(duration_time) != self.DURATION_INTERVAL:
                pylog.error(
                    "duration_time:%s is differet from etc.DURATION_INTERVAL:%s"
                    % (duration_time, self.DURATION_INTERVAL))

        self.last_situation_time = update_situation_time

    def _run_with_situation_data(self):
        self.mozi_service.update_situation(self.scenario)
        # self._check_duration()

    def _get_waypoint_heading(self, last_heading, action_value):
        current_heading = last_heading + action_value
        if current_heading < 0:
            current_heading += 360
        if current_heading > 360:
            current_heading -= 360
        return current_heading

    def _get_new_waypoint(self, heading, lat, lon, distance=20.0):
        dic = get_point_with_point_bearing_distance(lat, lon, heading,
                                                    distance)
        return dic

    def _deal_point_data(self, waypoint):
        if self.control_noise:
            lon = str(
                float(waypoint["longitude"]) + random.random() / 10.0 - 0.05)
            lat = str(
                float(waypoint["latitude"]) + random.random() / 10.0 - 0.05)
        else:
            lon = str(waypoint["longitude"]),
            lat = str(waypoint["latitude"]),
        return lon, lat

    def _get_tank_waypoint(self, obs, action_value):
        longitude = obs[0]
        latitude = obs[1]
        heading = obs[2]

        waypoint_heading = self._get_waypoint_heading(heading,
                                                      action_value * 90)
        waypoint = self._get_new_waypoint(waypoint_heading, latitude,
                                          longitude)
        distance = get_target_distance(latitude, longitude)
        return waypoint, distance

    def _execute_action(self, action_value):
        pylog.info(action_value)
        count = 0
        for guid in self.red_unit_list:
            obs_item = self.observation[count *
                                        self.element_item_count:(count + 1) *
                                        self.element_item_count]
            waypoint, distance = self._get_tank_waypoint(
                obs_item, action_value[count].item())
            tank = self.mozi_service.get_entity(guid)

            if distance < etc.target_radius:
                target_guid = self._get_target_guid(
                )  # 只有1个,如果一个red, 可以检测到多个怎么办?
                tank.fac_attack_auto(target_guid)
            else:
                if tank:
                    lon, lat = self._deal_point_data(waypoint)
                    tank.set_waypoint(self.red_side_name, guid, lon, lat)
            count += 1

    def _check_done(self):
        if not self._check_tank_exist():
            return True
        if not self._check_target_exist():
            return True
        return False

    def _check_tank_exist(self):
        obs = self.observation
        for i in range(len(obs)):
            if obs[i] != 0.0:
                return True
        return False

    def _check_target_exist(self):
        if not check_is_exist_target(etc.target_name,
                                     self.mozi_service.all_info_dict):
            return False
        return True

    def _get_target_guid(self):
        target_name = etc.target_name
        target_guid = get_target_contact_guid_from_target_name(
            self.red_side_name, target_name, self.mozi_service.all_info_dict)
        return target_guid

    def _check_is_find_target(self):
        target_guid = self._get_target_guid()

        if target_guid:
            pylog.info("find target_guid:%s" % target_guid)
            return True
        return False

    def _get_distance_reward(self, num, action_value):
        obs = self.observation
        longitude = obs[0]
        latitude = obs[1]
        heading = obs[2]

        distance = get_target_distance(latitude, longitude)
        # action_change_heading = action_value[0].item() * 90
        action_change_heading = action_value[num].item() * 90
        reward = get_distance_reward(latitude, longitude, heading,
                                     action_change_heading)
        return reward, distance

    def _get_reward(self, action_value):
        # reward = 0
        sum_reward = []
        count = 0
        for i in range(len(self.red_unit_list)):  # 一直是3个?,应该用更新后的。
            reward = 0
            distance_reward, distance = self._get_distance_reward(
                i, action_value)
            reward += distance_reward
            if self._check_is_find_target():
                reward += 10.0
                if distance < etc.target_radius:
                    reward += 10.0
                    if not self._check_tank_exist():
                        reward += -100.0
                # 红方打掉蓝方坦克, 加100

            # if distance < etc.target_radius:  # 其实就是距离的奖赏值。只不过在距离范围内,值增加的更多。保留。
            #     reward += 10.0
            # # else:
            # #     if not self._check_tank_exist():
            # #         # pylog.info("tank is not exist get -100.0 reward")
            # #         reward += -100.0
            # elif not self._check_tank_exist():
            #     reward += -100.0
            # elif self._check_is_find_target():
            #     reward += 10.0
            #
            # elif not self._check_target_exist():
            #     pylog.info("destroy target get 150.0 reward")
            #     reward += 150.0
            # else:
            #     print('没有用的else语句')
            sum_reward.append(reward)
            count += 1
        return sum(sum_reward)

    def reset(self):
        self._reset()
        self.mozi_service.init_situation(self.scenario)
        #self._init_unit_list()
        obs = self._get_observation()
        return np.array(obs)

    '''
        #by aie
    def step(self, action):
        self._execute_action(action)
        self._run_with_situation_data()  # 更新,update
        obs = self._get_observation()

        reward = self._get_reward(action)
        done = self._check_done()
        info = ""
        return np.array(obs), reward, done, info
    '''

    #by aie
    def step(self):
        self._run_with_situation_data()  # 更新,update
        return True