[Bug Report] Inconsistent attribute ordering in InteractiveSceneCfg When type hints are used on some entities
Describe the bug
I encountered an issue with InteractiveSceneCfg where the order of attributes in the configuration does not always follow the expected order when type hints are used only on some attributes, but not on others.
The documentation explicitly states that the order of entities in the scene configuration is crucial:
The adding of entities to the scene is sensitive to the order of the attributes in the configuration.
However, when type hints are applied selectively (i.e., only to some entities but not others), the order of attributes in scene_cfg.__dict__.keys() deviates from the expected declaration order.
Steps to reproduce
Example 1: No Type Hints
@configclass
class SceneCfg(InteractiveSceneCfg):
plane = AssetBaseCfg(...)
robot = ArticulationCfg(...)
peg = ArticulationCfg(...)
hole = ArticulationCfg(...)
camera = TiledCameraCfg(...)
light = AssetBaseCfg(...)
scene_cfg = SceneCfg(num_envs=4, env_spacing=2)
print(scene_cfg.__dict__.keys())
Output (Expected Order)
dict_keys(['num_envs', 'env_spacing', 'lazy_sensor_update', 'replicate_physics', 'filter_collisions', 'plane', 'robot', 'peg', 'hole', 'camera', 'light'])
Example 2: Type Hints on Some Entities (Unexpected Behavior)
@configclass
class SceneCfg(InteractiveSceneCfg):
plane = AssetBaseCfg(...)
robot = ArticulationCfg(...)
peg: ArticulationCfg = ArticulationCfg(...)
hole: ArticulationCfg = ArticulationCfg(...)
camera = TiledCameraCfg(...)
light = AssetBaseCfg(...)
scene_cfg = SceneCfg(num_envs=4, env_spacing=2)
print(scene_cfg.__dict__.keys())
Output
dict_keys(['num_envs', 'env_spacing', 'lazy_sensor_update', 'replicate_physics', 'filter_collisions', 'peg', 'hole', 'plane', 'robot', 'camera', 'light'])
System Info
Describe the characteristic of your environment:
- Commit: f1a4975
- Isaac Sim Version: 4.5.0
- OS: Ubuntu 22.04
- GPU: RTX 3080
- CUDA: 11.8
- GPU Driver: 535.183.01
Additional context
This issue is seems related to #1743 ,as both involve unintended attribute ordering behavior.
Checklist
- [x] I have checked that there is no similar issue in the repo (required)
- [x] I have checked that the issue is not in running Isaac Sim itself and is related to the repo
Thanks for posting this. We will review and follow up on this.
hello @right-chan thanks for reporting this.
Does the response in #1743 address this problem?
There's a workaround using field and default_factory that maintains the attribute ordering.
Or, type hints can be added to all attributes to maintain ordering, perhaps using None or some new stand-in class.
Thanks for the suggestions!
I tried using field(default_factory=...) for all attributes as shown below:
@configclass
class SceneCfg(InteractiveSceneCfg):
plane = field(
default_factory=lambda: AssetBaseCfg(...)
)
robot = field(
default_factory=lambda: ArticulationCfg(...)
)
peg: ArticulationCfg= field(
default_factory=lambda: ArticulationCfg(...)
)
hole: ArticulationCfg = field(
default_factory=lambda: ArticulationCfg(...)
)
camera = field(
default_factory=lambda: TiledCameraCfg(...)
)
light = field(
default_factory=lambda: AssetBaseCfg(...)
)
scene_cfg = SceneCfg(num_envs=4, env_spacing=2)
print(scene_cfg.__dict__.keys())
dict_keys(['num_envs', 'env_spacing', 'lazy_sensor_update', 'replicate_physics', 'filter_collisions', 'peg', 'hole', 'plane', 'robot', 'camera', 'light'])
However, even with this change, the order of attributes in __dict__ is still not preserved as expected in InteractiveSceneCfg.
Also, using field(default_factory=...) for every attribute makes the code a bit verbose and harder to maintain, especially when dealing with many attributes.
For this reason, I think it would be more practical to recommend adding type hints consistently to all attributes as a standard workaround.
Additionally, after looking into the source code, I found that this behavior occurs because of the following line:
https://github.com/isaac-sim/IsaacLab/blob/7de6d6fef9424c95fc68dc767af67ffbe0da6832/source/isaaclab/isaaclab/utils/configclass.py#L206-L209
This line inserts the annotated fields into the hints dictionary before iterating through the class body (base.__dict__),
so all fields with type annotations are added first, regardless of their position in the source code.
This explains why type-annotated attributes always appear before non-annotated ones in the final ordering.