增加CPP
0
cali_web.py
Normal file
BIN
images/back.png
|
Before Width: | Height: | Size: 2.6 MiB After Width: | Height: | Size: 2.5 MiB |
BIN
images/front.png
|
Before Width: | Height: | Size: 2.7 MiB After Width: | Height: | Size: 2.6 MiB |
BIN
images/left.png
|
Before Width: | Height: | Size: 2.8 MiB After Width: | Height: | Size: 2.5 MiB |
BIN
images/right.png
|
Before Width: | Height: | Size: 2.6 MiB After Width: | Height: | Size: 2.5 MiB |
731
lj360_manager.sh
Executable file
@@ -0,0 +1,731 @@
|
||||
#!/bin/bash
|
||||
|
||||
# =============================================
|
||||
# LJ360 全景监控服务管理脚本 - 增强版
|
||||
# 基于步骤化提示、彩色输出、友好交互
|
||||
# 适用于 RK3588 / Linux 本地或远程管理
|
||||
# =============================================
|
||||
|
||||
# ---------------------------------------------
|
||||
# 初始化设置
|
||||
# ---------------------------------------------
|
||||
|
||||
# 遇到错误立即退出
|
||||
set -e
|
||||
|
||||
# 颜色定义
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
CYAN='\033[0;36m'
|
||||
PURPLE='\033[0;35m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# 进度与状态打印函数
|
||||
print_header() {
|
||||
clear
|
||||
echo -e "${PURPLE}"
|
||||
echo "╔══════════════════════════════════════════════════════╗"
|
||||
echo "║ LJ360 全景监控服务管理工具 (增强版) ║"
|
||||
echo "║ RK3588 / Linux ║"
|
||||
echo "╚══════════════════════════════════════════════════════╝"
|
||||
echo -e "${NC}"
|
||||
}
|
||||
|
||||
print_step() {
|
||||
echo -e "${BLUE}[STEP $1/$2]${NC} $3"
|
||||
}
|
||||
|
||||
print_success() {
|
||||
echo -e "${GREEN}✓${NC} $1"
|
||||
}
|
||||
|
||||
print_warning() {
|
||||
echo -e "${YELLOW}⚠${NC} $1"
|
||||
}
|
||||
|
||||
print_error() {
|
||||
echo -e "${RED}✗${NC} $1"
|
||||
}
|
||||
|
||||
print_progress() {
|
||||
echo -e "${CYAN}[进度]${NC} $1"
|
||||
}
|
||||
|
||||
print_divider() {
|
||||
echo -e "${BLUE}──────────────────────────────────────────────${NC}"
|
||||
}
|
||||
|
||||
# ---------------------------------------------
|
||||
# 全局配置
|
||||
# ---------------------------------------------
|
||||
|
||||
TOTAL_STEPS=9
|
||||
STEP=1
|
||||
|
||||
SERVICE_NAME="lj360.service"
|
||||
WATCHDOG_SERVICE="lj360_watchdog.service"
|
||||
|
||||
# 获取当前用户
|
||||
CURRENT_USER=$(whoami)
|
||||
|
||||
# 检查是否以 root 运行
|
||||
if [ "$EUID" -eq 0 ]; then
|
||||
print_error "❌ 请勿使用 root 用户运行此脚本。"
|
||||
print_error "✅ 请使用以下命令运行(普通用户):"
|
||||
print_error " bash $0"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 项目目录
|
||||
PROJECT_DIR="/home/$CURRENT_USER/LJ360"
|
||||
|
||||
print_header
|
||||
print_success "🔧 当前用户: $CURRENT_USER"
|
||||
print_success "📂 项目目录: $PROJECT_DIR"
|
||||
echo ""
|
||||
|
||||
# ---------------------------------------------
|
||||
# 主菜单逻辑与步骤化功能
|
||||
# ---------------------------------------------
|
||||
|
||||
main_menu() {
|
||||
while true; do
|
||||
show_status
|
||||
|
||||
echo -e "${CYAN}🔧 请选择要执行的操作:${NC}"
|
||||
print_divider
|
||||
echo "1) 🛠️ 安装 LJ360 全景监控服务"
|
||||
echo "2) 🛡️ 安装并启动看门狗服务"
|
||||
echo "3) ▶️ 启动全景监控服务"
|
||||
echo "4) ⏹️ 停止全景监控服务"
|
||||
echo "5) 🔄 重启全景监控服务"
|
||||
echo "6) 🔔 启用开机自启"
|
||||
echo "7) 🚫 禁用开机自启"
|
||||
echo "8) 📜 查看实时日志"
|
||||
echo "9) 📊 查看系统状态"
|
||||
echo "10) 🧹 卸载 LJ360 服务"
|
||||
echo "0) 🚪 退出脚本"
|
||||
print_divider
|
||||
|
||||
read -p "👉 请输入选项 [0-10]: " choice
|
||||
|
||||
case $choice in
|
||||
1)
|
||||
STEP=1
|
||||
install_service
|
||||
;;
|
||||
2)
|
||||
STEP=1
|
||||
install_watchdog_service
|
||||
;;
|
||||
3)
|
||||
STEP=1
|
||||
start_service
|
||||
;;
|
||||
4)
|
||||
STEP=1
|
||||
stop_service
|
||||
;;
|
||||
5)
|
||||
STEP=1
|
||||
restart_service
|
||||
;;
|
||||
6)
|
||||
STEP=1
|
||||
enable_service
|
||||
;;
|
||||
7)
|
||||
STEP=1
|
||||
disable_service
|
||||
;;
|
||||
8)
|
||||
STEP=1
|
||||
view_logs
|
||||
;;
|
||||
9)
|
||||
STEP=1
|
||||
view_status
|
||||
;;
|
||||
10)
|
||||
STEP=1
|
||||
uninstall_service
|
||||
;;
|
||||
0)
|
||||
print_success "👋 再见!脚本已退出。"
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
print_error "❌ 无效选项,请重新输入 [0-10]"
|
||||
sleep 2
|
||||
;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
# ---------------------------------------------
|
||||
# 功能函数
|
||||
# ---------------------------------------------
|
||||
|
||||
show_status() {
|
||||
print_header
|
||||
|
||||
echo -e "${BLUE}【📊 当前服务状态】${NC}"
|
||||
print_divider
|
||||
|
||||
# 检查主服务状态
|
||||
if systemctl is-active --quiet $SERVICE_NAME 2>/dev/null; then
|
||||
echo -e "${GREEN}● LJ360 服务正在运行 ✅${NC}"
|
||||
else
|
||||
echo -e "${RED}● LJ360 服务未运行 ❌${NC}"
|
||||
fi
|
||||
|
||||
# 检查看门狗服务状态
|
||||
if systemctl is-active --quiet $WATCHDOG_SERVICE 2>/dev/null; then
|
||||
echo -e "${GREEN}● 看门狗服务正在运行 🛡️${NC}"
|
||||
else
|
||||
echo -e "${YELLOW}● 看门狗服务未运行 ⚠${NC}"
|
||||
fi
|
||||
|
||||
# 检查开机自启状态
|
||||
if systemctl is-enabled $SERVICE_NAME 2>/dev/null; then
|
||||
echo -e "${GREEN}● 开机自启已启用 ✅${NC}"
|
||||
else
|
||||
echo -e "${YELLOW}● 开机自启未启用 ⚠${NC}"
|
||||
fi
|
||||
|
||||
# 检查Web端口
|
||||
echo ""
|
||||
echo -e "${BLUE}【🌐 网络端口状态】${NC}"
|
||||
print_divider
|
||||
if netstat -tlnp 2>/dev/null | grep -q ":5000"; then
|
||||
echo -e "${GREEN}● Web 服务端口 5000 已监听 ✅${NC}"
|
||||
else
|
||||
echo -e "${RED}● Web 服务端口 5000 未监听 ❌${NC}"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
}
|
||||
|
||||
# --------------------------
|
||||
# Step 1: 安装服务
|
||||
# --------------------------
|
||||
install_service() {
|
||||
print_step $STEP $TOTAL_STEPS "安装 LJ360 全景监控服务"
|
||||
|
||||
# 检查项目目录是否存在
|
||||
if [ ! -d "$PROJECT_DIR" ]; then
|
||||
print_error "❌ 项目目录不存在: $PROJECT_DIR"
|
||||
print_error "请确认项目路径是否正确"
|
||||
read -p "🔘 按 Enter 继续..." -r
|
||||
return
|
||||
fi
|
||||
|
||||
# 检查web.py文件是否存在
|
||||
if [ ! -f "$PROJECT_DIR/web.py" ]; then
|
||||
print_error "❌ web.py 文件不存在: $PROJECT_DIR/web.py"
|
||||
print_error "请确认项目文件是否正确"
|
||||
read -p "🔘 按 Enter 继续..." -r
|
||||
return
|
||||
fi
|
||||
|
||||
# 创建启动脚本
|
||||
local START_SCRIPT="$PROJECT_DIR/start_lj360.sh"
|
||||
print_progress "🔧 创建启动脚本: $START_SCRIPT"
|
||||
cat > "$START_SCRIPT" << EOF
|
||||
#!/bin/bash
|
||||
# LJ360 全景监控启动脚本
|
||||
# 项目目录: $PROJECT_DIR
|
||||
|
||||
# 切换到项目目录
|
||||
cd "$PROJECT_DIR"
|
||||
|
||||
# 设置环境变量
|
||||
export DISPLAY=:0
|
||||
export XAUTHORITY=/home/$CURRENT_USER/.Xauthority
|
||||
export PYTHONPATH=$PROJECT_DIR:\$PYTHONPATH
|
||||
|
||||
# 日志文件
|
||||
LOG_FILE="$PROJECT_DIR/lj360.log"
|
||||
ERROR_LOG="$PROJECT_DIR/lj360_error.log"
|
||||
|
||||
echo "=========================================" >> "\$LOG_FILE"
|
||||
echo "LJ360 启动时间: \$(date)" >> "\$LOG_FILE"
|
||||
echo "=========================================" >> "\$LOG_FILE"
|
||||
|
||||
# 检查是否已有进程在运行
|
||||
if pgrep -f "python3 web.py" > /dev/null; then
|
||||
echo "\$(date): LJ360 应用已在运行,跳过启动" >> "\$LOG_FILE"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# 启动应用并记录输出
|
||||
echo "\$(date): 启动 LJ360 web.py..." >> "\$LOG_FILE"
|
||||
exec python3 web.py >> "\$LOG_FILE" 2>> "\$ERROR_LOG"
|
||||
EOF
|
||||
|
||||
chmod +x "$START_SCRIPT"
|
||||
chown "$CURRENT_USER:$CURRENT_USER" "$START_SCRIPT"
|
||||
print_success "✅ 启动脚本已创建并授权"
|
||||
|
||||
# 创建 systemd 服务
|
||||
print_progress "🔧 创建 systemd 服务文件: /etc/systemd/system/$SERVICE_NAME"
|
||||
sudo tee /etc/systemd/system/$SERVICE_NAME > /dev/null << EOF
|
||||
[Unit]
|
||||
Description=LJ360 Surround View Service
|
||||
After=network.target graphical.target
|
||||
Wants=network.target graphical.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=$CURRENT_USER
|
||||
WorkingDirectory=$PROJECT_DIR
|
||||
Environment="DISPLAY=:0"
|
||||
Environment="XAUTHORITY=/home/$CURRENT_USER/.Xauthority"
|
||||
Environment="PYTHONPATH=$PROJECT_DIR"
|
||||
Environment="XDG_RUNTIME_DIR=/run/user/1000"
|
||||
ExecStart=$PROJECT_DIR/start_lj360.sh
|
||||
Restart=always
|
||||
RestartSec=5
|
||||
StandardOutput=journal
|
||||
StandardError=journal
|
||||
|
||||
# 限制资源使用(可选)
|
||||
# MemoryMax=1G
|
||||
# CPUQuota=80%
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
|
||||
sudo systemctl daemon-reload
|
||||
print_success "✅ systemd 服务文件已部署 & 缓存已刷新"
|
||||
|
||||
STEP=$((STEP + 1))
|
||||
read -p "🔘 按 Enter 继续..." -r
|
||||
}
|
||||
|
||||
# --------------------------
|
||||
# Step 2: 安装看门狗服务
|
||||
# --------------------------
|
||||
install_watchdog_service() {
|
||||
print_step $STEP $TOTAL_STEPS "安装并启动看门狗服务"
|
||||
|
||||
# 创建看门狗脚本
|
||||
local WATCHDOG_SCRIPT="$PROJECT_DIR/watchdog_lj360.sh"
|
||||
print_progress "🔧 创建看门狗脚本: $WATCHDOG_SCRIPT"
|
||||
cat > "$WATCHDOG_SCRIPT" << EOF
|
||||
#!/bin/bash
|
||||
# LJ360 看门狗服务脚本
|
||||
# 项目目录: $PROJECT_DIR
|
||||
|
||||
APP_NAME="web.py"
|
||||
CHECK_INTERVAL=10
|
||||
LOG_FILE="$PROJECT_DIR/watchdog.log"
|
||||
|
||||
echo "=========================================" >> "\$LOG_FILE"
|
||||
echo "看门狗服务启动时间: \$(date)" >> "\$LOG_FILE"
|
||||
echo "=========================================" >> "\$LOG_FILE"
|
||||
|
||||
while true; do
|
||||
# 检查主服务进程是否存在
|
||||
if ! pgrep -f "python3 \$APP_NAME" > /dev/null; then
|
||||
echo "\$(date): 检测到 LJ360 未运行,正在启动..." >> "\$LOG_FILE"
|
||||
|
||||
cd "$PROJECT_DIR"
|
||||
|
||||
# 设置环境变量
|
||||
export DISPLAY=:0
|
||||
export XAUTHORITY=/home/$CURRENT_USER/.Xauthority
|
||||
export PYTHONPATH=$PROJECT_DIR:\$PYTHONPATH
|
||||
|
||||
# 启动应用
|
||||
nohup python3 web.py >> "$PROJECT_DIR/lj360.log" 2>> "$PROJECT_DIR/lj360_error.log" &
|
||||
|
||||
echo "\$(date): 已启动 LJ360,PID: \$!" >> "\$LOG_FILE"
|
||||
|
||||
# 等待应用启动
|
||||
sleep 5
|
||||
fi
|
||||
|
||||
sleep \$CHECK_INTERVAL
|
||||
done
|
||||
EOF
|
||||
|
||||
chmod +x "$WATCHDOG_SCRIPT"
|
||||
chown "$CURRENT_USER:$CURRENT_USER" "$WATCHDOG_SCRIPT"
|
||||
print_success "✅ 看门狗脚本已创建并授权"
|
||||
|
||||
# 创建看门狗 systemd 服务
|
||||
print_progress "🔧 创建看门狗服务文件: /etc/systemd/system/$WATCHDOG_SERVICE"
|
||||
sudo tee /etc/systemd/system/$WATCHDOG_SERVICE > /dev/null << EOF
|
||||
[Unit]
|
||||
Description=LJ360 Watchdog Service
|
||||
After=network.target
|
||||
Wants=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=$CURRENT_USER
|
||||
WorkingDirectory=$PROJECT_DIR
|
||||
ExecStart=$PROJECT_DIR/watchdog_lj360.sh
|
||||
Restart=always
|
||||
RestartSec=10
|
||||
StandardOutput=journal
|
||||
StandardError=journal
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
|
||||
sudo systemctl daemon-reload
|
||||
print_success "✅ 看门狗服务文件已部署"
|
||||
|
||||
# 启用并启动看门狗服务
|
||||
print_progress "🚀 启动看门狗服务"
|
||||
sudo systemctl enable $WATCHDOG_SERVICE
|
||||
sudo systemctl start $WATCHDOG_SERVICE
|
||||
sleep 2
|
||||
|
||||
if systemctl is-active --quiet $WATCHDOG_SERVICE; then
|
||||
print_success "✅ 看门狗服务启动成功"
|
||||
else
|
||||
print_warning "⚠️ 看门狗服务启动可能有问题,请查看日志"
|
||||
fi
|
||||
|
||||
STEP=$((STEP + 1))
|
||||
read -p "🔘 按 Enter 继续..." -r
|
||||
}
|
||||
|
||||
# --------------------------
|
||||
# Step 3: 启动服务
|
||||
# --------------------------
|
||||
start_service() {
|
||||
print_step $STEP $TOTAL_STEPS "启动 LJ360 全景监控服务"
|
||||
|
||||
# 检查服务文件是否存在
|
||||
if [ ! -f "/etc/systemd/system/$SERVICE_NAME" ]; then
|
||||
print_error "❌ 服务未安装,请先安装服务"
|
||||
read -p "🔘 按 Enter 继续..." -r
|
||||
return
|
||||
fi
|
||||
|
||||
print_progress "🚀 正在启动服务: $SERVICE_NAME"
|
||||
sudo systemctl start "$SERVICE_NAME"
|
||||
sleep 3
|
||||
|
||||
# 检查启动状态
|
||||
if systemctl is-active --quiet "$SERVICE_NAME"; then
|
||||
print_success "✅ 服务启动成功"
|
||||
|
||||
# 检查Web端口
|
||||
sleep 2
|
||||
if netstat -tlnp 2>/dev/null | grep -q ":5000"; then
|
||||
local IP_ADDR=$(hostname -I | awk '{print $1}')
|
||||
print_success "🌐 Web 服务已启动: http://$IP_ADDR:5000"
|
||||
print_success "🌐 本地访问: http://localhost:5000"
|
||||
fi
|
||||
else
|
||||
print_warning "⚠️ 服务启动可能有问题,请查看日志"
|
||||
fi
|
||||
|
||||
STEP=$((STEP + 1))
|
||||
read -p "🔘 按 Enter 继续..." -r
|
||||
}
|
||||
|
||||
# --------------------------
|
||||
# Step 4: 停止服务
|
||||
# --------------------------
|
||||
stop_service() {
|
||||
print_step $STEP $TOTAL_STEPS "停止 LJ360 全景监控服务"
|
||||
|
||||
# 检查服务文件是否存在
|
||||
if [ ! -f "/etc/systemd/system/$SERVICE_NAME" ]; then
|
||||
print_error "❌ 服务未安装,请先安装服务"
|
||||
read -p "🔘 按 Enter 继续..." -r
|
||||
return
|
||||
fi
|
||||
|
||||
print_progress "⏹️ 正在停止服务: $SERVICE_NAME"
|
||||
sudo systemctl stop "$SERVICE_NAME"
|
||||
sleep 2
|
||||
|
||||
# 清理可能的残留进程
|
||||
print_progress "🧹 清理残留进程..."
|
||||
pkill -f "python3 web.py" 2>/dev/null || true
|
||||
|
||||
# 检查停止状态
|
||||
if ! systemctl is-active --quiet "$SERVICE_NAME"; then
|
||||
print_success "✅ 服务停止成功"
|
||||
else
|
||||
print_warning "⚠️ 服务停止可能有问题"
|
||||
fi
|
||||
|
||||
STEP=$((STEP + 1))
|
||||
read -p "🔘 按 Enter 继续..." -r
|
||||
}
|
||||
|
||||
# --------------------------
|
||||
# Step 5: 重启服务
|
||||
# --------------------------
|
||||
restart_service() {
|
||||
print_step $STEP $TOTAL_STEPS "重启 LJ360 全景监控服务"
|
||||
|
||||
# 检查服务文件是否存在
|
||||
if [ ! -f "/etc/systemd/system/$SERVICE_NAME" ]; then
|
||||
print_error "❌ 服务未安装,请先安装服务"
|
||||
read -p "🔘 按 Enter 继续..." -r
|
||||
return
|
||||
fi
|
||||
|
||||
print_progress "🔄 正在重启服务: $SERVICE_NAME"
|
||||
sudo systemctl restart "$SERVICE_NAME"
|
||||
sleep 3
|
||||
|
||||
# 检查重启状态
|
||||
if systemctl is-active --quiet "$SERVICE_NAME"; then
|
||||
print_success "✅ 服务重启成功"
|
||||
|
||||
# 检查Web端口
|
||||
sleep 2
|
||||
if netstat -tlnp 2>/dev/null | grep -q ":5000"; then
|
||||
local IP_ADDR=$(hostname -I | awk '{print $1}')
|
||||
print_success "🌐 Web 服务已重启: http://$IP_ADDR:5000"
|
||||
fi
|
||||
else
|
||||
print_warning "⚠️ 服务重启可能有问题,请查看日志"
|
||||
fi
|
||||
|
||||
STEP=$((STEP + 1))
|
||||
read -p "🔘 按 Enter 继续..." -r
|
||||
}
|
||||
|
||||
# --------------------------
|
||||
# Step 6: 启用开机自启
|
||||
# --------------------------
|
||||
enable_service() {
|
||||
print_step $STEP $TOTAL_STEPS "启用开机自启"
|
||||
|
||||
# 检查服务文件是否存在
|
||||
if [ ! -f "/etc/systemd/system/$SERVICE_NAME" ]; then
|
||||
print_error "❌ 服务未安装,请先安装服务"
|
||||
read -p "🔘 按 Enter 继续..." -r
|
||||
return
|
||||
fi
|
||||
|
||||
print_progress "🔔 正在启用开机自启: $SERVICE_NAME"
|
||||
sudo systemctl enable "$SERVICE_NAME"
|
||||
sleep 1
|
||||
|
||||
if systemctl is-enabled "$SERVICE_NAME"; then
|
||||
print_success "✅ 开机自启已启用"
|
||||
else
|
||||
print_error "❌ 开机自启启用失败"
|
||||
fi
|
||||
|
||||
STEP=$((STEP + 1))
|
||||
read -p "🔘 按 Enter 继续..." -r
|
||||
}
|
||||
|
||||
# --------------------------
|
||||
# Step 7: 禁用开机自启
|
||||
# --------------------------
|
||||
disable_service() {
|
||||
print_step $STEP $TOTAL_STEPS "禁用开机自启"
|
||||
|
||||
# 检查服务文件是否存在
|
||||
if [ ! -f "/etc/systemd/system/$SERVICE_NAME" ]; then
|
||||
print_error "❌ 服务未安装,请先安装服务"
|
||||
read -p "🔘 按 Enter 继续..." -r
|
||||
return
|
||||
fi
|
||||
|
||||
print_progress "🚫 正在禁用开机自启: $SERVICE_NAME"
|
||||
sudo systemctl disable "$SERVICE_NAME"
|
||||
sleep 1
|
||||
|
||||
if ! systemctl is-enabled "$SERVICE_NAME"; then
|
||||
print_success "✅ 开机自启已禁用"
|
||||
else
|
||||
print_error "❌ 开机自启禁用失败"
|
||||
fi
|
||||
|
||||
STEP=$((STEP + 1))
|
||||
read -p "🔘 按 Enter 继续..." -r
|
||||
}
|
||||
|
||||
# --------------------------
|
||||
# Step 8: 查看日志
|
||||
# --------------------------
|
||||
view_logs() {
|
||||
print_step $STEP $TOTAL_STEPS "查看实时日志"
|
||||
|
||||
# 检查服务文件是否存在
|
||||
if [ ! -f "/etc/systemd/system/$SERVICE_NAME" ]; then
|
||||
print_error "❌ 服务未安装,请先安装服务"
|
||||
read -p "🔘 按 Enter 继续..." -r
|
||||
return
|
||||
fi
|
||||
|
||||
print_progress "📜 请选择要查看的日志类型:"
|
||||
echo "1) 📋 查看 systemd 服务日志"
|
||||
echo "2) 📄 查看应用日志文件"
|
||||
echo "3) ⚠️ 查看错误日志文件"
|
||||
echo "4) 🛡️ 查看看门狗日志"
|
||||
print_divider
|
||||
|
||||
read -p "👉 请选择 [1-4]: " log_choice
|
||||
|
||||
case $log_choice in
|
||||
1)
|
||||
print_progress "📜 正在打开 systemd 服务日志(按 Ctrl+C 退出)"
|
||||
echo ""
|
||||
sudo journalctl -u "$SERVICE_NAME" -f
|
||||
;;
|
||||
2)
|
||||
print_progress "📄 正在查看应用日志文件: $PROJECT_DIR/lj360.log"
|
||||
echo ""
|
||||
if [ -f "$PROJECT_DIR/lj360.log" ]; then
|
||||
tail -50 "$PROJECT_DIR/lj360.log"
|
||||
echo ""
|
||||
echo "按 Enter 查看更多,或按 Ctrl+C 退出..."
|
||||
tail -f "$PROJECT_DIR/lj360.log"
|
||||
else
|
||||
print_error "❌ 日志文件不存在"
|
||||
fi
|
||||
;;
|
||||
3)
|
||||
print_progress "⚠️ 正在查看错误日志文件: $PROJECT_DIR/lj360_error.log"
|
||||
echo ""
|
||||
if [ -f "$PROJECT_DIR/lj360_error.log" ]; then
|
||||
tail -50 "$PROJECT_DIR/lj360_error.log"
|
||||
else
|
||||
print_warning "⚠️ 错误日志文件不存在"
|
||||
fi
|
||||
;;
|
||||
4)
|
||||
print_progress "🛡️ 正在查看看门狗日志文件: $PROJECT_DIR/watchdog.log"
|
||||
echo ""
|
||||
if [ -f "$PROJECT_DIR/watchdog.log" ]; then
|
||||
tail -50 "$PROJECT_DIR/watchdog.log"
|
||||
else
|
||||
print_warning "⚠️ 看门狗日志文件不存在"
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
print_error "❌ 无效选项"
|
||||
;;
|
||||
esac
|
||||
|
||||
STEP=$((STEP + 1))
|
||||
read -p "🔘 日志查看结束,按 Enter 继续..." -r
|
||||
}
|
||||
|
||||
# --------------------------
|
||||
# Step 9: 查看系统状态
|
||||
# --------------------------
|
||||
view_status() {
|
||||
print_step $STEP $TOTAL_STEPS "查看详细系统状态"
|
||||
|
||||
echo -e "${CYAN}【📊 系统资源状态】${NC}"
|
||||
print_divider
|
||||
|
||||
# CPU使用率
|
||||
echo -e "${BLUE}● CPU 使用率:${NC}"
|
||||
top -bn1 | grep "Cpu(s)" | awk '{print " " $2 "% user, " $4 "% system, " $8 "% idle"}'
|
||||
|
||||
# 内存使用
|
||||
echo -e "${BLUE}● 内存使用:${NC}"
|
||||
free -h | awk '/^Mem:/ {print " " $3 " / " $2 " (" $3/$2*100 "%) used"}'
|
||||
|
||||
# 磁盘空间
|
||||
echo -e "${BLUE}● 磁盘空间:${NC}"
|
||||
df -h /home | awk 'NR==2 {print " " $3 " / " $2 " (" $5 ") used"}'
|
||||
|
||||
echo ""
|
||||
echo -e "${CYAN}【🔍 进程状态】${NC}"
|
||||
print_divider
|
||||
|
||||
# LJ360相关进程
|
||||
if pgrep -f "python3 web.py" > /dev/null; then
|
||||
echo -e "${GREEN}● LJ360 进程正在运行 ✅${NC}"
|
||||
ps aux | grep "python3 web.py" | grep -v grep | awk '{print " PID: " $2 ", CPU: " $3 "%, MEM: " $4 "%, CMD: " $11}'
|
||||
else
|
||||
echo -e "${RED}● LJ360 进程未运行 ❌${NC}"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo -e "${CYAN}【📈 服务运行时间】${NC}"
|
||||
print_divider
|
||||
|
||||
if systemctl is-active --quiet $SERVICE_NAME; then
|
||||
UPTIME=$(systemctl show $SERVICE_NAME --property=ActiveEnterTimestamp | awk -F= '{print $2}')
|
||||
echo -e "${GREEN}● 服务启动时间: $UPTIME${NC}"
|
||||
fi
|
||||
|
||||
if systemctl is-active --quiet $WATCHDOG_SERVICE; then
|
||||
WATCHDOG_UPTIME=$(systemctl show $WATCHDOG_SERVICE --property=ActiveEnterTimestamp | awk -F= '{print $2}')
|
||||
echo -e "${GREEN}● 看门狗启动时间: $WATCHDOG_UPTIME${NC}"
|
||||
fi
|
||||
|
||||
STEP=$((STEP + 1))
|
||||
read -p "🔘 按 Enter 继续..." -r
|
||||
}
|
||||
|
||||
# --------------------------
|
||||
# Step 10: 卸载服务
|
||||
# --------------------------
|
||||
uninstall_service() {
|
||||
print_step $STEP $TOTAL_STEPS "卸载 LJ360 全景监控服务"
|
||||
echo -e "${RED}⚠ 警告:此操作将卸载 LJ360 全景监控服务!${NC}"
|
||||
echo -n "✅ 确定要卸载吗?(y/N): "
|
||||
read -r confirm
|
||||
if [[ $confirm =~ ^[Yy]$ ]]; then
|
||||
print_progress "⏹️ 停止服务..."
|
||||
sudo systemctl stop "$SERVICE_NAME" 2>/dev/null || true
|
||||
sudo systemctl stop "$WATCHDOG_SERVICE" 2>/dev/null || true
|
||||
|
||||
print_progress "🚫 禁用开机自启..."
|
||||
sudo systemctl disable "$SERVICE_NAME" 2>/dev/null || true
|
||||
sudo systemctl disable "$WATCHDOG_SERVICE" 2>/dev/null || true
|
||||
|
||||
print_progress "🗑️ 删除 systemd 服务文件..."
|
||||
sudo rm -f /etc/systemd/system/"$SERVICE_NAME"
|
||||
sudo rm -f /etc/systemd/system/"$WATCHDOG_SERVICE"
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl reset-failed
|
||||
|
||||
print_progress "🗑️ 删除启动脚本..."
|
||||
rm -f "$PROJECT_DIR/start_lj360.sh"
|
||||
rm -f "$PROJECT_DIR/watchdog_lj360.sh"
|
||||
|
||||
print_progress "🔪 清理进程..."
|
||||
pkill -f "python3 web.py" 2>/dev/null || true
|
||||
pkill -f "watchdog_lj360.sh" 2>/dev/null || true
|
||||
|
||||
print_success "✅ LJ360 全景监控服务卸载完成"
|
||||
print_warning "📝 日志文件保留在: $PROJECT_DIR/"
|
||||
print_warning " - lj360.log"
|
||||
print_warning " - lj360_error.log"
|
||||
print_warning " - watchdog.log"
|
||||
else
|
||||
print_warning "❌ 取消卸载操作"
|
||||
fi
|
||||
|
||||
STEP=$((STEP + 1))
|
||||
read -p "🔘 按 Enter 继续..." -r
|
||||
}
|
||||
|
||||
# ---------------------------------------------
|
||||
# 启动主菜单
|
||||
# ---------------------------------------------
|
||||
|
||||
# 检查是否在正确的目录运行
|
||||
if [ ! -d "$PROJECT_DIR" ]; then
|
||||
print_error "❌ 项目目录不存在: $PROJECT_DIR"
|
||||
print_error "请确认项目路径是否正确,或者修改脚本中的 PROJECT_DIR 变量"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
main_menu
|
||||
@@ -1,4 +1,4 @@
|
||||
# mjpeg_streamer.py
|
||||
# mjpeg_streamer.pynano
|
||||
import threading
|
||||
import time
|
||||
from flask import Flask, Response, render_template, request, redirect, session, url_for
|
||||
|
||||
37
seial_test.py
Normal file
@@ -0,0 +1,37 @@
|
||||
import serial
|
||||
import time
|
||||
|
||||
# 配置串口(请根据实际情况修改设备名)
|
||||
PORT = '/dev/ttyS0' # 或 '/dev/ttyUSB0'
|
||||
BAUDRATE = 115200
|
||||
|
||||
try:
|
||||
# 打开串口
|
||||
ser = serial.Serial(PORT, BAUDRATE, timeout=1)
|
||||
print(f"✅ 已打开串口 {PORT}")
|
||||
|
||||
# 发送数据
|
||||
data_to_send = b'123456\n'
|
||||
|
||||
# 持续读取数据(注意:此时串口是打开的!)
|
||||
print("📥 开始监听串口数据...")
|
||||
while True:
|
||||
ser.write(data_to_send)
|
||||
print("📤 已发送数据")
|
||||
try:
|
||||
line = ser.readline()
|
||||
if line:
|
||||
print("接收到:", line.hex())
|
||||
except serial.SerialException as e:
|
||||
print("❌ 串口异常:", e)
|
||||
break
|
||||
time.sleep(1)
|
||||
|
||||
except serial.SerialException as e:
|
||||
print(f"❌ 无法打开串口 {PORT}: {e}")
|
||||
except KeyboardInterrupt:
|
||||
print("\n🛑 用户中断")
|
||||
finally:
|
||||
if 'ser' in locals() and ser.is_open:
|
||||
ser.close()
|
||||
print("🔌 串口已关闭")
|
||||
@@ -12,7 +12,7 @@ shift_h = 100
|
||||
|
||||
# 标定图案与车辆之间在水平和垂直方向上的间隙大小
|
||||
inn_shift_w = 20
|
||||
inn_shift_h = 20
|
||||
inn_shift_h = 30
|
||||
|
||||
# 拼接图像的总宽度/高度
|
||||
total_w = 300 + 2 * shift_w
|
||||
@@ -20,10 +20,10 @@ total_h = 350 + 2 * shift_h
|
||||
|
||||
|
||||
# 计算车辆在全景图中的位置
|
||||
xl = shift_w + 45 + inn_shift_w
|
||||
xl = shift_w + 55 + inn_shift_w
|
||||
xr = total_w - xl
|
||||
print(xl, xr)
|
||||
yt = shift_h + 60 + inn_shift_h
|
||||
yt = shift_h + 55 + inn_shift_h
|
||||
yb = total_h - yt
|
||||
# --------------------------------------------------------------------
|
||||
|
||||
@@ -44,18 +44,18 @@ project_keypoints = {
|
||||
|
||||
"back": [(shift_w + 0, shift_h),
|
||||
(shift_w + 300, shift_h),
|
||||
(shift_w + 0, shift_h + 80),
|
||||
(shift_w + 300, shift_h + 80)],
|
||||
(shift_w + 0, shift_h + 70),
|
||||
(shift_w + 300, shift_h + 70)],
|
||||
|
||||
"left": [(shift_h + 0, shift_w),
|
||||
(shift_h + 350, shift_w),
|
||||
(shift_h + 0, shift_w + 50),
|
||||
(shift_h + 350, shift_w + 50)],
|
||||
(shift_h + 0, shift_w + 40),
|
||||
(shift_h + 350, shift_w + 40)],
|
||||
|
||||
"right": [(shift_h + 0, shift_w),
|
||||
(shift_h + 350, shift_w),
|
||||
(shift_h + 0, shift_w + 50),
|
||||
(shift_h + 350, shift_w + 50)]
|
||||
(shift_h + 0, shift_w + 40),
|
||||
(shift_h + 350, shift_w + 40)]
|
||||
}
|
||||
|
||||
car_image = cv2.imread(os.path.join(os.getcwd(), "images", "car.png"))
|
||||
|
||||
BIN
test_dir/camera_v4l2
Executable file
53
test_dir/camera_v4l2.cpp
Normal file
@@ -0,0 +1,53 @@
|
||||
#include <opencv2/opencv.hpp>
|
||||
#include <iostream>
|
||||
|
||||
int main() {
|
||||
// 使用 V4L2 后端打开摄像头(设备索引 0 对应 /dev/video0)
|
||||
cv::VideoCapture cap(0, cv::CAP_V4L2);
|
||||
cap.set(cv::CAP_PROP_FRAME_WIDTH, 1920);
|
||||
cap.set(cv::CAP_PROP_FRAME_HEIGHT, 1080);
|
||||
cap.set(cv::CAP_PROP_FOURCC, cv::VideoWriter::fourcc('Y','U','Y','V'));
|
||||
// cap.set(cv::CAP_PROP_BUFFERSIZE, 1); // 减少缓冲,降低延迟
|
||||
|
||||
if (!cap.isOpened()) {
|
||||
std::cerr << "❌ 无法打开摄像头 /dev/video0\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 可选:设置分辨率和格式(根据你的摄像头能力调整)
|
||||
|
||||
|
||||
std::cout << "✅ 摄像头已打开,按 'q' 或 ESC 退出。\n";
|
||||
|
||||
cv::Mat frame;
|
||||
while (true) {
|
||||
cap >> frame; // 从摄像头读取一帧
|
||||
|
||||
if (frame.empty()) {
|
||||
std::cerr << "⚠️ 读取帧失败,可能摄像头被占用或断开。\n";
|
||||
break;
|
||||
}
|
||||
|
||||
// 如果是 YUYV 格式(2通道),转换为 BGR 显示彩色
|
||||
cv::Mat display_frame;
|
||||
if (frame.channels() == 2) {
|
||||
cv::cvtColor(frame, display_frame, cv::COLOR_YUV2BGR_YUYV);
|
||||
} else {
|
||||
display_frame = frame; // 假设已经是 BGR
|
||||
}
|
||||
|
||||
// 显示图像
|
||||
cv::imshow("Camera Feed (V4L2)", display_frame);
|
||||
|
||||
// 按 q 或 ESC 退出
|
||||
int key = cv::waitKey(1) & 0xFF;
|
||||
if (key == 'q' || key == 27) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
cap.release();
|
||||
cv::destroyAllWindows();
|
||||
std::cout << "👋 已退出。\n";
|
||||
return 0;
|
||||
}
|
||||
BIN
test_dir/check_opencv
Executable file
7
test_dir/v4l2.cpp
Normal file
@@ -0,0 +1,7 @@
|
||||
#include <opencv2/opencv.hpp>
|
||||
#include <iostream>
|
||||
|
||||
int main() {
|
||||
std::cout << cv::getBuildInformation() << std::endl;
|
||||
return 0;
|
||||
}
|
||||
BIN
test_dir/your_app
Executable file
190
web.py
@@ -5,9 +5,65 @@ import sys
|
||||
import os
|
||||
import argparse
|
||||
import numpy as np
|
||||
import serial
|
||||
import time
|
||||
from surround_view import FisheyeCameraModel, BirdView
|
||||
import surround_view.param_settings as settings
|
||||
|
||||
# 串口雷达配置
|
||||
RADAR_SERIAL_PORT = '/dev/ttyS0'
|
||||
RADAR_BAUDRATE = 115200 # 根据实际雷达配置调整
|
||||
RADAR_TIMEOUT = 0.1
|
||||
|
||||
# 距离阈值配置(单位:mm)
|
||||
DISTANCE_THRESHOLD = 3000 # 距离过近阈值,可以根据需要调整
|
||||
|
||||
# 雷达ID与方向映射
|
||||
RADAR_ID_MAP = {1: 'front', 2: 'left', 3: 'back', 4: 'right'}
|
||||
|
||||
def parse_radar_data(raw_data):
|
||||
"""
|
||||
解析雷达原始数据
|
||||
数据格式: 0xA5 0x5A [雷达ID-距离高字节-距离低字节]... 0x5A 0xA5
|
||||
"""
|
||||
try:
|
||||
# 查找帧头位置
|
||||
frame_start = raw_data.find(b'\xA5\x5A')
|
||||
if frame_start == -1:
|
||||
return None
|
||||
|
||||
# 查找帧尾位置
|
||||
frame_end = raw_data.find(b'\x5A\xA5', frame_start)
|
||||
if frame_end == -1:
|
||||
return None
|
||||
|
||||
# 提取完整帧数据
|
||||
frame_data = raw_data[frame_start+2:frame_end]
|
||||
|
||||
# 检查数据长度是否正确(每个雷达3字节 × 4雷达 = 12字节)
|
||||
if len(frame_data) != 12:
|
||||
return None
|
||||
|
||||
# 解析每个雷达数据
|
||||
radar_distances = {}
|
||||
for i in range(4):
|
||||
radar_id = frame_data[i*3]
|
||||
if radar_id not in RADAR_ID_MAP:
|
||||
continue
|
||||
|
||||
distance_high = frame_data[i*3+1]
|
||||
distance_low = frame_data[i*3+2]
|
||||
distance = (distance_high << 8) + distance_low
|
||||
|
||||
direction = RADAR_ID_MAP[radar_id]
|
||||
radar_distances[direction] = distance
|
||||
|
||||
return radar_distances
|
||||
|
||||
except Exception as e:
|
||||
print(f"[ERROR] 雷达数据解析失败: {e}")
|
||||
return None
|
||||
|
||||
sys.path.append(os.path.dirname(__file__)) # 确保能导入 py_utils
|
||||
from py_utils.coco_utils import COCO_test_helper
|
||||
from py_utils.rknn_executor import RKNN_model_container # 假设使用 RKNN
|
||||
@@ -269,6 +325,17 @@ class MultiCameraBirdView:
|
||||
"right": False
|
||||
}
|
||||
|
||||
# 雷达数据
|
||||
self.radar_distances = {
|
||||
"front": 0,
|
||||
"back": 0,
|
||||
"left": 0,
|
||||
"right": 0
|
||||
}
|
||||
self.radar_serial = None
|
||||
self.radar_thread = None
|
||||
self.radar_running = False
|
||||
|
||||
# === 新增:YOLO 人体检测模型 ===
|
||||
try:
|
||||
self.yolo_model = RKNN_model_container(YOLO_MODEL_PATH, target='rk3588')
|
||||
@@ -281,6 +348,9 @@ class MultiCameraBirdView:
|
||||
|
||||
self.shared_buffer = SharedFrameBuffer() # 👈 新增
|
||||
|
||||
# 初始化雷达串口
|
||||
self._init_radar_serial()
|
||||
|
||||
def overlay_alert(self, birdview_img):
|
||||
"""在鸟瞰图上叠加半透明红色预警区域"""
|
||||
h, w = birdview_img.shape[:2]
|
||||
@@ -369,6 +439,63 @@ class MultiCameraBirdView:
|
||||
print(f"[ERROR] YOLO检测失败: {e}")
|
||||
return image, [], []
|
||||
|
||||
def _init_radar_serial(self):
|
||||
"""
|
||||
初始化雷达串口并启动数据读取线程
|
||||
"""
|
||||
try:
|
||||
self.radar_serial = serial.Serial(
|
||||
port=RADAR_SERIAL_PORT,
|
||||
baudrate=RADAR_BAUDRATE,
|
||||
timeout=RADAR_TIMEOUT
|
||||
)
|
||||
print(f"✅ 已打开雷达串口 {RADAR_SERIAL_PORT}")
|
||||
|
||||
# 启动雷达数据读取线程
|
||||
self.radar_running = True
|
||||
self.radar_thread = threading.Thread(target=self._read_radar_data, daemon=True)
|
||||
self.radar_thread.start()
|
||||
print("[INFO] 雷达数据读取线程已启动")
|
||||
|
||||
except serial.SerialException as e:
|
||||
print(f"❌ 无法打开雷达串口 {RADAR_SERIAL_PORT}: {e}")
|
||||
self.radar_serial = None
|
||||
except Exception as e:
|
||||
print(f"[ERROR] 雷达初始化失败: {e}")
|
||||
self.radar_serial = None
|
||||
|
||||
def _read_radar_data(self):
|
||||
"""
|
||||
雷达数据读取线程函数
|
||||
"""
|
||||
buffer = b''
|
||||
while self.radar_running and self.radar_serial and self.radar_serial.is_open:
|
||||
try:
|
||||
# 读取可用数据
|
||||
if self.radar_serial.in_waiting > 0:
|
||||
data = self.radar_serial.read(self.radar_serial.in_waiting)
|
||||
buffer += data
|
||||
|
||||
# 尝试解析数据
|
||||
parsed_data = parse_radar_data(buffer)
|
||||
|
||||
if parsed_data:
|
||||
print(f"[RADAR] 前:{parsed_data.get('front', 0):4d}cm 后:{parsed_data.get('back', 0):4d}cm 左:{parsed_data.get('left', 0):4d}cm 右:{parsed_data.get('right', 0):4d}cm")
|
||||
|
||||
# 更新雷达距离数据
|
||||
self.radar_distances.update(parsed_data)
|
||||
# 清空已解析的缓冲区
|
||||
buffer = buffer[buffer.find(b'\x5A\xA5')+2:]
|
||||
|
||||
time.sleep(0.01) # 降低CPU占用
|
||||
|
||||
except serial.SerialException as e:
|
||||
print(f"❌ 雷达串口异常: {e}")
|
||||
break
|
||||
except Exception as e:
|
||||
print(f"[ERROR] 雷达数据读取失败: {e}")
|
||||
time.sleep(0.1)
|
||||
|
||||
def _initialize_weights(self):
|
||||
try:
|
||||
images = [os.path.join(os.getcwd(), "images", name + ".png") for name in self.names]
|
||||
@@ -405,6 +532,9 @@ class MultiCameraBirdView:
|
||||
frame_count = 0
|
||||
detection_interval = 3 # 每5帧进行一次检测,避免性能问题
|
||||
|
||||
# 雷达触发视图切换的方向优先级(距离过近时优先显示哪个方向)
|
||||
radar_priority = ['front', 'left', 'right', 'back']
|
||||
|
||||
while self.running:
|
||||
raw_frames = {}
|
||||
processed_frames = []
|
||||
@@ -414,7 +544,7 @@ class MultiCameraBirdView:
|
||||
ret, frame = cap.read()
|
||||
|
||||
raw_frames[name] = frame
|
||||
# self.shared_buffer.update(raw_frames[current_view])
|
||||
|
||||
|
||||
p_frame = self.process_frame_once(frame, model)
|
||||
|
||||
@@ -427,6 +557,18 @@ class MultiCameraBirdView:
|
||||
self.birdview.make_white_balance()
|
||||
self.birdview.copy_car_image()
|
||||
|
||||
# 检查雷达距离,自动切换视图
|
||||
auto_switch_view = None
|
||||
for direction in radar_priority:
|
||||
distance = self.radar_distances.get(direction, 0)
|
||||
if distance > 0 and distance < DISTANCE_THRESHOLD:
|
||||
auto_switch_view = direction
|
||||
break
|
||||
|
||||
if auto_switch_view:
|
||||
current_view = auto_switch_view
|
||||
print(f"[INFO] 雷达检测到{auto_switch_view}方向距离过近 ({self.radar_distances[auto_switch_view]}cm),自动切换视图")
|
||||
|
||||
# 获取单路图像(仅去畸变)
|
||||
single_img = self.process_frame_undistort(
|
||||
raw_frames[current_view],
|
||||
@@ -465,48 +607,22 @@ class MultiCameraBirdView:
|
||||
bird_resized = cv2.resize(birdview_with_alert, (w_bird, h_display))
|
||||
single_resized = cv2.resize(single_img, (w_single, h_display))
|
||||
display = np.hstack((bird_resized, single_resized))
|
||||
|
||||
|
||||
|
||||
|
||||
# 在显示窗口上添加状态信息
|
||||
# info_text = f"View: {current_view} | Persons detected: {len(person_boxes) if 'person_boxes' in locals() else 0}"
|
||||
# cv2.putText(display, info_text, (10, 30),
|
||||
# cv2.FONT_HERSHEY_SIMPLEX, 0.8, (255, 255, 255), 2)
|
||||
|
||||
self.shared_buffer.update(display)
|
||||
# 全屏显示
|
||||
cv2.namedWindow('Video', cv2.WND_PROP_FULLSCREEN)
|
||||
cv2.setWindowProperty('Video', cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN)
|
||||
cv2.imshow("Video", display)
|
||||
|
||||
key = cv2.waitKey(1) & 0xFF
|
||||
# if key == ord('q'):
|
||||
# self.running = False
|
||||
# break
|
||||
# elif key == ord('1'):
|
||||
# current_view = "front"
|
||||
# elif key == ord('2'):
|
||||
# current_view = "back"
|
||||
# elif key == ord('3'):
|
||||
# current_view = "left"
|
||||
# elif key == ord('4'):
|
||||
# current_view = "right"
|
||||
# # 新增:预警控制
|
||||
# elif key == ord('5'):
|
||||
# self.alerts["front"] = True
|
||||
# elif key == ord('6'):
|
||||
# self.alerts["back"] = True
|
||||
# elif key == ord('7'):
|
||||
# self.alerts["left"] = True
|
||||
# elif key == ord('8'):
|
||||
# self.alerts["right"] = True
|
||||
# elif key == ord('0'):
|
||||
# # 清除所有预警
|
||||
# for k in self.alerts:
|
||||
# self.alerts[k] = False
|
||||
# elif key == ord('d'):
|
||||
# # 手动触发一次检测
|
||||
# single_img, person_boxes, person_scores = self.detect_persons(single_img)
|
||||
|
||||
|
||||
# 清理雷达资源
|
||||
self.radar_running = False
|
||||
if self.radar_thread and self.radar_thread.is_alive():
|
||||
self.radar_thread.join(timeout=1.0)
|
||||
if self.radar_serial and self.radar_serial.is_open:
|
||||
self.radar_serial.close()
|
||||
print("🔌 雷达串口已关闭")
|
||||
|
||||
for cap in self.caps:
|
||||
cap.release()
|
||||
|
||||
@@ -4,14 +4,14 @@ camera_matrix: !!opencv-matrix
|
||||
rows: 3
|
||||
cols: 3
|
||||
dt: d
|
||||
data: [ 5.3042094228516248e+02, 0., 9.5131550663475389e+02, 0.,
|
||||
5.3026569308499541e+02, 5.3695007291032755e+02, 0., 0., 1. ]
|
||||
data: [ 5.2332271672164040e+02, 0., 9.3044951906127255e+02, 0.,
|
||||
5.2236471571534673e+02, 5.4345769772632696e+02, 0., 0., 1. ]
|
||||
dist_coeffs: !!opencv-matrix
|
||||
rows: 4
|
||||
cols: 1
|
||||
dt: d
|
||||
data: [ -9.2062464083377798e-03, -6.3620029090856196e-03,
|
||||
3.3735324773401221e-03, -1.0289639180500810e-03 ]
|
||||
data: [ -5.9498237920217710e-03, -1.0006293350185162e-03,
|
||||
5.3026728708821542e-03, -4.5615699893810256e-03 ]
|
||||
resolution: !!opencv-matrix
|
||||
rows: 2
|
||||
cols: 1
|
||||
@@ -21,10 +21,10 @@ project_matrix: !!opencv-matrix
|
||||
rows: 3
|
||||
cols: 3
|
||||
dt: d
|
||||
data: [ -2.2036739433214386e-01, -5.4728752801607983e-01,
|
||||
4.0669019104227289e+02, -2.2188976198317060e-02,
|
||||
-5.6384233390057015e-01, 3.2888161676725548e+02,
|
||||
-8.4090277960475698e-05, -2.2171947701663608e-03, 1. ]
|
||||
data: [ -3.9668895968930029e-01, -8.7369111224637641e-01,
|
||||
5.0478302196710462e+02, -6.4056023932043557e-02,
|
||||
-8.8811555523036101e-01, 3.8160313264225226e+02,
|
||||
-2.2060551352011550e-04, -3.5783374044860163e-03, 1. ]
|
||||
scale_xy: !!opencv-matrix
|
||||
rows: 2
|
||||
cols: 1
|
||||
@@ -34,4 +34,4 @@ shift_xy: !!opencv-matrix
|
||||
rows: 2
|
||||
cols: 1
|
||||
dt: f
|
||||
data: [ -150., -100. ]
|
||||
data: [ -150., -300. ]
|
||||
|
||||
@@ -4,14 +4,14 @@ camera_matrix: !!opencv-matrix
|
||||
rows: 3
|
||||
cols: 3
|
||||
dt: d
|
||||
data: [ 5.3382445956203196e+02, 0., 9.7253025945442369e+02, 0.,
|
||||
5.3393792084343488e+02, 5.6249605531924215e+02, 0., 0., 1. ]
|
||||
data: [ 5.3803744412978585e+02, 0., 9.5032314180353455e+02, 0.,
|
||||
5.3783453341561233e+02, 5.3627020384755701e+02, 0., 0., 1. ]
|
||||
dist_coeffs: !!opencv-matrix
|
||||
rows: 4
|
||||
cols: 1
|
||||
dt: d
|
||||
data: [ -1.5749135021037808e-02, 2.9390620422222835e-03,
|
||||
-4.3176357910129585e-03, 1.3296605027646462e-03 ]
|
||||
data: [ -1.6431143641380805e-02, -7.4804038255179171e-03,
|
||||
9.8754634365867712e-03, -4.6136179081623443e-03 ]
|
||||
resolution: !!opencv-matrix
|
||||
rows: 2
|
||||
cols: 1
|
||||
@@ -21,10 +21,10 @@ project_matrix: !!opencv-matrix
|
||||
rows: 3
|
||||
cols: 3
|
||||
dt: d
|
||||
data: [ -1.8474101274061588e-01, -5.4968582653196851e-01,
|
||||
4.1680109927253847e+02, 9.7678250049304510e-03,
|
||||
-4.9902821258073782e-01, 3.0304882941065989e+02,
|
||||
4.3706314843734903e-05, -2.1601287734653030e-03, 1. ]
|
||||
data: [ -4.1308938086273067e-01, -1.2364750670379583e+00,
|
||||
6.1409164370210317e+02, 1.5629889919431476e-02,
|
||||
-1.2402139306547297e+00, 4.4475253192373538e+02,
|
||||
1.6633363942594040e-04, -4.9162230937539594e-03, 1. ]
|
||||
scale_xy: !!opencv-matrix
|
||||
rows: 2
|
||||
cols: 1
|
||||
@@ -34,4 +34,4 @@ shift_xy: !!opencv-matrix
|
||||
rows: 2
|
||||
cols: 1
|
||||
dt: f
|
||||
data: [ -150., -100. ]
|
||||
data: [ -150., -300. ]
|
||||
|
||||
@@ -4,14 +4,14 @@ camera_matrix: !!opencv-matrix
|
||||
rows: 3
|
||||
cols: 3
|
||||
dt: d
|
||||
data: [ 5.3576790643136087e+02, 0., 9.5266112763930198e+02, 0.,
|
||||
5.3494293886479875e+02, 5.4089729625135715e+02, 0., 0., 1. ]
|
||||
data: [ 5.3234956441219367e+02, 0., 1.0016510548547229e+03, 0.,
|
||||
5.3229861100984783e+02, 5.4667741130363822e+02, 0., 0., 1. ]
|
||||
dist_coeffs: !!opencv-matrix
|
||||
rows: 4
|
||||
cols: 1
|
||||
dt: d
|
||||
data: [ -1.1422407725638895e-02, -1.2103818796148216e-02,
|
||||
9.0774770002077006e-03, -2.8278270352926444e-03 ]
|
||||
data: [ -2.1940734474311458e-02, 2.5390922658033822e-02,
|
||||
-2.7187547373220645e-02, 9.2193950144527706e-03 ]
|
||||
resolution: !!opencv-matrix
|
||||
rows: 2
|
||||
cols: 1
|
||||
@@ -21,10 +21,10 @@ project_matrix: !!opencv-matrix
|
||||
rows: 3
|
||||
cols: 3
|
||||
dt: d
|
||||
data: [ -2.0080056297490056e-01, -6.1187781235143224e-01,
|
||||
4.5434494858537062e+02, -2.9556627352318810e-03,
|
||||
-5.0502143174738201e-01, 3.0816263946657051e+02,
|
||||
-1.8229281242150158e-05, -2.1645728959083397e-03, 1. ]
|
||||
data: [ -4.9054850784465642e-01, -1.3514497357056201e+00,
|
||||
7.0604177518052268e+02, 1.0522109557771796e-02,
|
||||
-1.1178584461183012e+00, 4.4274468178801629e+02,
|
||||
8.2723610754286312e-05, -4.9130349378573015e-03, 1. ]
|
||||
scale_xy: !!opencv-matrix
|
||||
rows: 2
|
||||
cols: 1
|
||||
@@ -34,4 +34,4 @@ shift_xy: !!opencv-matrix
|
||||
rows: 2
|
||||
cols: 1
|
||||
dt: f
|
||||
data: [ -80., -100. ]
|
||||
data: [ -150., -300. ]
|
||||
|
||||
@@ -4,14 +4,14 @@ camera_matrix: !!opencv-matrix
|
||||
rows: 3
|
||||
cols: 3
|
||||
dt: d
|
||||
data: [ 5.3402108990030604e+02, 0., 9.2598444295282172e+02, 0.,
|
||||
5.3455325152709827e+02, 5.7771767919091610e+02, 0., 0., 1. ]
|
||||
data: [ 5.2209622748686536e+02, 0., 9.5144634774080509e+02, 0.,
|
||||
5.2226989398345188e+02, 5.3766700145639288e+02, 0., 0., 1. ]
|
||||
dist_coeffs: !!opencv-matrix
|
||||
rows: 4
|
||||
cols: 1
|
||||
dt: d
|
||||
data: [ -1.8724887233075402e-02, 6.4408558584901701e-03,
|
||||
-5.2069636709412993e-03, 8.4815411645490968e-04 ]
|
||||
data: [ -8.0625649755334261e-03, 1.9229042307457818e-02,
|
||||
-1.6765217009295411e-02, 2.3943754181756584e-03 ]
|
||||
resolution: !!opencv-matrix
|
||||
rows: 2
|
||||
cols: 1
|
||||
@@ -21,10 +21,10 @@ project_matrix: !!opencv-matrix
|
||||
rows: 3
|
||||
cols: 3
|
||||
dt: d
|
||||
data: [ -2.0592797222758674e-01, -6.8891188079230814e-01,
|
||||
4.5964514365855666e+02, 2.1763027489573539e-02,
|
||||
-6.3287857963783611e-01, 3.4166476009354983e+02,
|
||||
1.3350446934563321e-04, -2.6387220529307219e-03, 1. ]
|
||||
data: [ -2.5531960850826479e-01, -8.5968191881593725e-01,
|
||||
5.2529047158069864e+02, 2.8508251494131515e-02,
|
||||
-6.9799661435239291e-01, 3.3028662032142546e+02,
|
||||
1.4612833761795866e-04, -3.1783223690618283e-03, 1. ]
|
||||
scale_xy: !!opencv-matrix
|
||||
rows: 2
|
||||
cols: 1
|
||||
@@ -34,4 +34,4 @@ shift_xy: !!opencv-matrix
|
||||
rows: 2
|
||||
cols: 1
|
||||
dt: f
|
||||
data: [ -80., -100. ]
|
||||
data: [ -80., -200. ]
|
||||
|
||||