From 7a9e754be61aadfd9ba9cfcfed04f6175d81c805 Mon Sep 17 00:00:00 2001 From: liuao08 <2496556459@qq.com> Date: Tue, 17 Mar 2026 18:13:38 +0800 Subject: [PATCH 1/6] =?UTF-8?q?=E5=AE=9E=E7=8E=B0V2X=E4=BF=A1=E6=81=AF?= =?UTF-8?q?=E6=94=B6=E5=8F=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../collect_intersection_camera_lidar.py | 239 ++++++++++++++---- 1 file changed, 183 insertions(+), 56 deletions(-) diff --git a/waypoint_control/multi_obj_track/collect_intersection_camera_lidar.py b/waypoint_control/multi_obj_track/collect_intersection_camera_lidar.py index 1b25d06..50f8f25 100644 --- a/waypoint_control/multi_obj_track/collect_intersection_camera_lidar.py +++ b/waypoint_control/multi_obj_track/collect_intersection_camera_lidar.py @@ -21,6 +21,9 @@ import argparse import json import subprocess +import pickle +import struct +from ultralytics import YOLO from queue import Queue from queue import Empty from scipy.spatial.transform import Rotation as R @@ -31,6 +34,7 @@ WAITE_NEXT_INTERSECTION_TIME = 300 # 等待一定时间后第二路口相机雷达开始记录数据 # 定义全局变量 global_time = 0.0 +base_frame = None relativePose_to_egoVehicle = { "back_camera": [-7.00, 0.00, 2.62, -180.00, 0.00, 0.00], # 1 @@ -288,40 +292,39 @@ def dist(actor): return all_labels -def send_v2x_message_lidar(lidar_data, sensor): - """ - 不进行任何降采样,直接将完整激光雷达帧发送出去 - """ - # # 提取点云数据 (使用 Numpy 安全读取底层内存) - # points = np.frombuffer(lidar_data.raw_data, dtype=np.dtype('f4')) - # - # # 把点云字节流转换成十六进制字符串 (hex string) - # payload_hex_str = points.tobytes().hex() - # - # # 组装接收端期望的字典结构 - # v2x_msg_dict = { - # "Message": { - # "Header": { - # "Station ID": "5", - # "Msg Type": "LiDAR_PointCloud" - # }, - # "Message": { - # "Bytes": payload_hex_str # 这里存的是十六进制长字符串 - # } - # } - # } - # - # # 将字典转换为 JSON 文本字符串 (这就对应你代码里的 text) - # text = json.dumps(v2x_msg_dict) - - # 【测试代码】:只发送一个极短的文本 - text = '{"Message": {"Header": {"Station ID": 1001}, "Message": {"Bytes": "Hello"}}}' - - # 使用底层 API 进行打包和发送! - msg = carla.CustomV2XBytes() - msg.set_bytes(bytearray(text, 'utf-8')) - # 触发 V2X 发送 - sensor.send(msg) +def send_v2x_message_lidar(lidar_data, sensor, pkl_file_path, junc): + try: + # 1. 读取 pkl 文件获取帧 ID + with open(pkl_file_path, 'rb') as f: + data = pickle.load(f) + + if isinstance(data, list): + data = data[0] + + # 获取 frame_id 并转为字符串 (如果没有则默认为 "0") + frame_id = str(data.get('frame_id', '0')) + + # 2. 获取当前时间戳 (保留4位小数即可) + current_time = f"{time.time():.4f}" + + # 3. 拼接成最简单的纯文本字符串,用逗号隔开 + # 结果类似: "000001,1710660000.1234" + text_payload = f"{frame_id},{current_time},{junc},点云数据" + + # 4. 没有任何多余操作,直接按照您要求的 utf-8 格式转换并发送! + msg = carla.CustomV2XBytes() + msg.set_bytes(bytearray(text_payload, 'utf-8')) + sensor.send(msg) + + print(f"[V2X] 极简发送成功!") + print(f"发送的内容: '{text_payload}'") + print(f"占用字节数: {len(text_payload.encode('utf-8'))} 字节") + + except Exception as e: + import traceback + traceback.print_exc() + print(f"[发包报错]: {e}") + # 定义函数来保存雷达点云数据 def save_radar_data(radar_data, world, ego_vehicle_transform, actual_vehicle_num, actual_pedestrian_num,lidar_to_world_inv, all_vehicle_labels, all_pedestrian_labels, junc, town_folder, file_num, sensors): @@ -336,7 +339,8 @@ def save_radar_data(radar_data, world, ego_vehicle_transform, actual_vehicle_num all_labels = save_point_label(world, location, lidar_to_world_inv, timestamp, all_vehicle_labels, all_pedestrian_labels) sensor = sensors["v2x_point"] - send_v2x_message_lidar(radar_data, sensor) + pkl_file_path = "/home/yons/traffic_twin/waypoint_control/multi_obj_track/OpenPCDet/output/cfgs/custom_models/pv_rcnn/default/pv_rcnn/default/eval/epoch_no_number/val/default/result.pkl" + send_v2x_message_lidar(radar_data, sensor, pkl_file_path, junc) # 获取雷达数据并将其转化为numpy数组 points = np.frombuffer(radar_data.raw_data, dtype=np.dtype('f4')) points = np.reshape(points, (len(points) // 4, 4)) @@ -450,7 +454,7 @@ def dist(actor): radar_folder = create_radar_folder_py(town_folder, junc) np.save(os.path.join(radar_folder, f"{file_num}.npy"), datalogpy) # 保存备份用于目标检测 - target_dir = "OpenPCDet/data/custom/points" + target_dir = "/home/yons/traffic_twin/waypoint_control/multi_obj_track/OpenPCDet/data/custom/points" clear_folder_contents(target_dir) np.save(os.path.join(target_dir, f"{file_num}.npy"), datalogpy) # 2. 保存 label 为 .txt @@ -473,7 +477,7 @@ def dist(actor): f.write(str(all_labels)) # 保存备份用于目标检测 - goal_dir = "OpenPCDet/data/custom/labels" + goal_dir = "/home/yons/traffic_twin/waypoint_control/multi_obj_track/OpenPCDet/data/custom/labels" clear_folder_contents(goal_dir) with open(os.path.join(goal_dir, f"{file_num}.txt"), 'w') as f: # 处理不同的数据结构 @@ -495,8 +499,8 @@ def dist(actor): with open("num.txt", 'a') as f: # 'a' 表示追加模式 f.write(str(file_num) + "\n") # 添加换行符 # 保存备份用于目标检测 - dir_train = "OpenPCDet/data/custom/ImageSets/train.txt" - dir_val = "OpenPCDet/data/custom/ImageSets/val.txt" + dir_train = "/home/yons/traffic_twin/waypoint_control/multi_obj_track/OpenPCDet/data/custom/ImageSets/train.txt" + dir_val = "/home/yons/traffic_twin/waypoint_control/multi_obj_track/OpenPCDet/data/custom/ImageSets/val.txt" with open(dir_train, 'w') as f: f.write(str(file_num) + "\n") # 添加换行符 with open(dir_val, 'w') as f: @@ -528,13 +532,48 @@ def clear_folder_contents(folder_path): print(f"文件夹内容已清空: {folder_path}") - # 定义函数来保存相机图像数据 -def save_camera_data(image_data, camera_id, junc, town_folder): +def save_camera_data(image_data, camera_id, junc, town_folder, model, sensors): + global base_frame current_frame = image_data.frame + # 如果是第一帧,就把它的 ID 存为基数 + if base_frame is None: + base_frame = current_frame + print(f"收到第一帧数据!将原始帧 ID {base_frame} 设置为基数 0。") + # 计算重置后的当前帧 + normalized_frame = current_frame - base_frame + frame_str = f"{normalized_frame:06d}" + image = np.array(image_data.raw_data) image = image.reshape((image_data.height, image_data.width, 4)) # 4th channel is alpha image = image[:, :, :3] # 去掉 alpha 通道,只保留 RGB + # 使用yolov8检测图片 + results = model.predict(source=image, stream=True) + for r in results: + # 获取检测框、置信度和类别 + boxes = r.boxes + for box in boxes: + # 获取坐标 (x1, y1, x2, y2) + b = box.xyxy[0].tolist() + cls = int(box.cls[0]) + conf = float(box.conf[0]) + print(f"检测到: {model.names[cls]}, 置信度: {conf:.2f}") + + if camera_id == "back_camera": + sensor = sensors["v2x_back"] + elif camera_id == "front_camera": + sensor = sensors["v2x_front"] + elif camera_id == "right_camera": + sensor = sensors["v2x_front_left"] + elif camera_id == "front_right_camera": + sensor = sensors["v2x_front_right"] + elif camera_id == "left_camera": + sensor = sensors["v2x_left"] + elif camera_id == "front_left_camera": + sensor = sensors["v2x_right"] + + send_v2x_message_camera(sensor, junc, frame_str) + camera_folder = create_camera_folder(camera_id, junc, town_folder) file_name = os.path.join(camera_folder, f"{current_frame}.jpg") try: @@ -545,6 +584,29 @@ def save_camera_data(image_data, camera_id, junc, town_folder): return image +def send_v2x_message_camera(sensor, junc, frame_id): + try: + # 获取当前时间戳 (保留4位小数即可) + current_time = f"{time.time():.4f}" + + # 拼接成最简单的纯文本字符串,用逗号隔开 + # 结果类似: "000001,1710660000.1234" + text_payload = f"{frame_id},{current_time},{junc},图片数据" + + # 4. 没有任何多余操作,直接按照您要求的 utf-8 格式转换并发送! + msg = carla.CustomV2XBytes() + msg.set_bytes(bytearray(text_payload, 'utf-8')) + sensor.send(msg) + + print(f"[V2X] 极简发送成功!") + print(f"发送的内容: '{text_payload}'") + print(f"占用字节数: {len(text_payload.encode('utf-8'))} 字节") + + except Exception as e: + import traceback + traceback.print_exc() + print(f"❌ [发包报错]: {e}") + def sensor_callback(sensor_data, sensor_queue, sensor_name): sensor_queue.put((sensor_data, sensor_name)) @@ -713,15 +775,17 @@ def spawn_autonomous_pedestrians(world, num_pedestrians=100, random_seed=20): return pedestrian_list - -def spawn_v2x_sensors(world, lidar_transform, z_height=2.62): +def spawn_v2x_sensors(world, lidar_transform, z_height=2.57): sensors = {} # 字典 # 用字典直接给坐标命名,明确区分 coordinates = { - "v2x_left": (3.0, 4.0), - "v2x_right": (3.0, -4.0), - "v2x_center": (1.0, 0.0), + "v2x_back": (-7.0, 0.0), + "v2x_front": (7.0, 0.0), + "v2x_front_left": (7.0, 4.0), + "v2x_front_right": (7.0, -4.0), + "v2x_left": (0.0, 4.0), + "v2x_right": (0.0, -4.0), "v2x_point": (0.5, 0.5) } @@ -737,12 +801,15 @@ def spawn_v2x_sensors(world, lidar_transform, z_height=2.62): # 生成V2X传感器 sensor = world.spawn_actor(bp, transform) # 激活传感器 - sensor.listen(lambda data: _on_v2x_received(data)) + sensor.listen(lambda data: do_nothing(data)) # 将生成的传感器以名字存入字典 sensors[name] = sensor return sensors +def do_nothing(data): + pass + def spawn_v2x_receiver(world): location = carla.Location(x=0, y=0, z=2.62) transform = carla.Transform(location, carla.Rotation(yaw=0)) @@ -757,14 +824,66 @@ def spawn_v2x_receiver(world): return receiver -def _on_v2x_received(sensor_data): - print(f"收到消息") - for data in sensor_data: - msg_dict = data.get() - raw_bytes = msg_dict["Message"]["Message"]["Bytes"] - content = raw_bytes.decode('utf-8', errors='ignore') - print(f" [接收端] 收到消息 ") +def _on_v2x_received(event): + """ + 接收端回调函数:将所有帧的数据保存在同一个文件夹下的独立 txt 中 + """ + if event.get_message_count() == 0: + return + for i, custom_data in enumerate(event): + try: + # 1. 获取底层数据 + parsed_data = custom_data.get() + text_payload = "" + + # 2. 智能提取文本内容 + if isinstance(parsed_data, dict): + payload = parsed_data.get("Message", {}).get("Message", {}).get("Bytes", "") + if isinstance(payload, (bytes, bytearray)): + text_payload = payload.decode('utf-8') + elif isinstance(payload, str): + text_payload = payload + elif isinstance(parsed_data, (bytes, bytearray)): + text_payload = parsed_data.decode('utf-8') + elif isinstance(parsed_data, str): + text_payload = parsed_data + else: + continue + + # 3. 解析逗号分隔的 "帧ID,发送时间" + if ',' not in text_payload: + continue + + frame_id_str, send_time_str, JUNC_ID, data_type = text_payload.split(',') + frame_id = int(frame_id_str) + send_time = float(send_time_str) + + # 4. 计算当前延迟 + receive_time = time.time() + latency_ms = (receive_time - send_time) * 1000 + + print(f"✅ [V2X 接收] 帧 ID: {frame_id:06d} | 延迟: {latency_ms:.2f} ms") + + # 核心保存逻辑:扁平化保存,按帧号命名 txt + # 直接在总文件夹下生成对应的 txt 文件路径 + BASE_SAVE_DIR = "./v2x_latency_logs" + txt_file_path = os.path.join(BASE_SAVE_DIR, f"frame_{frame_id:06d}.txt") + + # 追加写入模式 'a':如果该帧的 txt 文件不存在,会自动创建; + # 如果已经存在(即收到了同一帧其他车辆发来的数据),则会在下一行继续写入。 + with open(txt_file_path, "a", encoding="utf-8") as f: + log_line = (f"路口号: {JUNC_ID}, " + f"发送时间: {send_time:.6f}, " + f"接收时间: {receive_time:.6f}, " + f"延迟(ms): {latency_ms:.2f}, " + f"数据类型: {data_type}\n") + f.write(log_line) + + except ValueError: + pass + except Exception as e: + print(f"❌ [解析与保存报错]: {e}") def destroy_actor(lidar, camera_dict, vehicles, sensor_queue, pedestrians): if lidar is not None: lidar.stop() # 确保停止传感器线程 @@ -834,7 +953,7 @@ def run_shell_script(): # 定义脚本的绝对路径 script_path = "/home/yons/object_detection.sh" - # 定义工作目录(脚本在哪里运行很重要!) + # 定义工作目录 work_dir = "/mnt/mydrive/traffic_twin/waypoint_control/multi_obj_track" print("开始执行 Shell 脚本...") try: @@ -936,6 +1055,10 @@ def main(): 'points_per_second': '4000000', 'rotation_frequency': '20' } + + # 加载yolo模型 + model = YOLO('yolov8n.pt') + try: # 设置随机种子 random_seed = 20 @@ -978,6 +1101,10 @@ def main(): sensors = spawn_v2x_sensors(world, lidar_transform, z_height=2.62) # 生成并启动V2X数据收集端 receiver = spawn_v2x_receiver(world) + # 定义保存数据的唯一总文件夹 + BASE_SAVE_DIR = "./v2x_latency_logs" + # 在程序启动时,确保总文件夹存在(如果不存在则创建) + os.makedirs(BASE_SAVE_DIR, exist_ok=True) actual_vehicle_num = [] actual_pedestrian_num = [] all_vehicle_labels = [] @@ -1019,7 +1146,7 @@ def main(): if "lidar" in sensor_name: # lidar数据 save_radar_data(data, world, ego_transform, actual_vehicle_num, actual_pedestrian_num, lidar_to_world_inv, all_vehicle_labels, all_pedestrian_labels, junc, town_folder, file_num, sensors) else: - save_camera_data(data, sensor_name, junc, town_folder) + save_camera_data(data, sensor_name, junc, town_folder, model, sensors) # time.sleep(0.05) folder_index += 1 From 55b6048a5d1250e4cdf1c352eda9514d788a33a3 Mon Sep 17 00:00:00 2001 From: liuao08 <2496556459@qq.com> Date: Wed, 18 Mar 2026 17:45:34 +0800 Subject: [PATCH 2/6] =?UTF-8?q?=E5=B0=86openpcdet=E8=BF=90=E8=A1=8C?= =?UTF-8?q?=E6=97=B6=E9=97=B4=E6=8E=92=E9=99=A4=E5=9C=A8=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E4=BC=A0=E8=BE=93=E6=97=B6=E9=97=B4=E4=B9=8B=E5=A4=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../collect_intersection_camera_lidar.py | 49 ++++++++++++++----- 1 file changed, 36 insertions(+), 13 deletions(-) diff --git a/waypoint_control/multi_obj_track/collect_intersection_camera_lidar.py b/waypoint_control/multi_obj_track/collect_intersection_camera_lidar.py index 50f8f25..753d492 100644 --- a/waypoint_control/multi_obj_track/collect_intersection_camera_lidar.py +++ b/waypoint_control/multi_obj_track/collect_intersection_camera_lidar.py @@ -35,6 +35,8 @@ # 定义全局变量 global_time = 0.0 base_frame = None +# openpcdet进行目标识别所用时间 +extra_time = 0 relativePose_to_egoVehicle = { "back_camera": [-7.00, 0.00, 2.62, -180.00, 0.00, 0.00], # 1 @@ -305,7 +307,8 @@ def send_v2x_message_lidar(lidar_data, sensor, pkl_file_path, junc): frame_id = str(data.get('frame_id', '0')) # 2. 获取当前时间戳 (保留4位小数即可) - current_time = f"{time.time():.4f}" + + current_time = f"{time.time() - extra_time:.4f}" # 3. 拼接成最简单的纯文本字符串,用逗号隔开 # 结果类似: "000001,1710660000.1234" @@ -327,7 +330,7 @@ def send_v2x_message_lidar(lidar_data, sensor, pkl_file_path, junc): # 定义函数来保存雷达点云数据 -def save_radar_data(radar_data, world, ego_vehicle_transform, actual_vehicle_num, actual_pedestrian_num,lidar_to_world_inv, all_vehicle_labels, all_pedestrian_labels, junc, town_folder, file_num, sensors): +def save_radar_data(radar_data, world, ego_vehicle_transform, actual_vehicle_num, actual_pedestrian_num,lidar_to_world_inv, all_vehicle_labels, all_pedestrian_labels, junc, town_folder, file_num, sensors, num): global global_time # 获取当前帧编号 current_frame = radar_data.frame @@ -338,9 +341,9 @@ def save_radar_data(radar_data, world, ego_vehicle_transform, actual_vehicle_num location = ego_vehicle_transform.location all_labels = save_point_label(world, location, lidar_to_world_inv, timestamp, all_vehicle_labels, all_pedestrian_labels) - sensor = sensors["v2x_point"] - pkl_file_path = "/home/yons/traffic_twin/waypoint_control/multi_obj_track/OpenPCDet/output/cfgs/custom_models/pv_rcnn/default/pv_rcnn/default/eval/epoch_no_number/val/default/result.pkl" - send_v2x_message_lidar(radar_data, sensor, pkl_file_path, junc) + # sensor = sensors["v2x_point"] + # pkl_file_path = "/home/yons/traffic_twin/waypoint_control/multi_obj_track/OpenPCDet/output/cfgs/custom_models/pv_rcnn/default/pv_rcnn/default/eval/epoch_no_number/val/default/result.pkl" + # send_v2x_message_lidar(radar_data, sensor, pkl_file_path, junc) # 获取雷达数据并将其转化为numpy数组 points = np.frombuffer(radar_data.raw_data, dtype=np.dtype('f4')) points = np.reshape(points, (len(points) // 4, 4)) @@ -506,8 +509,14 @@ def dist(actor): with open(dir_val, 'w') as f: f.write(str(file_num) + "\n") # 添加换行符 - # 运行自动化目标检测脚本 - run_shell_script() + # # 运行自动化目标检测脚本 + # duration = run_shell_script() + # global extra_time + # extra_time += duration + + sensor = sensors["v2x_point"] + pkl_file_path = "/home/yons/traffic_twin/waypoint_control/multi_obj_track/OpenPCDet/output/cfgs/custom_models/pv_rcnn/default/pv_rcnn/default/eval/epoch_no_number/val/default/result.pkl" + send_v2x_message_lidar(radar_data, sensor, pkl_file_path, junc) # 更新目标检测的文件夹 def clear_folder_contents(folder_path): @@ -533,7 +542,7 @@ def clear_folder_contents(folder_path): print(f"文件夹内容已清空: {folder_path}") # 定义函数来保存相机图像数据 -def save_camera_data(image_data, camera_id, junc, town_folder, model, sensors): +def save_camera_data(image_data, camera_id, junc, town_folder, model, sensors, num): global base_frame current_frame = image_data.frame # 如果是第一帧,就把它的 ID 存为基数 @@ -587,7 +596,7 @@ def save_camera_data(image_data, camera_id, junc, town_folder, model, sensors): def send_v2x_message_camera(sensor, junc, frame_id): try: # 获取当前时间戳 (保留4位小数即可) - current_time = f"{time.time():.4f}" + current_time = f"{time.time() - extra_time:.4f}" # 拼接成最简单的纯文本字符串,用逗号隔开 # 结果类似: "000001,1710660000.1234" @@ -860,7 +869,7 @@ def _on_v2x_received(event): send_time = float(send_time_str) # 4. 计算当前延迟 - receive_time = time.time() + receive_time = time.time() - extra_time latency_ms = (receive_time - send_time) * 1000 print(f"✅ [V2X 接收] 帧 ID: {frame_id:06d} | 延迟: {latency_ms:.2f} ms") @@ -956,6 +965,8 @@ def run_shell_script(): # 定义工作目录 work_dir = "/mnt/mydrive/traffic_twin/waypoint_control/multi_obj_track" print("开始执行 Shell 脚本...") + # 记录开始时间 (高精度) + start_time = time.time() try: # 使用 subprocess.run 执行脚本 # cwd=work_dir 确保脚本是在 OpenPCDet 根目录下运行的 @@ -970,6 +981,11 @@ def run_shell_script(): print("✅ 脚本执行成功!输出如下:") print(result.stdout) + # 记录结束时间 + end_time = time.time() + # 计算耗时 + duration = end_time - start_time + return duration except subprocess.CalledProcessError as e: print("❌ 脚本执行失败!") @@ -1011,7 +1027,7 @@ def main(): argparser.add_argument( '-i', '--intersection', metavar='INTERSECTION', - default='road_intersection_5', # 默认路口 + default='road_intersection_2', # 默认路口 help='Name of the intersection within the town (default: road_intersection_1)' ) args = argparser.parse_args() @@ -1112,8 +1128,11 @@ def main(): vehicles_traj = {} pedestrians_traj = {} folder_index = 0 + # 设置变量 + num = 0 for _ in range(DATA_MUN): world.tick() + num += 1 actor_list_vehicle = world.get_actors().filter('vehicle.*') for actor in actor_list_vehicle: vehicle_id = actor.id @@ -1141,12 +1160,16 @@ def main(): pedestrians_traj[pedestrian_id].append([x, y, z]) # 同步保存多传感器数据 file_num = f"{folder_index:06d}" + # 运行自动化目标检测脚本 + duration = run_shell_script() + global extra_time + extra_time += duration for _ in range(1 + len(camera_dict)): data, sensor_name = sensor_queue.get(True, 1.0) if "lidar" in sensor_name: # lidar数据 - save_radar_data(data, world, ego_transform, actual_vehicle_num, actual_pedestrian_num, lidar_to_world_inv, all_vehicle_labels, all_pedestrian_labels, junc, town_folder, file_num, sensors) + save_radar_data(data, world, ego_transform, actual_vehicle_num, actual_pedestrian_num, lidar_to_world_inv, all_vehicle_labels, all_pedestrian_labels, junc, town_folder, file_num, sensors, num) else: - save_camera_data(data, sensor_name, junc, town_folder, model, sensors) + save_camera_data(data, sensor_name, junc, town_folder, model, sensors, num) # time.sleep(0.05) folder_index += 1 From c42ddd5877e28fa35a11ff0a423d4d998fe908bc Mon Sep 17 00:00:00 2001 From: liuao08 <2496556459@qq.com> Date: Thu, 19 Mar 2026 18:21:09 +0800 Subject: [PATCH 3/6] =?UTF-8?q?=E8=AE=A1=E7=AE=97=E6=80=BB=E4=BC=A0?= =?UTF-8?q?=E8=BE=93=E6=97=B6=E9=97=B4=E5=B9=B6=E5=89=94=E9=99=A4=E4=B8=8D?= =?UTF-8?q?=E5=AE=8C=E6=95=B4=E7=9A=84=E5=B8=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../collect_intersection_camera_lidar.py | 18 +-- .../multi_obj_track/process_v2x_data.py | 138 ++++++++++++++++++ 2 files changed, 147 insertions(+), 9 deletions(-) create mode 100644 waypoint_control/multi_obj_track/process_v2x_data.py diff --git a/waypoint_control/multi_obj_track/collect_intersection_camera_lidar.py b/waypoint_control/multi_obj_track/collect_intersection_camera_lidar.py index 753d492..ba27066 100644 --- a/waypoint_control/multi_obj_track/collect_intersection_camera_lidar.py +++ b/waypoint_control/multi_obj_track/collect_intersection_camera_lidar.py @@ -509,10 +509,10 @@ def dist(actor): with open(dir_val, 'w') as f: f.write(str(file_num) + "\n") # 添加换行符 - # # 运行自动化目标检测脚本 - # duration = run_shell_script() - # global extra_time - # extra_time += duration + # 运行自动化目标检测脚本 + duration = run_shell_script() + global extra_time + extra_time += duration sensor = sensors["v2x_point"] pkl_file_path = "/home/yons/traffic_twin/waypoint_control/multi_obj_track/OpenPCDet/output/cfgs/custom_models/pv_rcnn/default/pv_rcnn/default/eval/epoch_no_number/val/default/result.pkl" @@ -1027,7 +1027,7 @@ def main(): argparser.add_argument( '-i', '--intersection', metavar='INTERSECTION', - default='road_intersection_2', # 默认路口 + default='road_intersection_1', # 默认路口 help='Name of the intersection within the town (default: road_intersection_1)' ) args = argparser.parse_args() @@ -1160,10 +1160,10 @@ def main(): pedestrians_traj[pedestrian_id].append([x, y, z]) # 同步保存多传感器数据 file_num = f"{folder_index:06d}" - # 运行自动化目标检测脚本 - duration = run_shell_script() - global extra_time - extra_time += duration + # # 运行自动化目标检测脚本 + # duration = run_shell_script() + # global extra_time + # extra_time += duration for _ in range(1 + len(camera_dict)): data, sensor_name = sensor_queue.get(True, 1.0) if "lidar" in sensor_name: # lidar数据 diff --git a/waypoint_control/multi_obj_track/process_v2x_data.py b/waypoint_control/multi_obj_track/process_v2x_data.py new file mode 100644 index 0000000..bbae104 --- /dev/null +++ b/waypoint_control/multi_obj_track/process_v2x_data.py @@ -0,0 +1,138 @@ +import os +import re +import shutil +import scipy.io as sio + + +def get_min_send_time(file_path): + """提取文件中的最早发送时间""" + pattern = re.compile(r"发送时间:\s*([0-9\.]+)") + times = [] + try: + with open(file_path, 'r', encoding='utf-8') as file: + for line in file: + match = pattern.search(line) + if match: + times.append(float(match.group(1))) + return min(times) if times else None + except Exception as e: + print(f"读取 {file_path} 出错: {e}") + return None + + +def get_max_receive_time(file_path): + """提取文件中的最晚接收时间""" + pattern = re.compile(r"接收时间:\s*([0-9\.]+)") + times = [] + try: + with open(file_path, 'r', encoding='utf-8') as file: + for line in file: + match = pattern.search(line) + if match: + times.append(float(match.group(1))) + return max(times) if times else None + except Exception as e: + print(f"读取 {file_path} 出错: {e}") + return None + + +def calculate_simulation_time(folder_path): + """ + 计算指定文件夹内所有帧数据的总耗时,并将结果保存为 mat 和 txt + """ + all_files = [f for f in os.listdir(folder_path) if f.startswith("frame_") and f.endswith(".txt")] + + if not all_files: + print("错误:在指定文件夹中没有找到匹配的数据文件!") + return False + + all_files.sort() + first_file = os.path.join(folder_path, all_files[0]) + last_file = os.path.join(folder_path, all_files[-1]) + + print(f"原始第一帧: {all_files[0]}") + print(f"原始最后一帧: {all_files[-1]}") + + start_time = get_min_send_time(first_file) + end_time = get_max_receive_time(last_file) + + if start_time and end_time: + total_seconds = end_time - start_time + print(f"数据传输总耗时: {total_seconds:.4f} 秒") + + # 保存结果到原始文件夹中 + mat_filename = os.path.join(folder_path, "simulation_total_time.mat") + sio.savemat(mat_filename, {'total_time': total_seconds}) + print(f"已保存为 MATLAB 原生文件: {mat_filename}") + + txt_filename = os.path.join(folder_path, "simulation_total_time_pure.txt") + with open(txt_filename, 'w') as f: + f.write(f"{total_seconds:.4f}") + print(f"已保存为 txt 备用文件: {txt_filename}") + return True + else: + print("错误:未能成功提取时间。如果首尾帧数据完全损坏,可能会导致此错误。") + return False + + +def clean_and_resort_frames(source_folder, target_folder, required_lines=35): + """ + 清洗并重排帧数据,剔除不完整的帧 + """ + + if not os.path.exists(target_folder): + os.makedirs(target_folder) + print(f" 创建了新的目标文件夹: {target_folder}") + else: + print(f" 目标文件夹已存在: {target_folder}") + + all_files = [f for f in os.listdir(source_folder) if f.startswith("frame_") and f.endswith(".txt")] + all_files.sort() + + valid_count = 0 + discarded_count = 0 + + for original_filename in all_files: + source_filepath = os.path.join(source_folder, original_filename) + + with open(source_filepath, 'r', encoding='utf-8') as f: + lines = f.readlines() + valid_lines = [line.strip() for line in lines if line.strip()] + + line_count = len(valid_lines) + + if line_count == required_lines: + new_filename = f"frame_{valid_count:06d}.txt" + target_filepath = os.path.join(target_folder, new_filename) + shutil.copy2(source_filepath, target_filepath) + valid_count += 1 + else: + print(f" 剔除: {original_filename} (仅包含 {line_count} 条数据)") + discarded_count += 1 + + print(f" 完成数据清洗!保留并重排: {valid_count} 个文件,剔除: {discarded_count} 个文件。") + + +def main(): + # 配置文件路径 + raw_data_folder = "./v2x_latency_logs" # 含有全部原始数据的文件夹 + cleaned_data_folder = "./v2x_clean_logs" # 清洗并重排后存放数据的目标文件夹 + + # 假设每帧完整应该有的条数 + REQUIRED_LINES_PER_FRAME = 7 + + # 计算总耗时 + calculate_simulation_time(folder_path=raw_data_folder) + + # 清洗数据,剔除坏帧并重排 + clean_and_resort_frames( + source_folder=raw_data_folder, + target_folder=cleaned_data_folder, + required_lines=REQUIRED_LINES_PER_FRAME + ) + + print("\n 全部数据处理完毕!") + + +if __name__ == "__main__": + main() \ No newline at end of file From 9e9522e94c0ca3a3c3edb642d211de5907342f58 Mon Sep 17 00:00:00 2001 From: liuao08 <2496556459@qq.com> Date: Fri, 20 Mar 2026 17:57:42 +0800 Subject: [PATCH 4/6] =?UTF-8?q?=E5=BE=97=E5=88=B0=E6=9C=80=E7=BB=88?= =?UTF-8?q?=E5=AD=AA=E7=94=9F=E5=BC=80=E5=A7=8B=E8=BF=90=E8=A1=8C=E7=9A=84?= =?UTF-8?q?=E6=97=B6=E9=97=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../collect_intersection_camera_lidar.py | 2 +- waypoint_control/multi_obj_track/demo.m | 37 ++++++++---- .../navigation/generate_trajectories.py | 58 ++++++++++++++++++ .../multi_obj_track/reID/Utils/DEMO.m | 60 +++++++------------ 4 files changed, 108 insertions(+), 49 deletions(-) diff --git a/waypoint_control/multi_obj_track/collect_intersection_camera_lidar.py b/waypoint_control/multi_obj_track/collect_intersection_camera_lidar.py index ba27066..6511edd 100644 --- a/waypoint_control/multi_obj_track/collect_intersection_camera_lidar.py +++ b/waypoint_control/multi_obj_track/collect_intersection_camera_lidar.py @@ -1027,7 +1027,7 @@ def main(): argparser.add_argument( '-i', '--intersection', metavar='INTERSECTION', - default='road_intersection_1', # 默认路口 + default='road_intersection_3', # 默认路口 help='Name of the intersection within the town (default: road_intersection_1)' ) args = argparser.parse_args() diff --git a/waypoint_control/multi_obj_track/demo.m b/waypoint_control/multi_obj_track/demo.m index 3db14c8..2663600 100644 --- a/waypoint_control/multi_obj_track/demo.m +++ b/waypoint_control/multi_obj_track/demo.m @@ -4,8 +4,12 @@ % 用户输入地图名和路口编号 townName = 'Town10'; % 例如 Town01 或 Town10) -juncNum = 1; % 请输入路口编号(1 或 2) +juncNum = 4; % 请输入路口编号(1 或 2) +data = load('/mnt/mydrive/traffic_twin/waypoint_control/multi_obj_track/v2x_latency_logs/simulation_total_time.mat'); +t_start = data.last_receive_time; +% 获取程序开始时间 +sys_time_before = posixtime(datetime('now')); % 根据输入选择配置 if isfield(dataset, townName) townConfig = dataset.(townName); @@ -33,20 +37,31 @@ convertTrackToCarlaCoordinate(junc, transMatrix); %% 计算单个路口跟踪指标并保存 - %currentPath = fileparts(mfilename('fullpath')); - %folderPath = fullfile(currentPath, 'Evaluation'); - % 将文件夹添加到路径 - %addpath(folderPath); - %demoSingleJuncEvaluation(junc, juncConfig.juncNum); - %if strcmp(townName, 'Town10') + % currentPath = fileparts(mfilename('fullpath')); + % folderPath = fullfile(currentPath, 'Evaluation'); + %% 将文件夹添加到路径 + % addpath(folderPath); + % demoSingleJuncEvaluation(junc, juncConfig.juncNum); + % if strcmp(townName, 'Town10') % townPath = [townName 'HD_Opt_Metric']; - %else + % else % townPath = [townName '_Metric']; - %end - %MCTPResults = demoMultiSensorEvaluation(townPath); + % end + % MCTPResults = demoMultiSensorEvaluation(townPath); else error('路口编号不存在!'); end else error('地图名不存在!'); -end \ No newline at end of file +end + +% 获取程序结束时间 +sys_time_after = posixtime(datetime('now')); +% 计算程序耗时 +program_run_time = sys_time_after - sys_time_before; +% 得出在线结束时间 +t_end = t_start + program_run_time; +% 保存为.mat 文件 +save_folder = '/mnt/mydrive/traffic_twin/waypoint_control/multi_obj_track'; +mat_save_path = fullfile(save_folder, 'matlab_final_timeline.mat'); +save(mat_save_path, 't_start', 't_end', 'program_run_time'); \ No newline at end of file diff --git a/waypoint_control/multi_obj_track/navigation/generate_trajectories.py b/waypoint_control/multi_obj_track/navigation/generate_trajectories.py index f3d5692..f147011 100644 --- a/waypoint_control/multi_obj_track/navigation/generate_trajectories.py +++ b/waypoint_control/multi_obj_track/navigation/generate_trajectories.py @@ -8,6 +8,7 @@ import os import random import time +import re from fastdtw import fastdtw from config import IntersectionConfig, town_configurations from global_route_planner import GlobalRoutePlanner @@ -251,6 +252,52 @@ def create_pedestrian_move(start_location, end_location, world, totaltime): return position_history +def read_matlab_timeline(file_path): + """ + 读取 matlab_final.txt 文件,提取起始时间、终止时间和总耗时 + """ + # 初始化一个字典来存放提取到的数据 + extracted_data = { + "start_time": None, + "end_time": None, + "total_cost": None + } + + if not os.path.exists(file_path): + print(f"错误:找不到文件 {file_path}") + return extracted_data + + # 定义正则表达式,兼容中文全角冒号 ":" 和英文半角冒号 ":" + # 匹配规则:找到指定文字和冒号,然后提取后面的所有数字和小数点 + pattern_start = re.compile(r"起始时间[::]\s*([0-9\.]+)") + pattern_end = re.compile(r"终止时间[::]\s*([0-9\.]+)") + pattern_total = re.compile(r"总耗时[::]\s*([0-9\.]+)") + + try: + with open(file_path, 'r', encoding='utf-8') as file: + content = file.read() + + # 提取起始时间 + match_start = pattern_start.search(content) + if match_start: + extracted_data["start_time"] = float(match_start.group(1)) + + # 提取终止时间 + match_end = pattern_end.search(content) + if match_end: + extracted_data["end_time"] = float(match_end.group(1)) + + # 提取总耗时 + match_total = pattern_total.search(content) + if match_total: + extracted_data["total_cost"] = float(match_total.group(1)) + + return extracted_data + + except Exception as e: + print(f"读取文件出错: {e}") + return extracted_data + def main(): argparser = argparse.ArgumentParser( description=__doc__) @@ -275,6 +322,10 @@ def main(): args = argparser.parse_args() np.random.seed(42) random.seed(42) + # 读取起始时间 + file_path = "../matlab_final.txt" + all_time = read_matlab_timeline(file_path) + str_time = time.time() # 连接到Carla服务器 client = carla.Client(args.host, args.port) client.set_timeout(10.0) @@ -717,6 +768,13 @@ def main(): for line in sorted_lines: file.write(line) + # 保存最终时间 + end_time = time.time() + duration = end_time - str_time + final_time = all_time['end_time'] + duration + with open("final.txt", "w") as f: + f.write(f"{final_time:.2f}") + if __name__ == '__main__': main() diff --git a/waypoint_control/multi_obj_track/reID/Utils/DEMO.m b/waypoint_control/multi_obj_track/reID/Utils/DEMO.m index 823b26a..b948e67 100644 --- a/waypoint_control/multi_obj_track/reID/Utils/DEMO.m +++ b/waypoint_control/multi_obj_track/reID/Utils/DEMO.m @@ -1,49 +1,26 @@ %% 将生成的轨迹与外观特征绑定 %% 匹配轨迹之前,处理单个路口的轨迹id变化的情况 config; -townNameFull = 'Town10HD_Opt'; % 可以修改城镇和路口 -if strcmp(townName, 'Town10HD_Opt') - townName = erase(townName, "HD_Opt"); -end -%% 获取跟踪轨迹路径 -currentPath = fileparts(mfilename('fullpath')); -% 获取当前路径的上级目录 -parentPath = fileparts(currentPath); -% 再次获取上级目录,即上上级目录 -grandparentPath = fileparts(parentPath); -addpath(grandparentPath) -dataPath = fullfile(grandparentPath, townNameFull); - -%% 获取路口数量 -d = dir(dataPath); -% 筛选出文件夹(排除 . 和 ..) -isDir = [d.isdir] & ~ismember({d.name}, {'.','..'}); -% 文件夹数量 -numFolders = sum(isDir); +data = load('/mnt/mydrive/traffic_twin/waypoint_control/multi_obj_track/matlab_final_timeline.mat'); +t_start = data.t_end; +% 获取程序开始时间 +sys_time_before = posixtime(datetime('now')); +townName = 'Town10'; % 可以修改城镇和;路口 +dataSets = {'Town10HD_Opt/test_data_junc1', 'Town10HD_Opt/test_data_junc2', 'Town10HD_Opt/test_data_junc3', 'Town10HD_Opt/test_data_junc4', 'Town10HD_Opt/test_data_junc5'}; -dataSets = arrayfun(@(i) fullfile(dataPath, sprintf('test_data_junc%d', i)), ... - 1:numFolders, 'UniformOutput', false); -dirParts = strsplit(dataSets{1}, '\'); +dirParts = strsplit(dataSets{1}, filesep); townConfig = dataset.(townName); - for i = 1:length(dataSets) - [p, last1, ~] = fileparts(dataSets{i}); % 'test_data_junc1' - - [p, last2, ~] = fileparts(p); % 'Town10HD_Opt' - % 合并 - lastTwo = fullfile(last2, last1); % 'Town10HD_Opt\test_data_junc1' - juncField = sprintf('intersection_%d', i); juncConfig = townConfig.(juncField); transMatrix = juncConfig.TransformationMatrix; - loadAllTraj(lastTwo, transMatrix); + loadAllTraj(dataSets{i}, transMatrix); end - %% 加载所有轨迹 currentPath = fileparts(mfilename('fullpath')); -juncTracksFolderPath = fullfile(currentPath, townNameFull); +juncTracksFolderPath = fullfile(currentPath, dirParts{1}); % 获取所有轨迹文件 matFiles = dir(fullfile(juncTracksFolderPath, "*.mat")); numMatFiles = length(matFiles); @@ -56,15 +33,24 @@ end %% 轨迹匹配,链接全部路口的轨迹 -matchThreshold = 0.7; % 车辆匹配阈值 +matchThreshold = 0.65; % 车辆匹配阈值 traj = linkIdentities(juncTrajCell, matchThreshold); +% 获取程序结束时间 +sys_time_after = posixtime(datetime('now')); +% 计算程序耗时 +program_run_time = sys_time_after - sys_time_before; +% 得出在线结束时间 +t_end = t_start + program_run_time; +% 保存为.mat 文件 +save_folder = '/mnt/mydrive/traffic_twin/waypoint_control/multi_obj_track'; +txt_save_path = fullfile(save_folder, 'matlab_final.txt'); +fileID = fopen(txt_save_path, 'w'); +fprintf(fileID, '起始时间:%.6f\n终止时间:%.6f\n总耗时:%.4f', t_start, t_end, program_run_time); +fclose(fileID); + % 获取当前目录 currentFileDir = fileparts(mfilename('fullpath')); % 保存 traj 到当前目录下的 traj.mat 文件 save(fullfile(currentFileDir, 'traj.mat'), 'traj'); - -computeSpeedCorrelations(townName) - -computeDelay(townName) \ No newline at end of file From f969a0730d36baa6eb838242a69f66c21c7c80e4 Mon Sep 17 00:00:00 2001 From: liuao08 <2496556459@qq.com> Date: Mon, 23 Mar 2026 18:59:24 +0800 Subject: [PATCH 5/6] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=89=A7=E8=A1=8Cmatlab?= =?UTF-8?q?=E8=84=9A=E6=9C=AC=E7=9A=84=E8=87=AA=E5=8A=A8=E5=8C=96=E7=9B=91?= =?UTF-8?q?=E5=90=AC=E8=84=9A=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../multi_obj_track/run_matlab.sh | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100755 waypoint_control/multi_obj_track/run_matlab.sh diff --git a/waypoint_control/multi_obj_track/run_matlab.sh b/waypoint_control/multi_obj_track/run_matlab.sh new file mode 100755 index 0000000..05c6fb1 --- /dev/null +++ b/waypoint_control/multi_obj_track/run_matlab.sh @@ -0,0 +1,51 @@ +#!/bin/bash + +# MATLAB 脚本名字 + +MATLAB_SCRIPT="demo" + +# 2. MATLAB 可执行文件的路径 +# 如果你在终端直接输入 matlab 能打开,这里保持 "matlab" 即可。 +# 如果不行,请改成绝对路径,例如 "/usr/local/MATLAB/R2023a/bin/matlab" +MATLAB_CMD="/home/yons/matlab/2024B/bin/matlab" + +# 3. 日志文件名 (运行结果会保存在这个文件里,方便你以后查看) +LOG_FILE="matlab_output.log" + +# ========================================== +# 🚀 执行区 (以下代码不需要修改) +# ========================================== + +# 获取当前 .sh 脚本所在的绝对路径,并切换过去 +# (这一步非常关键!防止你在其他文件夹运行这个脚本时,MATLAB 找不到相对路径下的数据文件) +WORK_DIR="$(cd "$(dirname "$0")" && pwd)" +cd "$WORK_DIR" || exit 1 + +echo "========================================" +echo "▶ 开始时间: $(date)" +echo "▶ 工作目录: $WORK_DIR" +echo "▶ 运行脚本: ${MATLAB_SCRIPT}.m" +echo "========================================" +echo "正在后台调用 MATLAB,请稍候..." + +# 组合 MATLAB 运行命令 +# -nodisplay: 不加载图形界面 (纯命令行运行) +# -nosplash: 不显示启动时的 MATLAB Logo +# -logfile: 将所有终端输出保存到日志文件中 +# -batch: 执行代码并在完成后自动退出 MATLAB +$MATLAB_CMD -nodisplay -nosplash -logfile "$LOG_FILE" -batch "$MATLAB_SCRIPT" + +# 检查上一条命令 (MATLAB) 的退出状态码 +EXIT_CODE=$? + +echo "========================================" +if [ $EXIT_CODE -eq 0 ]; then + echo "✅ 运行成功!" + echo "结束时间: $(date)" + echo "详细输出已保存至: $WORK_DIR/$LOG_FILE" +else + echo "❌ 运行失败!(退出码: $EXIT_CODE)" + echo "请检查日志文件排查错误: $WORK_DIR/$LOG_FILE" + exit 1 +fi +echo "========================================" \ No newline at end of file From 901875d7c808a329e9d146d58660b7661a2d1cf8 Mon Sep 17 00:00:00 2001 From: liuao08 <2496556459@qq.com> Date: Mon, 23 Mar 2026 19:03:21 +0800 Subject: [PATCH 6/6] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E5=8C=96=E8=84=9A=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../multi_obj_track/run_matlab.sh | 81 +++++++++---------- 1 file changed, 39 insertions(+), 42 deletions(-) diff --git a/waypoint_control/multi_obj_track/run_matlab.sh b/waypoint_control/multi_obj_track/run_matlab.sh index 05c6fb1..4adac60 100755 --- a/waypoint_control/multi_obj_track/run_matlab.sh +++ b/waypoint_control/multi_obj_track/run_matlab.sh @@ -1,51 +1,48 @@ #!/bin/bash -# MATLAB 脚本名字 - -MATLAB_SCRIPT="demo" - -# 2. MATLAB 可执行文件的路径 -# 如果你在终端直接输入 matlab 能打开,这里保持 "matlab" 即可。 -# 如果不行,请改成绝对路径,例如 "/usr/local/MATLAB/R2023a/bin/matlab" -MATLAB_CMD="/home/yons/matlab/2024B/bin/matlab" - -# 3. 日志文件名 (运行结果会保存在这个文件里,方便你以后查看) +# 配置路径 +MATLAB_SCRIPT_DIR="/mnt/mydrive/traffic_twin/waypoint_control/multi_obj_track" +MATLAB_SCRIPT_NAME="demo" LOG_FILE="matlab_output.log" -# ========================================== -# 🚀 执行区 (以下代码不需要修改) -# ========================================== +# 定义触发条件 +TRIGGER_FILE="$MATLAB_SCRIPT_DIR/start_signal.txt" -# 获取当前 .sh 脚本所在的绝对路径,并切换过去 -# (这一步非常关键!防止你在其他文件夹运行这个脚本时,MATLAB 找不到相对路径下的数据文件) -WORK_DIR="$(cd "$(dirname "$0")" && pwd)" -cd "$WORK_DIR" || exit 1 +# 切换目录 +cd "$MATLAB_SCRIPT_DIR" || { echo "切换目录失败!"; exit 1; } echo "========================================" -echo "▶ 开始时间: $(date)" -echo "▶ 工作目录: $WORK_DIR" -echo "▶ 运行脚本: ${MATLAB_SCRIPT}.m" +echo " 监听模式已启动..." +echo "正在等待触发条件满足 (按 Ctrl+C 退出)..." echo "========================================" -echo "正在后台调用 MATLAB,请稍候..." -# 组合 MATLAB 运行命令 -# -nodisplay: 不加载图形界面 (纯命令行运行) -# -nosplash: 不显示启动时的 MATLAB Logo -# -logfile: 将所有终端输出保存到日志文件中 -# -batch: 执行代码并在完成后自动退出 MATLAB -$MATLAB_CMD -nodisplay -nosplash -logfile "$LOG_FILE" -batch "$MATLAB_SCRIPT" - -# 检查上一条命令 (MATLAB) 的退出状态码 -EXIT_CODE=$? - -echo "========================================" -if [ $EXIT_CODE -eq 0 ]; then - echo "✅ 运行成功!" - echo "结束时间: $(date)" - echo "详细输出已保存至: $WORK_DIR/$LOG_FILE" -else - echo "❌ 运行失败!(退出码: $EXIT_CODE)" - echo "请检查日志文件排查错误: $WORK_DIR/$LOG_FILE" - exit 1 -fi -echo "========================================" \ No newline at end of file +# 开启条件判定循环 +while true; do + + # 判断 TRIGGER_FILE 是否存在 + if [ -f "$TRIGGER_FILE" ]; then + + echo "" + echo " [$(date)] 触发条件已满足!开始执行 MATLAB 脚本..." + + # 执行 MATLAB 代码 + matlab -nodisplay -nosplash -logfile "$LOG_FILE" -batch "$MATLAB_SCRIPT_NAME" + + EXIT_CODE=$? + if [ $EXIT_CODE -eq 0 ]; then + echo " 执行成功!" + else + echo " 执行失败!(退出码: $EXIT_CODE)" + fi + + # 重置触发条件 + rm -f "$TRIGGER_FILE" + + echo " 继续监听中..." + + else + # 如果条件不满足,让脚本睡 1 秒钟再查。 + sleep 1 + fi + +done \ No newline at end of file