UAV/utils/odm_monitor.py
2024-12-25 15:35:08 +08:00

89 lines
3.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import os
import time
import logging
import docker
from typing import Tuple
class ODMProcessMonitor:
"""ODM进程监控器"""
def __init__(self, max_retries: int = 3, mode: str = "快拼模式"):
self.max_retries = max_retries
self.logger = logging.getLogger('UAV_Preprocess.ODMMonitor')
self.mode = mode
self.client = docker.from_env()
def _check_success(self, grid_dir: str) -> bool:
"""检查ODM是否执行成功"""
success_markers = ['odm_orthophoto', 'odm_georeferencing']
if self.mode != "快拼模式":
success_markers.append('odm_texturing')
return all(os.path.exists(os.path.join(grid_dir, 'project', marker)) for marker in success_markers)
def run_odm_with_monitor(self, grid_dir: str, grid_idx: int, fast_mode: bool = True) -> Tuple[bool, str]:
"""运行ODM容器"""
attempt = 0
while attempt < self.max_retries:
try:
self.logger.info(f"网格 {grid_idx + 1}{attempt + 1} 次尝试")
# 准备容器配置
volumes = {
grid_dir: {'bind': '/datasets', 'mode': 'rw'}
}
# 准备命令参数
command = [
"--project-path", "/datasets", "project",
"--max-concurrency", "10",
"--force-gps",
"--rerun-all"
]
if fast_mode:
command.extend([
"--feature-quality", "lowest",
"--orthophoto-resolution", "8",
"--fast-orthophoto",
"--skip-3dmodel"
])
# 运行容器
container = self.client.containers.run(
"opendronemap/odm",
command=command,
volumes=volumes,
detach=True,
remove=True
)
# 等待容器完成
result = container.wait()
# 只在失败时获取日志
if result['StatusCode'] != 0:
logs = container.logs().decode('utf-8')
self.logger.error("容器执行失败最后10行日志")
self.logger.error(''.join(logs.split('\n')[-10:]))
# 检查是否成功完成
if result['StatusCode'] == 0 and self._check_success(grid_dir):
self.logger.info(f"网格 {grid_idx + 1} ODM处理成功")
return True, ""
self.logger.warning(f"网格 {grid_idx + 1}{attempt + 1} 次尝试失败")
except Exception as e:
error_msg = f"执行异常: {str(e)}"
self.logger.error(error_msg)
return False, error_msg
attempt += 1
if attempt < self.max_retries:
time.sleep(30)
error_msg = f"网格 {grid_idx + 1}{self.max_retries} 次尝试后仍然失败"
self.logger.error(error_msg)
return False, error_msg