text: from carla_utils import carla
  SpawnActor = carla.command.SpawnActor
  SetAutopilot = carla.command.SetAutopilot
  FutureActor = carla.command.FutureActor
  
  import random
  import time
  import logging
  
  
  class NPC(object):
      def __init__(self, config, client, world):
          self.client = client
          self.world, self.carla_map = world, world.get_map()
  
          self.number_of_vehicles = config.number_of_vehicles
          self.number_of_walkers = config.number_of_walkers
          self.filterv = config.vehicles_filter
          self.filterw = config.pedestrians_filter
          self.safe = config.safe
  
          self.vehicles_list = []
          self.walkers_list = []
          self.all_id = []
  
  
      def spawn(self):
          blueprints = self.world.get_blueprint_library().filter(self.filterv)
          blueprintsWalkers = self.world.get_blueprint_library().filter(self.filterw)
  
          if self.safe:
              blueprints = [x for x in blueprints if int(x.get_attribute('number_of_wheels')) == 4]
              blueprints = [x for x in blueprints if not x.id.endswith('isetta')]
              blueprints = [x for x in blueprints if not x.id.endswith('carlacola')]
  
          spawn_points = self.carla_map.get_spawn_points()
          number_of_spawn_points = len(spawn_points)
  
          if self.number_of_vehicles < number_of_spawn_points:
              random.shuffle(spawn_points)
          elif self.number_of_vehicles > number_of_spawn_points:
              msg = 'requested %d vehicles, but could only find %d spawn points'
              logging.warning(msg, self.number_of_vehicles, number_of_spawn_points)
              self.number_of_vehicles = number_of_spawn_points
  
  
          # --------------
          # Spawn vehicles
          # --------------
          batch = []
          for n, transform in enumerate(spawn_points):
              if n >= self.number_of_vehicles:
                  break
              blueprint = random.choice(blueprints)
              if blueprint.has_attribute('color'):
                  color = random.choice(blueprint.get_attribute('color').recommended_values)
                  blueprint.set_attribute('color', color)
              if blueprint.has_attribute('driver_id'):
                  driver_id = random.choice(blueprint.get_attribute('driver_id').recommended_values)
                  blueprint.set_attribute('driver_id', driver_id)
              blueprint.set_attribute('role_name', 'autopilot')
              batch.append(SpawnActor(blueprint, transform).then(SetAutopilot(FutureActor, True)))
  
          for response in self.client.apply_batch_sync(batch):
              if response.error:
                  logging.error(response.error)
              else:
                  self.vehicles_list.append(response.actor_id)
  
          # -------------
          # Spawn Walkers
          # -------------
          # some settings
          percentagePedestriansRunning = 0.0      # how many pedestrians will run
          percentagePedestriansCrossing = 0.0     # how many pedestrians will walk through the road
          # 1. take all the random locations to spawn
          spawn_points = []
          for i in range(self.number_of_walkers):
              spawn_point = carla.Transform()
              loc = self.world.get_random_location_from_navigation()
              if (loc != None):
                  spawn_point.location = loc
                  spawn_points.append(spawn_point)
          # 2. we spawn the walker object
          batch = []
          walker_speed = []
          for spawn_point in spawn_points:
              walker_bp = random.choice(blueprintsWalkers)
              # set as not invencible
              if walker_bp.has_attribute('is_invincible'):
                  walker_bp.set_attribute('is_invincible', 'false')
              # set the max speed
              if walker_bp.has_attribute('speed'):
                  if (random.random() > percentagePedestriansRunning):
                      # walking
                      walker_speed.append(walker_bp.get_attribute('speed').recommended_values[1])
                  else:
                      # running
                      walker_speed.append(walker_bp.get_attribute('speed').recommended_values[2])
              else:
                  print("Walker has no speed")
                  walker_speed.append(0.0)
              batch.append(SpawnActor(walker_bp, spawn_point))
          results = self.client.apply_batch_sync(batch, True)
          walker_speed2 = []
          for i in range(len(results)):
              if results[i].error:
                  logging.error(results[i].error)
              else:
                  self.walkers_list.append({"id": results[i].actor_id})
                  walker_speed2.append(walker_speed[i])
          walker_speed = walker_speed2
          # 3. we spawn the walker controller
          batch = []
          walker_controller_bp = self.world.get_blueprint_library().find('controller.ai.walker')
          for i in range(len(self.walkers_list)):
              batch.append(SpawnActor(walker_controller_bp, carla.Transform(), self.walkers_list[i]["id"]))
          results = self.client.apply_batch_sync(batch, True)
          for i in range(len(results)):
              if results[i].error:
                  logging.error(results[i].error)
              else:
                  self.walkers_list[i]["con"] = results[i].actor_id
          # 4. we put altogether the walkers and controllers id to get the objects from their id
          for i in range(len(self.walkers_list)):
              self.all_id.append(self.walkers_list[i]["con"])
              self.all_id.append(self.walkers_list[i]["id"])
          self.all_actors = self.world.get_actors(self.all_id)
  
          # wait for a tick to ensure client receives the last transform of the walkers we have just created
          self.world.wait_for_tick()
  
          # 5. initialize each controller and set target to walk to (list is [controler, actor, controller, actor ...])
          # set how many pedestrians can cross the road
          self.world.set_pedestrians_cross_factor(percentagePedestriansCrossing)
          for i in range(0, len(self.all_id), 2):
              # start walker
              self.all_actors[i].start()
              # set walk to random point
              self.all_actors[i].go_to_location(self.world.get_random_location_from_navigation())
              # max speed
              self.all_actors[i].set_max_speed(float(walker_speed[int(i/2)]))
  
          print('spawned %d vehicles and %d walkers, press Ctrl+C to exit.' % (len(self.vehicles_list), len(self.walkers_list)))
  
          # while True:
          # 	self.world.wait_for_tick()
  
  
  
      def destroy(self):
          print('\ndestroying %d vehicles' % len(self.vehicles_list))
          self.client.apply_batch([carla.command.DestroyActor(x) for x in self.vehicles_list])
  
          # stop walker controllers (list is [controller, actor, controller, actor ...])
          for i in range(0, len(self.all_id), 2):
              self.all_actors[i].stop()
  
          print('\ndestroying %d walkers' % len(self.walkers_list))
          self.client.apply_batch([carla.command.DestroyActor(x) for x in self.all_id])
  
          time.sleep(0.5)
  
  
  