Skip to content
57 changes: 50 additions & 7 deletions habitat/core/batched_env.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,17 @@ def __init__(

include_depth = "DEPTH_SENSOR" in config.SENSORS
include_rgb = "RGB_SENSOR" in config.SENSORS

self.include_point_goal_gps_compass = "POINTGOAL_WITH_GPS_COMPASS_SENSOR" in config.SENSORS
# This key is a hard_coded_string. Will not work with any value:
# see this line : https://github.com/eundersander/habitat-lab/blob/eundersander/gala_kinematic/habitat_baselines/rl/ppo/policy.py#L206
self.gps_compass_key = "pointgoal_with_gps_compass"
gps_compass_sensor_shape= 4
self.include_ee_pos = "EE_POS_SENSOR" in config.SENSORS
self.ee_pos_key = "ee_pos"
ee_pos_shape = 3


assert include_depth or include_rgb

self._num_envs = config.NUM_ENVIRONMENTS
Expand All @@ -72,7 +83,7 @@ def __init__(
bsim_config.sensor0.width = sensor_width
bsim_config.sensor0.height = sensor_height
bsim_config.sensor0.hfov = 60.0
bsim_config.force_random_actions = True
bsim_config.force_random_actions = False
bsim_config.do_async_physics_step = self._config.OVERLAP_PHYSICS
bsim_config.num_physics_substeps = self._config.NUM_PHYSICS_SUBSTEPS
bsim_config.do_procedural_episode_set = True
Expand Down Expand Up @@ -107,10 +118,13 @@ def __init__(
else:
observations["rgb"] = torch.rand([self._num_envs, sensor_height, sensor_width, 3], dtype=torch.float32) * 255
observations["depth"] = torch.rand([self._num_envs, sensor_height, sensor_width, 1], dtype=torch.float32) * 255
if self.include_point_goal_gps_compass:
observations[self.gps_compass_key] = torch.empty([self._num_envs, gps_compass_sensor_shape], dtype=torch.float32)
if self.include_ee_pos:
observations[self.ee_pos_key] = torch.empty([self._num_envs, ee_pos_shape], dtype=torch.float32)

self._observations = observations

# print('observations["rgb"].shape: ', observations["rgb"].shape)

self._is_closed = False

num_other_actions = 1 # doAttemptGrip/doAttemptDrop
Expand Down Expand Up @@ -145,6 +159,20 @@ def __init__(
dtype=np.float32,
)
obs_dict["depth"] = depth_obs
if self.include_point_goal_gps_compass:
obs_dict[self.gps_compass_key] = spaces.Box(
low=-np.inf,
high=np.inf, # todo: investigate depth min/max
shape=(gps_compass_sensor_shape,),
dtype=np.float32,
)
if self.include_ee_pos:
obs_dict[self.ee_pos_key] = spaces.Box(
low=-np.inf,
high=np.inf, # todo: investigate depth min/max
shape=(ee_pos_shape,),
dtype=np.float32,
)

self.observation_spaces = [obs_dict] * 1 # config.NUM_ENVIRONMENTS # note we only ever read element #0 of this array

Expand All @@ -157,6 +185,7 @@ def __init__(
# self.number_of_episodes = []
self._paused: List[int] = []


@property
def num_envs(self):
r"""number of individual environments."""
Expand Down Expand Up @@ -184,10 +213,20 @@ def get_metrics(self):
return results

def get_nonpixel_observations(self, env_states, observations):
for state in env_states:
robot_pos = state.robot_position
robot_yaw = state.robot_yaw
# todo: update observations here
# TODO: update observations here
for (b, state) in enumerate(env_states):
if self.include_point_goal_gps_compass:
robot_pos = state.robot_position
robot_yaw = state.robot_yaw

observations[self.gps_compass_key] [b, 0] = robot_pos[0]
observations[self.gps_compass_key] [b, 1] = robot_pos[1]
observations[self.gps_compass_key] [b, 2] = robot_pos[2]
observations[self.gps_compass_key] [b, 3] = robot_yaw
if self.include_ee_pos:
for i in range(3):
observations[self.ee_pos_key][b, i] = state.ee_pos[i]



def get_dones_rewards_resets(self, env_states, actions):
Expand Down Expand Up @@ -236,8 +275,11 @@ def async_step(
self._bsim.wait_step_physics_or_reset()
self._bsim.start_render()
env_states = self._bsim.get_environment_states()

self.get_nonpixel_observations(env_states, self._observations)
self.get_dones_rewards_resets(env_states, actions_flat_list)
self._bsim.start_step_physics_or_reset(actions_flat_list, self.resets)

else:
# note: this path is untested
self._bsim.start_step_physics_or_reset(actions_flat_list, self.resets)
Expand All @@ -256,6 +298,7 @@ def wait_step(self) -> List[Any]:
# perf todo: ensure we're getting here before rendering finishes (issue a warning otherwise)
self._bsim.wait_render()


# these are "one frame behind" like the observations (i.e. computed from
# the same earlier env state).
rewards = self.rewards
Expand Down
2 changes: 1 addition & 1 deletion habitat_baselines/config/default.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@
_C.RL.POLICY.action_distribution_type = "categorical" # or 'gaussian'
# For gaussian action distribution:
_C.RL.POLICY.ACTION_DIST = CN()
_C.RL.POLICY.ACTION_DIST.use_log_std = False
_C.RL.POLICY.ACTION_DIST.use_log_std = True
_C.RL.POLICY.ACTION_DIST.use_softplus = False
_C.RL.POLICY.ACTION_DIST.min_std = 1e-6
_C.RL.POLICY.ACTION_DIST.max_std = 1
Expand Down
2 changes: 1 addition & 1 deletion habitat_baselines/config/rearrange/gala_kinematic.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ NUM_PHYSICS_SUBSTEPS: 1
SAVE_VIDEOS_INTERVAL: -1
NUM_UPDATES: 60
NUM_ENVIRONMENTS: 512
SENSORS: ["DEPTH_SENSOR", "RGB_SENSOR"]
# SENSORS: ["DEPTH_SENSOR", "RGB_SENSOR", "POINTGOAL_WITH_GPS_COMPASS_SENSOR"]

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed since it is in habitat_baselines/config/rearrange/gala_kinematic_ddppo.yaml

SIMULATOR:
AGENTS: ['AGENT_0']
AGENT_0:
Expand Down
3 changes: 2 additions & 1 deletion habitat_baselines/config/rearrange/gala_kinematic_ddppo.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ NUM_CHECKPOINTS: 0
BATCHED_ENV: True
OVERLAP_PHYSICS: True
SAVE_VIDEOS_INTERVAL: 500
NUM_UPDATES: 61
NUM_UPDATES: 6100
NUM_ENVIRONMENTS: 512
SENSORS: ["DEPTH_SENSOR", "RGB_SENSOR", "POINTGOAL_WITH_GPS_COMPASS_SENSOR", "EE_POS_SENSOR"]
SIMULATOR:
AGENTS: ['AGENT_0']
AGENT_0:
Expand Down
93 changes: 54 additions & 39 deletions habitat_baselines/rl/ppo/policy.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
import abc
from re import X

import torch
from gym import spaces
Expand Down Expand Up @@ -202,34 +203,41 @@ def __init__(
):
super().__init__()

if (
IntegratedPointGoalGPSAndCompassSensor.cls_uuid
in observation_space.spaces
):
self._n_input_goal = observation_space.spaces[
IntegratedPointGoalGPSAndCompassSensor.cls_uuid
].shape[0]
elif PointGoalSensor.cls_uuid in observation_space.spaces:
self._n_input_goal = observation_space.spaces[
PointGoalSensor.cls_uuid
].shape[0]
elif ImageGoalSensor.cls_uuid in observation_space.spaces:
goal_observation_space = spaces.Dict(
{"rgb": observation_space.spaces[ImageGoalSensor.cls_uuid]}
)
self.goal_visual_encoder = SimpleCNN(
goal_observation_space, hidden_size
)
self._n_input_goal = hidden_size
else:
self._n_input_goal = 0
#### [gala_kinematic] Manually adding sensors in there
self.observation_space = observation_space
self._n_state = 0
if "pointgoal_with_gps_compass" in self.observation_space.spaces:
self._n_state += 4
if "ee_pos" in self.observation_space.spaces:
self._n_state += 3

# if (
# IntegratedPointGoalGPSAndCompassSensor.cls_uuid
# in observation_space.spaces
# ):
# self._n_input_goal = observation_space.spaces[
# IntegratedPointGoalGPSAndCompassSensor.cls_uuid
# ].shape[0]
# elif PointGoalSensor.cls_uuid in observation_space.spaces:
# self._n_input_goal = observation_space.spaces[
# PointGoalSensor.cls_uuid
# ].shape[0]
# elif ImageGoalSensor.cls_uuid in observation_space.spaces:
# goal_observation_space = spaces.Dict(
# {"rgb": observation_space.spaces[ImageGoalSensor.cls_uuid]}
# )
# self.goal_visual_encoder = SimpleCNN(
# goal_observation_space, hidden_size
# )
# self._n_input_goal = hidden_size
#### [gala_kinematic] End of manually adding sensors in there

self._hidden_size = hidden_size

self.visual_encoder = SimpleCNN(observation_space, hidden_size)

self.state_encoder = build_rnn_state_encoder(
(0 if self.is_blind else self._hidden_size) + self._n_input_goal,
(0 if self.is_blind else self._hidden_size) + self._n_state,
self._hidden_size,
)

Expand All @@ -248,24 +256,31 @@ def num_recurrent_layers(self):
return self.state_encoder.num_recurrent_layers

def forward(self, observations, rnn_hidden_states, prev_actions, masks):
if IntegratedPointGoalGPSAndCompassSensor.cls_uuid in observations:
target_encoding = observations[
IntegratedPointGoalGPSAndCompassSensor.cls_uuid
]

elif PointGoalSensor.cls_uuid in observations:
target_encoding = observations[PointGoalSensor.cls_uuid]
elif ImageGoalSensor.cls_uuid in observations:
image_goal = observations[ImageGoalSensor.cls_uuid]
target_encoding = self.goal_visual_encoder({"rgb": image_goal})
else:
target_encoding = None
#### [gala_kinematic] Manually adding sensors in there
x = [self.visual_encoder(observations)]
if "pointgoal_with_gps_compass" in self.observation_space.spaces:
x += [observations["pointgoal_with_gps_compass"]]
if "ee_pos" in self.observation_space.spaces:
x += [observations["ee_pos"]]
# if IntegratedPointGoalGPSAndCompassSensor.cls_uuid in observations:
# target_encoding = observations[
# IntegratedPointGoalGPSAndCompassSensor.cls_uuid
# ]

# elif PointGoalSensor.cls_uuid in observations:
# target_encoding = observations[PointGoalSensor.cls_uuid]
# elif ImageGoalSensor.cls_uuid in observations:
# image_goal = observations[ImageGoalSensor.cls_uuid]
# target_encoding = self.goal_visual_encoder({"rgb": image_goal})
# else:
# target_encoding = None
# if not self.is_blind:
# perception_embed = self.visual_encoder(observations)
# x = [perception_embed]
# if target_encoding is not None:
# x += [target_encoding]
#### [gala_kinematic] End of manually adding sensors in there

if not self.is_blind:
perception_embed = self.visual_encoder(observations)
x = [perception_embed]
if target_encoding:
x += [target_encoding]

x_out = torch.cat(x, dim=1)
x_out, rnn_hidden_states = self.state_encoder(
Expand Down