Closed dkapur17 closed 2 years ago
import gym
import airsim
from gym import spaces
import numpy as np
import random
from airgym.envs import AirSimEnv
class RLEnv(AirSimEnv):
sim_target = *insert Unreal Engine's tag for the object you need to spawn around*
camera_name = '3'
image_type = airsim.ImageType.Scene
actions = {
0: [1, 0, 0], # front
1: [0, 1, 0], # right
2: [0, 0, 1], # down
3: [-1, 0, 0], # back
4: [0, -1, 0], # left
5: [1, 1, 0], # forward + right
6: [1, -1, 0], # forward + left
7: [-1, 1, 0], # backward + right
8: [-1, -1, 0], # backward + left
9: [0, 0, -1] # up
}
def __init__(self, image_shape, lower_xy_bounds, upper_xy_bound):
super(RLEnv, self).__init__(image_shape)
"""
Initialize clients, enable API control and arm the drone
"""
self.lower_xy_bound, self.upper_xy_bound = lower_xy_bound, upper_xy_bound
self.image_shape=image_shape
self.client = airsim.MultirotorClient(ip="")
self.client.enableApiControl(True)
self.client.armDisarm(True)
"""
Define ACTION and STATE SPACE of gym env
"""
self.action_space = spaces.Discrete(10)
self.observation_space = spaces.Box(low=0, high=255, shape=self.image_shape, dtype=np.uint8)
"""
Enable Unreal Engine objects to be found by the drone, then get the drone's and target's location
and teleport the drone at a random location near the target
"""
# Set detection radius in [cm]
self.client.simSetDetectionFilterRadius(RLEnv.camera_name, RLEnv.image_type, 200 * 100)
# Add desired object name to detect in wild card/regex format
self.client.simAddDetectionFilterMeshName(RLEnv.camera_name, RLEnv.image_type, RLEnv.sim_target)
self.drone_state = self.client.getMultirotorState()
self.client.pose = self.initialize_location()
self.client.simSetVehiclePose(self.client.pose, True)
self.client.moveToZAsync(-self.height, 10).join() #takeoff
@staticmethod
def random_bounded_location(min_bound, max_bound):
"""
Generate random starting position in the bounds given
"""
return random.randint(min_bound, max_bound)
def initialize_location(self):
x = self.random_bounded_location(self.lower_xy_bound, self.upper_xy_bound) # x distance from target
y = self.random_bounded_location(self.lower_xy_bound, self.upper_xy_bound) # y distance from target
# Set relative position and orientation wrt to the target, not 100% correct but can't be bothered
self.client.pose = self.client.simGetVehiclePose()
obj_loc = [float(i) for i in self.client.simGetObjectPose(RLEnv.sim_target).position][:2]
x_obj, y_obj = obj_loc[0] + x, obj_loc[1] + y
self.client.pose.position.x_val = x_obj * random.randint(-1, 1)
self.client.pose.position.y_val = y_obj * random.randint(-1, 1)
self.client.pose.position.z_val = 0
if x_obj == 0:
x_obj = 1e-4
self.client.pose.orientation.z_val = np.degrees(np.arctan(y_obj / x_obj)) / 100
return self.client.pose
def _get_obs(self):
# make the api call to get images or readings you need and return them
return obs
def _do_action(self):
# Here you write how you want your drone to move
pass
def _compute_reward(self):
# here you code how you would compute reward for each timestep and return reward and observation
return reward, done
def step(self):
self._do_action(action)
obs = self._get_obs()
reward, done = self._compute_reward()
info ={"extra_info": "Fill in the dictionary with extra info that you need to plot"}
return obs, reward, done, info
def reset(self):
self.reset_initial_state() # Code a function almost identical to __init__() that resets all metrics to the initial state
return self._get_obs()
This should be decent to get you started, modify as you want and follow the example they have under reinforcement learning + sb3 +openaigym+ youtube examples.
Thanks a lot!
Question
What's your question?
Is there a way to spawn the multirotor at a given position, without losing Physics in the simulation?
Include context on what you are trying to achieve
I'm trying to train a Reinforcement Learning agent on an environment built using AirSim. I want to be able to randomly spawn the drone at different locations at the start of every episode, but the
reset()
method only moves it to its original position (the one set in the game engine before running the simulation) every time. I've read about thesimSetVehiclePose
method but it seems like that switches the simulation to Computer Vision mode, which disables all physics, and this is not ideal for me. Is there a way to spawn the drone at a random position in space while still keeping Multirotor Mode active?Context details
Using Unity Engine with AirSim 1.8.1 with Python Bindings 1.7.0 on Windows 10.
Include details of what you already did to find answers
Went through similar issues, especially #1856, but couldn't find the answer.