From a5c964516a7262c6f50ba56b432da2cf788e224a Mon Sep 17 00:00:00 2001 From: Hongru Date: Thu, 16 Oct 2025 14:34:16 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=BA=86=E4=B8=80=E7=89=88?= =?UTF-8?q?=E8=8A=B1=E9=87=8C=E8=83=A1=E5=93=A8=E7=9A=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- QUICK_START.md | 121 ----- README_MODULE.md | 284 ++++++++++ app.py | 1351 ++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 1517 insertions(+), 239 deletions(-) delete mode 100644 QUICK_START.md create mode 100644 README_MODULE.md diff --git a/QUICK_START.md b/QUICK_START.md deleted file mode 100644 index 6a9bffd..0000000 --- a/QUICK_START.md +++ /dev/null @@ -1,121 +0,0 @@ -# 🚀 5分钟快速上手指南 - -本指南帮助您快速配置并运行自动控制原理AI+数智平台。 - -## ⚡ 快速开始(3 步完成) - -### 步骤 1:安装依赖 - -```bash -pip install gradio numpy control matplotlib aiohttp -``` - -### 步骤 2:配置 API - -编辑 `app.py` 第 24 行,填入您的 DeepSeek API 密钥: - -```python -API_KEY = "sk-your-api-key-here" # 替换为您的密钥 -``` - -**获取密钥**:访问 https://platform.deepseek.com/api_keys - -### 步骤 3:运行应用 - -```bash -python app.py -``` - -浏览器会自动打开 http://localhost:7860 - ---- - -## 🎯 第一次使用 - -### 试试时域分析 - -1. 在"时域分析"标签页 -2. 输入传递函数: - - 分子:`1` - - 分母:`1,2,1` -3. 点击"开始分析" -4. 观察阶跃响应曲线和性能指标 - -### 试试 AI 问答 - -1. 切换到"智能问答"标签页 -2. 输入问题:`什么是 PID 控制器?` -3. 点击"发送" -4. AI 会实时回复并渲染数学公式 - ---- - -## 💡 常用传递函数示例 - -### 一阶系统 -``` -分子: 1 -分母: 1,1 -G(s) = 1/(s+1) -``` - -### 二阶欠阻尼系统 -``` -分子: 4 -分母: 1,2,4 -G(s) = 4/(s²+2s+4) -阻尼比 ζ = 0.5,超调量约 16% -``` - -### 三阶系统 -``` -分子: 1 -分母: 1,6,11,6 -G(s) = 1/[(s+1)(s+2)(s+3)] -``` - ---- - -## 🔧 故障排查 - -### 问题 1:模块导入错误 - -``` -ModuleNotFoundError: No module named 'gradio' -``` - -**解决**:重新安装依赖 -```bash -pip install -r requirements.txt -``` - -### 问题 2:API 密钥错误 - -``` -❌ 错误:API_KEY 未配置 -``` - -**解决**:确认 `app.py` 第 24 行已填入有效密钥 - -### 问题 3:中文乱码 - -**解决**:确保终端支持 UTF-8 编码 -```powershell -# Windows PowerShell -chcp 65001 -``` - ---- - -## 📚 下一步 - -- 阅读完整 [README.md](README.md) -- 查看 [API 配置详细说明](API_CONFIG.md) -- 探索四大功能模块 -- 调整系统增益观察变化 - ---- - -**需要帮助?** 查看 [常见问题](API_CONFIG.md#常见问题) 或提交 Issue。 - -祝学习愉快!🎓 diff --git a/README_MODULE.md b/README_MODULE.md new file mode 100644 index 0000000..a3998ff --- /dev/null +++ b/README_MODULE.md @@ -0,0 +1,284 @@ +# 自动控制原理AI+数智平台 - 模块化架构说明 + +## 📁 项目结构 + +``` +AutoControl/ +├── app.py # 原始完整程序(已废弃,保留作参考) +├── app_main.py # 新的主程序入口 ⭐ 使用这个启动 +├── config.py # 配置文件:API密钥、系统参数 +├── utils.py # 工具函数:解析、验证、格式化 +├── analysis.py # 分析功能:时域、频域、根轨迹 +├── ai_chat.py # AI聊天:DeepSeek/Gemini接口 +├── ui_styles.py # CSS样式:480+行现代化样式 +├── ui_components.py # UI组件:横幅、知识卡片HTML +└── README_MODULE.md # 本文件 +``` + +## 🚀 快速开始 + +### 方法1:使用新的模块化主程序(推荐) + +```bash +python app_main.py +``` + +### 方法2:使用原始完整程序 + +```bash +python app.py +``` + +## 📦 模块说明 + +### 1. `config.py` - 配置管理 +**功能:** 集中管理所有配置常量 + +**内容:** +- `API_KEY`: DeepSeek API密钥 +- `API_BASE_URL`: API基础URL +- `API_MODEL`: 使用的模型名称 +- `DEFAULT_NUM_COEFFS`: 默认分子系数 +- `DEFAULT_DEN_COEFFS`: 默认分母系数 +- `TIME_SPAN`: 时间范围设置 +- `SERVER_PORT`: 服务器端口 +- `PROJECT_INFO`: 项目信息字典 + +**修改配置:** +```python +# 在 config.py 中修改 +API_KEY = "你的API密钥" +SERVER_PORT = 8080 # 更改端口 +``` + +### 2. `utils.py` - 工具函数库 +**功能:** 提供数据处理和格式化工具 + +**主要函数:** +- `coeffs_to_latex(coeffs, var='s')`: 系数转LaTeX多项式 +- `parse_coefficients(coeffs_str)`: 解析系数字符串 +- `validate_transfer_function(num, den)`: 验证传递函数 +- `format_complex_number(c)`: 格式化复数显示 + +**使用示例:** +```python +from utils import parse_coefficients, validate_transfer_function + +num = parse_coefficients("1,2,3") +den = parse_coefficients("1,4,5,2") +is_valid, msg = validate_transfer_function(num, den) +``` + +### 3. `analysis.py` - 核心分析功能 +**功能:** 控制系统的时域、频域、根轨迹分析 + +**主要函数:** +- `display_transfer_function(num_str, den_str)`: 显示传递函数 +- `time_domain_analysis(num_str, den_str)`: 时域分析(阶跃/脉冲响应) +- `frequency_domain_analysis(num_str, den_str, K)`: 频域分析(Bode/Nyquist图) +- `root_locus_analysis(num_str, den_str, log_k)`: 根轨迹分析 + +**返回值:** +- 图表:matplotlib Figure对象 +- 文本:性能指标、极点位置等 + +### 4. `ai_chat.py` - AI聊天功能 +**功能:** 与DeepSeek/Gemini大模型交互 + +**主要函数:** +- `chat_with_ai(message, history)`: 异步聊天函数(支持流式输出) + +**特点:** +- 支持对话历史记录 +- 流式响应(实时显示) +- 自动错误处理 +- Emoji状态指示 + +**系统提示词:** +``` +你是一位精通自动控制原理的专家教授,擅长用通俗易懂的方式解释复杂概念。 +回答要准确、专业,适当使用LaTeX公式,并举例说明。 +``` + +### 5. `ui_styles.py` - CSS样式定义 +**功能:** 提供480+行现代化CSS样式 + +**函数:** +- `get_custom_css()`: 返回完整CSS字符串 + +**样式特点:** +- 渐变背景和阴影效果 +- 动画过渡效果 +- 响应式设计(移动端适配) +- 暗色主题支持 +- Emoji彩色显示修复 + +### 6. `ui_components.py` - UI组件库 +**功能:** 提供HTML组件和知识卡片 + +**主要函数:** +- `get_main_title()`: 主标题 +- `get_subtitle()`: 副标题 +- `get_project_info_banner()`: 项目信息横幅 +- `get_tab_tip(tab_name)`: 标签页提示 +- `get_time_domain_knowledge_card()`: 时域知识卡片 +- `get_frequency_domain_knowledge_card()`: 频域知识卡片 +- `get_root_locus_knowledge_card()`: 根轨迹知识卡片 +- `get_ai_example_questions()`: AI示例问题 + +### 7. `app_main.py` - 主程序入口 +**功能:** 简化的主程序,组装所有模块 + +**代码行数:** ~350行(相比原来的2134行减少84%) + +**结构:** +```python +# 导入所有模块 +from config import * +from utils import * +from analysis import * +from ai_chat import * +from ui_styles import * +from ui_components import * + +# 使用Gradio构建UI +with gr.Blocks(css=get_custom_css()) as demo: + # UI布局 + # 事件绑定 + pass + +# 启动服务器 +demo.launch() +``` + +## 🎯 模块化的优势 + +### 1. 易于维护 +- 每个模块职责单一,代码清晰 +- 修改某个功能只需编辑对应模块 +- 减少代码重复,提高复用性 + +### 2. 易于扩展 +- 添加新功能:创建新模块或在现有模块添加函数 +- 添加新UI:在`ui_components.py`添加新函数 +- 添加新样式:在`ui_styles.py`修改CSS + +### 3. 易于调试 +- 模块独立,可单独测试 +- 错误定位更快速 +- 日志和异常处理更精确 + +### 4. 团队协作友好 +- 不同开发者可并行工作在不同模块 +- 代码冲突减少 +- 代码审查更高效 + +## 📝 常见修改场景 + +### 场景1:更改API密钥 +**文件:** `config.py` +```python +API_KEY = "sk-新的密钥" +``` + +### 场景2:添加新的分析功能 +**文件:** `analysis.py` +```python +def new_analysis_function(num_str, den_str): + """新的分析功能""" + # 实现代码 + return figure, metrics +``` + +**文件:** `app_main.py`(添加UI和事件绑定) +```python +from analysis import new_analysis_function + +# 添加UI组件 +new_button = gr.Button("新分析") +new_output = gr.Plot() + +# 绑定事件 +new_button.click(fn=new_analysis_function, inputs=[...], outputs=[...]) +``` + +### 场景3:修改知识卡片内容 +**文件:** `ui_components.py` +```python +def get_time_domain_knowledge_card(): + return """ +
+ +
+ """ +``` + +### 场景4:调整样式颜色 +**文件:** `ui_styles.py` +```python +def get_custom_css(): + return """ + .main-title { + background: linear-gradient(135deg, #新颜色1, #新颜色2); + } + """ +``` + +### 场景5:更改默认参数 +**文件:** `config.py` +```python +DEFAULT_DEN_COEFFS = "1,8,15,8" # 更改默认分母系数 +SERVER_PORT = 8080 # 更改服务器端口 +``` + +## 🔧 依赖库 + +```txt +gradio>=5.0.0 +numpy>=1.21.0 +matplotlib>=3.5.0 +scipy>=1.7.0 +control>=0.9.0 +aiohttp>=3.8.0 # AI聊天功能 +``` + +**安装命令:** +```bash +pip install gradio numpy matplotlib scipy control aiohttp +``` + +## ⚠️ 注意事项 + +1. **首次运行:** 需要在`config.py`中配置DeepSeek API密钥才能使用AI聊天功能 +2. **端口冲突:** 如果7860端口被占用,修改`config.py`中的`SERVER_PORT` +3. **模块导入:** 所有模块必须在同一目录下 +4. **Python版本:** 建议使用Python 3.8+ + +## 📊 代码对比 + +| 指标 | 原版 (app.py) | 模块化版本 | +|-----|--------------|-----------| +| 总代码行数 | 2134行 | 分散在7个文件 | +| 主程序行数 | 2134行 | 350行 (↓84%) | +| 可维护性 | ⭐⭐ | ⭐⭐⭐⭐⭐ | +| 可扩展性 | ⭐⭐ | ⭐⭐⭐⭐⭐ | +| 团队协作 | ⭐⭐ | ⭐⭐⭐⭐⭐ | + +## 🎓 学习建议 + +1. **初学者:** 先运行`app_main.py`,熟悉整体功能 +2. **进阶学习:** 阅读各模块代码,理解功能实现 +3. **高级应用:** 尝试添加新功能或修改现有模块 +4. **问题排查:** 参考模块注释和本文档 + +## 📮 联系方式 + +**项目负责人:** 魏鹏飞 教授 +**邮箱:** pengfeiwei@nwpu.edu.cn +**单位:** 西北工业大学 +**资助:** 2025年校级本科生建设项目 + +--- + +**最后更新:** 2025年1月 +**版本:** 2.0 (模块化架构) diff --git a/app.py b/app.py index 4e71f20..65e4217 100644 --- a/app.py +++ b/app.py @@ -408,143 +408,714 @@ async def chat_with_ai(message, history): # --- Gradio 界面定义 --- -# 自定义 CSS 样式 +# 自定义 CSS 样式 - 全面现代化升级 custom_css = """ -/* 整体界面样式优化 */ -.gradio-container { - font-family: 'Segoe UI', Arial, sans-serif !important; +/* ==================== 全局样式 ==================== */ +* { + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); } -/* 标题样式 */ +.gradio-container { + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Helvetica Neue', Arial, sans-serif !important; + background: linear-gradient(135deg, #f5f7fa 0%, #e8eef5 100%) !important; +} + +/* ==================== Emoji 显示修复 ==================== */ +/* 确保所有 emoji 正常显示,不被背景色覆盖 */ +* { + font-feature-settings: "liga" 1, "calt" 1, "kern" 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +/* 针对 Gradio Markdown 组件的 emoji 修复 */ +.gr-markdown code { + background: transparent !important; + padding: 0 !important; + font-family: inherit !important; +} + +/* 确保 HTML 内容中的 emoji 不受影响 */ +.gr-html * { + background-clip: border-box !important; + -webkit-background-clip: border-box !important; + -webkit-text-fill-color: initial !important; +} + +/* ==================== 标题区域 ==================== */ .main-title { text-align: center; - background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + font-size: 3em !important; + font-weight: 900 !important; + margin-bottom: 0.3em; + letter-spacing: -1px; + animation: titleGlow 3s ease-in-out infinite; + color: #333; +} + +/* 标题渐变效果(不影响emoji) */ +h1.main-title { + background: linear-gradient(135deg, #667eea 0%, #764ba2 50%, #f093fb 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; - font-size: 2.5em !important; - font-weight: bold; - margin-bottom: 0.5em; + background-clip: text; +} + +@keyframes titleGlow { + 0%, 100% { filter: brightness(1); } + 50% { filter: brightness(1.2); } } .subtitle { text-align: center; - color: #666; - font-size: 1.1em; - margin-bottom: 2em; + color: #555; + font-size: 1.2em; + font-weight: 500; + margin-bottom: 1.5em; + letter-spacing: 0.5px; } -/* 可滚动的知识卡片 */ -.knowledge-card { - background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%); +/* 确保 subtitle 中的 emoji 正常显示 */ +p.subtitle { + color: #555 !important; +} + +/* ==================== 项目信息横幅 ==================== */ +.project-info-banner { + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + color: white; + padding: 15px 20px; border-radius: 12px; - padding: 20px; - margin-top: 20px; - box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); - max-height: 500px; - overflow-y: auto; + margin-bottom: 25px; + box-shadow: 0 8px 32px rgba(102, 126, 234, 0.3); + animation: bannerSlide 0.6s ease-out; } -.knowledge-card::-webkit-scrollbar { - width: 8px; +@keyframes bannerSlide { + from { transform: translateY(-20px); opacity: 0; } + to { transform: translateY(0); opacity: 1; } } -.knowledge-card::-webkit-scrollbar-track { - background: #f1f1f1; - border-radius: 10px; +/* ==================== 标签页样式 ==================== */ +.tab-nav { + background: white; + border-radius: 12px; + padding: 8px; + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08); + margin-bottom: 20px; } -.knowledge-card::-webkit-scrollbar-thumb { - background: #888; - border-radius: 10px; -} - -.knowledge-card::-webkit-scrollbar-thumb:hover { - background: #555; -} - -/* 按钮样式优化 */ -.primary-btn { - background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important; +.tab-nav button { + font-weight: 600 !important; + font-size: 1.1em !important; + padding: 12px 24px !important; + border-radius: 8px !important; border: none !important; - color: white !important; - font-weight: bold !important; - transition: transform 0.2s; + transition: all 0.3s ease !important; } -.primary-btn:hover { - transform: translateY(-2px); +.tab-nav button:hover { + background: linear-gradient(135deg, #667eea15 0%, #764ba215 100%) !important; + transform: translateY(-2px) !important; +} + +.tab-nav button.selected { + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important; + color: white !important; box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4) !important; } -/* 标签页样式 */ -.tab-nav button { - font-weight: 600 !important; - font-size: 1.05em !important; +/* ==================== 卡片和分组样式 ==================== */ +.gr-group { + background: white !important; + border-radius: 16px !important; + padding: 24px !important; + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.08) !important; + border: 1px solid rgba(102, 126, 234, 0.1) !important; + margin-bottom: 20px !important; + transition: transform 0.3s ease, box-shadow 0.3s ease !important; } -/* 图表容器 */ -.plot-container { - border-radius: 12px; - box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); - overflow: hidden; -} - -/* 输入框样式 */ -.input-section { - background: #f8f9fa; - border-radius: 8px; - padding: 15px; - margin-bottom: 15px; +.gr-group:hover { + transform: translateY(-4px) !important; + box-shadow: 0 12px 48px rgba(102, 126, 234, 0.15) !important; } /* 卡片标题 */ .card-title { - font-size: 1.3em; - font-weight: bold; + font-size: 1.4em; + font-weight: 700; + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; + margin-bottom: 15px; + border-bottom: 3px solid; + border-image: linear-gradient(90deg, #667eea, #764ba2) 1; + padding-bottom: 10px; + display: flex; + align-items: center; + gap: 8px; +} + +/* 修复 emoji 显示问题 - emoji 不应用渐变色 */ +.card-title::before { + content: ''; + display: inline-block; +} + +/* 确保 HTML 内的 emoji 正常显示 */ +div.card-title { + background: transparent !important; + -webkit-background-clip: initial !important; + -webkit-text-fill-color: initial !important; + background-clip: initial !important; + color: #333 !important; +} + +/* 只对文字部分应用渐变(如果需要) */ +div.card-title span { + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; +} + +/* ==================== 输入框样式 ==================== */ +.gr-textbox input, .gr-textbox textarea { + border: 2px solid #e0e7ff !important; + border-radius: 10px !important; + padding: 12px 16px !important; + font-size: 1em !important; + transition: all 0.3s ease !important; + background: #fafbff !important; +} + +.gr-textbox input:focus, .gr-textbox textarea:focus { + border-color: #667eea !important; + box-shadow: 0 0 0 4px rgba(102, 126, 234, 0.1) !important; + background: white !important; + transform: translateY(-2px); +} + +.gr-textbox label { + font-weight: 600 !important; + color: #4a5568 !important; + margin-bottom: 8px !important; +} + +/* ==================== 按钮样式 ==================== */ +button { + border-radius: 10px !important; + font-weight: 600 !important; + padding: 12px 24px !important; + font-size: 1em !important; + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important; + border: none !important; + cursor: pointer !important; +} + +.primary-btn, button[variant="primary"] { + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important; + color: white !important; + box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4) !important; +} + +.primary-btn:hover, button[variant="primary"]:hover { + transform: translateY(-3px) scale(1.02) !important; + box-shadow: 0 8px 25px rgba(102, 126, 234, 0.5) !important; +} + +.primary-btn:active, button[variant="primary"]:active { + transform: translateY(-1px) scale(0.98) !important; +} + +button[variant="secondary"] { + background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%) !important; + color: white !important; + box-shadow: 0 4px 15px rgba(240, 147, 251, 0.4) !important; +} + +button[variant="secondary"]:hover { + transform: translateY(-3px) scale(1.02) !important; + box-shadow: 0 8px 25px rgba(240, 147, 251, 0.5) !important; +} + +/* ==================== 滑块样式 ==================== */ +.gr-slider { + padding: 20px 10px !important; +} + +.gr-slider input[type="range"] { + height: 8px !important; + border-radius: 4px !important; + background: linear-gradient(90deg, #667eea 0%, #764ba2 100%) !important; +} + +.gr-slider input[type="range"]::-webkit-slider-thumb { + width: 20px !important; + height: 20px !important; + background: white !important; + border: 3px solid #667eea !important; + box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4) !important; + cursor: pointer !important; +} + +.gr-slider input[type="range"]::-webkit-slider-thumb:hover { + transform: scale(1.2) !important; + box-shadow: 0 6px 20px rgba(102, 126, 234, 0.6) !important; +} + +/* ==================== 图表容器 ==================== */ +.plot-container { + border-radius: 16px !important; + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.08) !important; + overflow: hidden !important; + background: white !important; + padding: 10px !important; + border: 1px solid rgba(102, 126, 234, 0.1) !important; +} + +.gr-plot { + border-radius: 12px !important; +} + +/* ==================== 知识卡片 ==================== */ +.knowledge-card { + background: linear-gradient(135deg, #ffffff 0%, #f8f9ff 100%); + border-radius: 16px; + padding: 24px; + margin-top: 20px; + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.08); + max-height: 550px; + overflow-y: auto; + border: 1px solid rgba(102, 126, 234, 0.15); + animation: cardFadeIn 0.6s ease-out; +} + +@keyframes cardFadeIn { + from { opacity: 0; transform: translateY(20px); } + to { opacity: 1; transform: translateY(0); } +} + +.knowledge-card::-webkit-scrollbar { + width: 10px; +} + +.knowledge-card::-webkit-scrollbar-track { + background: #f1f3f9; + border-radius: 10px; +} + +.knowledge-card::-webkit-scrollbar-thumb { + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + border-radius: 10px; + border: 2px solid #f1f3f9; +} + +.knowledge-card::-webkit-scrollbar-thumb:hover { + background: linear-gradient(135deg, #5568d3 0%, #65408b 100%); +} + +.knowledge-card h3 { + color: #667eea; + font-size: 1.5em; + font-weight: 700; + margin-top: 0; + margin-bottom: 20px; + padding-bottom: 12px; + border-bottom: 3px solid; + border-image: linear-gradient(90deg, #667eea, #764ba2) 1; +} + +/* 知识卡片标题中的 emoji 保持彩色 */ +.knowledge-card h3::first-letter { + color: inherit; +} + +.knowledge-card h4 { + color: #4a5568; + font-size: 1.2em; + font-weight: 600; + margin-top: 20px; + margin-bottom: 12px; +} + +.knowledge-card details { + margin: 15px 0; + border-radius: 8px; + overflow: hidden; +} + +.knowledge-card details summary { + cursor: pointer; + padding: 12px 16px; + font-weight: 700; + border-radius: 8px; + transition: all 0.3s ease; + user-select: none; color: #333; + font-size: 1.05em; +} + +.knowledge-card details summary:hover { + transform: translateX(5px); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); + filter: brightness(0.98); +} + +.knowledge-card details[open] summary { margin-bottom: 10px; - border-bottom: 3px solid #667eea; - padding-bottom: 8px; + border-radius: 8px 8px 0 0; +} + +.knowledge-card table { + border-collapse: collapse; + width: 100%; + margin: 15px 0; + font-size: 0.95em; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05); + border-radius: 8px; + overflow: hidden; +} + +.knowledge-card table th { + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + color: white; + padding: 12px; + font-weight: 700; +} + +.knowledge-card table td { + padding: 10px 12px; + border: 1px solid #e0e7ff; +} + +.knowledge-card table tr:hover { + background: #f8f9ff; + transition: background 0.2s ease; +} + +/* ==================== 聊天机器人样式 ==================== */ +.chatbot { + border-radius: 16px !important; + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.08) !important; + border: 1px solid rgba(102, 126, 234, 0.1) !important; +} + +/* 用户消息气泡 - 紫色渐变 + 白色文字 */ +.message.user { + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important; + color: white !important; + border-radius: 18px 18px 4px 18px !important; + padding: 12px 18px !important; + box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3) !important; +} + +/* 确保用户消息内的所有文字都是白色 */ +.message.user * { + color: white !important; +} + +/* 机器人消息气泡 - 白色背景 + 深色文字 */ +.message.bot { + background: white !important; + border: 1px solid #e0e7ff !important; + border-radius: 18px 18px 18px 4px !important; + padding: 12px 18px !important; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05) !important; + color: #2d3748 !important; +} + +/* 确保机器人消息内的文字清晰可见 */ +.message.bot * { + color: #2d3748 !important; +} + +.message.bot p { + color: #2d3748 !important; + line-height: 1.6 !important; + margin: 8px 0 !important; +} + +.message.bot strong { + color: #1a202c !important; + font-weight: 700 !important; +} + +.message.bot code { + background: #f7fafc !important; + color: #667eea !important; + padding: 2px 6px !important; + border-radius: 4px !important; + font-family: 'Consolas', 'Monaco', monospace !important; +} + +.message.bot pre { + background: #f7fafc !important; + border: 1px solid #e2e8f0 !important; + border-radius: 6px !important; + padding: 12px !important; + overflow-x: auto !important; +} + +.message.bot pre code { + background: transparent !important; + padding: 0 !important; +} + +/* ==================== 性能指标文本框 ==================== */ +.gr-textbox.output-metrics { + font-family: 'Consolas', 'Monaco', monospace !important; + background: linear-gradient(135deg, #f8f9ff 0%, #f0f4ff 100%) !important; + border: 2px solid #e0e7ff !important; + border-radius: 12px !important; + padding: 16px !important; + font-size: 0.95em !important; + line-height: 1.8 !important; +} + +/* ==================== 数字显示框 ==================== */ +.gr-number, .gain-display { + font-size: 1.3em !important; + font-weight: 700 !important; + color: #667eea !important; + text-align: center !important; + background: linear-gradient(135deg, #f8f9ff 0%, #f0f4ff 100%) !important; + border: 2px solid #667eea !important; + border-radius: 12px !important; + padding: 16px !important; +} + +.gain-display input { + text-align: center !important; + font-size: 1.5em !important; + font-weight: 800 !important; + color: #667eea !important; +} + +/* ==================== 输出显示框 ==================== */ +.output-display { + background: linear-gradient(135deg, #ffffff 0%, #f8f9ff 100%) !important; + padding: 20px !important; + border-radius: 12px !important; + border: 2px solid #e0e7ff !important; + min-height: 80px !important; +} + +.stability-result { + padding: 15px !important; + border-radius: 10px !important; + text-align: center !important; + font-size: 1.2em !important; + font-weight: 700 !important; + margin-top: 10px !important; +} + +/* ==================== 现代聊天机器人样式 ==================== */ +.modern-chatbot { + background: white !important; + border-radius: 16px !important; + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.08) !important; +} + +/* ==================== Markdown 样式增强 ==================== */ +.gr-markdown { + line-height: 1.8 !important; +} + +.gr-markdown h1, .gr-markdown h2, .gr-markdown h3 { + font-weight: 700 !important; + margin-top: 1.5em !important; + margin-bottom: 0.8em !important; +} + +.gr-markdown code { + background: #f0f4ff !important; + padding: 2px 8px !important; + border-radius: 4px !important; + font-family: 'Consolas', 'Monaco', monospace !important; + color: #667eea !important; + border: 1px solid #e0e7ff !important; +} + +.gr-markdown pre { + background: #f8f9ff !important; + border: 2px solid #e0e7ff !important; + border-radius: 8px !important; + padding: 16px !important; +} + +/* ==================== 加载动画 ==================== */ +@keyframes pulse { + 0%, 100% { opacity: 1; } + 50% { opacity: 0.6; } +} + +.loading { + animation: pulse 1.5s cubic-bezier(0.4, 0, 0.6, 1) infinite; +} + +/* ==================== 响应式设计 ==================== */ +@media (max-width: 768px) { + .main-title { + font-size: 2em !important; + } + + .subtitle { + font-size: 1em !important; + } + + .knowledge-card { + padding: 16px; + max-height: 400px; + } +} + +/* ==================== 暗色主题支持 ==================== */ +@media (prefers-color-scheme: dark) { + .gradio-container { + background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%) !important; + } + + .gr-group { + background: #0f3460 !important; + border-color: rgba(102, 126, 234, 0.3) !important; + } + + .knowledge-card { + background: linear-gradient(135deg, #0f3460 0%, #1a1a2e 100%); + border-color: rgba(102, 126, 234, 0.3); + } + + .knowledge-card h3, .knowledge-card h4 { + color: #a0aec0; + } +} + +/* ==================== 特殊效果 ==================== */ +.shimmer { + background: linear-gradient(90deg, + rgba(255,255,255,0) 0%, + rgba(255,255,255,0.3) 50%, + rgba(255,255,255,0) 100%); + animation: shimmer 2s infinite; +} + +@keyframes shimmer { + 0% { transform: translateX(-100%); } + 100% { transform: translateX(100%); } } """ -with gr.Blocks(title="自动控制原理学习网站", css=custom_css) as demo: - gr.Markdown("

自动控制原理AI+数智平台

") - gr.Markdown("

交互式控制系统分析与设计工具 | 时域·频域·根轨迹·AI问答

") +with gr.Blocks(title="自动控制原理学习网站 - AI+数智平台", css=custom_css) as demo: + # 主标题 - 带动画效果 + gr.HTML("

自动控制原理AI+数智平台

") + gr.HTML("

✨ 交互式控制系统分析与设计工具 | 时域·频域·根轨迹·AI问答 ✨

") - # 项目信息和版权声明 + # 项目信息横幅 - 优化对比度和可读性 gr.HTML(""" -
-

- 📚 课程:《自动控制理论》 | - 👨‍🏫 负责人:魏鹏飞 | - 📧 联系:pengfeiwei@nwpu.edu.cn -

-

- 🎓 西北工业大学2025年校级本科生建设项目资助 | Northwestern Polytechnical University -

+
+
+
+ 📚 +
+
课程 Course
+
自动控制理论
+
+
+ +
+ +
+ 👨‍🏫 +
+
负责人 Supervisor
+
魏鹏飞
+
+
+ +
+ +
+ 📧 +
+
联系方式 Contact
+ + pengfeiwei@nwpu.edu.cn + +
+
+
+ +
+ 🎓 + 西北工业大学 Northwestern Polytechnical University + | + 2025年校级本科生建设项目资助 +
""") with gr.Tabs() as tabs: - with gr.TabItem("时域分析 (Time Domain)", id=0): + with gr.TabItem("⏱️ 时域分析 (Time Domain)", id=0): + gr.HTML(""" +
+ + 💡 快速开始:输入传递函数的分子和分母系数(逗号分隔),点击"开始分析"查看系统响应特性 + +
+ """) with gr.Row(): with gr.Column(scale=1): with gr.Group(): - gr.Markdown("
📊 输入系统参数
") - num_input = gr.Textbox(label="传递函数分子系数 (Numerator)", value="1", placeholder="例如: 1 或 1,2,3") - den_input = gr.Textbox(label="传递函数分母系数 (Denominator)", value="1,6,11,6", placeholder="例如: 1,2,1") + gr.HTML("
📊 输入系统参数
") + num_input = gr.Textbox( + label="传递函数分子系数 (Numerator)", + value="1", + placeholder="例如: 1 或 1,2,3", + info="💡 用逗号分隔多个系数,从最高次项到常数项" + ) + den_input = gr.Textbox( + label="传递函数分母系数 (Denominator)", + value="1,6,11,6", + placeholder="例如: 1,2,1", + info="💡 分母阶数通常高于或等于分子阶数" + ) with gr.Row(): - confirm_button = gr.Button("✓ 显示传递函数", variant="secondary", scale=1) - analyze_button = gr.Button("🚀 开始分析", variant="primary", scale=1, elem_classes="primary-btn") + confirm_button = gr.Button( + "✓ 显示传递函数", + variant="secondary", + scale=1, + size="lg" + ) + analyze_button = gr.Button( + "🚀 开始分析", + variant="primary", + scale=1, + elem_classes="primary-btn", + size="lg" + ) with gr.Group(): - gr.Markdown("
🔧 系统模型
") - tf_display = gr.Markdown(label="当前传递函数") + gr.HTML("
🔧 系统模型
") + tf_display = gr.Markdown(label="当前传递函数", elem_classes="output-display") with gr.Group(): - gr.Markdown("
📈 动态性能指标
") - output_metrics = gr.Textbox(label="Performance Metrics", lines=8, interactive=False) + gr.HTML("
📈 动态性能指标
") + output_metrics = gr.Textbox( + label="Performance Metrics", + lines=8, + interactive=False, + elem_classes="output-metrics" + ) with gr.Column(scale=2): output_plot = gr.Plot(label="Time Response Curves", elem_classes="plot-container") @@ -554,7 +1125,11 @@ with gr.Blocks(title="自动控制原理学习网站", css=custom_css) as demo:

📚 常用公式 (Common Formulas)

-

二阶系统标准形式

+
+ + 📐 二阶系统标准形式 + +

对于一个典型的二阶系统,其标准传递函数形式为:

G(s) = ωn² / (s² + 2ζωns + ωn²)

@@ -577,8 +1152,14 @@ with gr.Blocks(title="自动控制原理学习网站", css=custom_css) as demo: +
+
-

时域性能指标(欠阻尼系统,0 < ζ < 1)

+
+ + 📊 时域性能指标(欠阻尼系统,0 < ζ < 1) + +
1️⃣ 上升时间 (Rise Time, tr) @@ -622,25 +1203,168 @@ with gr.Blocks(title="自动控制原理学习网站", css=custom_css) as demo:
• 单位抛物线输入:ess = 1/Ka

其中 Kp, Kv, Ka 分别为位置、速度、加速度误差常数

+
+
+ +
+ + 🎯 一阶系统特性 + +
+

标准传递函数:

+

G(s) = K / (τs + 1)

+ +

参数说明:

+
    +
  • K - 系统增益(稳态增益)
  • +
  • τ (tau) - 时间常数,单位:秒
  • +
+ +

阶跃响应:

+

y(t) = K(1 - e-t/τ)

+ +
+

💡 关键时间点:

+
    +
  • t = τ 时,响应达到稳态值的 63.2%
  • +
  • t = 3τ 时,响应达到稳态值的 95%
  • +
  • t = 4τ 时,响应达到稳态值的 98.2%
  • +
  • t = 5τ 时,响应达到稳态值的 99.3%
  • +
+
+ +

特点:一阶系统无超调,响应单调上升

+
+
+ +
+ + 🔄 系统类型与误差系数 + +
+

系统类型分类:

+

根据开环传递函数原点处的极点数(积分环节数)v 分类:

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
类型KpKvKa
0 型有限值00
I 型有限值0
II 型有限值
+ +

稳态误差计算:

+
    +
  • 阶跃输入 r(t) = R:ess = R/(1+Kp)
  • +
  • 斜坡输入 r(t) = Rt:ess = R/Kv
  • +
  • 抛物线输入 r(t) = Rt²/2:ess = R/Ka
  • +
+ +
+

⚡ 工程结论:

+

系统型别越高,跟踪能力越强,但稳定性可能降低。实际系统常用 I 型或 II 型。

+
+
+
+ +
+ + ⚙️ 主导极点与零点影响 + +
+

主导极点概念:

+

距虚轴最近的极点对系统动态响应起主导作用,其他极点影响较小。

+ +

判断条件:

+
    +
  • 主导极点与其他极点的实部相差 5倍以上
  • +
  • 主导极点与零点距离较远(相差3倍以上)
  • +
+ +

零点的影响:

+
+

🔺 左半平面零点(最小相位系统):

+
    +
  • 增加超调量
  • +
  • 减小上升时间
  • +
  • 零点越靠近极点,影响越大
  • +
+
+ +
+

🔻 右半平面零点(非最小相位系统):

+
    +
  • 引起反向响应(初始反向运动)
  • +
  • 增加调节时间
  • +
  • 降低系统性能
  • +
+
+
+
""") - with gr.TabItem("频域分析 (Frequency Domain)", id=1): + with gr.TabItem("📊 频域分析 (Frequency Domain)", id=1): + gr.HTML(""" +
+ + 💡 使用技巧:拖动增益滑块查看系统稳定性变化,观察Bode图和Nyquist图的实时更新 + +
+ """) with gr.Row(): with gr.Column(scale=1): with gr.Group(): - gr.Markdown("
🎚️ 调整系统增益
") - log_k_slider_freq = gr.Slider(minimum=-4, maximum=4, value=1, step=0.01, label="对数增益 log10(K)") - k_number_display_freq = gr.Number(value=10.0, label="增益 K (Gain)", interactive=False) + gr.HTML("
🎚️ 调整系统增益
") + log_k_slider_freq = gr.Slider( + minimum=-4, + maximum=4, + value=1, + step=0.01, + label="对数增益 log₁₀(K)", + info="💡 滑块范围:10⁻⁴ ~ 10⁴" + ) + k_number_display_freq = gr.Number( + value=10.0, + label="当前增益 K (Gain)", + interactive=False, + elem_classes="gain-display" + ) with gr.Group(): - gr.Markdown("
🔧 当前系统模型
") - freq_tf_display = gr.Markdown(label="含增益K的传递函数") + gr.HTML("
🔧 当前系统模型
") + freq_tf_display = gr.Markdown(label="含增益K的传递函数", elem_classes="output-display") with gr.Group(): - gr.Markdown("
📊 稳定裕度
") - freq_metrics_display = gr.Textbox(label="Stability Margins", lines=4, interactive=False) - freq_stability_display = gr.Markdown() + gr.HTML("
📊 稳定裕度分析
") + freq_metrics_display = gr.Textbox( + label="Stability Margins", + lines=4, + interactive=False, + elem_classes="output-metrics" + ) + freq_stability_display = gr.Markdown(elem_classes="stability-result") with gr.Column(scale=2): freq_plot_output = gr.Plot(label="Frequency Response Plots", elem_classes="plot-container") @@ -722,8 +1446,39 @@ with gr.Blocks(title="自动控制原理学习网站", css=custom_css) as demo:
- 📊 其他重要概念 + 📊 Bode图与Nyquist图
+

Bode图(伯德图)

+

组成:幅频特性图 + 相频特性图

+
    +
  • 横轴:频率 ω (对数刻度)
  • +
  • 纵轴(幅频):幅值 20log|G(jω)| (dB)
  • +
  • 纵轴(相频):相角 ∠G(jω) (度)
  • +
+ +
+

💡 优点:

+
    +
  • 便于绘制(用渐近线近似)
  • +
  • 直观读取稳定裕度
  • +
  • 便于串联系统分析(图形叠加)
  • +
+
+ +

Nyquist图(奈奎斯特图)

+

定义:开环频率特性 G(jω)H(jω) 在复平面上的轨迹图

+
    +
  • 横轴:实部 Re[G(jω)]
  • +
  • 纵轴:虚部 Im[G(jω)]
  • +
+ +
+

🎯 奈奎斯特稳定判据:

+

闭环系统稳定的充要条件:当 ω 从 -∞ 变化到 +∞ 时,Nyquist曲线逆时针包围(-1, j0)点的圈数 N 等于开环系统右半平面极点数 P。

+

Z = P - N

+

其中 Z 为闭环系统右半平面极点数

+
+

带宽 (Bandwidth, BW)

闭环频率响应的幅值下降到-3dB时的频率。BW 越大,系统响应越快。

@@ -731,20 +1486,117 @@ with gr.Blocks(title="自动控制原理学习网站", css=custom_css) as demo:

闭环频率响应的最大幅值。Mr 越小,系统阻尼越好。通常要求 Mr < 1.3 ~ 1.5。

+ +
+ 🔧 典型环节的频率特性 +
+

1️⃣ 比例环节 K

+

• 幅频:20logK (dB) - 水平直线
+ • 相频:0° - 水平直线

+ +

2️⃣ 积分环节 1/s

+

• 幅频:-20dB/dec 斜率的直线
+ • 相频:-90° - 水平直线

+ +

3️⃣ 微分环节 s

+

• 幅频:+20dB/dec 斜率的直线
+ • 相频:+90° - 水平直线

+ +

4️⃣ 惯性环节 1/(Ts+1)

+

• 转折频率:ω = 1/T
+ • 幅频:低频0dB,高频-20dB/dec
+ • 相频:从0°下降到-90°

+ +

5️⃣ 一阶微分环节 Ts+1

+

• 转折频率:ω = 1/T
+ • 幅频:低频0dB,高频+20dB/dec
+ • 相频:从0°上升到+90°

+ +

6️⃣ 二阶振荡环节 ωn²/(s²+2ζωns+ωn²)

+

• 转折频率:ω = ωn
+ • 幅频:低频0dB,高频-40dB/dec
+ • 相频:从0°下降到-180°
+ • 谐振峰值与阻尼比 ζ 相关

+
+
+ +
+ ⚡ 最小相位系统与全通系统 +
+

最小相位系统

+

定义:传递函数的所有零点和极点都在左半s平面的系统。

+ +
+

✅ 特点:

+
    +
  • 幅频特性与相频特性一一对应
  • +
  • 可由幅频特性唯一确定相频特性
  • +
  • 相角滞后最小(同样幅频特性下)
  • +
+
+ +

非最小相位系统

+

定义:传递函数在右半s平面有零点或极点的系统。

+ +
+

⚠️ 特点:

+
    +
  • 相角滞后较大
  • +
  • 幅频特性相同,相频特性不同
  • +
  • 稳定性和动态性能较差
  • +
+
+ +

全通系统

+

特点:幅频特性为常数(|G(jω)| = 1),只改变相频特性。

+

应用:相位校正、延时补偿

+
+
""") - with gr.TabItem("根轨迹 (Root Locus)", id=2): + with gr.TabItem("🎯 根轨迹 (Root Locus)", id=2): + gr.HTML(""" +
+ + 💡 分析要点:观察极点在s平面的运动轨迹,左半平面的极点表示系统稳定 + +
+ """) with gr.Row(): with gr.Column(scale=1): - gr.Markdown("### 1. 调整系统增益"); log_k_slider_rl = gr.Slider(minimum=-4, maximum=4, value=1, step=0.01, label="对数增益 log10(K)") - k_number_display = gr.Number(value=10.0, label="增益 K (Gain)", interactive=False); gr.Markdown("### 2. 当前增益下的闭环极点") - rl_poles_display = gr.Textbox(label="Closed-Loop Pole Locations", lines=4, interactive=False) + with gr.Group(): + gr.HTML("
🎚️ 调整系统增益
") + log_k_slider_rl = gr.Slider( + minimum=-4, + maximum=4, + value=1, + step=0.01, + label="对数增益 log₁₀(K)", + info="💡 拖动滑块观察极点移动" + ) + k_number_display = gr.Number( + value=10.0, + label="当前增益 K (Gain)", + interactive=False, + elem_classes="gain-display" + ) + + with gr.Group(): + gr.HTML("
📍 闭环极点位置
") + rl_poles_display = gr.Textbox( + label="Closed-Loop Pole Locations", + lines=6, + interactive=False, + elem_classes="output-metrics" + ) with gr.Column(scale=2): rl_plot_output = gr.Plot(label="Root Locus Plot") rl_formula_text = """
-

📚 根轨迹知识要点 (Root Locus Essentials)

+

📚 根轨迹知识要点 (Root Locus Essentials)

@@ -961,25 +1813,282 @@ with gr.Blocks(title="自动控制原理学习网站", css=custom_css) as demo:
+
+ + 🎨 根轨迹绘制规则总结 + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
规则内容
起点K=0,位于开环极点
终点K→∞,位于开环零点或无穷远
分支数等于 max(n, m)
实轴段右侧零极点总数为奇数的区段
渐近线数n - m 条
渐近线角度φa = (2k+1)·180°/(n-m)
渐近线交点σa = (Σp - Σz)/(n-m)
分离/会合点dK/ds = 0 的实根
与虚轴交点用劳斯判据或令 s=jω 求解
出射角/入射角复数极点/零点处的根轨迹切线角度
+ +
+

📝 绘制步骤:

+
    +
  1. 标出开环零极点
  2. +
  3. 确定实轴上的根轨迹
  4. +
  5. 计算渐近线(角度和交点)
  6. +
  7. 求分离点/会合点
  8. +
  9. 计算与虚轴交点
  10. +
  11. 求复数极点的出射角
  12. +
  13. 绘制完整根轨迹
  14. +
+
+
+
+ +
+ + 🔍 零度根轨迹(180°根轨迹) + +
+

定义:当参数 K 从 0 变化到 -∞ 时,闭环极点的轨迹。

+ +

相角条件:

+

+ ∠G(s0)H(s0) = 2k·180° (k = 0, ±1, ±2, ...) +

+ +
+

⚠️ 与常规根轨迹的区别:

+
    +
  • 实轴段:右侧零极点总数为偶数的区段
  • +
  • 渐近线角度:φa = 2k·180°/(n-m)
  • +
  • 图形表示:通常用虚线表示
  • +
+
+ +

应用场景:

+
    +
  • 负反馈系统中的正增益变化
  • +
  • 正反馈系统分析
  • +
  • 参数补偿器设计
  • +
+
+
+ +
+ + ⚙️ 根轨迹与系统性能 + +
+

稳定性分析:

+
+

✅ 稳定条件:所有闭环极点都在左半 s 平面

+
    +
  • 根轨迹完全在左半平面 → 系统对所有 K>0 都稳定
  • +
  • 根轨迹穿越虚轴 → 存在临界增益 Kc
  • +
  • 根轨迹在右半平面 → 某些 K 值下系统不稳定
  • +
+
+ +

动态性能分析:

+ + + + + + + + + + + + + + + + + + + + + +
极点位置系统响应特性
实轴负半轴单调响应,无振荡
左半平面共轭复数衰减振荡,有超调
虚轴上等幅振荡,临界稳定
右半平面发散,不稳定
+ +

增益 K 的选择:

+
+

💡 设计原则:

+
    +
  • 稳定性要求:K < Kc(临界增益)
  • +
  • 快速性要求:选择使主导极点实部较大的 K
  • +
  • 平稳性要求:选择使主导极点阻尼比 ζ ∈ [0.4, 0.8] 的 K
  • +
  • 精度要求:K 越大,稳态误差越小
  • +
+
+ +

性能折中:

+

+ 增大 K 可以提高系统精度和快速性,但可能降低稳定性和增大超调。 + 需要在根轨迹上选择合适的工作点,平衡各项性能指标。 +

+
+
+ +
+ + 🛠️ 根轨迹法的应用 + +
+

1️⃣ 系统分析:

+
    +
  • 判断系统稳定性及稳定范围
  • +
  • 确定临界增益 Kc
  • +
  • 分析参数变化对系统性能的影响
  • +
  • 确定主导极点位置
  • +
+ +

2️⃣ 控制器设计:

+
    +
  • 相位超前补偿:在根轨迹左侧增加零点,拉动根轨迹向左
  • +
  • 相位滞后补偿:在原点附近增加零极点对,提高低频增益
  • +
  • PID控制器:通过零极点配置实现性能要求
  • +
+ +

3️⃣ 极点配置:

+
+

通过添加合适的零极点,使闭环极点位于期望位置:

+
    +
  • 满足阻尼比要求:ζ = cosθ(θ为极点角度)
  • +
  • 满足调节时间要求:σ = 4/(ζωn)
  • +
  • 满足超调量要求:σ% = e-πζ/√(1-ζ²)
  • +
+
+ +

4️⃣ 鲁棒性分析:

+

+ 根轨迹可以直观显示参数不确定性对系统稳定性的影响, + 帮助评估系统的鲁棒性能。 +

+
+
+ """ gr.HTML(rl_formula_text) - with gr.TabItem("智能问答 (Q&A)", id=3): - chatbot = gr.Chatbot( - label="自控原理小助手", - bubble_full_width=False, - avatar_images=(None, "https://img.icons8.com/plasticine/100/bot.png"), - height=600, - latex_delimiters=[ - {"left": "$$", "right": "$$", "display": True}, - {"left": "$", "right": "$", "display": False}, - {"left": "\\[", "right": "\\]", "display": True}, - {"left": "\\(", "right": "\\)", "display": False} - ] - ) - chat_input = gr.Textbox(label="您的问题", placeholder="你好,请解释一下什么是PID控制器?", scale=4) - send_button = gr.Button("发送", variant="primary", scale=1) + with gr.TabItem("🤖 智能问答 (Q&A)", id=3): + gr.HTML(""" +
+ + 💡 AI助手:基于DeepSeek大模型,可以回答控制理论相关问题,支持LaTeX公式渲染 + +
+ """) + + with gr.Row(): + with gr.Column(scale=1): + chatbot = gr.Chatbot( + label="🎓 自控原理AI助教", + bubble_full_width=False, + avatar_images=( + "https://img.icons8.com/fluency/96/user-male-circle.png", + "https://img.icons8.com/fluency/96/chatbot.png" + ), + height=650, + latex_delimiters=[ + {"left": "$$", "right": "$$", "display": True}, + {"left": "$", "right": "$", "display": False}, + {"left": "\\[", "right": "\\]", "display": True}, + {"left": "\\(", "right": "\\)", "display": False} + ], + elem_classes="modern-chatbot" + ) + + with gr.Row(): + chat_input = gr.Textbox( + label="", + placeholder="💬 输入您的问题,例如:什么是PID控制器?如何分析系统稳定性?", + scale=4, + lines=2, + max_lines=4 + ) + with gr.Column(scale=1, min_width=120): + send_button = gr.Button( + "📤 发送", + variant="primary", + size="lg", + elem_classes="primary-btn" + ) + clear_button = gr.Button( + "🗑️ 清空", + variant="secondary", + size="lg" + ) + + # 示例问题 + gr.HTML(""" +
+
+ 💡 试试这些问题: +
+
+ + 什么是传递函数? + + + 如何判断系统稳定性? + + + 解释Bode图的物理意义 + + + PID控制器各参数的作用 + +
+
+ """) # --- 事件绑定部分 --- @@ -1023,6 +2132,12 @@ with gr.Blocks(title="自动控制原理学习网站", css=custom_css) as demo: lambda: "", # 清空输入框 outputs=chat_input ) + + # 清空聊天记录 + clear_button.click( + lambda: [], + outputs=chatbot + ) def on_tab_select(evt: gr.SelectData, num, den, log_k_freq, log_k_rl): outputs = {