IsaacSim机器人仿真类封装的模块导入优化方案咨询
问题
我正在使用IsaacSim编写机器人仿真程序,希望将仿真逻辑封装到自定义类中,与其他业务逻辑分离。但IsaacSim的Python API采用扩展机制,要求导入结构如下:
from isaacsim import SimulationApp app = SimulationApp(some_params) # 其他IsaacSim导入 import omni.isaacsim.whatever
所有omni.isaacsim.whatever这类模块必须在SimulationApp实例创建后才能被导入。创建该实例耗时较长(需启动IsaacSim模拟器),且参数需要动态设置。
当前代码结构如下:
class Sim(object): def __init__(self, params): from isaacsim import SimulationApp self.app = SimulationApp(params) import omni.isaacsim.whatever # 其他导入 def some_function(self): # 需要使用omni.XY模块 def other_func(self): # 也需要使用omni.XY模块 if __name__=='__main__': # 确定初始化逻辑和参数 ... sim = Sim(params) # 后续逻辑 sim.some_function() ...
现在需要解决的是如何合理放置omni.XY类的导入,满足以下约束:
- 所有
omni.whatever导入必须在SimulationApp实例创建后执行(理想在Sim.__init__中) - 这些
omni.whatever导入需能被Sim类的所有方法访问 SimulationApp实例仅在需要时创建,即Sim类实例化时
也接受非类结构的方案,但需注意SimulationApp的参数需根据系统其他部分动态设置,无法在模块层面确定;且创建该实例会启动重型模拟器,需控制创建时机,确保其他初始化逻辑先执行,不宜在模块层面创建。
解决方案
方案1:将导入的模块绑定为实例/类属性
在__init__中完成omni模块导入后,将其赋值给实例属性或类属性,让类的所有方法都能直接访问。
实例属性方式(简单直观,适合单实例场景)
class Sim(object): def __init__(self, params): from isaacsim import SimulationApp self.app = SimulationApp(params) # 导入模块并绑定到实例属性 import omni.isaacsim.whatever as whatever import omni.isaacsim.xy as xy self.whatever = whatever self.xy = xy def some_function(self): # 通过self访问导入的模块 self.xy.some_api_call() def other_func(self): self.whatever.another_api_call() if __name__=='__main__': # 先执行其他初始化逻辑,确定参数 params = {"headless": True} # 示例参数 sim = Sim(params) sim.some_function()
类属性方式(适合多实例共享模块引用,避免重复导入)
class Sim(object): # 类属性存储导入的模块,初始为None whatever = None xy = None def __init__(self, params): from isaacsim import SimulationApp self.app = SimulationApp(params) # 仅第一次实例化时导入模块 if Sim.whatever is None: import omni.isaacsim.whatever as whatever import omni.isaacsim.xy as xy Sim.whatever = whatever Sim.xy = xy def some_function(self): # 通过类名访问导入的模块 Sim.xy.some_api_call() def other_func(self): Sim.whatever.another_api_call() if __name__=='__main__': params = {"headless": True} sim = Sim(params) sim.some_function()
方案2:模块级延迟导入(非类结构)
如果不需要类封装,可以用全局变量存储SimulationApp实例和导入的模块,通过函数控制初始化时机。
sim_app = None omni_modules = {} def init_simulation(params): global sim_app, omni_modules from isaacsim import SimulationApp sim_app = SimulationApp(params) # 导入所需模块并存储到全局字典 omni_modules["whatever"] = __import__("omni.isaacsim.whatever", fromlist=[""]) omni_modules["xy"] = __import__("omni.isaacsim.xy", fromlist=[""]) def some_simulation_logic(): omni_modules["xy"].some_api_call() def other_simulation_logic(): omni_modules["whatever"].another_api_call() if __name__=='__main__': # 先执行其他初始化逻辑 params = {"headless": True} init_simulation(params) some_simulation_logic() other_simulation_logic()
方案3:延迟导入装饰器(进阶,防意外遗漏)
编写装饰器确保仿真方法执行前模块已导入,结合实例属性使用,适合复杂场景下的容错处理:
def require_omni_modules(func): def wrapper(self, *args, **kwargs): # 检查模块是否已导入,作为容错机制 if not hasattr(self, "xy"): import omni.isaacsim.xy as xy self.xy = xy if not hasattr(self, "whatever"): import omni.isaacsim.whatever as whatever self.whatever = whatever return func(self, *args, **kwargs) return wrapper class Sim(object): def __init__(self, params): from isaacsim import SimulationApp self.app = SimulationApp(params) import omni.isaacsim.whatever as whatever import omni.isaacsim.xy as xy self.whatever = whatever self.xy = xy @require_omni_modules def some_function(self): self.xy.some_api_call() @require_omni_modules def other_func(self): self.whatever.another_api_call()
内容的提问来源于stack exchange,提问作者Xilef11
相关产品推荐
相关产品推荐

