|
|
import irsim |
|
|
import numpy as np |
|
|
import random |
|
|
|
|
|
import shapely |
|
|
from irsim.lib.handler.geometry_handler import GeometryFactory |
|
|
from irsim.world import ObjectBase |
|
|
|
|
|
class SIM_ENV: |
|
|
def __init__(self, world_file="robot_world.yaml", save_ani=False): |
|
|
self.env = irsim.make(world_file, save_ani=save_ani) |
|
|
robot_info = self.env.get_robot_info(0) |
|
|
self.robot_goal = robot_info.goal |
|
|
|
|
|
def step(self, lin_velocity=0.0, ang_velocity=0.1): |
|
|
self.env.step(action_id=0, action=np.array([[lin_velocity], [ang_velocity]])) |
|
|
self.env.render() |
|
|
|
|
|
scan = self.env.get_lidar_scan() |
|
|
latest_scan = scan["ranges"] |
|
|
|
|
|
robot_state = self.env.get_robot_state() |
|
|
goal_vector = [ |
|
|
self.robot_goal[0].item() - robot_state[0].item(), |
|
|
self.robot_goal[1].item() - robot_state[1].item(), |
|
|
] |
|
|
distance = np.linalg.norm(goal_vector) |
|
|
goal = self.env.robot.arrive |
|
|
pose_vector = [np.cos(robot_state[2]).item(), np.sin(robot_state[2]).item()] |
|
|
cos, sin = self.cossin(pose_vector, goal_vector) |
|
|
collision = self.env.robot.collision |
|
|
action = [lin_velocity, ang_velocity] |
|
|
reward = self.get_reward(goal, collision, action, latest_scan) |
|
|
|
|
|
return latest_scan, distance, cos, sin, collision, goal, action, reward |
|
|
|
|
|
def reset(self, robot_state=None, robot_goal=None, random_obstacles=True): |
|
|
if robot_state is None: |
|
|
robot_state = [[random.uniform(1, 9)], [random.uniform(1, 9)], [0], [0]] |
|
|
|
|
|
self.env.robot.set_state( |
|
|
state=np.array(robot_state), |
|
|
init=True, |
|
|
) |
|
|
|
|
|
if random_obstacles: |
|
|
self.env.random_obstacle_position( |
|
|
range_low=[0, 0, -3.14], |
|
|
range_high=[10, 10, 3.14], |
|
|
ids=[i + 1 for i in range(7)], |
|
|
non_overlapping=True, |
|
|
) |
|
|
|
|
|
if robot_goal is None: |
|
|
unique = True |
|
|
while unique: |
|
|
robot_goal = [[random.uniform(1, 9)], [random.uniform(1, 9)], [0]] |
|
|
shape = {"name": "circle", "radius": 0.4} |
|
|
state = [robot_goal[0], robot_goal[1], robot_goal[2]] |
|
|
gf = GeometryFactory.create_geometry(**shape) |
|
|
geometry = gf.step(np.c_[state]) |
|
|
unique = any( |
|
|
[ |
|
|
shapely.intersects(geometry, obj._geometry) |
|
|
for obj in self.env.obstacle_list |
|
|
] |
|
|
) |
|
|
self.env.robot.set_goal(np.array(robot_goal), init=True) |
|
|
self.env.reset() |
|
|
self.robot_goal = self.env.robot.goal |
|
|
|
|
|
action = [0.0, 0.0] |
|
|
latest_scan, distance, cos, sin, _, _, action, reward = self.step( |
|
|
lin_velocity=action[0], ang_velocity=action[1] |
|
|
) |
|
|
return latest_scan, distance, cos, sin, False, False, action, reward |
|
|
|
|
|
@staticmethod |
|
|
def cossin(vec1, vec2): |
|
|
vec1 = vec1 / np.linalg.norm(vec1) |
|
|
vec2 = vec2 / np.linalg.norm(vec2) |
|
|
cos = np.dot(vec1, vec2) |
|
|
sin = vec1[0] * vec2[1] - vec1[1] * vec2[0] |
|
|
|
|
|
return cos, sin |
|
|
|
|
|
@staticmethod |
|
|
def get_reward(goal, collision, action, laser_scan): |
|
|
if goal: |
|
|
return 100.0 |
|
|
elif collision: |
|
|
return -100.0 |
|
|
else: |
|
|
r3 = lambda x: 1.35 - x if x < 1.35 else 0.0 |
|
|
return action[0] - abs(action[1]) / 2 - r3(min(laser_scan)) / 2 |
|
|
|