support/gym_remote/server.py (68 lines of code) (raw):
import gym
import time
from gym_remote import Bridge, FloatChannel, BoolChannel
import gym_remote.exceptions as gre
class RemoteEnvWrapper(gym.Wrapper):
def __init__(self, env, directory):
gym.Wrapper.__init__(self, env)
self.bridge = Bridge(directory)
self.ch_ac = self.bridge.wrap('ac', env.action_space)
self.ch_ob = self.bridge.wrap('ob', env.observation_space)
self.ch_reward = self.bridge.add_channel('reward', FloatChannel())
self.ch_done = self.bridge.add_channel('done', BoolChannel())
self.ch_reset = self.bridge.add_channel('reset', BoolChannel())
self.bridge.listen()
def serve(self, timestep_limit=None, wallclock_limit=None, ignore_reset=False):
if wallclock_limit is not None:
end = time.time() + wallclock_limit
self.bridge.settimeout(wallclock_limit)
else:
end = None
ts = 0
try:
self.bridge.server_accept()
except Bridge.Timeout:
return ts
done = True
while timestep_limit is None or ts < timestep_limit:
if wallclock_limit:
t = time.time()
if t >= end:
self.bridge.close(exception=gre.WallClockTimeoutError)
break
self.bridge.settimeout(end - t)
try:
self.bridge.recv()
except Bridge.Timeout:
self.bridge.close(exception=gre.WallClockTimeoutError)
break
except Bridge.Closed:
self.bridge.close(exception=gre.ClientDisconnectError)
break
if self.ch_reset.value:
if ignore_reset and not done:
self.bridge.exception(gre.ResetError)
self.bridge.send()
continue
self.ch_ob.value = self.env.reset()
self.ch_reset.value = False
self.ch_reward.value = 0
self.ch_done.value = False
done = False
else:
if ignore_reset and done:
self.bridge.exception(gre.ResetError)
self.bridge.send()
continue
ob, rew, done, _ = self.env.step(self.ch_ac.value)
self.ch_ob.value = ob
self.ch_reward.value = rew
self.ch_done.value = done
self.bridge.send()
ts += 1
if timestep_limit and ts >= timestep_limit:
self.bridge.close(exception=gre.TimestepTimeoutError)
return ts
def close(self):
self.bridge.close()
self.env.close()