Skip to content

Commit

Permalink
Merge pull request #2 from Souphis/mobile_robot_vision_env
Browse files Browse the repository at this point in the history
Mobile robot vision env
  • Loading branch information
gbartyzel authored Nov 22, 2018
2 parents 1247e1e + d3d9622 commit a4ae945
Show file tree
Hide file tree
Showing 11 changed files with 235 additions and 340 deletions.
62 changes: 28 additions & 34 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,48 +1,42 @@
# Open-AI Gym extension for robotics based on V-REP

## Environments

1. Mobile robot navigation:
* description: Mobile robot is a learning agent. It contains five proximity
sensors, IMU and two DC motors. The task of this agent is to navigate from
position A to position B.
* variants:
* ideal - position is obtained from simulation engine
* odometry - position is obtained from encoders ticks
* gyrodometry - position is obtained from gyroscope and encoders ticks
* state:
* classic env:
* reading from 5 proximity sensors
* polar coordinates
* goal based env:
* observation:
* reading from 5 proximity sensors
* robot cartesian position
* achieved goal:
* robot cartesian position
* desired goal:
* goal cartesian position
## Open-AI Gym extension for robotics based on V-REP

### Environments

1. Mobile robot navigation - the mobile robot contains five proximity sensors,
IMU and two DC motors. The task of this agent is to navigate from position A to position B.
Four variants of this problem were implemented:

| Environment | Description |
| -------------------------------- | --------------------------------------------------------------------------------------------------- |
| MobileRobotIdealNavigation | Position is obtained from simulation engine. Collision is detected with proximity sensor |
| MobileRobotVisualIdealNavigation | Position is obtained from simulation engine. Collision is detected with camera sensor |
| MobileRobotOdometryNavigation | Position is obtained from encoders ticks. Collision is detected with proximity sensor |
| MobileRobotGyrodometryNavigation | Position is obtained from encoders ticks and gyroscope. Collision is detected with proximity sensor |

Environment state description:

| Classic env: | Visual env: |
| ---------------------------------- | ---------------------------------- |
| distances from 5 proximity sensors | distances from 5 proximity sensors |
| polar coordinates | polar coordinates |
| | image from camera sensor |

## Installation
### Installation

### Requirements:
#### Requirements:
Basic requirements:
* V-REP 3.5.0
* Python 3.5+
* Ubuntu 16.04 / Arch Linux
* OpenAI gym


### V-REP
#### V-REP
```
cd ~
wget http://coppeliarobotics.com/files/V-REP_PRO_EDU_V3_5_0_Linux.tar.gz
tar -xzvf V-REP_PRO_EDU_V3_5_0_Linux
sudo mv V-REP_PRO_EDU_V3_5_0_Linux /opt/V-REP
rm -rf V-REP_PRO_EDU_V3_5_0_Linux
export V_REP=/opt/V-REP
chmod +x ./install_vrep.sh
./install_vrep.sh
```
### Python
#### Python
```
git clone https://github.com/Souphis/gym-vrep.git
cd gym-vrep
Expand Down
16 changes: 8 additions & 8 deletions gym_vrep/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,33 @@

logger = logging.getLogger(__name__)
register(
id='VrepMobileRobotIdealNavigation-v0',
id='MobileRobotIdealNavigation-v0',
entry_point=
'gym_vrep.envs.mobile_robot_navigation:VrepMobileRobotNavigationEnv',
'gym_vrep.envs.mobile_robot_navigation:MobileRobotNavigationEnv',
max_episode_steps=1200,
kwargs={'dt': 0.05},
)

register(
id='VrepMobileRobotOdometryNavigation-v0',
id='MobileRobotVisionIdealNavigation-v0',
entry_point=
'gym_vrep.envs.mobile_robot_navigation:VrepMobileRobotOdomNavigationEnv',
'gym_vrep.envs.mobile_robot_navigation:MobileRobotVisionNavigationEnv',
max_episode_steps=1200,
kwargs={'dt': 0.05},
)

register(
id='VrepMobileRobotGyrodometryNavigation-v0',
id='MobileRobotOdometryNavigation-v0',
entry_point=
'gym_vrep.envs.mobile_robot_navigation:VrepMobileRobotGyroNavigationEnv',
'gym_vrep.envs.mobile_robot_navigation:MobileRobotOdomNavigationEnv',
max_episode_steps=1200,
kwargs={'dt': 0.05},
)

register(
id='VrepMobileRobotNavigationGoal-v0',
id='MobileRobotGyrodometryNavigation-v0',
entry_point=
'gym_vrep.envs.mobile_robot_navigation:VrepMobileRobotNavigationGoalEnv',
'gym_vrep.envs.mobile_robot_navigation:MobileRobotGyroNavigationEnv',
max_episode_steps=1200,
kwargs={'dt': 0.05},
)
2 changes: 1 addition & 1 deletion gym_vrep/envs/gym_vrep.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class VrepEnv(gym.Env):
metadata = {'render.modes': ['human']}

def __init__(self, scene, dt):
self.seed(1337)
self.seed()

self._dt = dt
self._port = self.np_random.randint(20000, 21000)
Expand Down
9 changes: 5 additions & 4 deletions gym_vrep/envs/mobile_robot_navigation/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
from gym_vrep.envs.mobile_robot_navigation.vrep_mobile_robot_navigation import VrepMobileRobotNavigationEnv
from gym_vrep.envs.mobile_robot_navigation.vrep_mobile_robot_navigation import VrepMobileRobotOdomNavigationEnv
from gym_vrep.envs.mobile_robot_navigation.vrep_mobile_robot_navigation import VrepMobileRobotGyroNavigationEnv
from gym_vrep.envs.mobile_robot_navigation.vrep_mobile_robot_navigation import VrepMobileRobotNavigationGoalEnv
from gym_vrep.envs.mobile_robot_navigation.mobile_robot_navigation import MobileRobotNavigationEnv
from gym_vrep.envs.mobile_robot_navigation.mobile_robot_navigation import MobileRobotVisionNavigationEnv
from gym_vrep.envs.mobile_robot_navigation.mobile_robot_navigation import MobileRobotOdomNavigationEnv
from gym_vrep.envs.mobile_robot_navigation.mobile_robot_navigation import MobileRobotGyroNavigationEnv
from gym_vrep.envs.mobile_robot_navigation.mobile_robot_navigation_goal import MobileRobotNavigationGoalEnv

from gym_vrep.envs.mobile_robot_navigation.navigation import Ideal
from gym_vrep.envs.mobile_robot_navigation.navigation import Odometry
Expand Down
161 changes: 161 additions & 0 deletions gym_vrep/envs/mobile_robot_navigation/mobile_robot_navigation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
import numpy as np

from gym import spaces
from gym_vrep.envs import gym_vrep
from gym_vrep.envs.vrep import vrep
from gym_vrep.envs.mobile_robot_navigation.robot import Robot
from gym_vrep.envs.mobile_robot_navigation.navigation import Ideal
from gym_vrep.envs.mobile_robot_navigation.navigation import Odometry
from gym_vrep.envs.mobile_robot_navigation.navigation import Gyrodometry

NAVIGATION_TYPE = {
'Ideal': Ideal,
'Odometry': Odometry,
'Gyrodometry': Gyrodometry,
}


def _choose_world_type(enable_vision):
if enable_vision:
return 'mobile_robot_navigation_room_vision'
return 'mobile_robot_navigation_room'


class MobileRobotNavigationEnv(gym_vrep.VrepEnv):
metadata = {'render.modes': ['human']}
navigation_type = NAVIGATION_TYPE['Ideal']
enable_vision = False

def __init__(self, dt):
super(MobileRobotNavigationEnv, self).__init__(
_choose_world_type(self.enable_vision), dt)
v_rep_obj_names = {
'left_motor': 'smartBotLeftMotor',
'right_motor': 'smartBotRightMotor',
'robot': 'smartBot',
}
if self.enable_vision:
v_rep_obj_names['camera'] = 'smartBotCamera'

v_rep_stream_names = {
'proximity_sensor': 'proximitySensorsSignal',
'encoders': 'encodersSignal',
'accelerometer': 'accelerometerSignal',
'gyroscope': 'gyroscopeSignal',
}

self._goal = np.array([2.0, 2.0])

self._prev_polar_coords = np.zeros(2)

self._alpha_factor = 25
self._goal_threshold = 0.02
self._collision_dist = 0.04

self._robot = Robot(self._client, self._dt, v_rep_obj_names,
v_rep_stream_names)

self._navigation = self.navigation_type(
self._goal, self._robot.wheel_diameter, self._robot.body_width,
self._dt)

self.action_space = spaces.Box(
self._robot.velocity_bound[0],
self._robot.velocity_bound[1],
shape=self._robot.velocity_bound.shape,
dtype='float32')

env_diagonal = np.sqrt(2.0 * (5.0 ** 2))

low = np.array([0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -np.pi])
high = np.array([2.0, 2.0, 2.0, 2.0, 2.0, env_diagonal, np.pi])
if self.enable_vision:
self.observation_space = spaces.Dict(dict(
image=spaces.Box(
low=0, high=255, shape=(640, 480, 3), dtype=np.uint8),
scalars=spaces.Box(low=low, high=high, dtype=np.float32),
))
else:
self.observation_space = spaces.Box(
low=low, high=high, dtype=np.float32)

def step(self, action):
self._robot.set_motor_velocities(action)
vrep.simxSynchronousTrigger(self._client)
vrep.simxGetPingTime(self._client)

cart_pose = self._robot.get_position()
gyro_data = self._robot.get_gyroscope_values()
delta_phi = self._robot.get_encoders_rotations()

self._navigation.compute_position(
position=cart_pose, phi=delta_phi, anuglar_velocity=gyro_data[2])

polar_coords = self._navigation.polar_coordinates
prox_dist = self._robot.get_proximity_values()
done = False

state = np.concatenate((prox_dist, polar_coords))
if self.enable_vision:
image = self._robot.get_image()
state = {'image': image, 'scalars': polar_coords}

ds = self._prev_polar_coords[0] - polar_coords[0]
reward = ds * self._alpha_factor

if not np.all(prox_dist > self._collision_dist):
reward = -1.0
done = True

if polar_coords[0] < self._goal_threshold:
reward = 1.0
done = True

if done:
vrep.simxStopSimulation(self._client,
vrep.simx_opmode_oneshot_wait)

self._prev_polar_coords = polar_coords

return state, reward, done, {}

def reset(self):
vrep.simxStopSimulation(self._client, vrep.simx_opmode_oneshot_wait)
self._robot.reset()
vrep.simxStartSimulation(self._client, vrep.simx_opmode_oneshot_wait)

for _ in range(2):
vrep.simxSynchronousTrigger(self._client)
vrep.simxGetPingTime(self._client)

cart_pose = self._robot.get_position()
self._navigation.reset(cart_pose)

prox_dist = self._robot.get_proximity_values()
gyro_data = self._robot.get_gyroscope_values()
delta_phi = self._robot.get_encoders_rotations()

self._navigation.compute_position(
position=cart_pose, phi=delta_phi, anuglar_velocity=gyro_data[2])

polar_coords = self._navigation.polar_coordinates
self._prev_polar_coords = polar_coords

state = np.concatenate((prox_dist, polar_coords))
if self.enable_vision:
image = self._robot.get_image()
state = {'image': image, 'scalars': polar_coords}

return state


class MobileRobotOdomNavigationEnv(MobileRobotNavigationEnv):
navigation_type = NAVIGATION_TYPE['Odometry']


class MobileRobotGyroNavigationEnv(MobileRobotNavigationEnv):
navigation_type = NAVIGATION_TYPE['Gyrodometry']


class MobileRobotVisionNavigationEnv(MobileRobotNavigationEnv):
enable_vision = True
15 changes: 14 additions & 1 deletion gym_vrep/envs/mobile_robot_navigation/robot.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,12 @@ def reset(self):

for key, stream in self._stream_names.items():
vrep.simxGetStringSignal(self._client, stream,
vrep.simx_opmode_streaming)
vrep.simx_opmode_streaming)

if 'camera' in self._objects_hanlders:
vrep.simxGetVisionSensorImage(self._client,
self._objects_hanlders['camera'],
False, vrep.simx_opmode_streaming)

vrep.simxGetObjectPosition(self._client,
self._objects_hanlders['robot'], -1,
Expand Down Expand Up @@ -72,6 +77,14 @@ def get_encoders_rotations(self):

return np.round(self._encoder_reading, 3)

def get_image(self):
res, resolution, image = vrep.simxGetVisionSensorImage(
self._client, self._objects_hanlders['camera'], False,
vrep.simx_opmode_buffer)
img = np.array(image, dtype=np.uint8)
img.resize([resolution[1], resolution[0], 3])
return img

def get_proximity_values(self):
res, packed_vec = vrep.simxGetStringSignal(
self._client, self._stream_names['proximity_sensor'],
Expand Down
Loading

0 comments on commit a4ae945

Please sign in to comment.