Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sim info dict #601

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion donkeycar/parts/datastore.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ def put_record(self, data):
# in case val is a numpy.float32, which json doesn't like
json_data[key] = float(val)

elif typ in ['str', 'float', 'int', 'boolean', 'vector']:
elif typ in ['str', 'float', 'int', 'boolean', 'vector', 'dict']:
json_data[key] = val

elif typ is 'image':
Expand Down
21 changes: 20 additions & 1 deletion donkeycar/parts/dgym.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ def __init__(self, sim_path, host="127.0.0.1", port=9091, headless=0, env_name="
self.action = [0.0, 0.0]
self.running = True
self.info = { 'pos' : (0., 0., 0.)}

self.delay = float(delay)

if "body_style" in conf:
Expand All @@ -52,5 +53,23 @@ def shutdown(self):
time.sleep(0.2)
self.env.close()

class DonkeyGymEnvWithInfo(DonkeyGymEnv):
""" This subclass will return the Simulator's info dictionary along with the current image.
The info dictionary will include the reward and done flags.
"""
def __init__(self, *args, **kwargs):
# only allow known json-able entries from the sim's info dictionary
self.valid = ['pos', 'cte', 'speed', 'hit']

super(DonkeyGymEnvWithInfo,self).__init__(*args, **kwargs)

def update(self):
while self.running:
self.frame, reward, done, info = self.env.step(self.action)
self.info = {key: info[key] for key in info if key in self.valid}
self.info['reward'] = reward
self.info['done'] = done


def run_threaded(self, steering, throttle):
super(DonkeyGymEnvWithInfo,self).run_threaded(steering, throttle)
return self.frame, self.info
1 change: 1 addition & 0 deletions donkeycar/templates/cfg_complete.py
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@
GYM_CONF = { "body_style" : "donkey", "body_rgb" : (128, 128, 128), "car_name" : "me", "font_size" : 100} # body style(donkey|bare|car01) body rgb 0-255
SIM_HOST = "127.0.0.1" # when racing on virtual-race-league use host "trainmydonkey.com"
SIM_ARTIFICIAL_LATENCY = 0 # this is the millisecond latency in controls. Can use useful in emulating the delay when useing a remote server. values of 100 to 400 probably reasonable.
DONKEY_GYM_INFO = False # Include Sim info dict when saving Tub files.

#publish camera over network
#This is used to create a tcp service to pushlish the camera feed
Expand Down
1 change: 1 addition & 0 deletions donkeycar/templates/cfg_path_follow.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,3 +109,4 @@
DONKEY_GYM = False
DONKEY_SIM_PATH = "path to sim" #"/home/tkramer/projects/sdsandbox/sdsim/build/DonkeySimLinux/donkey_sim.x86_64"
DONKEY_GYM_ENV_NAME = "donkey-generated-track-v0" # ("donkey-generated-track-v0"|"donkey-generated-roads-v0"|"donkey-warehouse-v0"|"donkey-avc-sparkfun-v0")
DONKEY_GYM_INFO = False # Include Sim info dict when saving Tub files.
17 changes: 13 additions & 4 deletions donkeycar/templates/complete.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,15 @@ def drive(cfg, model_path=None, use_joystick=False, model_type=None, camera_type
from donkeycar.parts.dgym import DonkeyGymEnv

inputs = []
outputs=['cam/image_array']
threaded = True
if cfg.DONKEY_GYM:
from donkeycar.parts.dgym import DonkeyGymEnv
cam = DonkeyGymEnv(cfg.DONKEY_SIM_PATH, host=cfg.SIM_HOST, env_name=cfg.DONKEY_GYM_ENV_NAME, conf=cfg.GYM_CONF, delay=cfg.SIM_ARTIFICIAL_LATENCY)
from donkeycar.parts.dgym import DonkeyGymEnv, DonkeyGymEnvWithInfo
if cfg.DONKEY_GYM_INFO:
outputs.append( 'sim/info' )
cam = DonkeyGymEnvWithInfo(cfg.DONKEY_SIM_PATH, host=cfg.SIM_HOST, env_name=cfg.DONKEY_GYM_ENV_NAME, conf=cfg.GYM_CONF, delay=cfg.SIM_ARTIFICIAL_LATENCY)
else:
cam = DonkeyGymEnv(cfg.DONKEY_SIM_PATH, host=cfg.SIM_HOST, env_name=cfg.DONKEY_GYM_ENV_NAME, conf=cfg.GYM_CONF, delay=cfg.SIM_ARTIFICIAL_LATENCY)
threaded = True
inputs = ['angle', 'throttle']
elif cfg.CAMERA_TYPE == "PICAM":
Expand All @@ -130,7 +135,7 @@ def drive(cfg, model_path=None, use_joystick=False, model_type=None, camera_type
else:
raise(Exception("Unkown camera type: %s" % cfg.CAMERA_TYPE))

V.add(cam, inputs=inputs, outputs=['cam/image_array'], threaded=threaded)
V.add(cam, inputs=inputs, outputs=outputs, threaded=threaded)

if use_joystick or cfg.USE_JOYSTICK_AS_DEFAULT:
#modify max_throttle closer to 1.0 to have more power
Expand Down Expand Up @@ -569,7 +574,11 @@ def run(self, mode, recording):
if cfg.RECORD_DURING_AI:
inputs += ['pilot/angle', 'pilot/throttle']
types += ['float', 'float']


if cfg.DONKEY_GYM_INFO:
inputs += ['sim/info']
types += ['dict']

th = TubHandler(path=cfg.DATA_PATH)
tub = th.new_tub_writer(inputs=inputs, types=types, user_meta=meta)
V.add(tub, inputs=inputs, outputs=["tub/num_records"], run_condition='recording')
Expand Down
18 changes: 18 additions & 0 deletions donkeycar/tests/test_tub.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,24 @@ def test_tub_write_numpy(tub):
rec_out = tub.get_record(rec_index)
assert type(rec_out['user/throttle']) == float

def test_tub_dict(tub):
"""Tub can save a record that contains a dictionary with json-able types."""
d = {'pos': (49.99962, 0.7410042, 50.16277),
'cte': -0.0006235633,
'hit': None,
'done': True }
x=123
z=0.0
rec_in = {'user/angle': x, 'user/throttle':z, 'sim/info':d}
tub.meta['inputs'].append('sim/info')
tub.meta['types'].append('dict')
rec_index = tub.put_record(rec_in)
rec_out = tub.get_record(rec_index)
assert type(rec_out['sim/info']) == dict
assert type(rec_out['sim/info']['cte']) == float
assert rec_out['sim/info']['hit'] is None
assert rec_out['sim/info']['done'] is True


def test_tub_exclude(tub):
""" Make sure the Tub will exclude records in the exclude set """
Expand Down