Skip to content

Commit

Permalink
Merge pull request #631 from StanfordVL/lazy-gm-access
Browse files Browse the repository at this point in the history
lazy access of gm values
  • Loading branch information
hang-yin authored Apr 18, 2024
2 parents 461898d + 06cf9c0 commit 6ac4586
Show file tree
Hide file tree
Showing 30 changed files with 288 additions and 196 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ jobs:
- test_object_removal
- test_object_states
- test_primitives
- test_robot_states
- test_robot_states_flatcache
- test_robot_states_no_flatcache
- test_robot_teleoperation
- test_sensors
- test_symbolic_primitives
Expand Down
2 changes: 0 additions & 2 deletions omnigibson/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,6 @@

__version__ = "1.0.0"

log.setLevel(logging.DEBUG if gm.DEBUG else logging.INFO)

root_path = os.path.dirname(os.path.realpath(__file__))

# Store paths to example configs
Expand Down
72 changes: 48 additions & 24 deletions omnigibson/macros.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,33 +10,57 @@

from addict import Dict


class MacroDict(Dict):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self["_read"] = set()

def __setattr__(self, name, value):
if name in self.get("_read", set()):
raise AttributeError(f"Cannot set attribute {name} in MacroDict, it has already been used.")
# Use the super's setattr for setting attributes, but handle _read directly to avoid recursion.
if name == "_read":
self[name] = value
else:
super().__setattr__(name, value)

def __getattr__(self, item):
# Directly check and modify '_read' to avoid going through __getattr__ or __setattr__.
if item != "_read":
self["_read"].add(item)
# Use direct dictionary access to avoid infinite recursion.
try:
return self[item]
except KeyError:
raise AttributeError(f"'MacroDict' object has no attribute '{item}'")


# Initialize settings
macros = Dict()
macros = MacroDict()
gm = macros.globals


def determine_gm_path(default_path, env_var_name):
# Start with the default path
path = default_path
# Override with the environment variable, if set
if env_var_name in os.environ:
path = os.environ[env_var_name]
# Expand the user directory (~)
path = os.path.expanduser(path)
# Make the path absolute if it's not already
if not os.path.isabs(path):
path = os.path.join(os.path.dirname(os.path.realpath(__file__)), path)
return path


# Path (either relative to OmniGibson/omnigibson directory or global absolute path) for data
# Assets correspond to non-objects / scenes (e.g.: robots), and dataset incliudes objects + scene
# can override assets_path and dataset_path from environment variable
gm.ASSET_PATH = "data/assets"
if "OMNIGIBSON_ASSET_PATH" in os.environ:
gm.ASSET_PATH = os.environ["OMNIGIBSON_ASSET_PATH"]
gm.ASSET_PATH = os.path.expanduser(gm.ASSET_PATH)
if not os.path.isabs(gm.ASSET_PATH):
gm.ASSET_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), gm.ASSET_PATH)

gm.DATASET_PATH = "data/og_dataset"
if "OMNIGIBSON_DATASET_PATH" in os.environ:
gm.DATASET_PATH = os.environ["OMNIGIBSON_DATASET_PATH"]
gm.DATASET_PATH = os.path.expanduser(gm.DATASET_PATH)
if not os.path.isabs(gm.DATASET_PATH):
gm.DATASET_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), gm.DATASET_PATH)

gm.KEY_PATH = "data/omnigibson.key"
if "OMNIGIBSON_KEY_PATH" in os.environ:
gm.KEY_PATH = os.environ["OMNIGIBSON_KEY_PATH"]
gm.KEY_PATH = os.path.expanduser(gm.KEY_PATH)
if not os.path.isabs(gm.KEY_PATH):
gm.KEY_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), gm.KEY_PATH)
gm.ASSET_PATH = determine_gm_path("data/assets", "OMNIGIBSON_ASSET_PATH")
gm.DATASET_PATH = determine_gm_path("data/og_dataset", "OMNIGIBSON_DATASET_PATH")
gm.KEY_PATH = determine_gm_path("data/omnigibson.key", "OMNIGIBSON_KEY_PATH")

# Which GPU to use -- None will result in omni automatically using an appropriate GPU. Otherwise, set with either
# integer or string-form integer
Expand Down Expand Up @@ -130,7 +154,7 @@ def create_module_macros(module_path):
omnigibson/object_states_dirty.py, this would generate a dictionary existing at macros.object_states.dirty
Returns:
Dict: addict dictionary which can be populated with values
MacroDict: addict/macro dictionary which can be populated with values
"""
# Sanity check module path, make sure omnigibson/ is in the path
module_path = pathlib.Path(module_path)
Expand All @@ -148,14 +172,14 @@ def create_module_macros(module_path):
def _recursively_get_or_create_dict(dic, keys):
# If no entry is in @keys, it returns @dic
# Otherwise, checks whether the dictionary contains the first entry in @keys, if so, it grabs the
# corresponding nested dictionary, otherwise, generates a new Dict() as the value
# corresponding nested dictionary, otherwise, generates a new MacroDict() as the value
# It then recurisvely calls this function with the new dic and the remaining keys
if len(keys) == 0:
return dic
else:
key = keys[0]
if key not in dic:
dic[key] = Dict()
dic[key] = MacroDict()
return _recursively_get_or_create_dict(dic=dic[key], keys=keys[1:])

return _recursively_get_or_create_dict(dic=macros, keys=subsections)
12 changes: 9 additions & 3 deletions omnigibson/object_states/attached_to.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,8 +191,8 @@ def _find_attachment_links(
self,
other,
bypass_alignment_checking=False,
pos_thresh=m.DEFAULT_POSITION_THRESHOLD,
orn_thresh=m.DEFAULT_ORIENTATION_THRESHOLD,
pos_thresh=None,
orn_thresh=None,
):
"""
Args:
Expand All @@ -209,6 +209,10 @@ def _find_attachment_links(
- RigidPrim or None: link belonging to @self.obj that should be aligned to that corresponding link of @other
- RigidPrim or None: the corresponding link of @other
"""
if pos_thresh is None:
pos_thresh = m.DEFAULT_POSITION_THRESHOLD
if orn_thresh is None:
orn_thresh = m.DEFAULT_ORIENTATION_THRESHOLD
parent_candidates = self._get_parent_candidates(other)
if not parent_candidates:
return None, None
Expand Down Expand Up @@ -261,7 +265,7 @@ def attachment_joint_prim_path(self):
f"{self.parent_link.prim_path}/{self.obj.name}_attachment_joint" if self.parent_link is not None else None
)

def _attach(self, other, child_link, parent_link, joint_type=m.DEFAULT_JOINT_TYPE, can_joint_break=True):
def _attach(self, other, child_link, parent_link, joint_type=None, can_joint_break=True):
"""
Creates a fixed or spherical joint between a male meta link of self.obj (@child_link) and a female meta link of
@other (@parent_link) with a given @joint_type, @break_force and @break_torque
Expand All @@ -273,6 +277,8 @@ def _attach(self, other, child_link, parent_link, joint_type=m.DEFAULT_JOINT_TYP
joint_type (JointType): joint type of the attachment, {JointType.JOINT_FIXED, JointType.JOINT_SPHERICAL}
can_joint_break (bool): whether the joint can break or not.
"""
if joint_type is None:
joint_type = m.DEFAULT_JOINT_TYPE
assert joint_type in {JointType.JOINT_FIXED, JointType.JOINT_SPHERICAL}, f"Unsupported joint type {joint_type}"

# Set pose for self.obj so that child_link and parent_link align (6dof alignment for FixedJoint and 3dof alignment for SphericalJoint)
Expand Down
4 changes: 2 additions & 2 deletions omnigibson/object_states/burnt.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@


class Burnt(AbsoluteObjectState, BooleanStateMixin):
def __init__(self, obj, burn_temperature=m.DEFAULT_BURN_TEMPERATURE):
def __init__(self, obj, burn_temperature=None):
super(Burnt, self).__init__(obj)
self.burn_temperature = burn_temperature
self.burn_temperature = burn_temperature if burn_temperature is not None else m.DEFAULT_BURN_TEMPERATURE

@classmethod
def get_dependencies(cls):
Expand Down
4 changes: 2 additions & 2 deletions omnigibson/object_states/cooked.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@


class Cooked(AbsoluteObjectState, BooleanStateMixin):
def __init__(self, obj, cook_temperature=m.DEFAULT_COOK_TEMPERATURE):
def __init__(self, obj, cook_temperature=None):
super(Cooked, self).__init__(obj)
self.cook_temperature = cook_temperature
self.cook_temperature = cook_temperature if cook_temperature is not None else m.DEFAULT_COOK_TEMPERATURE

@classmethod
def get_dependencies(cls):
Expand Down
4 changes: 2 additions & 2 deletions omnigibson/object_states/frozen.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@


class Frozen(AbsoluteObjectState, BooleanStateMixin):
def __init__(self, obj, freeze_temperature=m.DEFAULT_FREEZE_TEMPERATURE):
def __init__(self, obj, freeze_temperature=None):
super(Frozen, self).__init__(obj)
self.freeze_temperature = freeze_temperature
self.freeze_temperature = freeze_temperature if freeze_temperature is not None else m.DEFAULT_FREEZE_TEMPERATURE

@classmethod
def get_dependencies(cls):
Expand Down
12 changes: 6 additions & 6 deletions omnigibson/object_states/heat_source_or_sink.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ class HeatSourceOrSink(AbsoluteObjectState, LinkBasedStateMixin, UpdateStateMixi
def __init__(
self,
obj,
temperature=m.DEFAULT_TEMPERATURE,
heating_rate=m.DEFAULT_HEATING_RATE,
distance_threshold=m.DEFAULT_DISTANCE_THRESHOLD,
temperature=None,
heating_rate=None,
distance_threshold=None,
requires_toggled_on=False,
requires_closed=False,
requires_inside=False,
Expand All @@ -64,9 +64,9 @@ def __init__(
ignored.
"""
super(HeatSourceOrSink, self).__init__(obj)
self._temperature = temperature
self._heating_rate = heating_rate
self.distance_threshold = distance_threshold
self._temperature = temperature if temperature is not None else m.DEFAULT_TEMPERATURE
self._heating_rate = heating_rate if heating_rate is not None else m.DEFAULT_HEATING_RATE
self.distance_threshold = distance_threshold if distance_threshold is not None else m.DEFAULT_DISTANCE_THRESHOLD

# If the heat source needs to be toggled on, we assert the presence
# of that ability.
Expand Down
4 changes: 2 additions & 2 deletions omnigibson/object_states/heated.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@


class Heated(AbsoluteObjectState, BooleanStateMixin):
def __init__(self, obj, heat_temperature=m.DEFAULT_HEAT_TEMPERATURE):
def __init__(self, obj, heat_temperature=None):
super(Heated, self).__init__(obj)
self.heat_temperature = heat_temperature
self.heat_temperature = heat_temperature if heat_temperature is not None else m.DEFAULT_HEAT_TEMPERATURE

@classmethod
def get_dependencies(cls):
Expand Down
14 changes: 10 additions & 4 deletions omnigibson/object_states/on_fire.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ class OnFire(HeatSourceOrSink):
def __init__(
self,
obj,
ignition_temperature=m.DEFAULT_IGNITION_TEMPERATURE,
fire_temperature=m.DEFAULT_FIRE_TEMPERATURE,
heating_rate=m.DEFAULT_HEATING_RATE,
distance_threshold=m.DEFAULT_DISTANCE_THRESHOLD,
ignition_temperature=None,
fire_temperature=None,
heating_rate=None,
distance_threshold=None,
):
"""
Args:
Expand All @@ -40,6 +40,12 @@ def __init__(
distance_threshold (float): The distance threshold which an object needs
to be closer than in order to receive heat from this heat source.
"""
ignition_temperature = (
ignition_temperature if ignition_temperature is not None else m.DEFAULT_IGNITION_TEMPERATURE
)
fire_temperature = fire_temperature if fire_temperature is not None else m.DEFAULT_FIRE_TEMPERATURE
heating_rate = heating_rate if heating_rate is not None else m.DEFAULT_HEATING_RATE
distance_threshold = distance_threshold if distance_threshold is not None else m.DEFAULT_DISTANCE_THRESHOLD
assert fire_temperature > ignition_temperature, "fire temperature should be higher than ignition temperature."

super().__init__(
Expand Down
4 changes: 2 additions & 2 deletions omnigibson/object_states/saturated.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,12 +100,12 @@ def _deserialize(self, state):


class Saturated(RelativeObjectState, BooleanStateMixin):
def __init__(self, obj, default_limit=m.DEFAULT_SATURATION_LIMIT):
def __init__(self, obj, default_limit=None):
# Run super first
super().__init__(obj=obj)

# Limits
self._default_limit = default_limit
self._default_limit = default_limit if default_limit is not None else m.DEFAULT_SATURATION_LIMIT
self._limits = None

def _initialize(self):
Expand Down
13 changes: 4 additions & 9 deletions omnigibson/objects/dataset_object.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,8 @@
import omnigibson.utils.transform_utils as T
from omnigibson.macros import create_module_macros, gm
from omnigibson.objects.usd_object import USDObject
from omnigibson.utils.asset_utils import get_all_object_category_models
from omnigibson.utils.constants import (
AVERAGE_CATEGORY_SPECS,
DEFAULT_JOINT_FRICTION,
SPECIAL_JOINT_FRICTIONS,
JointType,
PrimType,
)
from omnigibson.utils.asset_utils import get_all_object_category_models, get_og_avg_category_specs
from omnigibson.utils.constants import DEFAULT_JOINT_FRICTION, SPECIAL_JOINT_FRICTIONS, JointType, PrimType
from omnigibson.utils.ui_utils import create_module_logger

# Create module logger
Expand Down Expand Up @@ -467,7 +461,8 @@ def avg_obj_dims(self):
Returns:
None or dict: Average object information based on its category
"""
return AVERAGE_CATEGORY_SPECS.get(self.category, None)
avg_specs = get_og_avg_category_specs()
return avg_specs.get(self.category, None)

def _create_prim_with_same_kwargs(self, prim_path, name, load_config):
# Add additional kwargs (bounding_box is already captured in load_config)
Expand Down
6 changes: 3 additions & 3 deletions omnigibson/robots/manipulation_robot.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
m.ARTICULATED_ASSIST_FRACTION = 0.7
m.MIN_ASSIST_FORCE = 0
m.MAX_ASSIST_FORCE = 100
m.ASSIST_FORCE = m.MIN_ASSIST_FORCE + (m.MAX_ASSIST_FORCE - m.MIN_ASSIST_FORCE) * m.ASSIST_FRACTION
m.CONSTRAINT_VIOLATION_THRESHOLD = 0.1
m.RELEASE_WINDOW = 1 / 30.0 # release window in seconds

Expand Down Expand Up @@ -1231,7 +1230,8 @@ def _establish_grasp_rigid(self, arm="default", ag_data=None, contact_pos=None):

# Modify max force based on user-determined assist parameters
# TODO
max_force = m.ASSIST_FORCE if joint_type == "FixedJoint" else m.ASSIST_FORCE * m.ARTICULATED_ASSIST_FRACTION
assist_force = m.MIN_ASSIST_FORCE + (m.MAX_ASSIST_FORCE - m.MIN_ASSIST_FORCE) * m.ASSIST_FRACTION
max_force = assist_force if joint_type == "FixedJoint" else assist_force * m.ARTICULATED_ASSIST_FRACTION
# joint_prim.GetAttribute("physics:breakForce").Set(max_force)

self._ag_obj_constraint_params[arm] = {
Expand Down Expand Up @@ -1406,7 +1406,7 @@ def _establish_grasp_cloth(self, arm="default", ag_data=None):

# Modify max force based on user-determined assist parameters
# TODO
max_force = m.ASSIST_FORCE
max_force = m.MIN_ASSIST_FORCE + (m.MAX_ASSIST_FORCE - m.MIN_ASSIST_FORCE) * m.ASSIST_FRACTION
# joint_prim.GetAttribute("physics:breakForce").Set(max_force)

self._ag_obj_constraint_params[arm] = {
Expand Down
6 changes: 2 additions & 4 deletions omnigibson/scenes/scene_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,6 @@
# Create settings for this module
m = create_module_macros(module_path=__file__)

# Default texture to use for skybox
m.DEFAULT_SKYBOX_TEXTURE = f"{gm.ASSET_PATH}/models/background/sky.jpg"

# Global dicts that will contain mappings
REGISTERED_SCENES = dict()

Expand Down Expand Up @@ -208,7 +205,8 @@ def _load(self):
)
og.sim.import_object(self._skybox, register=False)
self._skybox.color = (1.07, 0.85, 0.61)
self._skybox.texture_file_path = m.DEFAULT_SKYBOX_TEXTURE
# Default texture to use for skybox
self._skybox.texture_file_path = f"{gm.ASSET_PATH}/models/background/sky.jpg"

def _load_objects_from_scene_file(self):
"""
Expand Down
6 changes: 6 additions & 0 deletions omnigibson/simulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ def print_save_usd_warning(_):


def _launch_app():
log.setLevel(logging.DEBUG if gm.DEBUG else logging.INFO)

log.info(f"{'-' * 5} Starting {logo_small()}. This will take 10-30 seconds... {'-' * 5}")

# If multi_gpu is used, og.sim.render() will cause a segfault when called during on_contact callbacks,
Expand Down Expand Up @@ -1467,6 +1469,10 @@ def _deserialize(self, state):
return self._scene.deserialize(state=state), self._scene.state_size

if not og.sim:
from omnigibson.systems.system_base import import_og_systems

# Import all OG systems from dataset
import_og_systems()
og.sim = Simulator(*args, **kwargs)

print()
Expand Down
3 changes: 0 additions & 3 deletions omnigibson/systems/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,3 @@
remove_callback_on_system_clear,
remove_callback_on_system_init,
)

# Import all OG systems from dataset
import_og_systems()
Loading

0 comments on commit 6ac4586

Please sign in to comment.