Isaac Sim 4.5中iRobot Create 3机器人LightBeam传感器系统完整实现教程

首先打开script editor如下图 复制下面这个代码(注意修改相关路径为读者本地的),并运行如下图

js 复制代码
#!/usr/bin/env python3
"""
Isaac Sim 4.5 - 简化版:导入机器人和创建LightBeam传感器
"""

import omni
import omni.kit.commands
from omni.isaac.core.utils.stage import add_reference_to_stage
from omni.isaac.core.utils.extensions import enable_extension
from pxr import Gf, Sdf, UsdLux, UsdPhysics
import os
import asyncio

# ==================== 配置部分 ====================
USERNAME = os.getenv('USER') or 'user'

# 路径配置
ISAAC_ASSETS_BASE = f"/home/{USERNAME}/isaacsim_assets/Assets/Isaac/4.5"
ROBOT_USD_PATH = os.path.join(ISAAC_ASSETS_BASE, "Isaac/Robots/iRobot/create_3_with_arm.usd")
ROBOT_PRIM_PATH = "/World/create3_robot"

# 传感器配置
SENSORS_CONFIG = [
    # 底部高度传感器 - 4个方向
    {
        "name": "front_bottom",
        "relative_position": [0, 0, 0.1],
        "min_range": 0.5,
        "max_range": 8.0,
        "num_rays": 2,
        "curtain_length": 0.05,
        "forward_axis": [1, 0, 0]
    },
    {
        "name": "back_bottom",
        "relative_position": [0, 0, 0.1],
        "min_range": 0.5,
        "max_range": 8.0,
        "num_rays": 2,
        "curtain_length": 0.05,
        "forward_axis": [-1, 0, 0]
    },
    {
        "name": "left_bottom",
        "relative_position": [0, 0, 0.1],
        "min_range": 0.5,
        "max_range": 8.0,
        "num_rays": 2,
        "curtain_length": 0.05,
        "forward_axis": [0, 1, 0]
    },
    {
        "name": "right_bottom",
        "relative_position": [0, 0, 0.1],
        "min_range": 0.5,
        "max_range": 8.0,
        "num_rays": 2,
        "curtain_length": 0.05,
        "forward_axis": [0, -1, 0]
    },
    # 顶部高度传感器 - 4个方向
    {
        "name": "front_top",
        "relative_position": [0, 0, 0.9],
        "min_range": 1,
        "max_range": 8.0,
        "num_rays": 2,
        "curtain_length": 0.05,
        "forward_axis": [1, 0, 0]
    },
    {
        "name": "back_top",
        "relative_position": [0, 0, 0.9],
        "min_range": 0.5,
        "max_range": 8.0,
        "num_rays": 2,
        "curtain_length": 0.05,
        "forward_axis": [-1, 0, 0]
    },
    {
        "name": "left_top",
        "relative_position": [0, 0, 0.9],
        "min_range": 0.5,
        "max_range": 8.0,
        "num_rays": 2,
        "curtain_length": 0.05,
        "forward_axis": [0, 1, 0]
    },
    {
        "name": "right_top",
        "relative_position": [0, 0, 0.9],
        "min_range": 0.5,
        "max_range": 8.0,
        "num_rays": 2,
        "curtain_length": 0.05,
        "forward_axis": [0, -1, 0]
    }
]

print("🤖 开始导入机器人和创建传感器...")

# ==================== 基础设置 ====================
def setup_basic_scene():
    """设置基础场景"""
    print("🔧 设置基础场景...")
    
    stage = omni.usd.get_context().get_stage()
    
    # 创建物理场景
    physics_scene_path = "/World/physicsScene"
    if not stage.GetPrimAtPath(physics_scene_path):
        UsdPhysics.Scene.Define(stage, Sdf.Path(physics_scene_path))
        print("✅ 物理场景创建成功")
    
    # 添加光照
    light_path = "/World/DistantLight"
    if not stage.GetPrimAtPath(light_path):
        distantLight = UsdLux.DistantLight.Define(stage, Sdf.Path(light_path))
        distantLight.CreateIntensityAttr(1000)
        print("✅ 光照创建成功")
    
    return stage

def import_robot():
    """导入机器人模型"""
    print("🤖 导入机器人模型...")
    
    if not os.path.exists(ROBOT_USD_PATH):
        print(f"❌ 机器人文件不存在: {ROBOT_USD_PATH}")
        print("💡 请检查路径配置")
        return False
    
    try:
        add_reference_to_stage(usd_path=ROBOT_USD_PATH, prim_path=ROBOT_PRIM_PATH)
        print(f"✅ 机器人导入成功: {ROBOT_PRIM_PATH}")
        return True
    except Exception as e:
        print(f"❌ 机器人导入失败: {e}")
        return False

def create_lightbeam_sensors():
    """创建所有LightBeam传感器"""
    print("📡 创建LightBeam传感器...")
    
    # 启用传感器扩展
    enable_extension("isaacsim.sensors.physx")
    
    created_sensors = []
    
    for sensor_config in SENSORS_CONFIG:
        sensor_name = sensor_config["name"]
        sensor_path = f"{ROBOT_PRIM_PATH}/sensors/{sensor_name}"
        
        print(f"🔧 创建传感器: {sensor_name}")
        
        try:
            result, sensor = omni.kit.commands.execute(
                "IsaacSensorCreateLightBeamSensor",
                path=sensor_path,
                parent=None,  # 不指定父级,稍后手动连接
                min_range=sensor_config["min_range"],
                max_range=sensor_config["max_range"],
                translation=Gf.Vec3d(
                    sensor_config["relative_position"][0],
                    sensor_config["relative_position"][1],
                    sensor_config["relative_position"][2]
                ),
                orientation=Gf.Quatd(1, 0, 0, 0),
                forward_axis=Gf.Vec3d(
                    sensor_config["forward_axis"][0],
                    sensor_config["forward_axis"][1],
                    sensor_config["forward_axis"][2]
                ),
                num_rays=sensor_config["num_rays"],
                curtain_length=sensor_config["curtain_length"],
            )
            
            if result:
                created_sensors.append(sensor_name)
                print(f"✅ {sensor_name} 传感器创建成功")
            else:
                print(f"❌ {sensor_name} 传感器创建失败")
                
        except Exception as e:
            print(f"❌ {sensor_name} 传感器创建异常: {e}")
    
    print(f"📊 总共创建了 {len(created_sensors)} 个传感器")
    return created_sensors

# ==================== 主要执行函数 ====================
async def main():
    """主要执行函数"""
    try:
        # 1. 设置场景
        stage = setup_basic_scene()
        
        # 2. 导入机器人
        if not import_robot():
            print("❌ 机器人导入失败,停止执行")
            return
        
        # 等待导入完成
        await omni.kit.app.get_app().next_update_async()
        
        # 3. 创建传感器
        created_sensors = create_lightbeam_sensors()
        
        if created_sensors:
            print(f"\n✅ 成功创建 {len(created_sensors)} 个传感器")
            print("📋 创建的传感器列表:")
            for sensor_name in created_sensors:
                sensor_path = f"{ROBOT_PRIM_PATH}/sensors/{sensor_name}"
                print(f"   📡 {sensor_name}: {sensor_path}")
            
            print("\n💡 接下来请您手动:")
            print("1. 在Stage面板中找到机器人和传感器")
            print("2. 为每个传感器创建Fixed Joint连接到机器人")
            print("3. 点击'Play'按钮测试传感器")
        else:
            print("❌ 没有成功创建任何传感器")
        
    except Exception as e:
        print(f"❌ 执行失败: {e}")
        import traceback
        traceback.print_exc()

# 运行主函数
asyncio.ensure_future(main())

print("🚀 脚本开始执行...")

运行后输出如下图

手动加一个地板用于测试,最后删掉地板资源即可

再将下面代码覆盖到script editor中,运行

js 复制代码
#!/usr/bin/env python3
"""
Isaac Sim 4.5 - Action Graph光线可视化脚本
为8个LightBeam传感器创建可视化Action Graph
"""

import omni
import omni.graph.core as og
from omni.isaac.core.utils.extensions import enable_extension
import asyncio

# ==================== 配置部分 ====================
ROBOT_PRIM_PATH = "/World/create3_robot"

# 传感器名称列表
SENSOR_NAMES = [
    "front_bottom", "back_bottom", "left_bottom", "right_bottom",
    "front_top", "back_top", "left_top", "right_top"
]

# 颜色配置 - 不同方向和层级使用不同颜色
COLOR_CONFIG = {
    # 底层传感器 - 深色系
    "front_bottom": [1.0, 0.0, 0.0, 1.0],    # 红色
    "back_bottom": [0.0, 0.0, 1.0, 1.0],     # 蓝色
    "left_bottom": [0.0, 1.0, 0.0, 1.0],     # 绿色
    "right_bottom": [1.0, 1.0, 0.0, 1.0],    # 黄色
    
    # 顶层传感器 - 浅色系
    "front_top": [1.0, 0.5, 0.5, 1.0],       # 浅红色
    "back_top": [0.5, 0.5, 1.0, 1.0],        # 浅蓝色
    "left_top": [0.5, 1.0, 0.5, 1.0],        # 浅绿色
    "right_top": [1.0, 1.0, 0.5, 1.0],       # 浅黄色
}

print("🎨 开始创建Action Graph可视化...")

def enable_required_extensions():
    """启用必要的扩展"""
    print("🔧 启用必要扩展...")
    
    extensions = [
        "isaacsim.sensors.physx",
        "isaacsim.util.debug_draw",
        "omni.graph.action",
        "omni.graph.core"
    ]
    
    for ext in extensions:
        try:
            enable_extension(ext)
            print(f"✅ {ext} 扩展已启用")
        except Exception as e:
            print(f"⚠️ {ext} 扩展启用失败: {e}")

def create_single_sensor_visualization(sensor_name):
    """为单个传感器创建可视化Action Graph"""
    sensor_path = f"{ROBOT_PRIM_PATH}/sensors/{sensor_name}"
    graph_path = f"/ActionGraph_{sensor_name}_Viz"
    
    print(f"🎨 创建 {sensor_name} 的可视化图表...")
    
    # 获取颜色配置
    color = COLOR_CONFIG.get(sensor_name, [1.0, 0.0, 0.0, 1.0])
    
    try:
        # 检查传感器是否存在
        stage = omni.usd.get_context().get_stage()
        if not stage.GetPrimAtPath(sensor_path):
            print(f"❌ 传感器不存在: {sensor_path}")
            return False
        
        # 创建Action Graph
        (action_graph, new_nodes, _, _) = og.Controller.edit(
            {"graph_path": graph_path, "evaluator_name": "execution"},
            {
                og.Controller.Keys.CREATE_NODES: [
                    ("OnPlaybackTick", "omni.graph.action.OnPlaybackTick"),
                    ("IsaacReadLightBeam", "isaacsim.sensors.physx.IsaacReadLightBeam"),
                    ("DebugDrawRayCast", "isaacsim.util.debug_draw.DebugDrawRayCast"),
                ],
                og.Controller.Keys.SET_VALUES: [
                    ("IsaacReadLightBeam.inputs:lightbeamPrim", sensor_path),
                    ("DebugDrawRayCast.inputs:beamWidth", 0.02),  # 光束宽度
                    ("DebugDrawRayCast.inputs:color", color),     # 光束颜色
                ],
                og.Controller.Keys.CONNECT: [
                    ("OnPlaybackTick.outputs:tick", "IsaacReadLightBeam.inputs:execIn"),
                    ("IsaacReadLightBeam.outputs:execOut", "DebugDrawRayCast.inputs:exec"),
                    ("IsaacReadLightBeam.outputs:beamOrigins", "DebugDrawRayCast.inputs:beamOrigins"),
                    ("IsaacReadLightBeam.outputs:beamEndPoints", "DebugDrawRayCast.inputs:beamEndPoints"),
                    ("IsaacReadLightBeam.outputs:numRays", "DebugDrawRayCast.inputs:numRays"),
                ],
            },
        )
        
        print(f"✅ {sensor_name} 可视化图表创建成功")
        return True
        
    except Exception as e:
        print(f"❌ {sensor_name} 可视化图表创建失败: {e}")
        return False

def create_all_visualizations():
    """为所有传感器创建可视化"""
    print("🎨 为所有传感器创建可视化...")
    
    success_count = 0
    
    for sensor_name in SENSOR_NAMES:
        if create_single_sensor_visualization(sensor_name):
            success_count += 1
    
    print(f"📊 成功创建了 {success_count}/{len(SENSOR_NAMES)} 个可视化图表")
    return success_count

def list_created_graphs():
    """列出创建的Action Graph"""
    print("\n📋 创建的Action Graph列表:")
    
    stage = omni.usd.get_context().get_stage()
    
    for sensor_name in SENSOR_NAMES:
        graph_path = f"/ActionGraph_{sensor_name}_Viz"
        color = COLOR_CONFIG.get(sensor_name, [1.0, 0.0, 0.0, 1.0])
        color_desc = f"RGB({color[0]:.1f}, {color[1]:.1f}, {color[2]:.1f})"
        
        if stage.GetPrimAtPath(graph_path):
            print(f"   ✅ {sensor_name}: {graph_path} - {color_desc}")
        else:
            print(f"   ❌ {sensor_name}: 图表未创建")

# ==================== 主要执行函数 ====================
async def main():
    """主要执行函数"""
    try:
        # 1. 启用必要扩展
        enable_required_extensions()
        
        # 等待扩展加载
        await omni.kit.app.get_app().next_update_async()
        
        # 2. 创建所有可视化
        success_count = create_all_visualizations()
        
        # 3. 列出创建结果
        list_created_graphs()
        
        if success_count > 0:
            print(f"\n🎉 Action Graph创建完成!")
            print("📋 颜色说明:")
            print("   🔴 红色系: 前方传感器")
            print("   🔵 蓝色系: 后方传感器") 
            print("   🟢 绿色系: 左侧传感器")
            print("   🟡 黄色系: 右侧传感器")
            print("   🎨 深色: 底层传感器 | 浅色: 顶层传感器")
            print("\n💡 使用说明:")
            print("1. 点击'Play'按钮开始仿真")
            print("2. 观察8条不同颜色的光束线条")
            print("3. 在场景中添加物体测试光束碰撞")
            print("4. 可在Window > Visual Scripting > Action Graph查看图表")
        else:
            print("❌ 没有成功创建任何可视化图表")
            print("💡 请确保:")
            print("   1. 传感器已正确创建")
            print("   2. 机器人路径正确")
            print("   3. 必要扩展已启用")
        
    except Exception as e:
        print(f"❌ 执行失败: {e}")
        import traceback
        traceback.print_exc()

# 运行主函数
asyncio.ensure_future(main())

print("🚀 Action Graph可视化脚本开始执行...")

有些小bug,需要手动修改高度如下图

然后按左侧play键,显示如下图,没有添加关节,所以光线不会跟随机器人,是正常的

然后手动添加关节(避免父子关系错误)如下图

依次把8个传感器都链接如下图,注意ctrl先点baselink再点对应传感器,顺序影响父子关系

然后将下图文件夹移至baselink文件夹中

之后在script editor运行以下代码

js 复制代码
import omni.usd
from pxr import UsdPhysics

def complete_sensor_cleanup():
    """完整清理传感器的物理属性和Joint"""
    stage = omni.usd.get_context().get_stage()
    
    sensor_names = [
        "front_bottom", "back_bottom", "left_bottom", "right_bottom", 
        "front_top", "back_top", "left_top", "right_top"
    ]
    
    base_path = "/World/create3_robot/create_3/base_link"
    
    for sensor_name in sensor_names:
        sensor_path = f"{base_path}/{sensor_name}"
        sensor_prim = stage.GetPrimAtPath(sensor_path)
        
        print(f"🔧 完整清理传感器: {sensor_name}")
        
        if sensor_prim.IsValid():
            # 1. 移除所有物理API
            if sensor_prim.HasAPI(UsdPhysics.RigidBodyAPI):
                sensor_prim.RemoveAPI(UsdPhysics.RigidBodyAPI)
                print(f"   ✅ 移除RigidBodyAPI")
            
            if sensor_prim.HasAPI(UsdPhysics.CollisionAPI):
                sensor_prim.RemoveAPI(UsdPhysics.CollisionAPI)
                print(f"   ✅ 移除CollisionAPI")
                
            if sensor_prim.HasAPI(UsdPhysics.MassAPI):
                sensor_prim.RemoveAPI(UsdPhysics.MassAPI)
                print(f"   ✅ 移除MassAPI")
        
        # 2. 删除FixedJoint
        joint_path = f"{sensor_path}/FixedJoint"
        joint_prim = stage.GetPrimAtPath(joint_path)
        
        if joint_prim.IsValid():
            stage.RemovePrim(joint_path)
            print(f"   🗑️ 删除FixedJoint")
        
        # 3. 验证传感器状态
        if sensor_prim.IsValid():
            print(f"   ✅ {sensor_name} 清理完成")
        else:
            print(f"   ❌ {sensor_name} 不存在")
    
    print("\n🎉 传感器完整清理完成!")
    print("💡 现在传感器通过层级关系连接,无需Joint")

# 运行完整清理
complete_sensor_cleanup()

现在运行效果如下(笔者再次修改了高度后的效果)

然后也可以实时输出每个传感器方向测量的距离,在script editor运行下面代码

js 复制代码
#!/usr/bin/env python3
"""
Isaac Sim 4.5 - LightBeam Sensor Distance Monitor (ASCII Only)
Monitor all sensor distances every 5 seconds - ASCII characters only
"""

import omni
from isaacsim.sensors.physx import _range_sensor
import time
import asyncio
import numpy as np

# ==================== Configuration ====================
ROBOT_PRIM_PATH = "/World/create3_robot"

# Sensor configuration (ASCII only)
SENSORS_CONFIG = [
    {"name": "front_bottom", "layer": "Bottom", "direction": "Front", "symbol": "^"},
    {"name": "back_bottom", "layer": "Bottom", "direction": "Back", "symbol": "v"},
    {"name": "left_bottom", "layer": "Bottom", "direction": "Left", "symbol": "<"},
    {"name": "right_bottom", "layer": "Bottom", "direction": "Right", "symbol": ">"},
    {"name": "front_top", "layer": "Top", "direction": "Front", "symbol": "^"},
    {"name": "back_top", "layer": "Top", "direction": "Back", "symbol": "v"},
    {"name": "left_top", "layer": "Top", "direction": "Left", "symbol": "<"},
    {"name": "right_top", "layer": "Top", "direction": "Right", "symbol": ">"},
]

print("Starting LightBeam Sensor Distance Monitor...")

class LightBeamMonitor:
    def __init__(self):
        self.lightbeam_interface = None
        self.timeline = None
        self.monitoring = False
        self.last_output_time = 0
        self.output_interval = 5.0  # 5 seconds
        
    def initialize(self):
        """Initialize sensor interface"""
        try:
            self.lightbeam_interface = _range_sensor.acquire_lightbeam_sensor_interface()
            self.timeline = omni.timeline.get_timeline_interface()
            print("SUCCESS: Sensor interface initialized")
            return True
        except Exception as e:
            print(f"ERROR: Sensor interface failed - {e}")
            return False
    
    def get_sensor_distance(self, sensor_path):
        """Get distance data from single sensor"""
        try:
            if not self.timeline.is_playing():
                return None, 0, []
            
            # Get sensor data
            linear_depth = self.lightbeam_interface.get_linear_depth_data(sensor_path)
            beam_hit = self.lightbeam_interface.get_beam_hit_data(sensor_path)
            hit_pos = self.lightbeam_interface.get_hit_pos_data(sensor_path)
            
            if linear_depth is not None and len(linear_depth) > 0:
                valid_distances = []
                min_distance = float('inf')
                hit_count = 0
                
                for i in range(len(linear_depth)):
                    if beam_hit[i]:  # If beam hit
                        distance = linear_depth[i]
                        if distance > 0.1:  # Filter invalid data
                            valid_distances.append(distance)
                            min_distance = min(min_distance, distance)
                            hit_count += 1
                
                final_distance = min_distance if min_distance != float('inf') else None
                return final_distance, hit_count, valid_distances
            
            return None, 0, []
            
        except Exception as e:
            return None, 0, []
    
    def get_distance_status(self, distance):
        """Get status based on distance"""
        if distance is None:
            return "NO_DETECT", "[X]", "----"
        elif distance < 1.0:
            return "VERY_CLOSE", "[!]", "CRIT"
        elif distance < 2.0:
            return "CLOSE", "[*]", "WARN"
        elif distance < 4.0:
            return "MEDIUM", "[-]", "NORM"
        elif distance < 6.0:
            return "FAR", "[+]", "SAFE"
        else:
            return "VERY_FAR", "[=]", "DIST"
    
    def format_distance(self, distance):
        """Format distance display"""
        if distance is None:
            return "----m"
        else:
            return f"{distance:.2f}m"
    
    def output_all_sensor_data(self):
        """Output all sensor data"""
        if not self.timeline.is_playing():
            print("PAUSE: Simulation not running, cannot get sensor data")
            return
        
        print("\n" + "="*90)
        print(f"iRobot Create 3 - LightBeam Distance Monitor | {time.strftime('%H:%M:%S')}")
        print("="*90)
        
        # Group by layer
        layers = {"Top": [], "Bottom": []}
        
        for sensor_config in SENSORS_CONFIG:
            sensor_name = sensor_config["name"]
            # Updated sensor path - now under base_link
            sensor_path = f"{ROBOT_PRIM_PATH}/create_3/base_link/{sensor_name}"
            direction = sensor_config["direction"]
            layer = sensor_config["layer"]
            symbol = sensor_config["symbol"]
            
            # Get distance data
            distance, hit_count, all_distances = self.get_sensor_distance(sensor_path)
            status_text, status_icon, status_code = self.get_distance_status(distance)
            distance_text = self.format_distance(distance)
            
            # Build display info
            if hit_count > 1:  # Multiple beams
                avg_distance = np.mean(all_distances) if all_distances else None
                avg_text = self.format_distance(avg_distance)
                info = f"  {symbol} {direction:>5} | {distance_text:>8} (min) | {avg_text:>8} (avg) | {hit_count}rays | {status_code} {status_icon}"
            else:
                info = f"  {symbol} {direction:>5} | {distance_text:>8} | {hit_count}rays | {status_code} {status_icon}"
            
            layers[layer].append(info)
        
        # Output top layer sensors
        print("TOP Layer Sensors (Z = +0.1m):")
        for info in layers["Top"]:
            print(info)
        
        print("")
        
        # Output bottom layer sensors
        print("BOTTOM Layer Sensors (Z = -0.5m):")
        for info in layers["Bottom"]:
            print(info)
        
        # Statistics
        all_distances = []
        total_hits = 0
        active_sensors = 0
        
        for sensor_config in SENSORS_CONFIG:
            sensor_name = sensor_config["name"]
            sensor_path = f"{ROBOT_PRIM_PATH}/create_3/base_link/{sensor_name}"
            distance, hit_count, _ = self.get_sensor_distance(sensor_path)
            if distance is not None:
                all_distances.append(distance)
                active_sensors += 1
            total_hits += hit_count
        
        if all_distances:
            min_dist = min(all_distances)
            max_dist = max(all_distances)
            avg_dist = np.mean(all_distances)
            
            print("")
            print("STATISTICS:")
            print(f"  Closest: {min_dist:.2f}m | Farthest: {max_dist:.2f}m | Average: {avg_dist:.2f}m")
            print(f"  Total hits: {total_hits} | Active sensors: {active_sensors}/8")
            
            # Safety assessment
            if min_dist < 1.0:
                safety = "DANGER - AVOID IMMEDIATELY"
                safety_level = "CRITICAL"
            elif min_dist < 2.0:
                safety = "WARNING - BE CAREFUL"
                safety_level = "WARNING"
            elif min_dist < 4.0:
                safety = "CAUTION - KEEP WATCHING"
                safety_level = "CAUTION"
            else:
                safety = "SAFE - NORMAL OPERATION"
                safety_level = "NORMAL"
            
            print(f"  Safety Status: {safety} ({safety_level})")
            
            # Direction analysis
            direction_analysis = self.analyze_directions(all_distances)
            if direction_analysis:
                print(f"  Direction Advice: {direction_analysis}")
        else:
            print("")
            print("STATISTICS: No obstacles detected")
            print("  Safety Status: SAFE - NO OBSTACLES")
        
        print("="*90)
    
    def analyze_directions(self, distances):
        """Analyze safety in different directions"""
        if not distances:
            return None
        
        min_dist = min(distances)
        if min_dist > 4.0:
            return "Open space - free movement"
        elif min_dist > 2.0:
            return "Reduce speed - proceed carefully"
        else:
            return "STOP or retreat to safe distance"
    
    def start_monitoring(self):
        """Start monitoring"""
        if not self.initialize():
            return
        
        self.monitoring = True
        print("SUCCESS: Monitoring started - Output every 5 seconds")
        print("INFO: Make sure to click 'Play' button to start simulation")
        print("INFO: Press Ctrl+C to stop monitoring")
        print("INFO: Sensor paths updated for cleaned hierarchy structure\n")
        
        # Output immediately
        self.output_all_sensor_data()
        self.last_output_time = time.time()
    
    def update(self):
        """Update monitoring - call in main loop"""
        if not self.monitoring:
            return
        
        current_time = time.time()
        if current_time - self.last_output_time >= self.output_interval:
            self.output_all_sensor_data()
            self.last_output_time = current_time
    
    def stop_monitoring(self):
        """Stop monitoring"""
        self.monitoring = False
        print("\nSTOP: Monitoring stopped")
    
    def set_output_interval(self, seconds):
        """Set output interval"""
        self.output_interval = seconds
        print(f"INFO: Output interval set to {seconds} seconds")

# ==================== Global monitor instance ====================
monitor = LightBeamMonitor()

# ==================== Main execution function ====================
async def main():
    """Main execution function"""
    try:
        # Start monitoring
        monitor.start_monitoring()
        
        # Keep running monitoring
        while monitor.monitoring:
            monitor.update()
            await asyncio.sleep(0.1)  # Avoid high CPU usage
            
    except KeyboardInterrupt:
        print("\nINFO: Stop signal received...")
        monitor.stop_monitoring()
    except Exception as e:
        print(f"ERROR: Monitoring error - {e}")
        monitor.stop_monitoring()

def start_monitoring():
    """Convenient function to start monitoring"""
    asyncio.ensure_future(main())

def stop_monitoring():
    """Convenient function to stop monitoring"""
    monitor.stop_monitoring()

def set_interval(seconds):
    """Convenient function to set monitoring interval"""
    monitor.set_output_interval(seconds)

# Auto start monitoring
start_monitoring()

print("READY: Distance monitoring script started!")
print("INFO: Available commands:")
print("  - stop_monitoring(): Stop monitoring")
print("  - set_interval(seconds): Set output interval")
print("  - start_monitoring(): Restart monitoring")
js 复制代码
stop_monitoring()       #如果需要停止监控,在Script Editor中运行:

笔者添加了一个物体测试输出距离(记得开启物理属性)

不想显示光线将下面几个文件deactivate即可

最后可以调整文件布局为下图baocun

相关推荐
玖剹7 小时前
Linux文件系统:从内核到缓冲区的奥秘
linux·c语言·c++·笔记·ubuntu
跑不了的你8 小时前
Ubuntu 开启wifi 5G 热点
服务器·5g·ubuntu
~狂想家~20 小时前
Ubuntu20.04安装和配置Samba实现Win11下共享文件夹
linux·ubuntu·samba
ansondroider20 小时前
Ubuntu 抽取系统制作便于chroot的镜像文件
linux·ubuntu·chroot
努力一点94821 小时前
ubuntu22.04系统入门 linux入门 简单命令基础复习 实现以及实践
linux·运维·服务器·ubuntu·gpu算力
笑稀了的野生俊1 天前
Ubuntu 下配置 NVIDIA 驱动与 CUDA 环境(适配 RTX 4060Ti)
linux·ubuntu·cuda·nvidia driver
没有余地 EliasJie1 天前
Ubuntu/Debian 搭建 Nginx RTMP 服务器全攻略
服务器·ubuntu·debian
三雷科技1 天前
window中qemu使用(安装ubuntu系统)
linux·运维·ubuntu
一匹电信狗1 天前
【Linux我做主】进程优先级
linux·运维·服务器·c++·ubuntu·小程序·unix
leafpipi2 天前
【机器学习】pycharm使用SSH SFTP 远程连接 ubuntu服务器 进行开发+调试+数据训练
服务器·学习·算法·ubuntu·pycharm·ssh