39
39
# from macad_gym.core.sensors.utils import get_transform_from_nearest_way_point
40
40
from macad_gym .carla .reward import Reward
41
41
from macad_gym .core .sensors .hud import HUD
42
- from macad_gym .viz .render import multi_view_render
42
+ from macad_gym .viz .render import Render
43
43
from macad_gym .carla .scenarios import Scenarios
44
44
45
45
# The following imports require carla to be imported already.
@@ -278,6 +278,21 @@ def __init__(self, configs=None):
278
278
self ._scenario_config = configs ["scenarios" ]
279
279
self ._env_config = configs ["env" ]
280
280
self ._actor_configs = configs ["actors" ]
281
+
282
+ # At most one actor can be manual controlled
283
+ manual_control_count = 0
284
+ for _ , actor_config in self ._actor_configs .items ():
285
+ if actor_config ["manual_control" ]:
286
+ if "vehicle" not in actor_config ["type" ]:
287
+ raise ValueError ("Only vehicles can be manual controlled." )
288
+
289
+ manual_control_count += 1
290
+
291
+ assert manual_control_count <= 1 , (
292
+ "At most one actor can be manually controlled. "
293
+ f"Found { manual_control_count } actors with manual_control=True"
294
+ )
295
+
281
296
# Camera position is problematic for certain vehicles and even in
282
297
# autopilot they are prone to error
283
298
self .exclude_hard_vehicles = False
@@ -317,6 +332,24 @@ def __init__(self, configs=None):
317
332
pygame .font .init () # for HUD
318
333
self ._hud = HUD (self ._render_x_res , self ._render_y_res )
319
334
335
+ # For manual_control
336
+ self ._control_clock = None
337
+ self ._manual_controller = None
338
+ self ._manual_control_camera_manager = None
339
+
340
+ # Render related
341
+ Render .resize_screen (self ._render_x_res , self ._render_y_res )
342
+
343
+ self ._camera_poses , window_dim = Render .get_surface_poses (
344
+ [self ._x_res , self ._y_res ], self ._actor_configs )
345
+
346
+ if manual_control_count == 0 :
347
+ Render .resize_screen (window_dim [0 ], window_dim [1 ])
348
+ else :
349
+ self ._manual_control_render_pose = (0 , window_dim [1 ])
350
+ Render .resize_screen (
351
+ max (self ._render_x_res , window_dim [0 ]), self ._render_y_res + window_dim [1 ])
352
+
320
353
# Actions space
321
354
if self ._discrete_actions :
322
355
self .action_space = Dict (
@@ -633,7 +666,8 @@ def _clear_server_state(self):
633
666
if self ._server_process :
634
667
if IS_WINDOWS_PLATFORM :
635
668
subprocess .call (
636
- ["taskkill" , "/F" , "/T" , "/PID" , str (self ._server_process .pid )]
669
+ ["taskkill" , "/F" , "/T" , "/PID" ,
670
+ str (self ._server_process .pid )]
637
671
)
638
672
live_carla_processes .remove (self ._server_process .pid )
639
673
else :
@@ -693,9 +727,7 @@ def reset(self):
693
727
694
728
return self ._obs_dict
695
729
696
- # TODO: Is this function required?
697
- # TODO: Thought: Run server in headless mode always. Use pygame win on
698
- # client when render=True
730
+ # ! Deprecated method
699
731
def _on_render (self ):
700
732
"""Render the pygame window.
701
733
@@ -704,11 +736,7 @@ def _on_render(self):
704
736
Returns:
705
737
N/A
706
738
"""
707
- for cam in self ._cameras .values ():
708
- surface = cam ._surface
709
- if surface is not None :
710
- self ._display .blit (surface , (0 , 0 ))
711
- pygame .display .flip ()
739
+ pass
712
740
713
741
def _spawn_new_actor (self , actor_id ):
714
742
"""Spawn an agent as per the blueprint at the given pose
@@ -867,7 +895,8 @@ def _reset(self, clean_world=True):
867
895
)
868
896
actor_config = self ._actor_configs [actor_id ]
869
897
870
- try : # Try to spawn actor (soft reset) or fail and reinitialize the server before get back here
898
+ # Try to spawn actor (soft reset) or fail and reinitialize the server before get back here
899
+ try :
871
900
self ._actors [actor_id ] = self ._spawn_new_actor (actor_id )
872
901
except RuntimeError as spawn_err :
873
902
del self ._done_dict [actor_id ]
@@ -928,6 +957,21 @@ def _reset(self, clean_world=True):
928
957
assert camera_manager .sensor .is_listening
929
958
self ._cameras .update ({actor_id : camera_manager })
930
959
960
+ # Manual Control
961
+ if actor_config ["manual_control" ]:
962
+ self ._control_clock = pygame .time .Clock ()
963
+
964
+ self ._manual_controller = KeyboardControl (
965
+ self , actor_config ["auto_control" ])
966
+ self ._manual_controller .actor_id = actor_id
967
+
968
+ self .world .on_tick (self ._hud .on_world_tick )
969
+ self ._manual_control_camera_manager = CameraManager (
970
+ self ._actors [actor_id ], self ._hud )
971
+ self ._manual_control_camera_manager .set_sensor (
972
+ CAMERA_TYPES ['rgb' ].value - 1 , pos = 2 , notify = False
973
+ )
974
+
931
975
self ._start_coord .update (
932
976
{
933
977
actor_id : [
@@ -1117,10 +1161,13 @@ def step(self, action_dict):
1117
1161
k for k , v in self ._actor_configs .items () if v .get ("render" , False )
1118
1162
]
1119
1163
if render_required :
1120
- images = {k : self ._decode_obs (k , v ) for k , v in obs_dict .items ()}
1121
- multi_view_render (
1122
- images , [self ._x_res , self ._y_res ], self ._actor_configs
1123
- )
1164
+ images = {k : self ._decode_obs (k , v )
1165
+ for k , v in obs_dict .items () if self ._actor_configs [k ]["render" ]}
1166
+
1167
+ Render .multi_view_render (images , self ._camera_poses )
1168
+ if self ._manual_controller is None :
1169
+ Render .dummy_event_handler ()
1170
+
1124
1171
return obs_dict , reward_dict , self ._done_dict , info_dict
1125
1172
except Exception :
1126
1173
print (
@@ -1166,18 +1213,14 @@ def _step(self, actor_id, action):
1166
1213
1167
1214
config = self ._actor_configs [actor_id ]
1168
1215
if config ["manual_control" ]:
1169
- clock = pygame .time .Clock ()
1170
- # pygame
1171
- self ._display = pygame .display .set_mode (
1172
- (config ["render_x_res" ], config ["render_y_res" ]),
1173
- pygame .HWSURFACE | pygame .DOUBLEBUF ,
1174
- )
1175
- logger .debug ("pygame started" )
1176
- controller = KeyboardControl (self , config ["auto_control" ])
1177
- controller .actor_id = actor_id
1178
- controller .parse_events (self , clock )
1179
- # TODO: Is this _on_render() method necessary? why?
1180
- self ._on_render ()
1216
+ self ._control_clock .tick (60 )
1217
+ self ._manual_control_camera_manager ._hud .tick (self .world , self ._actors [actor_id ], self ._collisions [actor_id ], self ._control_clock )
1218
+ self ._manual_controller .parse_events (self , self ._control_clock )
1219
+
1220
+ # TODO: consider move this to Render as well
1221
+ self ._manual_control_camera_manager .render (Render .get_screen (), self ._manual_control_render_pose )
1222
+ self ._manual_control_camera_manager ._hud .render (Render .get_screen (), self ._manual_control_render_pose )
1223
+ pygame .display .flip ()
1181
1224
elif config ["auto_control" ]:
1182
1225
if getattr (self ._actors [actor_id ], "set_autopilot" , 0 ):
1183
1226
self ._actors [actor_id ].set_autopilot (
@@ -1480,16 +1523,19 @@ def get_next_actions(measurements, is_discrete_actions):
1480
1523
1481
1524
1482
1525
if __name__ == "__main__" :
1483
- argparser = argparse .ArgumentParser (description = "CARLA Manual Control Client" )
1484
- argparser .add_argument ("--scenario" , default = "3" , help = "print debug information" )
1526
+ argparser = argparse .ArgumentParser (
1527
+ description = "CARLA Manual Control Client" )
1528
+ argparser .add_argument ("--scenario" , default = "3" ,
1529
+ help = "print debug information" )
1485
1530
# TODO: Fix the default path to the config.json;Should work after packaging
1486
1531
argparser .add_argument (
1487
1532
"--config" ,
1488
1533
default = "src/macad_gym/carla/config.json" ,
1489
1534
help = "print debug information" ,
1490
1535
)
1491
1536
1492
- argparser .add_argument ("--map" , default = "Town01" , help = "print debug information" )
1537
+ argparser .add_argument ("--map" , default = "Town01" ,
1538
+ help = "print debug information" )
1493
1539
1494
1540
args = argparser .parse_args ()
1495
1541
0 commit comments