Merge pull request 'feature/case-demo-model-minimal' (#1) from feature/case-demo-model-minimal into master
Reviewed-on: #1
This commit was merged in pull request #1.
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw
|
||||
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
|
||||
cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4
|
||||
WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu
|
||||
ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY
|
||||
MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc
|
||||
h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+
|
||||
0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U
|
||||
A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW
|
||||
T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH
|
||||
B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC
|
||||
B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv
|
||||
KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn
|
||||
OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn
|
||||
jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw
|
||||
qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI
|
||||
rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
|
||||
HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq
|
||||
hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL
|
||||
ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ
|
||||
3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK
|
||||
NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5
|
||||
ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur
|
||||
TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC
|
||||
jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc
|
||||
oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq
|
||||
4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA
|
||||
mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d
|
||||
emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=
|
||||
-----END CERTIFICATE-----
|
||||
+564
-125
@@ -1,201 +1,640 @@
|
||||
# API 配置指南
|
||||
|
||||
本文档详细说明如何配置 DeepSeek 和 Gemini API。
|
||||
|
||||
## 📋 目录
|
||||
|
||||
- [DeepSeek API 配置](#deepseek-api-配置)
|
||||
- [Gemini API 配置](#gemini-api-配置)
|
||||
- [常见问题](#常见问题)
|
||||
> 本文档详细说明如何为自动控制理论AI+数智平台配置 DeepSeek 和 Gemini API,包括密钥获取、配置方法、参数调优与常见问题排查。
|
||||
|
||||
---
|
||||
|
||||
## 🚀 DeepSeek API 配置
|
||||
## 一、API 概述
|
||||
|
||||
### 1. 获取 API 密钥
|
||||
### 1.1 平台支持的 AI API
|
||||
|
||||
1. 访问 [DeepSeek 平台](https://platform.deepseek.com/)
|
||||
2. 注册账号并登录
|
||||
3. 进入 [API Keys 页面](https://platform.deepseek.com/api_keys)
|
||||
4. 点击"创建新密钥"
|
||||
5. 复制生成的 API 密钥(格式:`sk-xxxxxxxxxxxxxxxx`)
|
||||
本平台目前支持以下 AI API 提供商:
|
||||
|
||||
### 2. 配置到应用
|
||||
| API 提供商 | 支持模型 | 访问地区 | 推荐程度 |
|
||||
|------------|----------|----------|----------|
|
||||
| DeepSeek | deepseek-chat / deepseek-coder | 中国大陆 | ⭐⭐⭐⭐⭐ 首选 |
|
||||
| Gemini (Google) | gemini-1.5-flash / gemini-1.5-pro | 部分受限 | ⭐⭐⭐ |
|
||||
|
||||
编辑 `app.py` 文件的配置区域(第 7-28 行):
|
||||
### 1.2 为什么需要 API
|
||||
|
||||
AI 智能问答模块依赖外部大语言模型 API 来实现:
|
||||
- 自动控制理论专业问题的理解和回答
|
||||
- LaTeX 数学公式的正确生成
|
||||
- 多轮对话的上下文记忆
|
||||
|
||||
### 1.3 配置优先级
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────┐
|
||||
│ 推荐配置顺序 │
|
||||
├─────────────────────────────────────────┤
|
||||
│ │
|
||||
│ 1. DeepSeek API(国内访问,速度快) │
|
||||
│ ↓ │
|
||||
│ 2. Gemini API(需要代理) │
|
||||
│ ↓ │
|
||||
│ 3. 本地部署(需高配置服务器) │
|
||||
│ │
|
||||
└─────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 二、DeepSeek API 配置
|
||||
|
||||
### 2.1 DeepSeek 简介
|
||||
|
||||
DeepSeek 是国内领先的 AI 大模型服务提供商,提供:
|
||||
- **deepseek-chat**:通用对话模型,适合教育场景
|
||||
- **deepseek-coder**:代码专用模型,适合技术问题
|
||||
- **价格优惠**:相比 OpenAI 等海外服务商更具性价比
|
||||
- **国内访问**:无需代理,网络延迟低
|
||||
|
||||
### 2.2 获取 API 密钥
|
||||
|
||||
**Step 1:访问 DeepSeek 平台**
|
||||
|
||||
打开浏览器,访问:https://platform.deepseek.com/
|
||||
|
||||
**Step 2:注册/登录账号**
|
||||
|
||||
- 使用手机号或邮箱注册
|
||||
- 已注册用户直接登录
|
||||
|
||||
**Step 3:进入 API Keys 管理页面**
|
||||
|
||||
登录后,点击顶部导航栏的 "API Keys":
|
||||
```
|
||||
https://platform.deepseek.com/api_keys
|
||||
```
|
||||
|
||||
**Step 4:创建新密钥**
|
||||
|
||||
1. 点击 "创建新密钥" 按钮
|
||||
2. 输入密钥名称(可自定义,如 "AutoControlCourse")
|
||||
3. 点击确认
|
||||
4. **立即复制密钥**(只显示一次!)
|
||||
|
||||
**密钥格式示例:**
|
||||
```
|
||||
sk-2292af2428d7419897ca1fb6e99ba6bc
|
||||
```
|
||||
|
||||
### 2.3 配置到项目
|
||||
|
||||
**方法一:直接编辑 config.py(最简单)**
|
||||
|
||||
1. 打开项目根目录下的 `config.py` 文件
|
||||
2. 找到 API 配置区域
|
||||
3. 将 `API_KEY` 替换为您的密钥
|
||||
|
||||
```python
|
||||
# ==================== API 配置 ====================
|
||||
API_KEY = "sk-your-api-key-here" # 粘贴您的 DeepSeek API 密钥
|
||||
API_KEY = "sk-2292af2428d7419897ca1fb6e99ba6bc" # 替换为您的密钥
|
||||
API_BASE_URL = "https://api.deepseek.com/v1"
|
||||
API_MODEL = "deepseek-chat" # 或 "deepseek-coder"
|
||||
API_TYPE = "deepseek"
|
||||
# ==================================================
|
||||
```
|
||||
|
||||
### 3. 可用模型
|
||||
**方法二:使用环境变量(推荐用于生产环境)**
|
||||
|
||||
| 模型名称 | 适用场景 | 特点 |
|
||||
|---------|---------|------|
|
||||
| `deepseek-chat` | 通用对话 | 平衡性能,推荐使用 |
|
||||
| `deepseek-coder` | 代码相关 | 代码理解和生成能力强 |
|
||||
|
||||
### 4. 费用说明
|
||||
|
||||
- 新用户通常有免费额度
|
||||
- 按 token 计费,价格实惠
|
||||
- 详见 [定价页面](https://platform.deepseek.com/pricing)
|
||||
|
||||
---
|
||||
|
||||
## 🌐 Gemini API 配置
|
||||
|
||||
### 1. 获取 API 密钥
|
||||
|
||||
1. 访问 [Google AI Studio](https://aistudio.google.com/app/apikey)
|
||||
2. 使用 Google 账号登录
|
||||
3. 点击"Get API Key"
|
||||
4. 创建或选择项目
|
||||
5. 复制生成的 API 密钥
|
||||
|
||||
### 2. 配置到应用
|
||||
|
||||
编辑 `app.py` 文件的配置区域:
|
||||
|
||||
```python
|
||||
# ==================== API 配置 ====================
|
||||
API_KEY = "AIzaSy-your-gemini-api-key-here"
|
||||
API_BASE_URL = "https://generativelanguage.googleapis.com/v1beta"
|
||||
API_MODEL = "gemini-1.5-flash" # 或其他可用模型
|
||||
API_TYPE = "gemini"
|
||||
# ==================================================
|
||||
```
|
||||
|
||||
### 3. 可用模型
|
||||
|
||||
| 模型名称 | 特点 |
|
||||
|---------|------|
|
||||
| `gemini-1.5-flash` | 快速响应,适合实时交互 |
|
||||
| `gemini-1.5-pro` | 更强大的理解和生成能力 |
|
||||
| `gemini-pro` | 经典版本 |
|
||||
|
||||
### 4. 注意事项
|
||||
|
||||
- Gemini API 在某些地区可能需要网络代理
|
||||
- 中国大陆用户推荐使用 DeepSeek API
|
||||
|
||||
---
|
||||
|
||||
## 🔒 安全建议
|
||||
|
||||
### 方法 1:环境变量(推荐)
|
||||
|
||||
不要直接在代码中硬编码 API 密钥,使用环境变量:
|
||||
|
||||
**Windows PowerShell:**
|
||||
1. **Windows PowerShell:**
|
||||
```powershell
|
||||
$env:DEEPSEEK_API_KEY="sk-your-key"
|
||||
$env:DEEPSEEK_API_KEY="sk-2292af2428d7419897ca1fb6e99ba6bc"
|
||||
python app.py
|
||||
```
|
||||
|
||||
**Linux/Mac:**
|
||||
2. **Linux / macOS:**
|
||||
```bash
|
||||
export DEEPSEEK_API_KEY="sk-your-key"
|
||||
export DEEPSEEK_API_KEY="sk-2292af2428d7419897ca1fb6e99ba6bc"
|
||||
python app.py
|
||||
```
|
||||
|
||||
然后在代码中读取:
|
||||
3. **在 config.py 中读取环境变量:**
|
||||
```python
|
||||
import os
|
||||
|
||||
API_KEY = os.environ.get("DEEPSEEK_API_KEY", "")
|
||||
```
|
||||
|
||||
### 方法 2:配置文件
|
||||
|
||||
创建 `config.json`(不要提交到 Git):
|
||||
**方法三:创建独立配置文件**
|
||||
|
||||
1. 在项目根目录创建 `config.json`:
|
||||
```json
|
||||
{
|
||||
"api_key": "sk-your-key",
|
||||
"api_key": "sk-2292af2428d7419897ca1fb6e99ba6bc",
|
||||
"api_base_url": "https://api.deepseek.com/v1",
|
||||
"api_model": "deepseek-chat",
|
||||
"api_type": "deepseek"
|
||||
}
|
||||
```
|
||||
|
||||
在代码中加载:
|
||||
2. 在 `config.py` 中加载:
|
||||
```python
|
||||
import json
|
||||
import os
|
||||
|
||||
with open('config.json', 'r') as f:
|
||||
config = json.load(f)
|
||||
API_KEY = config['api_key']
|
||||
API_BASE_URL = config['api_base_url']
|
||||
# ...
|
||||
config_path = os.path.join(os.path.dirname(__file__), "config.json")
|
||||
if os.path.exists(config_path):
|
||||
with open(config_path, "r") as f:
|
||||
config_data = json.load(f)
|
||||
API_KEY = config_data.get("api_key", "")
|
||||
API_BASE_URL = config_data.get("api_base_url", "https://api.deepseek.com/v1")
|
||||
API_MODEL = config_data.get("api_model", "deepseek-chat")
|
||||
API_TYPE = config_data.get("api_type", "deepseek")
|
||||
else:
|
||||
API_KEY = ""
|
||||
API_BASE_URL = "https://api.deepseek.com/v1"
|
||||
API_MODEL = "deepseek-chat"
|
||||
API_TYPE = "deepseek"
|
||||
```
|
||||
|
||||
### 2.4 DeepSeek 可用模型
|
||||
|
||||
| 模型名称 | 适用场景 | 特点 | 推荐场景 |
|
||||
|----------|----------|------|----------|
|
||||
| deepseek-chat | 通用对话 | 平衡性能与成本 | ⭐ 日常学习问答 |
|
||||
| deepseek-coder | 代码相关 | 代码理解能力强 | 专业开发者 |
|
||||
|
||||
### 2.5 费用说明
|
||||
|
||||
| 项目 | 说明 |
|
||||
|------|------|
|
||||
| 新用户优惠 | 通常有免费额度 |
|
||||
| 计费方式 | 按 token 用量计费 |
|
||||
| 价格水平 | 比 OpenAI 低约 80% |
|
||||
| 查看用量 | https://platform.deepseek.com/usage |
|
||||
| 详细定价 | https://platform.deepseek.com/pricing |
|
||||
|
||||
### 2.6 速率限制
|
||||
|
||||
| 账户类型 | RPM(每分钟请求数) | TPM(每分钟 Token 数) |
|
||||
|----------|---------------------|------------------------|
|
||||
| 免费用户 | 60 | 100,000 |
|
||||
| 付费用户 | 最高可达 2000 | 根据套餐 |
|
||||
|
||||
---
|
||||
|
||||
## 三、Gemini API 配置
|
||||
|
||||
### 3.1 Gemini 简介
|
||||
|
||||
Gemini 是 Google 开发的 AI 大模型,具备:
|
||||
- **gemini-1.5-flash**:快速响应,适合实时交互
|
||||
- **gemini-1.5-pro**:更强大的理解和生成能力
|
||||
- **多模态**:支持文本、图像等多种输入
|
||||
|
||||
**注意:** Gemini API 在中国大陆可能需要网络代理才能访问。
|
||||
|
||||
### 3.2 获取 API 密钥
|
||||
|
||||
**Step 1:访问 Google AI Studio**
|
||||
|
||||
打开浏览器,访问:https://aistudio.google.com/app/apikey
|
||||
|
||||
**Step 2:登录 Google 账号**
|
||||
|
||||
使用您的 Google 账号登录。
|
||||
|
||||
**Step 3:获取 API 密钥**
|
||||
|
||||
1. 点击 "Get API Key"
|
||||
2. 选择或创建项目
|
||||
3. 点击 "Create API Key"
|
||||
4. 复制生成的密钥
|
||||
|
||||
**密钥格式示例:**
|
||||
```
|
||||
AIzaSy-your-gemini-api-key-here
|
||||
```
|
||||
|
||||
### 3.3 配置到项目
|
||||
|
||||
编辑 `config.py` 文件:
|
||||
|
||||
```python
|
||||
# ==================== API 配置 ====================
|
||||
API_KEY = "AIzaSy-your-gemini-api-key-here"
|
||||
API_BASE_URL = "https://generativelanguage.googleapis.com/v1beta"
|
||||
API_MODEL = "gemini-1.5-flash" # 或 "gemini-1.5-pro"
|
||||
API_TYPE = "gemini"
|
||||
# ==================================================
|
||||
```
|
||||
|
||||
### 3.4 Gemini 可用模型
|
||||
|
||||
| 模型名称 | 特点 | 适用场景 | 响应速度 |
|
||||
|----------|------|----------|----------|
|
||||
| gemini-1.5-flash | 快速响应 | 实时交互 | ⚡⚡⚡⚡⚡ |
|
||||
| gemini-1.5-pro | 更强能力 | 复杂问题 | ⚡⚡⚡ |
|
||||
| gemini-pro | 经典版本 | 一般对话 | ⚡⚡⚡⚡ |
|
||||
|
||||
### 3.5 网络访问说明
|
||||
|
||||
| 地区 | 访问状态 | 解决方案 |
|
||||
|------|----------|----------|
|
||||
| 中国大陆 | 可能受限 | 使用 DeepSeek API 或配置代理 |
|
||||
| 港澳台 | 基本正常 | 直连或使用代理 |
|
||||
| 其他地区 | 正常 | 直连 |
|
||||
|
||||
---
|
||||
|
||||
## 四、配置参数详解
|
||||
|
||||
### 4.1 完整配置参数表
|
||||
|
||||
| 参数名 | 类型 | 默认值 | 说明 |
|
||||
|--------|------|--------|------|
|
||||
| API_KEY | string | "" | API 密钥,必填 |
|
||||
| API_BASE_URL | string | "https://api.deepseek.com/v1" | API 基础 URL |
|
||||
| API_MODEL | string | "deepseek-chat" | 模型名称 |
|
||||
| API_TYPE | string | "deepseek" | API 类型:deepseek 或 gemini |
|
||||
| SERVER_NAME | string | "0.0.0.0" | 监听网络接口 |
|
||||
| SERVER_PORT | int | 7860 | 监听端口 |
|
||||
| SHARE | bool | True | 是否创建公开链接 |
|
||||
|
||||
### 4.2 API_KEY 配置
|
||||
|
||||
**格式:** `sk-` 开头(DeepSeek)或 `AIzaSy` 开头(Gemini)
|
||||
|
||||
**常见错误:**
|
||||
- 密钥包含多余空格(复制时容易带入)
|
||||
- 密钥过期或被删除
|
||||
- 密钥未激活对应服务
|
||||
|
||||
**排查方法:**
|
||||
1. 确认密钥完整复制(无前后空格)
|
||||
2. 在官网控制台确认密钥状态
|
||||
3. 确认密钥已绑定正确的产品/服务
|
||||
|
||||
### 4.3 API_BASE_URL 配置
|
||||
|
||||
| API 类型 | 正确 URL | 错误示例 |
|
||||
|----------|----------|----------|
|
||||
| DeepSeek | https://api.deepseek.com/v1 | https://api.deepseek.com/ |
|
||||
| Gemini | https://generativelanguage.googleapis.com/v1beta | 其他 URL |
|
||||
|
||||
### 4.4 API_MODEL 配置
|
||||
|
||||
**DeepSeek 模型:**
|
||||
|
||||
| 模型 | 上下文长度 | 适用场景 |
|
||||
|------|------------|----------|
|
||||
| deepseek-chat | 64K tokens | 通用对话,推荐 |
|
||||
| deepseek-coder | 64K tokens | 代码相关问题 |
|
||||
|
||||
**Gemini 模型:**
|
||||
|
||||
| 模型 | 上下文长度 | 适用场景 |
|
||||
|------|------------|----------|
|
||||
| gemini-1.5-flash | 1M tokens | 快速响应 |
|
||||
| gemini-1.5-pro | 1M tokens | 复杂任务 |
|
||||
| gemini-pro | 32K tokens | 一般对话 |
|
||||
|
||||
---
|
||||
|
||||
## 五、流式响应配置
|
||||
|
||||
### 5.1 什么是流式响应
|
||||
|
||||
流式响应(Streaming)是指 AI 边生成答案边返回,用户可以实时看到回答内容,而不必等待完整答案生成完毕。
|
||||
|
||||
**优点:**
|
||||
- 减少等待感
|
||||
- 及时了解回答方向
|
||||
- 支持长答案的快速预览
|
||||
|
||||
### 5.2 当前配置
|
||||
|
||||
本平台默认启用流式响应,配置位于 `chatbot.py`:
|
||||
|
||||
```python
|
||||
payload = {
|
||||
"model": config.API_MODEL,
|
||||
"messages": messages_for_api,
|
||||
"stream": True, # 启用流式响应
|
||||
"temperature": 0.7, # 创造性参数
|
||||
"max_tokens": 2048 # 最大 Token 数
|
||||
}
|
||||
```
|
||||
|
||||
### 5.3 参数调优
|
||||
|
||||
| 参数 | 取值范围 | 说明 | 调整建议 |
|
||||
|------|----------|------|----------|
|
||||
| temperature | 0.0 ~ 2.0 | 创造性控制,值越低越确定 | 学习问答建议 0.3~0.7 |
|
||||
| max_tokens | 1 ~ 32768 | 单次回复最大 Token 数 | 长回答设为 4096 |
|
||||
| top_p | 0.0 ~ 1.0 | 核采样参数 | 通常保持默认 1.0 |
|
||||
| frequency_penalty | -2.0 ~ 2.0 | 频率惩罚 | 保持默认 0.0 |
|
||||
| presence_penalty | -2.0 ~ 2.0 | 存在惩罚 | 保持默认 0.0 |
|
||||
|
||||
---
|
||||
|
||||
## 六、系统提示词配置
|
||||
|
||||
### 6.1 系统提示词的作用
|
||||
|
||||
系统提示词(System Prompt)定义了 AI 助手的角色定位、回答风格和专业范围。本平台的默认提示词位于 `chatbot.py`。
|
||||
|
||||
### 6.2 默认提示词
|
||||
|
||||
```python
|
||||
system_prompt = """你是一位精通自动控制原理的专家教授。请用清晰、准确、专业的中文来回答有关自动控制课程内容的问题。
|
||||
|
||||
重要规则:
|
||||
1. 当需要表达数学公式时,必须使用 LaTeX 格式
|
||||
2. 行内公式使用 $公式$ 或 \\(公式\\)
|
||||
3. 独立公式使用 $$公式$$ 或 \\[公式\\]
|
||||
4. 例如:传递函数可以写成 $G(s) = \\frac{K}{s(s+1)}$
|
||||
5. 二阶系统标准形式:$$G(s) = \\frac{\\omega_n^2}{s^2 + 2\\zeta\\omega_n s + \\omega_n^2}$$
|
||||
|
||||
请在适当的时候使用公式和示例来辅助解释。"""
|
||||
```
|
||||
|
||||
### 6.3 自定义提示词
|
||||
|
||||
根据教学需求,您可以修改系统提示词:
|
||||
|
||||
**修改方法:** 编辑 `chatbot.py` 中的 `system_prompt` 变量。
|
||||
|
||||
**示例1:强化公式推导**
|
||||
```python
|
||||
system_prompt = """你是一位严谨的自动控制原理教授。在回答问题时:
|
||||
1. 注重公式的推导过程
|
||||
2. 每一步推导都要清晰呈现
|
||||
3. 适当使用 LaTeX 公式
|
||||
4. 结合实例帮助理解"""
|
||||
```
|
||||
|
||||
**示例2:简化回答风格**
|
||||
```python
|
||||
system_prompt = """你是一位friendly的自动控制课程助教。请用简洁、易懂的语言回答问题:
|
||||
1. 尽量少用专业术语
|
||||
2. 多用生活实例类比
|
||||
3. 重要公式用 LaTeX 展示"""
|
||||
```
|
||||
|
||||
**示例3:英文问答模式**
|
||||
```python
|
||||
system_prompt = """You are an expert professor of Automatic Control Theory.
|
||||
Answer questions in English using LaTeX for mathematical formulas.
|
||||
Focus on clarity and practical examples."""
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ❓ 常见问题
|
||||
## 七、安全建议
|
||||
|
||||
### Q1: API 请求失败,显示 401 错误
|
||||
### 7.1 密钥安全原则
|
||||
|
||||
**原因**:API 密钥无效或未配置
|
||||
**❌ 不要做的事情:**
|
||||
- 在代码中硬编码密钥并提交到 Git
|
||||
- 在公开场合分享密钥
|
||||
- 使用过于简单的密钥
|
||||
|
||||
**解决**:
|
||||
1. 检查 API 密钥是否正确复制(无多余空格)
|
||||
2. 确认密钥未过期或被删除
|
||||
3. 重新生成密钥并更新配置
|
||||
**✅ 推荐的做法:**
|
||||
- 使用环境变量存储密钥
|
||||
- 将敏感配置文件加入 .gitignore
|
||||
- 定期更换密钥
|
||||
- 为不同项目使用不同的密钥
|
||||
|
||||
### Q2: 网络连接错误
|
||||
### 7.2 .gitignore 配置
|
||||
|
||||
**原因**:网络问题或 API 服务不可达
|
||||
确保以下文件不会被提交到 Git:
|
||||
|
||||
**解决**:
|
||||
1. DeepSeek 用户:检查国内网络连接
|
||||
2. Gemini 用户:可能需要配置网络代理
|
||||
3. 尝试切换到 DeepSeek API(国内友好)
|
||||
```
|
||||
# API 配置文件
|
||||
config.json
|
||||
secrets.json
|
||||
.env
|
||||
|
||||
### Q3: 回复速度慢或超时
|
||||
# Python
|
||||
__pycache__/
|
||||
*.pyc
|
||||
*.pyo
|
||||
|
||||
**原因**:网络延迟或 API 负载高
|
||||
# IDE
|
||||
.vscode/
|
||||
.idea/
|
||||
|
||||
**解决**:
|
||||
1. 检查网络连接速度
|
||||
2. 调整超时设置(app.py 中的 `ClientTimeout`)
|
||||
3. 尝试切换模型(如 flash 版本)
|
||||
# 模型权重(较大文件)
|
||||
Model/data/*.pth
|
||||
```
|
||||
|
||||
### Q4: 公式不渲染
|
||||
### 7.3 生产环境部署
|
||||
|
||||
**原因**:Chatbot 未启用 LaTeX 支持
|
||||
**推荐做法:**
|
||||
|
||||
**解决**:
|
||||
确认 `gr.Chatbot` 包含 `latex_delimiters` 参数:
|
||||
1. **使用环境变量**
|
||||
```bash
|
||||
# Docker 部署
|
||||
docker run -p 7860:7860 \
|
||||
-e DEEPSEEK_API_KEY="sk-xxx" \
|
||||
autocontrol-course
|
||||
```
|
||||
|
||||
2. **使用配置服务**
|
||||
- AWS Secrets Manager
|
||||
- Azure Key Vault
|
||||
- HashiCorp Vault
|
||||
|
||||
3. **限制 API 访问**
|
||||
- 设置 API 密钥的使用 IP 白名单
|
||||
- 配置请求频率限制
|
||||
- 开启使用量告警
|
||||
|
||||
---
|
||||
|
||||
## 八、常见问题排查
|
||||
|
||||
### 8.1 API 请求失败
|
||||
|
||||
**问题1:401 Unauthorized**
|
||||
|
||||
| 可能原因 | 解决方法 |
|
||||
|----------|----------|
|
||||
| API 密钥无效 | 检查密钥是否正确复制 |
|
||||
| 密钥已过期 | 在平台控制台重新创建密钥 |
|
||||
| 密钥未激活 | 确认密钥已绑定正确服务 |
|
||||
|
||||
**问题2:403 Forbidden**
|
||||
|
||||
| 可能原因 | 解决方法 |
|
||||
|----------|----------|
|
||||
| 账户余额不足 | 充值或等待免费额度刷新 |
|
||||
| 权限不足 | 检查账户权限设置 |
|
||||
| 服务未开通 | 在控制台开通对应服务 |
|
||||
|
||||
**问题3:429 Rate Limit**
|
||||
|
||||
| 可能原因 | 解决方法 |
|
||||
|----------|----------|
|
||||
| 请求过于频繁 | 降低请求频率 |
|
||||
| 超出 TPM/RPM 限制 | 等待或升级套餐 |
|
||||
| 并发数过高 | 减少并发请求数 |
|
||||
|
||||
**解决方法:**
|
||||
1. 等待一段时间后重试
|
||||
2. 配置请求间隔(如每次提问间隔 2 秒)
|
||||
3. 升级到更高配额套餐
|
||||
|
||||
### 8.2 网络连接问题
|
||||
|
||||
**问题:Connection Error / Timeout**
|
||||
|
||||
**排查步骤:**
|
||||
|
||||
1. **检查网络连接**
|
||||
```bash
|
||||
# 测试 API 端点是否可达
|
||||
curl -I https://api.deepseek.com/v1
|
||||
```
|
||||
|
||||
2. **检查代理设置(如需要)**
|
||||
```python
|
||||
# 在 chatbot.py 中配置代理
|
||||
import os
|
||||
os.environ["HTTP_PROXY"] = "http://proxy.example.com:8080"
|
||||
os.environ["HTTPS_PROXY"] = "http://proxy.example.com:8080"
|
||||
```
|
||||
|
||||
3. **增加超时时间**
|
||||
```python
|
||||
# 在 aiohttp 请求中增加 timeout
|
||||
async with session.post(api_url, json=payload, headers=headers,
|
||||
timeout=aiohttp.ClientTimeout(total=120)) as response:
|
||||
```
|
||||
|
||||
### 8.3 回复质量问题
|
||||
|
||||
**问题:回复内容不准确**
|
||||
|
||||
**解决方法:**
|
||||
|
||||
1. **优化系统提示词**
|
||||
- 明确指定回答风格
|
||||
- 强调专业领域要求
|
||||
- 添加示例回答
|
||||
|
||||
2. **调整 temperature 参数**
|
||||
- 降低 temperature(0.3~0.5)使回答更确定
|
||||
- 提高 temperature(0.7~1.0)使回答更有创造性
|
||||
|
||||
3. **优化提问方式**
|
||||
- 提供更多上下文
|
||||
- 明确问题范围
|
||||
- 指出具体困惑点
|
||||
|
||||
**问题:回复速度慢**
|
||||
|
||||
**解决方法:**
|
||||
|
||||
1. **使用较轻量的模型**
|
||||
- DeepSeek:选择 deepseek-chat 而非 deepseek-coder
|
||||
- Gemini:选择 gemini-1.5-flash
|
||||
|
||||
2. **减少 max_tokens**
|
||||
- 根据实际需求设置合理的最大长度
|
||||
- 避免生成过长的回答
|
||||
|
||||
3. **检查网络延迟**
|
||||
- 选择距离更近的 API 端点
|
||||
- 考虑使用 CDN 加速
|
||||
|
||||
### 8.4 公式渲染问题
|
||||
|
||||
**问题:LaTeX 公式不显示**
|
||||
|
||||
**可能原因:**
|
||||
|
||||
1. **Chatbot 未启用 LaTeX**
|
||||
2. **MathJax 加载失败**
|
||||
3. **公式语法错误**
|
||||
|
||||
**解决方法:**
|
||||
|
||||
1. 确认 `gr.Chatbot` 配置包含 `latex_delimiters`:
|
||||
```python
|
||||
chatbot = gr.Chatbot(
|
||||
latex_delimiters=[
|
||||
{"left": "$$", "right": "$$", "display": True},
|
||||
{"left": "$", "right": "$", "display": False}
|
||||
{"left": "$", "right": "$", "display": False},
|
||||
{"left": "\\[", "right": "\\]", "display": True},
|
||||
{"left": "\\(", "right": "\\)", "display": False}
|
||||
]
|
||||
)
|
||||
```
|
||||
|
||||
### Q5: 如何限制 API 调用成本?
|
||||
2. 刷新页面重试
|
||||
|
||||
**建议**:
|
||||
1. 在 API 平台设置使用限额
|
||||
2. 代码中添加 `max_tokens` 限制
|
||||
3. 监控 API 使用情况
|
||||
4. 使用轻量级模型(如 flash 版本)
|
||||
3. 检查 LaTeX 语法是否正确
|
||||
|
||||
---
|
||||
|
||||
## 📞 获取帮助
|
||||
## 九、API 使用成本优化
|
||||
|
||||
- **DeepSeek 文档**:https://platform.deepseek.com/docs
|
||||
- **Gemini 文档**:https://ai.google.dev/docs
|
||||
- **项目 Issues**:[GitHub Issues 链接]
|
||||
### 9.1 成本构成
|
||||
|
||||
API 使用成本主要由以下因素决定:
|
||||
|
||||
| 因素 | 说明 | 优化建议 |
|
||||
|------|------|----------|
|
||||
| 输入 Token 数 | 问题文本长度 | 精简提问 |
|
||||
| 输出 Token 数 | 回答文本长度 | 限制 max_tokens |
|
||||
| 请求次数 | 提问频率 | 减少无效请求 |
|
||||
| 模型单价 | 不同模型价格不同 | 选择性价比模型 |
|
||||
|
||||
### 9.2 优化策略
|
||||
|
||||
**策略1:精简提问**
|
||||
- 移除问题中不必要的修饰词
|
||||
- 明确指出核心疑问
|
||||
- 提供必要的上下文但不过度
|
||||
|
||||
**策略2:合理限制输出长度**
|
||||
- 根据问题类型设置 max_tokens
|
||||
- 简单问题设置较短限制
|
||||
- 复杂问题允许更长回答
|
||||
|
||||
**策略3:缓存常用回答**
|
||||
- 实现本地缓存机制
|
||||
- 避免重复提问相同问题
|
||||
- 减少 API 调用次数
|
||||
|
||||
**策略4:选择合适模型**
|
||||
- 日常问答:使用轻量模型(flash 版本)
|
||||
- 复杂问题:按需使用强大模型
|
||||
|
||||
### 9.3 预算设置
|
||||
|
||||
在 DeepSeek 控制台设置用量限制:
|
||||
|
||||
1. 访问 https://platform.deepseek.com/
|
||||
2. 进入 "用量限制" 设置
|
||||
3. 设置月度预算上限
|
||||
4. 开启用量告警
|
||||
|
||||
---
|
||||
|
||||
最后更新:2025年10月15日
|
||||
## 十、获取帮助
|
||||
|
||||
### 10.1 官方文档
|
||||
|
||||
| 资源 | 链接 |
|
||||
|------|------|
|
||||
| DeepSeek 文档 | https://platform.deepseek.com/docs |
|
||||
| Gemini 文档 | https://ai.google.dev/docs |
|
||||
| Gradio 文档 | https://gradio.app/docs |
|
||||
|
||||
### 10.2 技术支持
|
||||
|
||||
| 渠道 | 联系方式 |
|
||||
|------|----------|
|
||||
| 项目问题 | GitHub Issues |
|
||||
| API 问题 | 平台官方支持 |
|
||||
| 使用咨询 | 课程教师/助教 |
|
||||
|
||||
---
|
||||
|
||||
**最后更新:2026年4月7日**
|
||||
|
||||
+363
-44
@@ -1,60 +1,379 @@
|
||||
# Changelog
|
||||
# 更新日志 (Changelog)
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
> 本文档记录自动控制理论AI+数智平台的所有重要更新,包括新增功能、功能改进、问题修复与技术变更。
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
本文档格式遵循 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/) 规范,并遵循 [语义化版本 (SemVer)](https://semver.org/lang/zh-CN/) 约定。
|
||||
|
||||
---
|
||||
|
||||
## 版本命名规范
|
||||
|
||||
版本号格式:`主版本.次版本.修订号`
|
||||
|
||||
| 标识 | 含义 |
|
||||
|------|------|
|
||||
| 主版本 (MAJOR) | 不兼容的重大架构变更 |
|
||||
| 次版本 (MINOR) | 向后兼容的新功能添加 |
|
||||
| 修订号 (PATCH) | 向后兼容的问题修复 |
|
||||
|
||||
---
|
||||
|
||||
## [1.2.0] - 2026-04-07
|
||||
|
||||
> **重要更新:新增算例演示模块与完整混动模型联动**
|
||||
|
||||
### Added(新增功能)
|
||||
|
||||
#### 🧪 算例演示模块(Case Demo)
|
||||
|
||||
本版本最核心的更新是新增了完整的算例演示模块,通过串联式混合动力系统模型展示控制系统设计在实际工程中的应用。
|
||||
|
||||
**阶段零:模型训练**
|
||||
- 新增 `case_demo_functions.py` 模块,作为算例演示的核心入口
|
||||
- 新增 GPR(高斯过程回归)模型训练/加载功能
|
||||
- 支持从头训练(需要 botorch/gpytorch/sklearn)
|
||||
- 支持加载已有 .pth 权重文件
|
||||
- 生成训练/验证结果可视化(散点图、方差热力图)
|
||||
- 新增 NN 模型训练(知识蒸馏)功能
|
||||
- 将 GPR 教师模型的知识蒸馏到轻量级 MLP
|
||||
- 可视化训练损失曲线、燃油流量与功率的 parity plot
|
||||
- 支持自定义 epochs、learning_rate、hidden_size 参数
|
||||
|
||||
**阶段一:发动机控制器设计**
|
||||
- 新增基于 NN 代理模型的涡轴发动机动态仿真
|
||||
- 新增 PID 控制器(增量式)
|
||||
- 可调参数:Kp、Ki、Kd
|
||||
- 支持输入/输出量程归一化
|
||||
- 新增 MPC 控制器(模型预测控制)
|
||||
- 纯 Python 实现的投影梯度下降求解器
|
||||
- 可调参数:预测时域、功率跟踪权重、控制增量权重、超调限制
|
||||
- 支持超调量硬约束(5%)
|
||||
|
||||
**阶段二:电机控制器设计**
|
||||
- 新增永磁同步电机(PMSM)离散时间动力学模型
|
||||
- 新增 d/q 轴电流控制与 MTPA 控制策略
|
||||
- 新增 PID / MPC 两种控制器
|
||||
- 新增负载扰动测试(60% 时刻施加 150% 额定负载)
|
||||
|
||||
**阶段三:能量管理策略设计**
|
||||
- 新增基于规则的功率跟随策略
|
||||
- 新增 SOC 滞环控制(防止模式频繁切换)
|
||||
- 新增完整混动系统仿真(发动机 + 电机 + 电池)
|
||||
- 新增三联图输出(转速响应/功率分配/电气状态)
|
||||
- 新增关键时刻数据表(8 个关键时刻点)
|
||||
|
||||
**模型核心模块(Model/src/)**
|
||||
|
||||
| 文件 | 功能 | 关键特性 |
|
||||
|------|------|----------|
|
||||
| `lightweight_model.py` | NN 代理模型 | MLP 3→64→64→2,Tanh 激活,归一化处理 |
|
||||
| `engine_gpr_class.py` | GPR 模型 | 高斯过程回归,支持批量预测 |
|
||||
| `distill_gpr_to_nn.py` | 知识蒸馏脚本 | CSV 直接训练或 GPR 蒸馏 |
|
||||
| `engine_dynamic_sim.py` | 涡轴发动机仿真 | 燃油执行机构 + 转子动力学 |
|
||||
| `motor_sim.py` | PMSM 电机仿真 | SVPWM、Clarke/Park 变换、损耗模型 |
|
||||
| `battery_sim.py` | 电池仿真 | OCV-SOC 查表、内阻模型、安时积分 |
|
||||
| `mpc_controller.py` | MPC 控制器 | 投影梯度下降、硬约束处理 |
|
||||
| `increPID.py` | 增量式 PID | 归一化缩放、自动抗积分饱和 |
|
||||
| `series_hybrid_sim.py` | 混动系统总成 | 功率平衡、滞环控制 |
|
||||
|
||||
### Changed(功能变更)
|
||||
|
||||
#### 📁 Model 目录结构优化
|
||||
|
||||
为提高项目可维护性,对 Model 目录进行了精简:
|
||||
|
||||
**移除的文件/目录:**
|
||||
- `scripts/` 目录(功能已整合到 `case_demo_functions.py`)
|
||||
- `EngineData.xlsx`(原始数据,已被 CSV 替代)
|
||||
- `.git/`(子模块 Git 历史)
|
||||
- `.claude/`(IDE 配置)
|
||||
- `README.md`(已整合到主项目文档)
|
||||
- `LICENSE`(已使用主项目许可证)
|
||||
- `environment.yml`(conda 环境配置)
|
||||
- `figures/`(输出目录)
|
||||
- `.gitignore`(已使用主项目配置)
|
||||
|
||||
**保留的核心文件:**
|
||||
- `Model/src/` — 所有源代码
|
||||
- `Model/data/` — 模型权重与数据文件
|
||||
- `requirements.txt` — 依赖列表
|
||||
|
||||
#### 模型路径解析改进
|
||||
|
||||
`series_hybrid_sim.py` 等文件改为按 Model 目录定位资源:
|
||||
|
||||
```python
|
||||
# 旧方式(可能因工作目录而失败)
|
||||
nn_pth = "Model/data/engine_nn_proxy.pth"
|
||||
|
||||
# 新方式(基于脚本位置定位)
|
||||
MODEL_DATA_PATH = os.path.join(os.path.dirname(__file__), "..", "data")
|
||||
nn_pth = os.path.join(MODEL_DATA_PATH, "engine_nn_proxy.pth")
|
||||
```
|
||||
|
||||
#### 依赖版本锁定
|
||||
|
||||
`requirements.txt` 更新如下:
|
||||
|
||||
| 依赖 | 新版本 | 变更说明 |
|
||||
|------|--------|----------|
|
||||
| gradio | 4.44.1 | 升级到最新稳定版 |
|
||||
| gradio-client | 1.3.0 | 新增 |
|
||||
| pydantic | 2.10.6 | 升级 |
|
||||
| pydantic-core | 2.27.2 | 升级 |
|
||||
| huggingface_hub | 0.23.0 | 新增 |
|
||||
| numpy | 1.26.4 | 锁定版本 |
|
||||
| control | 0.9.4 | 锁定版本 |
|
||||
| matplotlib | 3.9.4 | 升级 |
|
||||
| aiohttp | 3.13.5 | 升级 |
|
||||
| pillow | 10.4.0 | 升级 |
|
||||
| torch | 2.4.1+cu121 | 新增(GPU 版本) |
|
||||
| botorch | 0.14.0 | 新增(GPR 依赖) |
|
||||
| gpytorch | 1.14 | 新增(GPR 依赖) |
|
||||
| pyro-ppl | 1.9.1 | 新增(GPR 依赖) |
|
||||
| pandas | 2.3.3 | 新增(数据处理) |
|
||||
| scipy | >=1.10 | 新增(数值计算) |
|
||||
| scikit-learn | 1.7.1 | 新增(数据归一化) |
|
||||
| psutil | >=5.9 | 新增(系统监控) |
|
||||
|
||||
**PyTorch 下载源配置:**
|
||||
```txt
|
||||
--extra-index-url https://download.pytorch.org/whl/cu121
|
||||
```
|
||||
|
||||
#### 文档同步更新
|
||||
|
||||
- `README.md`:同步为"五大功能"结构,新增算例演示详解
|
||||
- `GUIDANCE.md`:新增四阶段操作指南、混动系统架构说明
|
||||
- `API_CONFIG.md`:新增 API 配置详解、安全建议
|
||||
- `CHANGELOG.md`:新增详细版本记录
|
||||
|
||||
### Removed(移除功能)
|
||||
|
||||
| 移除项 | 原位置 | 替代方案 |
|
||||
|--------|--------|----------|
|
||||
| 独立训练脚本 | `Model/scripts/distill_gpr_to_nn.py` | 已整合到 `case_demo_functions.py` |
|
||||
| Excel 数据文件 | `Model/EngineData.xlsx` | 使用 `Model/data/Cleaned_Engine_Data_Full.csv` |
|
||||
| conda 环境文件 | `Model/environment.yml` | 使用 `requirements.txt` |
|
||||
|
||||
### Fixed(问题修复)
|
||||
|
||||
| 问题 | 修复内容 |
|
||||
|------|----------|
|
||||
| Model 路径解析错误 | 改用 `__file__` 相对定位,避免工作目录影响 |
|
||||
| GPR 训练缺少依赖提示 | 新增清晰的依赖安装指引 |
|
||||
| 模型权重未找到 | 提供更详细的错误提示与解决步骤 |
|
||||
|
||||
---
|
||||
|
||||
## [1.1.0] - 2026-02-15
|
||||
|
||||
> **功能增强与问题修复**
|
||||
|
||||
### Added(新增功能)
|
||||
|
||||
| 功能 | 说明 |
|
||||
|------|------|
|
||||
| 实时在线人数统计 | 页面顶部显示当前在线用户数与历史总人数 |
|
||||
| 总访问人数统计 | 持久化记录累计访问人数 |
|
||||
| 系统资源监控 | 显示 CPU、内存、GPU 使用率 |
|
||||
| 页面自动刷新 | 每 10 秒更新在线人数,每 3 秒更新系统资源 |
|
||||
|
||||
### Changed(功能变更)
|
||||
|
||||
| 变更项 | 变更内容 |
|
||||
|--------|----------|
|
||||
| 在线统计存储 | 从内存改为 JSON 文件持久化 |
|
||||
| 统计更新频率 | 在线人数每 10 秒刷新,资源每 3 秒刷新 |
|
||||
| 界面布局优化 | 顶部状态栏与系统监控整合 |
|
||||
|
||||
### Fixed(问题修复)
|
||||
|
||||
| 问题 | 修复内容 |
|
||||
|------|----------|
|
||||
| 页面刷新导致在线人数重置 | 改用 Session ID 跟踪用户会话 |
|
||||
| 多用户并发统计不准 | 添加线程锁保护共享状态 |
|
||||
|
||||
---
|
||||
|
||||
## [1.0.0] - 2025-10-15
|
||||
|
||||
### Added
|
||||
- ✨ 时域分析功能(阶跃响应、脉冲响应、性能指标计算)
|
||||
- ✨ 频域分析功能(Bode 图、Nyquist 图、稳定裕度)
|
||||
- ✨ 根轨迹分析功能(动态轨迹绘制、增益调节、极点跟踪)
|
||||
- ✨ AI 智能问答功能(支持 DeepSeek 和 Gemini API)
|
||||
- 🎨 现代化 UI 设计(渐变色、卡片布局、可滚动知识区)
|
||||
- 📚 详细的知识卡片(时域、频域、根轨迹理论)
|
||||
- 🔧 对数增益滑块(精确调节 0.1 到 1000 范围)
|
||||
- 💬 LaTeX 公式渲染(聊天机器人内数学公式支持)
|
||||
- 📊 英文图表标签(避免中文显示问题)
|
||||
> **首次正式发布**
|
||||
|
||||
### Features
|
||||
- 支持任意阶次线性时不变(LTI)系统分析
|
||||
- 实时参数调节和图表更新
|
||||
- 流式 AI 对话响应
|
||||
- 标签页切换自动加载数据
|
||||
- 可折叠的知识点章节
|
||||
### Added(新增功能)
|
||||
|
||||
### Documentation
|
||||
- 📄 完整的 README.md
|
||||
- 📄 API 配置指南(API_CONFIG.md)
|
||||
- 📄 快速上手指南(QUICK_START.md)
|
||||
- 📄 依赖列表(requirements.txt)
|
||||
- 📄 .gitignore 配置
|
||||
- 📄 MIT 开源许可证
|
||||
#### 🎯 核心分析功能
|
||||
|
||||
## [Unreleased]
|
||||
**1. 时域分析模块**
|
||||
- 单位阶跃响应分析与绘图
|
||||
- 单位脉冲响应分析与绘图
|
||||
- 自动性能指标计算:
|
||||
- 上升时间 (Rise Time)
|
||||
- 峰值时间 (Peak Time)
|
||||
- 超调量 (Overshoot)
|
||||
- 调节时间 (Settling Time)
|
||||
- 稳态值 (Steady State Value)
|
||||
- 传递函数系数解析与 LaTeX 渲染
|
||||
|
||||
### Planned
|
||||
- [ ] 状态空间分析模块
|
||||
- [ ] 离散系统分析支持
|
||||
- [ ] 更多控制器设计工具(PID 调优、极点配置)
|
||||
- [ ] 系统对比功能(多个传递函数对比)
|
||||
- [ ] 导出分析报告(PDF/Word)
|
||||
- [ ] 历史记录保存
|
||||
- [ ] 更多 AI 模型支持
|
||||
- [ ] 多语言界面(英文版)
|
||||
- [ ] 移动端适配
|
||||
**2. 频域分析模块**
|
||||
- Bode 图绘制(幅频特性 + 相频特性)
|
||||
- Nyquist 图绘制(极坐标频率响应)
|
||||
- 自动增益裕度 (GM) 计算
|
||||
- 自动相位裕度 (PM) 计算
|
||||
- 稳定性自动判断
|
||||
|
||||
**3. 根轨迹分析模块**
|
||||
- 完整根轨迹自动绘制
|
||||
- 对数增益滑块(log₁₀(K) 范围 -4 到 4)
|
||||
- 实时极点位置显示
|
||||
- 动态坐标范围调整
|
||||
- 阻尼比等值线参考
|
||||
|
||||
**4. AI 智能问答模块**
|
||||
- DeepSeek API 集成
|
||||
- Gemini API 备用支持
|
||||
- 流式响应(实时显示生成过程)
|
||||
- 多轮对话上下文记忆
|
||||
- LaTeX 数学公式渲染
|
||||
- 自动控制原理专业问答
|
||||
|
||||
#### 🎨 界面设计
|
||||
|
||||
| 特性 | 说明 |
|
||||
|------|------|
|
||||
| 渐变色标题 | 紫色渐变视觉效果 |
|
||||
| 卡片式布局 | 分组清晰,层次分明 |
|
||||
| 可滚动知识卡片 | 节省屏幕空间 |
|
||||
| 可折叠章节 | 按需展开 |
|
||||
| 实时参数更新 | 图表即时反映变化 |
|
||||
| 标签页联动 | 切换自动加载数据 |
|
||||
| 平滑动画效果 | 悬停、滚动动效 |
|
||||
|
||||
#### 📚 知识卡片内容
|
||||
|
||||
| 模块 | 知识点 |
|
||||
|------|--------|
|
||||
| 时域分析 | 二阶系统标准形式、阻尼比与响应特性、性能指标公式、稳态误差分析 |
|
||||
| 频域分析 | Bode 图绘制技巧、稳定裕度定义、稳定性判断准则、频域-时域对应关系 |
|
||||
| 根轨迹 | 基本规则、起点终点、渐近线、分离点、s 平面稳定性区域 |
|
||||
|
||||
#### 🔧 交互设计
|
||||
|
||||
| 特性 | 实现 |
|
||||
|------|------|
|
||||
| 对数增益滑块 | log₁₀(K) 范围 -4~4,对应 K = 0.0001~10000 |
|
||||
| 传递函数输入 | 系数从高次幂到常数项,逗号分隔 |
|
||||
| 实时预览 | 显示传递函数 LaTeX 公式 |
|
||||
| 松开更新 | 滑块释放后才更新图表,避免卡顿 |
|
||||
|
||||
### Documentation(文档)
|
||||
|
||||
| 文档 | 内容 |
|
||||
|------|------|
|
||||
| README.md | 项目简介、功能说明、快速开始、技术栈 |
|
||||
| GUIDANCE.md | 学生使用指南、详细教程、示例库 |
|
||||
| API_CONFIG.md | DeepSeek/Gemini API 配置指南 |
|
||||
| CHANGELOG.md | 版本更新记录 |
|
||||
| requirements.txt | Python 依赖列表 |
|
||||
| .gitignore | Git 忽略配置 |
|
||||
|
||||
### Features(技术特性)
|
||||
|
||||
| 特性 | 说明 |
|
||||
|------|------|
|
||||
| 任意阶次 LTI 系统 | 支持任意阶次线性时不变系统分析 |
|
||||
| python-control 集成 | 复用成熟控制系统工具箱 |
|
||||
| 英文图表标签 | 避免中文显示问题 |
|
||||
| LaTeX 公式渲染 | Chatbot 内数学公式支持 |
|
||||
|
||||
---
|
||||
|
||||
## Version History
|
||||
## [Unreleased] - 开发中
|
||||
|
||||
### v1.0.0 (2025-10-15)
|
||||
- 🎉 首次正式发布
|
||||
- 包含四大核心功能模块
|
||||
- 完整的文档和配置文件
|
||||
> 以下为计划中但尚未发布的功能
|
||||
|
||||
### Planned(计划功能)
|
||||
|
||||
| 功能 | 状态 | 说明 |
|
||||
|------|------|------|
|
||||
| 状态空间分析模块 | 🔄 计划中 | 状态空间模型构建、能控性/能观性分析 |
|
||||
| 离散系统分析支持 | 🔄 计划中 | 离散传递函数、Z变换、根轨迹 |
|
||||
| PID 控制器自动调参 | 🔄 计划中 | Ziegler-Nichols、遗传算法优化 |
|
||||
| 极点配置设计工具 | 🔄 计划中 | 通过状态反馈实现指定极点位置 |
|
||||
| 系统对比功能 | 🔄 计划中 | 多个传递函数对比分析 |
|
||||
| 分析报告导出 | 🔄 计划中 | PDF/Word 格式报告生成 |
|
||||
| 历史记录保存 | 🔄 计划中 | 本地保存分析历史 |
|
||||
| 更多 AI 模型支持 | 🔄 计划中 | Claude、GPT-4 等 |
|
||||
| 多语言界面 | 🔄 计划中 | 英文版界面 |
|
||||
| 移动端适配 | 🔄 计划中 | 响应式布局优化 |
|
||||
|
||||
---
|
||||
|
||||
**Note**: For detailed commit history, see the [Git log](https://github.com/your-repo/commits).
|
||||
## 版本历史
|
||||
|
||||
| 版本 | 日期 | 重大变更 |
|
||||
|------|------|----------|
|
||||
| 1.2.0 | 2026-04-07 | 新增算例演示模块、混动模型联动、精简 Model 目录 |
|
||||
| 1.1.0 | 2026-02-15 | 新增在线统计、系统资源监控、持久化存储 |
|
||||
| 1.0.0 | 2025-10-15 | 首次正式发布,四大核心功能 + AI 问答 |
|
||||
|
||||
---
|
||||
|
||||
## 分支管理
|
||||
|
||||
| 分支 | 用途 |
|
||||
|------|------|
|
||||
| `master` | 主分支,稳定版本 |
|
||||
| `feature/case-demo-model-minimal` | 算例演示模块开发分支 |
|
||||
|
||||
### 合并策略
|
||||
|
||||
```bash
|
||||
# 功能完成后,创建 Pull Request
|
||||
git checkout -b feature/your-feature
|
||||
git add .
|
||||
git commit -m "feat: add new feature"
|
||||
git push -u origin feature/your-feature
|
||||
|
||||
# 合并到 master
|
||||
git checkout master
|
||||
git merge feature/your-feature
|
||||
git push origin master
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 贡献者
|
||||
|
||||
| 贡献者 | 角色 | 主要贡献 |
|
||||
|--------|------|----------|
|
||||
| 魏鹏飞 | 项目负责人 | 整体架构设计、核心算法 |
|
||||
| 项目团队 | 开发 | 各功能模块实现 |
|
||||
|
||||
---
|
||||
|
||||
## 提交信息规范
|
||||
|
||||
本项目采用 [Conventional Commits](https://www.conventionalcommits.org/) 规范:
|
||||
|
||||
| 类型 | 说明 |
|
||||
|------|------|
|
||||
| `feat:` | 新功能 |
|
||||
| `fix:` | 问题修复 |
|
||||
| `docs:` | 文档更新 |
|
||||
| `style:` | 代码格式调整(不影响功能) |
|
||||
| `refactor:` | 代码重构 |
|
||||
| `perf:` | 性能优化 |
|
||||
| `test:` | 测试相关 |
|
||||
| `chore:` | 构建/工具变更 |
|
||||
|
||||
**示例:**
|
||||
```bash
|
||||
git commit -m "feat: add MPC controller for engine design"
|
||||
git commit -m "fix: resolve path resolution issue in Model loading"
|
||||
git commit -m "docs: update README with new case demo section"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**注意:** 详细的 Git 提交历史请参阅 `git log` 或 GitHub 仓库的 Commit 页面。
|
||||
|
||||
+759
-187
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,785 @@
|
||||
Altitude_m,Mach,RPM,SFC,Power_kW,Inlet_T2_K,Inlet_P2_kPa,RPM_Rel_Phys,RPM_Rel_Corr,Flight_Vel_kmh,WF_kg_h
|
||||
0.0,0.0,58000.0,0.517840950638725,249.582776334593,288.15,101.325005740179,1.0,1.00000000810418,0.0,129.24418216015792
|
||||
0.0,0.0,56550.0,0.523671728560371,225.628264104881,288.15,101.325005740179,0.975,0.975000007901579,0.0,118.15514307587895
|
||||
0.0,0.0,55100.0,0.541853755600857,199.858261719303,288.15,101.325005740179,0.95,0.950000007698975,0.0,108.29394970046332
|
||||
0.0,0.0,53650.0,0.574210664480304,172.570200963337,288.15,101.325005740179,0.925,0.92500000749637,0.0,99.09164976465733
|
||||
0.0,0.0,52200.0,0.634153554768018,141.195238600974,288.15,101.325005740179,0.9,0.900000007293765,0.0,89.53946247512614
|
||||
0.0,0.0,50750.0,0.739625131431326,108.051321175276,288.15,101.325005740179,0.875,0.875000007091161,0.0,79.91747262559193
|
||||
0.0,0.0,49300.0,0.889708703850822,80.8082872194116,288.15,101.325005740179,0.85,0.850000006888556,0.0,71.89583648238764
|
||||
0.0,0.0,47850.0,1.08140792247008,60.7887493798357,288.15,101.325005740179,0.825,0.825000006685951,0.0,65.7374351764025
|
||||
0.0,0.0,46400.0,1.29064944286157,47.6405112445542,288.15,101.325005740179,0.8,0.800000006483347,0.0,61.48719929542423
|
||||
0.0,0.0,44950.0,1.51493801357613,38.5098458611298,288.15,101.325005740179,0.775,0.775000006280742,0.0,58.340029391982924
|
||||
0.0,0.0,43500.0,1.77665628493182,31.3519538053187,288.15,101.325005740179,0.75,0.750000006078138,0.0,55.70164577311156
|
||||
0.0,0.0,42050.0,2.13113424114961,24.9483532621358,288.15,101.325005740179,0.725,0.725000005875533,0.0,53.168289897234175
|
||||
0.0,0.0,40600.0,2.66079262801875,19.0435113641824,288.15,101.325005740179,0.7,0.700000005672928,0.0,50.67083464940782
|
||||
0.0,0.0,0.0,0.0,0.0,288.15,101.325005740179,0.0,0.0,0.0,0.0
|
||||
0.0,0.05,58000.0,0.516516781939578,250.658217899343,288.294288851519,101.50245395591,1.0,0.999749731014721,61.2540781071208,129.46917607607816
|
||||
0.0,0.05,56550.0,0.522545552740258,226.315592419349,288.294288851519,101.50245395591,0.975,0.974755987739353,61.2540781071208,118.26020633450767
|
||||
0.0,0.05,55100.0,0.540702165324945,200.446769067162,288.294288851519,101.50245395591,0.95,0.949762244463985,61.2540781071208,108.3820020670037
|
||||
0.0,0.05,53650.0,0.572924816015739,173.069984669624,288.294288851519,101.50245395591,0.925,0.924768501188617,61.2540781071208,99.15608912469109
|
||||
0.0,0.05,52200.0,0.632705856008601,141.575524377551,288.294288851519,101.50245395591,0.9,0.899774757913249,61.2540781071208,89.57566334116497
|
||||
0.0,0.05,50750.0,0.73790833583659,108.30563465016,288.294288851519,101.50245395591,0.875,0.874781014637881,61.2540781071208,79.91963062642529
|
||||
0.0,0.05,49300.0,0.887385695585721,81.0001237411043,288.294288851519,101.50245395591,0.85,0.849787271362513,61.2540781071208,71.87835114852932
|
||||
0.0,0.05,47850.0,1.07779232680311,60.9732715859449,288.294288851519,101.50245395591,0.825,0.824793528087145,61.2540781071208,65.7165242554135
|
||||
0.0,0.05,46400.0,1.28582871717267,47.7971346450755,288.294288851519,101.50245395591,0.8,0.799799784811776,61.2540781071208,61.45892832520682
|
||||
0.0,0.05,44950.0,1.50879846329932,38.6449856348878,288.294288851519,101.50245395591,0.775,0.774806041536408,61.2540781071208,58.307494940143016
|
||||
0.0,0.05,43500.0,1.76929731842248,31.4626795287867,288.294288851519,101.50245395591,0.75,0.74981229826104,61.2540781071208,55.66683452066817
|
||||
0.0,0.05,42050.0,2.12262473079863,25.0296488161928,288.294288851519,101.50245395591,0.725,0.724818554985672,61.2540781071208,53.12855158045549
|
||||
0.0,0.05,40600.0,2.65054955410193,19.0998400915557,288.294288851519,101.50245395591,0.7,0.699824811710304,61.2540781071208,50.62507263809112
|
||||
0.0,0.05,0.0,0.0,0.0,288.15,101.50245395591,0.0,0.0,0.0,0.0
|
||||
0.0,0.1,58000.0,0.513436195618546,252.835841959937,288.727155406076,102.036129697856,1.0,0.999000025738633,122.508156214242,129.815072811922
|
||||
0.0,0.1,56550.0,0.519207561513579,228.379823641232,288.727155406076,102.036129697856,0.975,0.974025025095167,122.508156214242,118.57653133166531
|
||||
0.0,0.1,55100.0,0.537279892817707,202.216306865266,288.727155406076,102.036129697856,0.95,0.949050024451701,122.508156214242,108.64675567856268
|
||||
0.0,0.1,53650.0,0.569111688484241,174.569497630313,288.727155406076,102.036129697856,0.925,0.924075023808235,122.508156214242,99.34954155423314
|
||||
0.0,0.1,52200.0,0.628416151322243,142.713704486095,288.727155406076,102.036129697856,0.9,0.899100023164769,122.508156214242,89.68359691409175
|
||||
0.0,0.1,50750.0,0.732800403291141,109.070720613081,288.727155406076,102.036129697856,0.875,0.874125022521303,122.508156214242,79.92706805252112
|
||||
0.0,0.1,49300.0,0.880428242025916,81.5850645288629,288.727155406076,102.036129697856,0.85,0.849150021877838,122.508156214242,71.82979493871768
|
||||
0.0,0.1,47850.0,1.06703252243469,61.529752385002,288.727155406076,102.036129697856,0.825,0.824175021234372,122.508156214242,65.65424689215057
|
||||
0.0,0.1,46400.0,1.27139563873693,48.2751901598378,288.727155406076,102.036129697856,0.8,0.799200020590906,122.508156214242,61.37686622841374
|
||||
0.0,0.1,44950.0,1.49055357865882,39.0529730041172,288.727155406076,102.036129697856,0.775,0.77422501994744,122.508156214242,58.21054866855318
|
||||
0.0,0.1,43500.0,1.74741166189252,31.7971341312229,288.727155406076,102.036129697856,0.75,0.749250019303974,122.508156214242,55.56268299565958
|
||||
0.0,0.1,42050.0,2.09733168791679,25.274786200372,288.727155406076,102.036129697856,0.725,0.724275018660508,122.508156214242,53.00961000336219
|
||||
0.0,0.1,40600.0,2.6200205283376,19.2702125463316,288.727155406076,102.036129697856,0.7,0.699300018017043,122.508156214242,50.488352456817566
|
||||
0.0,0.1,0.0,0.0,0.0,288.727155406076,102.036129697856,0.0,0.0,0.0,0.0
|
||||
0.0,0.15,58000.0,0.508303822197168,256.522280001327,289.448599663671,102.930036212294,1.0,0.997754256213846,183.762234321362,130.39125540340663
|
||||
0.0,0.15,56550.0,0.513768108402086,231.834139600599,289.448599663671,102.930036212294,0.975,0.9728103998085,183.762234321362,119.10898736562488
|
||||
0.0,0.15,55100.0,0.53169036295966,205.18808691688,289.448599663671,102.930036212294,0.95,0.947866543403153,183.762234321362,109.09652840783419
|
||||
0.0,0.15,53650.0,0.562885984655253,177.074104192777,289.448599663671,102.930036212294,0.925,0.922922686997807,183.762234321362,99.67253149549815
|
||||
0.0,0.15,52200.0,0.621415585310371,144.607194862463,289.448599663671,102.930036212294,0.9,0.897978830592461,183.762234321362,89.8611646355483
|
||||
0.0,0.15,50750.0,0.724398298070544,110.353702900077,289.448599663671,102.930036212294,0.875,0.873034974187115,183.762234321362,79.94003456659823
|
||||
0.0,0.15,49300.0,0.868963419440882,82.5696612854769,289.448599663671,102.930036212294,0.85,0.848091117781769,183.762234321362,71.75001521270342
|
||||
0.0,0.15,47850.0,1.04936322033586,62.4692059005246,289.448599663671,102.930036212294,0.825,0.823147261376423,183.762234321362,65.5528870755984
|
||||
0.0,0.15,46400.0,1.24760086285893,49.0811249323403,289.448599663671,102.930036212294,0.8,0.798203404971076,183.762234321362,61.2336538156747
|
||||
0.0,0.15,44950.0,1.46065400610989,39.7418051078847,289.448599663671,102.930036212294,0.775,0.77325954856573,183.762234321362,58.04902684087028
|
||||
0.0,0.15,43500.0,1.71166228196001,32.3575211803761,289.448599663671,102.930036212294,0.75,0.748315692160384,183.762234321362,55.385148542171905
|
||||
0.0,0.15,42050.0,2.05587560606064,25.6882448380733,289.448599663671,102.930036212294,0.725,0.723371835755038,183.762234321362,52.81183592510804
|
||||
0.0,0.15,40600.0,2.56982715771228,19.5585663923114,289.448599663671,102.930036212294,0.7,0.698427979349692,183.762234321362,50.262135080880526
|
||||
0.0,0.15,0.0,0.0,0.0,289.448599663671,102.930036212294,0.0,0.0,0.0,0.0
|
||||
0.0,0.2,58000.0,0.501250800659334,261.759459202845,290.458621624305,104.190878817561,1.0,0.996017982548927,245.016312428483,131.20713850558033
|
||||
0.0,0.2,56550.0,0.506402418440838,236.701150317205,290.458621624305,104.190878817561,0.975,0.971117532985204,245.016312428483,119.86603496836094
|
||||
0.0,0.2,55100.0,0.524081760131972,209.382452906353,290.458621624305,104.190878817561,0.95,0.946217083421481,245.016312428483,109.73352445991122
|
||||
0.0,0.2,53650.0,0.554408655520227,180.606119878927,290.458621624305,104.190878817561,0.925,0.921316633857758,245.016312428483,100.12959610080085
|
||||
0.0,0.2,52200.0,0.611924089122952,147.248936419038,290.458621624305,104.190878817561,0.9,0.896416184294035,245.016312428483,90.1051712925433
|
||||
0.0,0.2,50750.0,0.712867614487687,112.162709165899,290.458621624305,104.190878817561,0.875,0.871515734730311,245.016312428483,79.95716291757064
|
||||
0.0,0.2,49300.0,0.853191265962915,83.9669272358269,290.458621624305,104.190878817561,0.85,0.846615285166588,245.016312428483,71.63984894735111
|
||||
0.0,0.2,47850.0,1.02520783334495,63.8070427154862,290.458621624305,104.190878817561,0.825,0.821714835602865,245.016312428483,65.41548001449227
|
||||
0.0,0.2,46400.0,1.21506130958451,50.2323898197981,290.458621624305,104.190878817561,0.8,0.796814386039142,245.016312428483,61.03543335800349
|
||||
0.0,0.2,44950.0,1.41996403959041,40.7236070141082,290.458621624305,104.190878817561,0.775,0.771913936475419,245.016312428483,57.82605752244543
|
||||
0.0,0.2,43500.0,1.66295238675979,33.1619847107919,290.458621624305,104.190878817561,0.75,0.747013486911695,245.016312428483,55.14680162450305
|
||||
0.0,0.2,42050.0,1.99941687675703,26.2756343548397,290.458621624305,104.190878817561,0.725,0.722113037347972,245.016312428483,52.53594677656331
|
||||
0.0,0.2,40600.0,2.50119886215125,19.9707328363875,290.458621624305,104.190878817561,0.7,0.697212587784249,245.016312428483,49.95077424669903
|
||||
0.0,0.2,0.0,0.0,0.0,290.458621624305,104.190878817561,0.0,0.0,0.0,0.0
|
||||
0.0,0.25,58000.0,0.492562714842441,268.601992942731,291.757221287976,105.828114886451,1.0,0.993798892524202,306.270390535604,132.30332685596176
|
||||
0.0,0.25,56550.0,0.497354898953314,243.004445916489,291.757221287976,105.828114886451,0.975,0.968953920211097,306.270390535604,120.85945164400144
|
||||
0.0,0.25,55100.0,0.514640513982778,214.839918815304,291.757221287976,105.828114886451,0.95,0.944108947897992,306.270390535604,110.56532624312635
|
||||
0.0,0.25,53650.0,0.543944515764917,185.170887141512,291.757221287976,105.828114886451,0.925,0.919263975584887,306.270390535604,100.72268853994983
|
||||
0.0,0.25,52200.0,0.600220793043495,150.628263370275,291.757221287976,105.828114886451,0.9,0.894419003271782,306.270390535604,90.41021569487089
|
||||
0.0,0.25,50750.0,0.698506218063967,114.489697130401,291.757221287976,105.828114886451,0.875,0.869574030958677,306.270390535604,79.97176534984541
|
||||
0.0,0.25,49300.0,0.83342174200584,85.8000169578578,291.757221287976,105.828114886451,0.85,0.844729058645572,306.270390535604,71.50759959714846
|
||||
0.0,0.25,47850.0,0.995097049054201,65.5677696774729,291.757221287976,105.828114886451,0.825,0.819884086332467,306.270390535604,65.2462941191188
|
||||
0.0,0.25,46400.0,1.17446559612791,51.7593888654142,291.757221287976,105.828114886451,0.8,0.795039114019362,306.270390535604,60.789621499035
|
||||
0.0,0.25,44950.0,1.36938137294802,42.0245346692307,291.757221287976,105.828114886451,0.775,0.770194141706257,306.270390535604,57.5476149828528
|
||||
0.0,0.25,43500.0,1.60268807424156,34.2200050133504,291.757221287976,105.828114886451,0.75,0.745349169393151,306.270390535604,54.84399393538308
|
||||
0.0,0.25,42050.0,1.92925158155243,27.0448145664854,291.757221287976,105.828114886451,0.725,0.720504197080046,306.270390535604,52.17625127518416
|
||||
0.0,0.25,40600.0,2.41452165781416,20.5214146028223,291.757221287976,105.828114886451,0.7,0.695659224766941,306.270390535604,49.549400007498214
|
||||
0.0,0.25,0.0,0.0,0.0,291.757221287976,105.828114886451,0.0,0.0,0.0,0.0
|
||||
0.0,0.3,58000.0,0.482367372847481,277.126239778584,293.344398654686,107.854024062161,1.0,0.991106708010945,367.524468642725,133.67665622909666
|
||||
0.0,0.3,56550.0,0.486870031914151,250.789144178591,293.344398654686,107.854024062161,0.975,0.966329040310672,367.524468642725,122.10171862995321
|
||||
0.0,0.3,55100.0,0.503598043800678,221.611062031802,293.344398654686,107.854024062161,0.95,0.941551372610398,367.524468642725,111.60289732380618
|
||||
0.0,0.3,53650.0,0.531818601227221,190.750348595921,293.344398654686,107.854024062161,0.925,0.916773704910124,367.524468642725,101.44458357388751
|
||||
0.0,0.3,52200.0,0.586686128176419,154.692509344946,293.344398654686,107.854024062161,0.9,0.891996037209851,367.524468642725,90.75594936548087
|
||||
0.0,0.3,50750.0,0.681053189804184,117.520945887004,293.344398654686,107.854024062161,0.875,0.867218369509577,367.524468642725,80.03801506514897
|
||||
0.0,0.3,49300.0,0.810028838788352,88.0704136228099,293.344398654686,107.854024062161,0.85,0.842440701809304,367.524468642725,71.33957487849456
|
||||
0.0,0.3,47850.0,0.959664690959701,67.7841412516794,293.344398654686,107.854024062161,0.825,0.81766303410903,367.524468642725,65.05004696626163
|
||||
0.0,0.3,46400.0,1.12676432858678,53.6995558374525,293.344398654686,107.854024062161,0.8,0.792885366408756,367.524468642725,60.50674397859547
|
||||
0.0,0.3,44950.0,1.31026983912815,43.6700802700707,293.344398654686,107.854024062161,0.775,0.768107698708483,367.524468642725,57.21958905017893
|
||||
0.0,0.3,43500.0,1.53250532677088,35.5476521639635,293.344398654686,107.854024062161,0.75,0.743330031008209,367.524468642725,54.47696629547246
|
||||
0.0,0.3,42050.0,1.84715125774841,28.0133860735945,293.344398654686,107.854024062161,0.725,0.718552363307935,367.524468642725,51.74496131963187
|
||||
0.0,0.3,40600.0,2.31213798797291,21.2209657867659,293.344398654686,107.854024062161,0.7,0.693774695607662,367.524468642725,49.06580113705487
|
||||
0.0,0.3,0.0,0.0,0.0,293.344398654686,107.854024062161,0.0,0.0,0.0,0.0
|
||||
0.0,0.35,58000.0,0.470982676252837,287.448191862454,295.220153724433,110.283798947079,1.0,0.987953068515966,428.778546749846,135.38311868741755
|
||||
0.0,0.35,56550.0,0.475218114456363,260.108270129808,295.220153724433,110.283798947079,0.975,0.963254241803067,428.778546749846,123.60816168559369
|
||||
0.0,0.35,55100.0,0.491174946865564,229.795617605291,295.220153724433,110.283798947079,0.95,0.938555415090168,428.778546749846,112.86985026721827
|
||||
0.0,0.35,53650.0,0.518318948567858,197.334217399414,295.220153724433,110.283798947079,0.925,0.913856588377269,428.778546749846,102.28206407892537
|
||||
0.0,0.35,52200.0,0.571682608308068,159.409924689662,295.220153724433,110.283798947079,0.9,0.889157761664369,428.778546749846,91.13188153677866
|
||||
0.0,0.35,50750.0,0.66132568386357,121.135080521774,295.220153724433,110.283798947079,0.875,0.86445893495147,428.778546749846,80.10973996593081
|
||||
0.0,0.35,49300.0,0.783144154629023,90.8624063235755,295.220153724433,110.283798947079,0.85,0.839760108238571,428.778546749846,71.15836238783533
|
||||
0.0,0.35,47850.0,0.91948639236671,70.5006201141703,295.220153724433,110.283798947079,0.825,0.815061281525672,428.778546749846,64.82436084839436
|
||||
0.0,0.35,46400.0,1.0730676040304,56.0937180021038,295.220153724433,110.283798947079,0.8,0.790362454812773,428.778546749846,60.19235157767444
|
||||
0.0,0.35,44950.0,1.24430053465644,45.6846095464051,295.220153724433,110.283798947079,0.775,0.765663628099874,428.778546749846,56.84538408416257
|
||||
0.0,0.35,43500.0,1.45417587540355,37.1632115898238,295.220153724433,110.283798947079,0.75,0.740964801386974,428.778546749846,54.041845746439385
|
||||
0.0,0.35,42050.0,1.75444595442007,29.1975393285886,295.220153724433,110.283798947079,0.725,0.716265974674075,428.778546749846,51.22550475406315
|
||||
0.0,0.35,40600.0,2.19546192091381,22.0904790876996,295.220153724433,110.283798947079,0.7,0.691567147961176,428.778546749846,48.49880565178731
|
||||
0.0,0.35,0.0,0.0,0.0,295.220153724433,110.283798947079,0.0,0.0,0.0,0.0
|
||||
1000.0,0.0,58000.0,0.515510044506519,231.347045275657,281.65,89.8745653777784,1.0,1.01147333392362,0.0,119.26172560650562
|
||||
1000.0,0.0,56550.0,0.521319051346396,208.529434436095,281.65,89.8745653777784,0.975,0.986186500575529,0.0,108.71036693802552
|
||||
1000.0,0.0,55100.0,0.533408708360696,186.672798453626,281.65,89.8745653777784,0.95,0.960899667227439,0.0,99.57289630922517
|
||||
1000.0,0.0,53650.0,0.561805068138577,162.286894360006,281.65,89.8745653777784,0.925,0.935612833879348,0.0,91.17359974392122
|
||||
1000.0,0.0,52200.0,0.608779472420338,136.377620387831,281.65,89.8745653777784,0.9,0.910326000531258,0.0,83.0238957896449
|
||||
1000.0,0.0,50750.0,0.698825801404107,106.340081289564,281.65,89.8745653777784,0.875,0.885039167183167,0.0,74.31319252855745
|
||||
1000.0,0.0,49300.0,0.837141835069454,79.542500537258,281.65,89.8745653777784,0.85,0.859752333835077,0.0,66.5883548657732
|
||||
1000.0,0.0,47850.0,1.02541544810262,59.0387574346416,281.65,89.8745653777784,0.825,0.834465500486986,0.0,60.53925391026491
|
||||
1000.0,0.0,46400.0,1.24073035229992,45.3425702128889,281.65,89.8745653777784,0.8,0.809178667138896,0.0,56.25790311442151
|
||||
1000.0,0.0,44950.0,1.47134751687178,36.1922572739731,281.65,89.8745653777784,0.775,0.783891833790805,0.0,53.25138787004494
|
||||
1000.0,0.0,43500.0,1.73333034540858,29.3477867111523,281.65,89.8745653777784,0.75,0.758605000442715,0.0,50.869409277018946
|
||||
1000.0,0.0,42050.0,2.07333744397542,23.4978035602648,281.65,89.8745653777784,0.725,0.733318167094624,0.0,48.71887597267594
|
||||
1000.0,0.0,40600.0,2.58613994598036,18.0061465244471,281.65,89.8745653777784,0.7,0.708031333746534,0.0,46.56641480004807
|
||||
0.0,0.0,0.0,0.0,0.0,281.65,89.8745653777784,0.0,0.0,0.0,0.0
|
||||
1000.0,0.05,58000.0,0.514407544001346,232.057071431022,281.791043194302,90.0319709371256,1.0,1.01122016887588,60.5612300201938,119.37190818297695
|
||||
1000.0,0.05,56550.0,0.520197895272965,209.155609403893,281.791043194302,90.0319709371256,0.975,0.985939664653983,60.5612300201938,108.80230779643951
|
||||
1000.0,0.05,55100.0,0.532275217566708,187.223180163877,281.791043194302,90.0319709371256,0.95,0.960659160432086,60.5612300201938,99.65425895525861
|
||||
1000.0,0.05,53650.0,0.56055009449265,162.762944486508,281.791043194302,90.0319709371256,0.925,0.935378656210189,60.5612300201938,91.236783911814
|
||||
1000.0,0.05,52200.0,0.607406502827473,136.748078761447,281.791043194302,90.0319709371256,0.9,0.910098151988292,60.5612300201938,83.06167228886636
|
||||
1000.0,0.05,50750.0,0.697187921761441,106.606249474818,281.791043194302,90.0319709371256,0.875,0.884817647766395,60.5612300201938,74.32458951813007
|
||||
1000.0,0.05,49300.0,0.835046324508423,79.7276235815022,281.791043194302,90.0319709371256,0.85,0.859537143544498,60.5612300201938,66.57625903352448
|
||||
1000.0,0.05,47850.0,1.02226108118176,59.2005754221843,281.791043194302,90.0319709371256,0.825,0.834256639322601,60.5612300201938,60.518444237664454
|
||||
1000.0,0.05,46400.0,1.2361741222274,45.487062658334,281.791043194302,90.0319709371256,0.8,0.808976135100704,60.5612300201938,56.229929754368776
|
||||
1000.0,0.05,44950.0,1.46543348145882,36.3170660139083,281.791043194302,90.0319709371256,0.775,0.783695630878807,60.5612300201938,53.22024448513143
|
||||
1000.0,0.05,43500.0,1.7260791323154,29.4521460135816,281.791043194302,90.0319709371256,0.75,0.75841512665691,60.5612300201938,50.8367346359494
|
||||
1000.0,0.05,42050.0,2.06476425078307,23.577492698345,281.791043194302,90.0319709371256,0.725,0.733134622435013,60.5612300201938,48.681964046641625
|
||||
1000.0,0.05,40600.0,2.57601707924468,18.0605120273877,281.791043194302,90.0319709371256,0.7,0.707854118213116,60.5612300201938,46.524187442454675
|
||||
1000.0,0.05,0.0,0.0,0.0,281.791043194302,90.0319709371256,0.0,0.0,0.0,0.0
|
||||
1000.0,0.1,58000.0,0.511323931509567,234.051973284574,282.214172777207,90.5053684407736,1.0,1.01046181279174,121.122460040388,119.67637515744052
|
||||
1000.0,0.1,56550.0,0.516860901055493,211.043872820739,282.214172777207,90.5053684407736,0.975,0.985200267471946,121.122460040388,109.08032626836803
|
||||
1000.0,0.1,55100.0,0.528913100039104,188.876591961705,282.214172777207,90.5053684407736,0.95,0.959938722152153,121.122460040388,99.8993037792863
|
||||
1000.0,0.1,53650.0,0.556815473768111,164.196894302291,282.214172777207,90.5053684407736,0.925,0.934677176832359,121.122460040388,91.42737149218262
|
||||
1000.0,0.1,52200.0,0.603333857444066,137.857859017078,282.214172777207,90.5053684407736,0.9,0.909415631512566,121.122460040388,83.17431385975388
|
||||
1000.0,0.1,50750.0,0.692315772188055,107.405528367254,282.214172777207,90.5053684407736,0.875,0.884154086192772,121.122460040388,74.3585413088415
|
||||
1000.0,0.1,49300.0,0.828802161037887,80.2847066192652,282.214172777207,90.5053684407736,0.85,0.858892540872979,121.122460040388,66.54013834433974
|
||||
1000.0,0.1,47850.0,1.01285752406058,59.6891383315025,282.214172777207,90.5053684407736,0.825,0.833630995553185,121.122460040388,60.45659286375508
|
||||
1000.0,0.1,46400.0,1.22260490227503,45.9239216945485,282.214172777207,90.5053684407736,0.8,0.808369450233392,121.122460040388,56.1468117954496
|
||||
1000.0,0.1,44950.0,1.44784591856524,36.6940706105627,282.214172777207,90.5053684407736,0.775,0.783107904913598,121.122460040388,53.12736036904792
|
||||
1000.0,0.1,43500.0,1.70447817617648,29.7676876469067,282.214172777207,90.5053684407736,0.75,0.757846359593805,121.122460040388,50.73837394939067
|
||||
1000.0,0.1,42050.0,2.03934058277994,23.8173918741994,282.214172777207,90.5053684407736,0.725,0.732584814274011,121.122460040388,48.57177382502802
|
||||
1000.0,0.1,40600.0,2.54582687956037,18.2250708190903,282.214172777207,90.5053684407736,0.7,0.707323268954218,121.122460040388,46.39787517313141
|
||||
1000.0,0.1,0.0,0.0,0.0,282.214172777207,90.5053684407736,0.0,0.0,0.0,0.0
|
||||
1000.0,0.15,58000.0,0.506314395500302,237.404529912313,282.919388748717,91.2983092035152,1.0,1.00920166864562,181.683690060581,120.20133105158612
|
||||
1000.0,0.15,56550.0,0.511387888409563,214.222716976481,282.919388748717,91.2983092035152,0.975,0.983971626929483,181.683690060581,109.55090288396205
|
||||
1000.0,0.15,55100.0,0.52341748065481,191.646427610897,282.919388748717,91.2983092035152,0.95,0.958741585213343,181.683690060581,100.31109031659012
|
||||
1000.0,0.15,53650.0,0.550690020565192,166.605593921518,282.919388748717,91.2983092035152,0.925,0.933511543497202,181.683690060581,91.74803794291677
|
||||
1000.0,0.15,52200.0,0.596790691764497,139.667866391822,282.919388748717,91.2983092035152,0.9,0.908281501781062,181.683690060581,83.35248260124679
|
||||
1000.0,0.15,50750.0,0.684314755335882,108.744814355104,282.919388748717,91.2983092035152,0.875,0.883051460064921,181.683690060581,74.41568102945891
|
||||
1000.0,0.15,49300.0,0.818584457801641,81.2116685319316,282.919388748717,91.2983092035152,0.85,0.85782141834878,181.683690060581,66.47860965237781
|
||||
1000.0,0.15,47850.0,0.997361889035037,60.5150997924293,282.919388748717,91.2983092035152,0.825,0.83259137663264,181.683690060581,60.355454244121056
|
||||
1000.0,0.15,46400.0,1.20030024896332,46.6640080678968,282.919388748717,91.2983092035152,0.8,0.807361334916499,181.683690060581,56.01082050152291
|
||||
1000.0,0.15,44950.0,1.41899676814152,37.3320805814069,282.919388748717,91.2983092035152,0.775,0.782131293200358,181.683690060581,52.97410169301519
|
||||
1000.0,0.15,43500.0,1.66918699537015,30.2996289602214,282.919388748717,91.2983092035152,0.75,0.756901251484218,181.683690060581,50.57574662494234
|
||||
1000.0,0.15,42050.0,1.99770934875897,24.2225459222734,282.919388748717,91.2983092035152,0.725,0.731671209768077,181.683690060581,48.389606439669045
|
||||
1000.0,0.15,40600.0,2.49619212322723,18.5037167448737,282.919388748717,91.2983092035152,0.7,0.706441168051937,181.683690060581,46.188831988981526
|
||||
1000.0,0.15,0.0,0.0,0.0,289.448599663671,102.930036212294,0.0,0.0,0.0,0.0
|
||||
1000.0,0.2,58000.0,0.499500545527715,242.133031404394,283.90669110883,92.4167415738559,1.0,1.00744536106482,242.244920080775,120.94558127677415
|
||||
1000.0,0.2,56550.0,0.503928165349098,218.725359848472,283.90669110883,92.4167415738559,0.975,0.982259227038199,242.244920080775,110.22186930376176
|
||||
1000.0,0.2,55100.0,0.515952727887589,195.550713428736,283.90669110883,92.4167415738559,0.95,0.957073093011579,242.244920080775,100.89492403392052
|
||||
1000.0,0.2,53650.0,0.542317761076815,170.019365303365,283.90669110883,92.4167415738559,0.925,0.931886958984958,242.244920080775,92.20452153102202
|
||||
1000.0,0.2,52200.0,0.587897595951998,142.199704887738,283.90669110883,92.4167415738559,0.9,0.906700824958338,242.244920080775,83.59886464858474
|
||||
1000.0,0.2,50750.0,0.673398464263004,110.622962113858,283.90669110883,92.4167415738559,0.875,0.881514690931717,242.244920080775,74.49333279969645
|
||||
1000.0,0.2,49300.0,0.804574283732402,82.5201578438976,283.90669110883,92.4167415738559,0.85,0.856328556905097,242.244920080775,66.39359689073866
|
||||
1000.0,0.2,47850.0,0.976056231812973,61.6956889529813,283.90669110883,92.4167415738559,0.825,0.831142422878476,242.244920080775,60.21846167855219
|
||||
1000.0,0.2,46400.0,1.16979524635858,47.7229964225794,283.90669110883,92.4167415738559,0.8,0.805956288851856,242.244920080775,55.82613435712089
|
||||
1000.0,0.2,44950.0,1.37966973395626,38.2438230126976,283.90669110883,92.4167415738559,0.775,0.780770154825235,242.244920080775,52.76384512139879
|
||||
1000.0,0.2,43500.0,1.621139175837,31.0584541615992,283.90669110883,92.4167415738559,0.75,0.755584020798615,242.244920080775,50.35007678230617
|
||||
1000.0,0.2,42050.0,1.94088839464961,24.7984406532303,283.90669110883,92.4167415738559,0.725,0.730397886771994,242.244920080775,48.13100566926179
|
||||
1000.0,0.2,40600.0,2.42776174404928,18.9045997432519,283.90669110883,92.4167415738559,0.7,0.705211752745374,242.244920080775,45.8958640432308
|
||||
1000.0,0.2,0.0,0.0,0.0,283.90669110883,92.4167415738559,0.0,0.0,0.0,0.0
|
||||
1000.0,0.25,58000.0,0.491106870834565,248.295084764935,285.176079857547,93.8690552767738,1.0,1.00520066703131,302.806150100969,121.93942212251031
|
||||
1000.0,0.25,56550.0,0.494674130615802,224.619478913764,285.176079857547,93.8690552767738,0.975,0.980070650355526,302.806150100969,111.11344545104068
|
||||
1000.0,0.25,55100.0,0.506710974296498,200.636726936331,285.176079857547,93.8690552767738,0.95,0.954940633679743,302.806150100969,101.66483138556872
|
||||
1000.0,0.25,53650.0,0.531891669068342,174.48256837113,285.176079857547,93.8690552767738,0.925,0.92981061700396,302.806150100969,92.80582451425141
|
||||
1000.0,0.25,52200.0,0.576834995127259,145.458943806754,285.176079857547,93.8690552767738,0.9,0.904680600328178,302.806150100969,83.90580914198519
|
||||
1000.0,0.25,50750.0,0.659833245731738,113.042614094839,285.176079857547,93.8690552767738,0.875,0.879550583652395,302.806150100969,74.58927496419793
|
||||
1000.0,0.25,49300.0,0.787113280285323,84.2161426694686,285.176079857547,93.8690552767738,0.85,0.854420566976612,302.806150100969,66.28764430954219
|
||||
1000.0,0.25,47850.0,0.949270548719875,63.2601066250733,285.176079857547,93.8690552767738,0.825,0.829290550300829,302.806150100969,60.05095612806113
|
||||
1000.0,0.25,46400.0,1.13176060787858,49.1256977066405,285.176079857547,93.8690552767738,0.8,0.804160533625047,302.806150100969,55.598529498926816
|
||||
1000.0,0.25,44950.0,1.33080591702903,39.4500197423346,285.176079857547,93.8690552767738,0.775,0.779030516949264,302.806150100969,52.500319700010934
|
||||
1000.0,0.25,43500.0,1.56164397544693,32.0589300930277,285.176079857547,93.8690552767738,0.75,0.753900500273481,302.806150100969,50.06463503905099
|
||||
1000.0,0.25,42050.0,1.87068932127897,25.5556436643225,285.176079857547,93.8690552767738,0.725,0.728770483597698,302.806150100969,47.80666970125866
|
||||
1000.0,0.25,40600.0,2.34272339485242,19.434349895432,285.176079857547,93.8690552767738,0.7,0.703640466921916,302.806150100969,45.529306163776226
|
||||
1000.0,0.25,0.0,0.0,0.0,285.176079857547,93.8690552767738,0.0,0.0,0.0,0.0
|
||||
1000.0,0.3,58000.0,0.481334847455855,255.920202280522,286.727554994867,95.6661437070395,1.0,1.00247742120916,363.367380121163,123.18331152556661
|
||||
1000.0,0.3,56550.0,0.483921798146751,231.894451240306,286.727554994867,95.6661437070395,0.975,0.977415485678929,363.367380121163,112.21877982446296
|
||||
1000.0,0.3,55100.0,0.495933328551175,206.933825773019,286.727554994867,95.6661437070395,0.95,0.9523535501487,363.367380121163,102.62538100544224
|
||||
1000.0,0.3,53650.0,0.519736573799463,179.984095165987,286.727554994867,95.6661437070395,0.925,0.927291614618471,363.367380121163,93.54431695996658
|
||||
1000.0,0.3,52200.0,0.563971973204375,149.462959868794,286.727554994867,95.6661437070395,0.9,0.902229679088242,363.367380121163,84.29292039817007
|
||||
1000.0,0.3,50750.0,0.643942242463018,115.999665097739,286.727554994867,95.6661437070395,0.875,0.877167743558013,363.367380121163,74.69708446799713
|
||||
1000.0,0.3,49300.0,0.766418607040161,86.3322915762664,286.727554994867,95.6661437070395,0.85,0.852105808027784,363.367380121163,66.16667465246712
|
||||
1000.0,0.3,47850.0,0.917325200115547,65.2429981447152,286.727554994867,95.6661437070395,0.825,0.827043872497555,363.367380121163,59.84904632923913
|
||||
1000.0,0.3,46400.0,1.08686716694676,50.9079859557327,286.727554994867,95.6661437070395,0.8,0.801981936967326,363.367380121163,55.33021847067264
|
||||
1000.0,0.3,44950.0,1.27353794841834,40.9857875552953,286.727554994867,95.6661437070395,0.775,0.776920001437097,363.367380121163,52.19695579748071
|
||||
1000.0,0.3,43500.0,1.49236777331988,33.3168463018979,286.727554994867,95.6661437070395,0.75,0.751858065906868,363.367380121163,49.72098772960404
|
||||
1000.0,0.3,42050.0,1.78881980291953,26.5065014540787,286.727554994867,95.6661437070395,0.725,0.726796130376639,363.367380121163,47.41535470717129
|
||||
1000.0,0.3,40600.0,2.24145710517143,20.1131429503249,286.727554994867,95.6661437070395,0.7,0.70173419484641,363.367380121163,45.082747173334404
|
||||
1000.0,0.3,0.0,0.0,0.0,286.727554994867,95.6661437070395,0.0,0.0,0.0,0.0
|
||||
1000.0,0.35,58000.0,0.47039404555375,265.043478251638,288.561116520791,97.8214843854198,1.0,0.999287398130672,423.928610141357,124.67487398242535
|
||||
1000.0,0.35,56550.0,0.472045317312734,240.596937246103,288.561116520791,97.8214843854198,0.975,0.974305213177405,423.928610141357,113.57265758680865
|
||||
1000.0,0.35,55100.0,0.48389604314158,214.471789263338,288.561116520791,97.8214843854198,0.95,0.949323028224138,423.928610141357,103.78205019002407
|
||||
1000.0,0.35,53650.0,0.506310938509629,186.502342985338,288.561116520791,97.8214843854198,0.925,0.924340843270871,423.928610141357,94.42817631115122
|
||||
1000.0,0.35,52200.0,0.549551042070556,154.193828903687,288.561116520791,97.8214843854198,0.9,0.899358658317605,423.928610141357,84.73737935487021
|
||||
1000.0,0.35,50750.0,0.625907160843942,119.560597867778,288.561116520791,97.8214843854198,0.875,0.874376473364338,423.928610141357,74.8338343602252
|
||||
1000.0,0.35,49300.0,0.742637052860997,88.9166687625891,288.561116520791,97.8214843854198,0.85,0.849394288411071,423.928610141357,66.03281284006664
|
||||
1000.0,0.35,47850.0,0.88132580473439,67.6577944554284,288.561116520791,97.8214843854198,0.825,0.824412103457804,423.928610141357,59.62856014498439
|
||||
1000.0,0.35,46400.0,1.03637969937351,53.1367453506142,288.561116520791,97.8214843854198,0.8,0.799429918504537,423.928610141357,55.069844172156294
|
||||
1000.0,0.35,44950.0,1.20954895436051,42.8644097074849,288.561116520791,97.8214843854198,0.775,0.774447733551271,423.928610141357,51.84660194096886
|
||||
1000.0,0.35,43500.0,1.41534127897073,34.842722610254,288.561116520791,97.8214843854198,0.75,0.749465548598004,423.928610141357,49.31434358201927
|
||||
1000.0,0.35,42050.0,1.69712370225193,27.6602108108716,288.561116520791,97.8214843854198,0.725,0.724483363644737,423.928610141357,46.94279937641527
|
||||
1000.0,0.35,40600.0,2.17503761097496,20.0585876591485,288.561116520791,97.8214843854198,0.7,0.69950117869147,423.928610141357,43.62818258168617
|
||||
1000.0,0.35,0.0,0.0,0.0,288.561116520791,97.8214843854198,0.0,0.0,0.0,0.0
|
||||
2000.0,0.0,58000.0,0.515040664520812,213.569545962531,275.15,79.495201431303,1.0,1.02335085536676,0.0,109.99700087395007
|
||||
2000.0,0.0,56550.0,0.519299186792368,192.755816584944,275.15,79.495201431303,0.975,0.997767083982586,0.0,100.09793880206026
|
||||
2000.0,0.0,55100.0,0.528089114170692,173.16041580167,275.15,79.495201431303,0.95,0.972183312598417,0.0,91.44413059013262
|
||||
2000.0,0.0,53650.0,0.550795550902113,152.166960620804,275.15,79.495201431303,0.925,0.946599541214248,0.0,83.81288490423586
|
||||
2000.0,0.0,52200.0,0.590253307886354,129.83818614625,275.15,79.495201431303,0.9,0.92101576983008,0.0,76.63741886278824
|
||||
2000.0,0.0,50750.0,0.663847887312897,104.040691406009,275.15,79.495201431303,0.875,0.895431998445911,0.0,69.06719318445215
|
||||
2000.0,0.0,49300.0,0.788899101634556,78.3153168982003,275.15,79.495201431303,0.85,0.869848227061742,0.0,61.78288314521578
|
||||
2000.0,0.0,47850.0,0.967447846640383,57.8097254335603,275.15,79.495201431303,0.825,0.844264455677573,0.0,55.927894385569694
|
||||
2000.0,0.0,46400.0,1.18925988996186,43.3988491834337,275.15,79.495201431303,0.8,0.818680684293404,0.0,51.61251060436172
|
||||
2000.0,0.0,44950.0,1.42866392429822,34.1105861782349,275.15,79.495201431303,0.775,0.793096912909235,0.0,48.732563909509686
|
||||
2000.0,0.0,43500.0,1.69672297450453,27.4562797051368,275.15,79.495201431303,0.75,0.767513141525066,0.0,46.585700570128076
|
||||
2000.0,0.0,42050.0,2.02976391081085,22.0427161641825,275.15,79.495201431303,0.725,0.741929370140897,0.0,44.74150976630461
|
||||
2000.0,0.0,40600.0,2.52252750412449,17.0250742966338,275.15,79.495201431303,0.7,0.716345598756728,0.0,42.94621817302166
|
||||
2000.0,0.0,0.0,0.0,0.0,275.15,79.495201431303,0.0,0.0,0.0,0.0
|
||||
2000.0,0.05,58000.0,0.513998514586902,214.194454653585,275.287797113977,79.6344377189261,1.0,1.02309470081355,59.8602712653275,110.09563152469424
|
||||
2000.0,0.05,56550.0,0.518292761439053,193.248370151508,275.287797113977,79.6344377189261,0.975,0.997517333293213,59.8602712653275,100.15923140942135
|
||||
2000.0,0.05,55100.0,0.526954837499877,173.679538868261,275.287797113977,79.6344377189261,0.95,0.971939965772874,59.8602712653275,91.52127318137805
|
||||
2000.0,0.05,53650.0,0.549638241152388,152.602234420244,275.287797113977,79.6344377189261,0.925,0.946362598252535,59.8602712653275,83.87602372266733
|
||||
2000.0,0.05,52200.0,0.588924479021849,130.206082713338,275.287797113977,79.6344377189261,0.9,0.920785230732197,59.8602712653275,76.68154942742835
|
||||
2000.0,0.05,50750.0,0.662263113328942,104.324346491018,275.287797113977,79.6344377189261,0.875,0.895207863211858,59.8602712653275,69.09016650314888
|
||||
2000.0,0.05,49300.0,0.787023024813282,78.4974207861195,275.287797113977,79.6344377189261,0.85,0.869630495691519,59.8602712653275,61.77927754713277
|
||||
2000.0,0.05,47850.0,0.96477046936105,57.9481248111078,275.287797113977,79.6344377189261,0.825,0.84405312817118,59.8602712653275,55.90663957260519
|
||||
2000.0,0.05,46400.0,1.18493401412138,43.5394583586965,275.287797113977,79.6344377189261,0.8,0.818475760650841,59.8602712653275,51.591385165640915
|
||||
2000.0,0.05,44950.0,1.42299961041599,34.2275854226577,275.287797113977,79.6344377189261,0.775,0.792898393130502,59.8602712653275,48.70584072192192
|
||||
2000.0,0.05,43500.0,1.68953382430745,27.5545073182161,275.287797113977,79.6344377189261,0.75,0.767321025610164,59.8602712653275,46.55427212625327
|
||||
2000.0,0.05,42050.0,2.02157328496948,22.1156665748395,275.287797113977,79.6344377189261,0.725,0.741743658089825,59.8602712653275,44.70844072698802
|
||||
2000.0,0.05,40600.0,2.51233778089155,17.0812536237758,275.287797113977,79.6344377189261,0.7,0.716166290569486,59.8602712653275,42.913878824002644
|
||||
2000.0,0.05,0.0,0.0,0.0,275.287797113977,79.6344377189261,0.0,0.0,59.8602712653275,0.0
|
||||
2000.0,0.1,58000.0,0.510919083743302,216.065589871836,275.70118845591,80.0531911732792,1.0,1.0223273897384,119.720542530655,110.39203320577452
|
||||
2000.0,0.1,56550.0,0.515125202745729,194.911234844513,275.70118845591,80.0531911732792,0.975,0.996769204994944,119.720542530655,100.40368936670016
|
||||
2000.0,0.1,55100.0,0.523544919442829,175.258927837278,275.70118845591,80.0531911732792,0.95,0.971211020251484,119.720542530655,91.75592125620429
|
||||
2000.0,0.1,53650.0,0.546104394811035,153.922796754545,275.70118845591,80.0531911732792,0.925,0.945652835508024,119.720542530655,84.05791576926275
|
||||
2000.0,0.1,52200.0,0.584972407301244,131.296458225794,275.70118845591,80.0531911732792,0.9,0.920094650764564,119.720542530655,76.80480523846994
|
||||
2000.0,0.1,50750.0,0.657612822883715,105.15383292654,275.70118845591,80.0531911732792,0.875,0.894536466021103,119.720542530655,69.15050890786452
|
||||
2000.0,0.1,49300.0,0.78139803562091,79.0433486403363,275.70118845591,80.0531911732792,0.85,0.868978281277643,119.720542530655,61.76431735645752
|
||||
2000.0,0.1,47850.0,0.956657672643004,58.3836603153741,275.70118845591,80.0531911732792,0.825,0.843420096534183,119.720542530655,55.853176597685504
|
||||
2000.0,0.1,46400.0,1.17240468553146,43.9430413111819,275.70118845591,80.0531911732792,0.8,0.817861911790723,119.720542530655,51.51902752973217
|
||||
2000.0,0.1,44950.0,1.4060986663735,34.579567492174,275.70118845591,80.0531911732792,0.775,0.792303727047263,119.720542530655,48.6222837345183
|
||||
2000.0,0.1,43500.0,1.66820357321683,27.852059961693,275.70118845591,80.0531911732792,0.75,0.766745542303803,119.720542530655,46.46290594954567
|
||||
2000.0,0.1,42050.0,1.99603555324785,22.3509269040472,275.70118845591,80.0531911732792,0.725,0.741187357560343,119.720542530655,44.613244748522106
|
||||
2000.0,0.1,40600.0,2.4821583380156,17.2427048424978,275.70118845591,80.0531911732792,0.7,0.715629172816883,119.720542530655,42.79912359474788
|
||||
2000.0,0.1,0.0,0.0,0.0,275.70118845591,80.0531911732792,0.0,0.0,119.720542530655,0.0
|
||||
2000.0,0.15,58000.0,0.505940469287619,219.170507032382,276.390174025797,80.7546033876493,1.0,1.02105236552231,179.580813795983,110.88722918196876
|
||||
2000.0,0.15,56550.0,0.509876075856986,197.741197803105,276.390174025797,80.7546033876493,0.975,0.995526056384251,179.580813795983,100.82350597110724
|
||||
2000.0,0.15,55100.0,0.517965667072572,177.90754201704,276.390174025797,80.7546033876493,0.95,0.969999747246193,179.580813795983,92.14999867809775
|
||||
2000.0,0.15,53650.0,0.540326499367254,156.13910437807,276.390174025797,80.7546033876493,0.925,0.944473438108135,179.580813795983,84.36609568294084
|
||||
2000.0,0.15,52200.0,0.578528560029528,133.112833708327,276.390174025797,80.7546033876493,0.9,0.918947128970078,179.580813795983,77.00957600672844
|
||||
2000.0,0.15,50750.0,0.650061689936006,106.523511684329,276.390174025797,80.7546033876493,0.875,0.89342081983202,179.580813795983,69.24685402343279
|
||||
2000.0,0.15,49300.0,0.772130195036696,79.9603355666991,276.390174025797,80.7546033876493,0.85,0.867894510693962,179.580813795983,61.73978949631503
|
||||
2000.0,0.15,47850.0,0.943383685282142,59.1134126225871,276.390174025797,80.7546033876493,0.825,0.842368201555904,179.580813795983,55.76662904950011
|
||||
2000.0,0.15,46400.0,1.15182262373302,44.6256045231463,276.390174025797,80.7546033876493,0.8,0.816841892417847,179.580813795983,51.4007808875225
|
||||
2000.0,0.15,44950.0,1.37839265567595,35.1750628777158,276.390174025797,80.7546033876493,0.775,0.791315583279789,179.580813795983,48.48504833358321
|
||||
2000.0,0.15,43500.0,1.63334259022189,28.3538801484714,276.390174025797,80.7546033876493,0.75,0.765789274141731,179.580813795983,46.31160004454531
|
||||
2000.0,0.15,42050.0,1.95393164948942,22.7457146696403,276.390174025797,80.7546033876493,0.725,0.740262965003674,179.580813795983,44.44357178326597
|
||||
2000.0,0.15,40600.0,2.43216017712677,17.5175992884029,276.390174025797,80.7546033876493,0.7,0.714736655865616,179.580813795983,42.60560738811777
|
||||
2000.0,0.15,0.0,0.0,0.0,276.390174025797,80.7546033876493,0.0,0.0,179.580813795983,0.0
|
||||
2000.0,0.2,58000.0,0.499232130684788,223.499410948191,277.35475382364,81.7439364407149,1.0,1.01927531957574,239.44108506131,111.57808713446043
|
||||
2000.0,0.2,56550.0,0.502718503653552,201.74576590171,277.35475382364,81.7439364407149,0.975,0.993793436586342,239.44108506131,101.42132955254743
|
||||
2000.0,0.2,55100.0,0.510439467551189,181.625973772937,277.35475382364,81.7439364407149,0.95,0.968311553596949,239.44108506131,92.70906534612416
|
||||
2000.0,0.2,53650.0,0.532446869721074,159.26960906653,277.35475382364,81.7439364407149,0.925,0.942829670607555,239.44108506131,84.80260478917309
|
||||
2000.0,0.2,52200.0,0.569771402012033,135.661668382115,277.35475382364,81.7439364407149,0.9,0.917347787618162,239.44108506131,77.29613899336915
|
||||
2000.0,0.2,50750.0,0.639810490337827,108.43542661099,277.35475382364,81.7439364407149,0.875,0.891865904628768,239.44108506131,69.37812346996897
|
||||
2000.0,0.2,49300.0,0.759387811981252,81.2584775475928,277.35475382364,81.7439364407149,0.85,0.866384021639375,239.44108506131,61.70669746979419
|
||||
2000.0,0.2,47850.0,0.925360676952596,60.138363527241,277.35475382364,81.7439364407149,0.825,0.840902138649982,239.44108506131,55.649676784389044
|
||||
2000.0,0.2,46400.0,1.12346899321624,45.6108797381169,277.35475382364,81.7439364407149,0.8,0.815420255660588,239.44108506131,51.2424091390892
|
||||
2000.0,0.2,44950.0,1.34057128208328,36.0265684010973,277.35475382364,81.7439364407149,0.775,0.789938372671195,239.44108506131,48.296182990519995
|
||||
2000.0,0.2,43500.0,1.58591300908105,29.0694892137872,277.35475382364,81.7439364407149,0.75,0.764456489681801,239.44108506131,46.101681111486386
|
||||
2000.0,0.2,42050.0,1.89686191592384,23.3095712875742,277.35475382364,81.7439364407149,0.725,0.738974606692408,239.44108506131,44.21503805191133
|
||||
2000.0,0.2,40600.0,2.3640887401846,17.9122257023548,277.35475382364,81.7439364407149,0.7,0.713492723703015,239.44108506131,42.34609109458217
|
||||
2000.0,0.2,0.0,0.0,0.0,277.35475382364,81.7439364407149,0.0,0.0,239.44108506131,0.0
|
||||
2000.0,0.25,58000.0,0.490943210954541,229.083884602049,278.594927849437,83.0286121259999,1.0,1.01700412121317,299.301356326638,112.46717788446948
|
||||
2000.0,0.25,56550.0,0.493825203742373,206.98265691698,278.594927849437,83.0286121259999,0.975,0.991579018182845,299.301356326638,102.21325272316534
|
||||
2000.0,0.25,55100.0,0.501186802222428,186.431460591808,278.594927849437,83.0286121259999,0.95,0.966153915152516,299.301356326638,93.43698756766484
|
||||
2000.0,0.25,53650.0,0.52264881073961,163.35157559787,278.594927849437,83.0286121259999,0.925,0.940728812122187,299.301356326638,85.37550671866826
|
||||
2000.0,0.25,52200.0,0.55891656606103,138.962133832492,278.594927849437,83.0286121259999,0.9,0.915303709091857,299.301356326638,77.6682386541697
|
||||
2000.0,0.25,50750.0,0.627151765084877,110.880795710008,278.594927849437,83.0286121259999,0.875,0.889878606061528,299.301356326638,69.53908674354717
|
||||
2000.0,0.25,49300.0,0.743417723081925,82.9462259129654,278.594927849437,83.0286121259999,0.85,0.864453503031198,299.301356326638,61.663694406455704
|
||||
2000.0,0.25,47850.0,0.902422639815665,61.497550318509,278.594927849437,83.0286121259999,0.825,0.839028400000869,299.301356326638,55.496781700625576
|
||||
2000.0,0.25,46400.0,1.08805487679301,46.9318427594,278.594927849437,83.0286121259999,0.8,0.81360329697054,299.301356326638,51.064420391247886
|
||||
2000.0,0.25,44950.0,1.29379201367826,37.1450034063478,278.594927849437,83.0286121259999,0.775,0.78817819394021,299.301356326638,48.05790875518454
|
||||
2000.0,0.25,43500.0,1.52724022403009,30.0105866069096,278.594927849437,83.0286121259999,0.75,0.762753090909881,299.301356326638,45.83337501281104
|
||||
2000.0,0.25,42050.0,1.82625085802079,24.0544040573426,278.594927849437,83.0286121259999,0.725,0.737327987879551,299.301356326638,43.92937604890069
|
||||
2000.0,0.25,40600.0,2.27925095605852,18.434278259216,278.594927849437,83.0286121259999,0.7,0.711902884849222,299.301356326638,42.01634634656686
|
||||
2000.0,0.25,0.0,0.0,0.0,278.594927849437,83.0286121259999,0.0,0.0,299.301356326638,0.0
|
||||
2000.0,0.3,58000.0,0.481312194233186,235.949797564156,280.110696103189,84.618267061966,1.0,1.01424872185047,359.161627591965,113.56551479447997
|
||||
2000.0,0.3,56550.0,0.483411445566456,213.536169122694,280.110696103189,84.618267061966,0.975,0.988892503804209,359.161627591965,103.22582819632473
|
||||
2000.0,0.3,55100.0,0.490485005697224,192.340298597972,280.110696103189,84.618267061966,0.95,0.963536285757948,359.161627591965,94.34003245363206
|
||||
2000.0,0.3,53650.0,0.511129913146882,168.431204556053,280.110696103189,84.618267061966,0.925,0.938180067711686,359.161627591965,86.09022695596009
|
||||
2000.0,0.3,52200.0,0.54627806233195,143.008985787908,280.110696103189,84.618267061966,0.9,0.912823849665424,359.161627591965,78.12267165227576
|
||||
2000.0,0.3,50750.0,0.612417604594913,113.852681014766,280.110696103189,84.618267061966,0.875,0.887467631619162,359.161627591965,69.72538618377173
|
||||
2000.0,0.3,49300.0,0.724501331066055,85.0427936768085,280.110696103189,84.618267061966,0.85,0.8621114135729,359.161627591965,61.61361721642364
|
||||
2000.0,0.3,47850.0,0.875007223444898,63.2213183382253,280.110696103189,84.618267061966,0.825,0.836755195526639,359.161627591965,55.31911022165654
|
||||
2000.0,0.3,46400.0,1.0468720270292,48.5772676411829,280.110696103189,84.618267061966,0.8,0.811398977480377,359.161627591965,50.85418264306511
|
||||
2000.0,0.3,44950.0,1.23898811000289,38.5602010579051,280.110696103189,84.618267061966,0.775,0.786042759434115,359.161627591965,47.77563063006528
|
||||
2000.0,0.3,43500.0,1.45886596464954,31.196860542239,280.110696103189,84.618267061966,0.75,0.760686541387853,359.161627591965,45.512038048990675
|
||||
2000.0,0.3,42050.0,1.7440198811413,24.9846441432261,280.110696103189,84.618267061966,0.725,0.735330323341591,359.161627591965,43.573716109026854
|
||||
2000.0,0.3,40600.0,2.22439955238856,18.3610232895413,280.110696103189,84.618267061966,0.7,0.70997410529533,359.161627591965,40.84225198665159
|
||||
2000.0,0.3,0.0,0.0,0.0,280.110696103189,84.618267061966,0.0,0.0,359.161627591965,0.0
|
||||
2000.0,0.35,58000.0,0.470566372455659,244.132662822051,281.902058584896,86.5248238705945,1.0,1.01102103578495,419.021898857293,114.88062154211308
|
||||
2000.0,0.35,56550.0,0.471779071681757,221.429485396085,281.902058584896,86.5248238705945,0.975,0.985745509890324,419.021898857293,104.46579706313415
|
||||
2000.0,0.35,55100.0,0.478606798245897,199.386389652093,281.902058584896,86.5248238705945,0.95,0.960469983995701,419.021898857293,95.42768156519708
|
||||
2000.0,0.35,53650.0,0.498152985137602,174.60167917058,281.902058584896,86.5248238705945,0.925,0.935194458101077,419.021898857293,86.9783476888623
|
||||
2000.0,0.35,52200.0,0.532149599633283,147.79918290782,281.902058584896,86.5248238705945,0.9,0.909918932206453,419.021898857293,78.65127601052278
|
||||
2000.0,0.35,50750.0,0.596055825341059,117.300089959081,281.902058584896,86.5248238705945,0.875,0.884643406311829,419.021898857293,69.9174019331405
|
||||
2000.0,0.35,49300.0,0.702768369468572,87.603531790668,281.902058584896,86.5248238705945,0.85,0.859367880417206,419.021898857293,61.56499119621596
|
||||
2000.0,0.35,47850.0,0.843455670817316,65.3619111562417,281.902058584896,86.5248238705945,0.825,0.834092354522582,419.021898857293,55.12987462018965
|
||||
2000.0,0.35,46400.0,1.00062754679037,50.5876558682368,281.902058584896,86.5248238705945,0.8,0.808816828627958,419.021898857293,50.61940198930926
|
||||
2000.0,0.35,44950.0,1.17751547849603,40.3045624359361,281.902058584896,86.5248238705945,0.775,0.783541302733334,419.021898857293,47.45924612232441
|
||||
2000.0,0.35,43500.0,1.38261523588192,32.6536229148696,281.902058584896,86.5248238705945,0.75,0.758265776838711,419.021898857293,45.1473965488417
|
||||
2000.0,0.35,42050.0,1.65968933222744,25.845334524983,281.902058584896,86.5248238705945,0.725,0.732990250944087,419.021898857293,42.89522599896383
|
||||
2000.0,0.35,40600.0,2.1101137137546,19.1389319939315,281.902058584896,86.5248238705945,0.7,0.707714725049463,419.021898857293,40.38532286701153
|
||||
2000.0,0.35,0.0,0.0,0.0,281.902058584896,86.5248238705945,0.0,0.0,419.021898857293,0.0
|
||||
3000.0,0.0,58000.0,0.516198592397567,195.639492579802,268.65,70.108523423274,1.0,1.03565687626109,0.0,100.98883068706806
|
||||
3000.0,0.0,56550.0,0.517518224001758,178.107075009453,268.65,70.108523423274,0.975,1.00976545435457,0.0,92.17365714104001
|
||||
3000.0,0.0,55100.0,0.526298404523301,159.542557524104,268.65,70.108523423274,0.95,0.983874032448039,0.0,83.96699347850291
|
||||
3000.0,0.0,53650.0,0.542169860110265,141.998290178002,268.65,70.108523423274,0.925,0.957982610541512,0.0,76.98719312170417
|
||||
3000.0,0.0,52200.0,0.577299820106671,122.140961867175,268.65,70.108523423274,0.9,0.932091188634984,0.0,70.5119553135759
|
||||
3000.0,0.0,50750.0,0.635607020742967,100.847615486545,268.65,70.108523423274,0.875,0.906199766728457,0.0,64.09945242843517
|
||||
3000.0,0.0,49300.0,0.74551022679156,77.029406676729,268.65,70.108523423274,0.85,0.88030834482193,0.0,57.426210441187536
|
||||
3000.0,0.0,47850.0,0.91260806276764,56.8060837234955,268.65,70.108523423274,0.825,0.854416922915402,0.0,51.84169002031559
|
||||
3000.0,0.0,46400.0,1.13593142382492,41.88698292111,268.65,70.108523423274,0.8,0.828525501008875,0.0,47.580740149306585
|
||||
3000.0,0.0,44950.0,1.38709060620493,32.2798747866438,268.65,70.108523423274,0.775,0.802634079102348,0.0,44.775111086024985
|
||||
3000.0,0.0,43500.0,1.66645574471295,25.7003648976502,268.65,70.108523423274,0.75,0.77674265719582,0.0,42.82852072490822
|
||||
3000.0,0.0,42050.0,2.00192509947777,20.6096542931463,268.65,70.108523423274,0.725,0.750851235289293,0.0,41.25898422100936
|
||||
3000.0,0.0,40600.0,2.47533674011158,16.0905941489086,268.65,70.108523423274,0.7,0.724959813382765,0.0,39.82963886701788
|
||||
3000.0,0.0,0.0,0.0,0.0,268.65,70.108523423274,0.0,0.0,0.0,0.0
|
||||
3000.0,0.05,58000.0,0.515231915059655,196.194005351224,268.784550610546,70.2313268802712,1.0,1.03539762455165,59.1509135005756,101.08541310033536
|
||||
3000.0,0.05,56550.0,0.516512621894976,178.58707151681,268.784550610546,70.2313268802712,0.975,1.00951268393785,59.1509135005756,92.24247654569312
|
||||
3000.0,0.05,55100.0,0.525172172581759,160.029535187731,268.784550610546,70.2313268802712,0.95,0.983627743324063,59.1509135005756,84.04305867178974
|
||||
3000.0,0.05,53650.0,0.541029319101805,142.406353030404,268.784550610546,70.2313268802712,0.925,0.957742802710272,59.1509135005756,77.04601221581073
|
||||
3000.0,0.05,52200.0,0.575988523705559,122.497476600987,268.784550610546,70.2313268802712,0.9,0.931857862096481,59.1509135005756,70.55714070505876
|
||||
3000.0,0.05,50750.0,0.634221898516558,101.09491519428,268.784550610546,70.2313268802712,0.875,0.90597292148269,59.1509135005756,64.11660904488669
|
||||
3000.0,0.05,49300.0,0.743690340587394,77.2205723755214,268.784550610546,70.2313268802712,0.85,0.880087980868899,59.1509135005756,57.42819377030502
|
||||
3000.0,0.05,47850.0,0.910238011377281,56.9410124794452,268.784550610546,70.2313268802712,0.825,0.854203040255108,59.1509135005756,51.82987396509914
|
||||
3000.0,0.05,46400.0,1.13211118338588,42.0112243748278,268.784550610546,70.2313268802712,0.8,0.828318099641316,59.1509135005756,47.56137694247602
|
||||
3000.0,0.05,44950.0,1.38149285186014,32.3952482558376,268.784550610546,70.2313268802712,0.775,0.802433159027525,59.1509135005756,44.75380389967431
|
||||
3000.0,0.05,43500.0,1.65940716359725,25.7917096490945,268.784550610546,70.2313268802712,0.75,0.776548218413734,59.1509135005756,42.79894775312773
|
||||
3000.0,0.05,42050.0,1.99374360102655,20.6815217588909,268.784550610546,70.2313268802712,0.725,0.750663277799943,59.1509135005756,41.23365166628009
|
||||
3000.0,0.05,40600.0,2.4653435716055,16.1429138507143,268.784550610546,70.2313268802712,0.7,0.724778337186152,59.1509135005756,39.79782888883989
|
||||
3000.0,0.05,0.0,0.0,0.0,268.784550610546,70.2313268802712,0.0,0.0,59.1509135005756,0.0
|
||||
3000.0,0.1,58000.0,0.512345912060705,197.86374949014,269.188202442184,70.6006586189506,1.0,1.0346210360193,118.301827001151,101.37468319627664
|
||||
3000.0,0.1,56550.0,0.513413933056788,180.101323052972,269.188202442184,70.6006586189506,0.975,1.00875551011882,118.301827001151,92.4665286173575
|
||||
3000.0,0.1,55100.0,0.52175065401875,161.479481606083,269.188202442184,70.6006586189506,0.95,0.982889984218339,118.301827001151,84.25202513858251
|
||||
3000.0,0.1,53650.0,0.537576876437044,143.647704717215,269.188202442184,70.6006586189506,0.925,0.957024458317857,118.301827001151,77.22168440923126
|
||||
3000.0,0.1,52200.0,0.572048276498673,123.573915217015,269.188202442184,70.6006586189506,0.9,0.931158932417374,118.301827001151,70.69024522008657
|
||||
3000.0,0.1,50750.0,0.629858992528352,101.905019044549,269.188202442184,70.6006586189506,0.875,0.905293406516891,118.301827001151,64.18579262898216
|
||||
3000.0,0.1,49300.0,0.738307215403671,77.7996067229204,269.188202442184,70.6006586189506,0.85,0.879427880616409,118.301827001151,57.44001099910008
|
||||
3000.0,0.1,47850.0,0.903148621554008,57.3434133381391,269.188202442184,70.6006586189506,0.825,0.853562354715926,118.301827001151,51.78962471154205
|
||||
3000.0,0.1,46400.0,1.12074221435107,42.3846174863529,269.188202442184,70.6006586189506,0.8,0.827696828815443,118.301827001151,47.50223005607823
|
||||
3000.0,0.1,44950.0,1.36543973089148,32.7185689600467,269.188202442184,70.6006586189506,0.775,0.801831302914961,118.301827001151,44.675233995960504
|
||||
3000.0,0.1,43500.0,1.63845504536074,26.0687311518205,269.188202442184,70.6006586189506,0.75,0.775965777014478,118.301827001151,42.71244408185299
|
||||
3000.0,0.1,42050.0,1.96772503810352,20.9056456117382,269.188202442184,70.6006586189506,0.725,0.750100251113995,118.301827001151,41.13656230793624
|
||||
3000.0,0.1,40600.0,2.43414831939933,16.3053846163222,269.188202442184,70.6006586189506,0.7,0.724234725213513,118.301827001151,39.68972456098037
|
||||
3000.0,0.1,0.0,0.0,0.0,269.188202442184,70.6006586189506,0.0,0.0,118.301827001151,0.0
|
||||
3000.0,0.15,58000.0,0.507623659124732,200.648460035772,269.860955494913,71.219289639328,1.0,1.03333059590403,177.452740501727,101.85390548110112
|
||||
3000.0,0.15,56550.0,0.508354033233313,182.639513091272,269.860955494913,71.219289639328,0.975,1.00749733100643,177.452740501727,92.84553310771658
|
||||
3000.0,0.15,55100.0,0.516147431309761,163.916869291261,269.860955494913,71.219289639328,0.95,0.981664066108829,177.452740501727,84.60527103302222
|
||||
3000.0,0.15,53650.0,0.53193673873951,145.727056071528,269.860955494913,71.219289639328,0.925,0.955830801211228,177.452740501727,77.51757495279831
|
||||
3000.0,0.15,52200.0,0.565577151470904,125.385421266134,269.860955494913,71.219289639328,0.9,0.929997536313627,177.452740501727,70.91512939567939
|
||||
3000.0,0.15,50750.0,0.622738403664192,103.254690685758,269.860955494913,71.219289639328,0.875,0.904164271416027,177.452740501727,64.30066124848885
|
||||
3000.0,0.15,49300.0,0.729483424920677,78.7676699438951,269.860955494913,71.219289639328,0.85,0.878331006518426,177.452740501727,57.45970964369407
|
||||
3000.0,0.15,47850.0,0.891377571043883,58.0225717220937,269.860955494913,71.219289639328,0.825,0.852497741620825,177.452740501727,51.72001904735938
|
||||
3000.0,0.15,46400.0,1.10212242624491,43.011546952595,269.860955494913,71.219289639328,0.8,0.826664476723224,177.452740501727,47.403990483940866
|
||||
3000.0,0.15,44950.0,1.33916696062851,33.2638563590631,269.860955494913,71.219289639328,0.775,0.800831211825623,177.452740501727,44.54585741914986
|
||||
3000.0,0.15,43500.0,1.60422105198309,26.5349844446992,269.860955494913,71.219289639328,0.75,0.774997946928023,177.452740501727,42.56798066023028
|
||||
3000.0,0.15,42050.0,1.92529334753574,21.2868541154318,269.860955494913,71.219289639328,0.725,0.749164682030422,177.452740501727,40.98343861840464
|
||||
3000.0,0.15,40600.0,2.38352766396669,16.5791994398573,269.860955494913,71.219289639328,0.7,0.723331417132821,177.452740501727,39.51698051132093
|
||||
3000.0,0.15,0.0,0.0,0.0,269.860955494913,71.219289639328,0.0,0.0,177.452740501727,0.0
|
||||
3000.0,0.2,58000.0,0.501185432900655,204.553991144178,270.802809768734,72.0918612884988,1.0,1.0315320648,236.603654002302,102.5194806031516
|
||||
3000.0,0.2,56550.0,0.501480921468596,186.226500093892,270.802809768734,72.0918612884988,0.975,1.00574376318,236.603654002302,93.38903686895655
|
||||
3000.0,0.2,55100.0,0.508504270338231,167.375177042223,270.802809768734,72.0918612884988,0.95,0.979955461559997,236.603654002302,85.11099227458783
|
||||
3000.0,0.2,53650.0,0.524269528761642,148.660587591747,270.802809768734,72.0918612884988,0.925,0.954167159939997,236.603654002302,77.93821620215401
|
||||
3000.0,0.2,52200.0,0.556766921198546,127.94229372089,270.802809768734,72.0918612884988,0.9,0.928378858319997,236.603654002302,71.23403696605999
|
||||
3000.0,0.2,50750.0,0.613143633130921,105.122312806304,270.802809768734,72.0918612884988,0.875,0.902590556699997,236.603654002302,64.45507679718237
|
||||
3000.0,0.2,49300.0,0.717431075852181,80.1280916908039,270.802809768734,72.0918612884988,0.85,0.876802255079997,236.603654002302,57.48638302771565
|
||||
3000.0,0.2,47850.0,0.875135412441549,58.9887447443547,270.802809768734,72.0918612884988,0.825,0.851013953459997,236.603654002302,51.6231394612601
|
||||
3000.0,0.2,46400.0,1.07666913219795,43.9044758421852,270.802809768734,72.0918612884988,0.8,0.825225651839997,236.603654002302,47.2705939046114
|
||||
3000.0,0.2,44950.0,1.30327148119615,34.0429892996113,270.802809768734,72.0918612884988,0.775,0.799437350219997,236.603654002302,44.36725708884911
|
||||
3000.0,0.2,43500.0,1.55759115970373,27.201651536094,270.802809768734,72.0918612884988,0.75,0.773649048599997,236.603654002302,42.369051961961404
|
||||
3000.0,0.2,42050.0,1.86760996407068,21.8302868028718,270.802809768734,72.0918612884988,0.725,0.747860746979997,236.603654002302,40.77046115156404
|
||||
3000.0,0.2,40600.0,2.3145523285331,16.9696338616178,270.802809768734,72.0918612884988,0.7,0.722072445359997,236.603654002302,39.27710556876162
|
||||
3000.0,0.2,0.0,0.0,0.0,270.802809768734,72.0918612884988,0.0,0.0,236.603654002302,0.0
|
||||
3000.0,0.25,58000.0,0.493044736925006,209.741876091979,272.013765263647,73.2249198647342,1.0,1.02923340767317,295.754567502878,103.41212811992699
|
||||
3000.0,0.25,56550.0,0.493016086818814,190.906702601767,272.013765263647,73.2249198647342,0.975,1.00350257248134,295.754567502878,94.12007546420625
|
||||
3000.0,0.25,55100.0,0.498999810156414,171.900234685622,272.013765263647,73.2249198647342,0.95,0.977771737289507,295.754567502878,85.77818447396838
|
||||
3000.0,0.25,53650.0,0.514758053908504,152.496215317938,272.013765263647,73.2249198647342,0.925,0.952040902097678,295.754567502878,78.49865502547398
|
||||
3000.0,0.25,52200.0,0.545908562471256,131.239726557535,272.013765263647,73.2249198647342,0.9,0.926310066905848,295.754567502878,71.64489046414464
|
||||
3000.0,0.25,50750.0,0.601429440402033,107.480498771677,272.013765263647,73.2249198647342,0.875,0.900579231714019,295.754567502878,64.6419362303811
|
||||
3000.0,0.25,49300.0,0.702430133887488,81.8855611304295,272.013765263647,73.2249198647342,0.85,0.87484839652219,295.754567502878,57.518885668299674
|
||||
3000.0,0.25,47850.0,0.854709778303298,60.2570342136682,272.013765263647,73.2249198647342,0.825,0.849117561330361,295.754567502878,51.50227635397859
|
||||
3000.0,0.25,46400.0,1.04496328367278,45.0775541636288,272.013765263647,73.2249198647342,0.8,0.823386726138532,295.754567502878,47.10438901876314
|
||||
3000.0,0.25,44950.0,1.25864283323665,35.0732039986435,272.013765263647,73.2249198647342,0.775,0.797655890946703,295.754567502878,44.14463685153965
|
||||
3000.0,0.25,43500.0,1.49981457910647,28.0820201747691,272.013765263647,73.2249198647342,0.75,0.771925055754874,295.754567502878,42.11782326888072
|
||||
3000.0,0.25,42050.0,1.79627203198008,22.5473720061643,272.013765263647,73.2249198647342,0.725,0.746194220563044,295.754567502878,40.50121372932352
|
||||
3000.0,0.25,40600.0,2.27207002071196,16.8772709516511,272.013765263647,73.2249198647342,0.7,0.720463385371215,295.754567502878,38.34634136067927
|
||||
3000.0,0.25,0.0,0.0,0.0,272.013765263647,73.2249198647342,0.0,0.0,295.754567502878,0.0
|
||||
3000.0,0.3,58000.0,0.483212310229862,216.394931124031,273.493821979652,74.6269652298273,1.0,1.02644469688801,354.905481003454,104.56469459047489
|
||||
3000.0,0.3,56550.0,0.483149838965041,196.705730667205,273.493821979652,74.6269652298273,0.975,1.00078357946581,354.905481003454,95.03834209536082
|
||||
3000.0,0.3,55100.0,0.488056398822271,177.459517061511,273.493821979652,74.6269652298273,0.95,0.975122462043613,354.905481003454,86.61025283378042
|
||||
3000.0,0.3,53650.0,0.503668113657407,157.246369449317,273.493821979652,74.6269652298273,0.925,0.949461344621413,354.905481003454,79.19998228001322
|
||||
3000.0,0.3,52200.0,0.533363326042695,135.270507536815,273.493821979652,74.6269652298273,0.9,0.923800227199213,354.905481003454,72.14832781531908
|
||||
3000.0,0.3,50750.0,0.587742618221576,110.365769713501,273.493821979652,74.6269652298273,0.875,0.898139109777012,354.905481003454,64.8666664534526
|
||||
3000.0,0.3,49300.0,0.684916991699412,84.0270035167196,273.493821979652,74.6269652298273,0.85,0.872477992354812,354.905481003454,57.5515224701875
|
||||
3000.0,0.3,47850.0,0.830430214476331,61.849568649524,273.493821979652,74.6269652298273,0.825,0.846816874932611,354.905481003454,51.36175055889278
|
||||
3000.0,0.3,46400.0,1.00774747838925,46.5501145190164,273.493821979652,74.6269652298273,0.8,0.821155757510411,354.905481003454,46.91076052526959
|
||||
3000.0,0.3,44950.0,1.20633964836406,36.3788583081415,273.493821979652,74.6269652298273,0.775,0.795494640088211,354.905481003454,43.885259139329385
|
||||
3000.0,0.3,43500.0,1.43234395031108,29.1971445855973,273.493821979652,74.6269652298273,0.75,0.76983352266601,354.905481003454,41.8203534135382
|
||||
3000.0,0.3,42050.0,1.72122869963321,23.2197717618068,273.493821979652,74.6269652298273,0.725,0.74417240524381,354.905481003454,39.96653755535465
|
||||
3000.0,0.3,40600.0,2.17167754759247,17.4911434746984,273.493821979652,74.6269652298273,0.7,0.71851128782161,354.905481003454,37.985123565721054
|
||||
3000.0,0.3,0.0,0.0,0.0,273.493821979652,74.6269652298273,0.0,0.0,354.905481003454,0.0
|
||||
3000.0,0.35,58000.0,0.472377875256421,224.117498662516,275.242979916748,76.3085135953898,1.0,1.02317799153118,414.056394504029,105.86814782598309
|
||||
3000.0,0.35,56550.0,0.472087318262611,203.654671541338,275.242979916748,76.3085135953898,0.975,0.997598541742899,414.056394504029,96.14278773960314
|
||||
3000.0,0.35,55100.0,0.475974871527027,184.106553281819,275.242979916748,76.3085135953898,0.95,0.97201909195462,414.056394504029,87.63009304559755
|
||||
3000.0,0.35,53650.0,0.491299920063109,162.913180056173,275.242979916748,76.3085135953898,0.925,0.94643964216634,414.056394504029,80.03923233882468
|
||||
3000.0,0.35,52200.0,0.519409889904715,140.03975178673,275.242979916748,76.3085135953898,0.9,0.920860192378061,414.056394504029,72.73803205782905
|
||||
3000.0,0.35,50750.0,0.572378922906064,113.782313899562,275.242979916748,76.3085135953898,0.875,0.895280742589781,414.056394504029,65.12659827559096
|
||||
3000.0,0.35,49300.0,0.665146477769296,86.5752299323786,275.242979916748,76.3085135953898,0.85,0.869701292801502,414.056394504029,57.58520925158856
|
||||
3000.0,0.35,47850.0,0.802663251930636,63.7955835720671,275.242979916748,76.3085135953898,0.825,0.844121843013222,414.056394504029,51.206370568768044
|
||||
3000.0,0.35,46400.0,0.965734318974126,48.3510479578558,275.242979916748,76.3085135953898,0.8,0.818542393224943,414.056394504029,46.69426637126517
|
||||
3000.0,0.35,44950.0,1.14773031129811,37.9887663411447,275.242979916748,76.3085135953898,0.775,0.792962943436663,414.056394504029,43.60085861855317
|
||||
3000.0,0.35,43500.0,1.35782527889575,30.5736206223629,275.242979916748,76.3085135953898,0.75,0.767383493648384,414.056394504029,41.51363494841276
|
||||
3000.0,0.35,42050.0,1.6277387689257,24.3404742354921,275.242979916748,76.3085135953898,0.725,0.741804043860104,414.056394504029,39.619933567147626
|
||||
3000.0,0.35,40600.0,2.0580200828216,18.2525946417168,275.242979916748,76.3085135953898,0.7,0.716224594071825,414.056394504029,37.564206336255104
|
||||
3000.0,0.35,0.0,0.0,0.0,275.242979916748,76.3085135953898,0.0,0.0,414.056394504029,0.0
|
||||
4000.0,0.0,58000.0,0.516638281867925,178.956148146694,262.15,61.6402085371994,1.0,1.04841779681353,0.0,92.45559690820986
|
||||
4000.0,0.0,56550.0,0.517698996617252,164.099830469518,262.15,61.6402085371994,0.975,1.02220735189319,0.0,84.95431757913063
|
||||
4000.0,0.0,55100.0,0.525209218898279,147.045180231338,262.15,61.6402085371994,0.95,0.995996906972856,0.0,77.22948425205769
|
||||
4000.0,0.0,53650.0,0.537282838606111,131.501113827668,262.15,61.6402085371994,0.925,0.969786462052518,0.0,70.65329171719479
|
||||
4000.0,0.0,52200.0,0.566777606055763,114.39213394041,262.15,61.6402085371994,0.9,0.94357601713218,0.0,64.83489982635578
|
||||
4000.0,0.0,50750.0,0.615639115570513,96.2801220887395,262.15,61.6402085371994,0.875,0.917365572211841,0.0,59.2738092097326
|
||||
4000.0,0.0,49300.0,0.707528060515687,75.6053666021411,262.15,61.6402085371994,0.85,0.891155127291503,0.0,53.49291839659039
|
||||
4000.0,0.0,47850.0,0.86127605780735,55.9637237486576,262.15,61.6402085371994,0.825,0.864944682371165,0.0,48.20021537046338
|
||||
4000.0,0.0,46400.0,1.08140224846311,40.784742447101,262.15,61.6402085371994,0.8,0.838734237450826,0.0,44.10471218528387
|
||||
4000.0,0.0,44950.0,1.34659370617067,30.7113471726083,262.15,61.6402085371994,0.775,0.812523792530488,0.0,41.35570681065674
|
||||
4000.0,0.0,43500.0,1.64321324926485,24.0962641608192,262.15,61.6402085371994,0.75,0.78631334761015,0.0,39.59530052684387
|
||||
4000.0,0.0,42050.0,1.99155360744515,19.2292285894136,262.15,61.6402085371994,0.725,0.760102902689811,0.0,38.296039565634075
|
||||
4000.0,0.0,40600.0,2.45997578782358,15.1243510158406,262.15,61.6402085371994,0.7,0.733892457769473,0.0,37.20553730551285
|
||||
4000.0,0.0,0.0,0.0,0.0,262.15,61.6402085371994,0.0,0.0,0.0,0.0
|
||||
4000.0,0.05,58000.0,0.515718549742496,179.461260957381,262.281303684007,61.7481857507349,1.0,1.04815533366707,58.4328508421484,92.55150123590015
|
||||
4000.0,0.05,56550.0,0.516669155633388,164.564005923171,262.281303684007,61.7481857507349,0.975,1.02195145032539,58.4328508421484,85.02514598797262
|
||||
4000.0,0.05,55100.0,0.524093387193184,147.458148552501,262.281303684007,61.7481857507349,0.95,0.995747566983717,58.4328508421484,77.28184054411595
|
||||
4000.0,0.05,53650.0,0.536108567854045,131.895209701211,262.281303684007,61.7481857507349,0.925,0.96954368364204,58.4328508421484,70.71015197972518
|
||||
4000.0,0.05,52200.0,0.565545873010277,114.716405982292,262.281303684007,61.7481857507349,0.9,0.943339800300364,58.4328508421484,64.8773899698567
|
||||
4000.0,0.05,50750.0,0.614212120107261,96.5530506540875,262.281303684007,61.7481857507349,0.875,0.917135916958687,58.4328508421484,59.30405394507085
|
||||
4000.0,0.05,49300.0,0.705841729967435,75.8030453697481,262.281303684007,61.7481857507349,0.85,0.89093203361701,58.4328508421484,53.50495268058297
|
||||
4000.0,0.05,47850.0,0.859104489425206,56.0955551086461,262.281303684007,61.7481857507349,0.825,0.864728150275333,58.4328508421484,48.191943230636916
|
||||
4000.0,0.05,46400.0,1.07814530639424,40.8877165887748,262.281303684007,61.7481857507349,0.8,0.838524266933656,58.4328508421484,44.08289972936546
|
||||
4000.0,0.05,44950.0,1.3413713649141,30.8152345613731,262.281303684007,61.7481857507349,0.775,0.81232038359198,58.4328508421484,41.33467324373718
|
||||
4000.0,0.05,43500.0,1.6363091413416,24.1796892362239,262.281303684007,61.7481857507349,0.75,0.786116500250303,58.4328508421484,39.56544653203226
|
||||
4000.0,0.05,42050.0,1.98263996649043,19.3003093545278,262.281303684007,61.7481857507349,0.725,0.759912616908626,58.4328508421484,38.265564691915934
|
||||
4000.0,0.05,40600.0,2.44952867467539,15.1753102954739,262.281303684007,61.7481857507349,0.7,0.733708733566949,58.4328508421484,37.17235771585998
|
||||
4000.0,0.05,0.0,0.0,0.0,262.281303684007,61.7481857507349,0.0,0.0,58.4328508421484,0.0
|
||||
4000.0,0.1,58000.0,0.512933719785062,180.987461006568,262.675214736028,62.0729275737883,1.0,1.04736912535132,116.865701684297,92.83457160855278
|
||||
4000.0,0.1,56550.0,0.513583714575495,165.986526452651,262.675214736028,62.0729275737883,0.975,1.02118489721753,116.865701684297,85.24797682503616
|
||||
4000.0,0.1,55100.0,0.520828743115578,148.736826411575,262.675214736028,62.0729275737883,0.95,0.995000669083752,116.865701684297,77.46641435494053
|
||||
4000.0,0.1,53650.0,0.532572195102974,133.0967600745,262.675214736028,62.0729275737883,0.925,0.968816440949969,116.865701684297,70.88363367397034
|
||||
4000.0,0.1,52200.0,0.561835821096151,115.69705645734,262.675214736028,62.0729275737883,0.9,0.942632212816186,116.865701684297,65.00275071311736
|
||||
4000.0,0.1,50750.0,0.610020844493543,97.3398208671766,262.675214736028,62.0729275737883,0.875,0.916447984682403,116.865701684297,59.379319728245264
|
||||
4000.0,0.1,49300.0,0.700814883149515,76.3816585593923,262.675214736028,62.0729275737883,0.85,0.89026375654862,116.865701684297,53.529403118066675
|
||||
4000.0,0.1,47850.0,0.852606428977874,56.4915958370926,262.675214736028,62.0729275737883,0.825,0.864079528414837,116.865701684297,48.16509779392486
|
||||
4000.0,0.1,46400.0,1.06829204463706,41.2124099743184,262.675214736028,62.0729275737883,0.8,0.837895300281054,116.865701684297,44.02688971588537
|
||||
4000.0,0.1,44950.0,1.32630913954704,31.1100782357251,262.675214736028,62.0729275737883,0.775,0.811711072147271,116.865701684297,41.26158109606566
|
||||
4000.0,0.1,43500.0,1.6157012281043,24.4363880379284,262.675214736028,62.0729275737883,0.75,0.785526844013488,116.865701684297,39.48190216331414
|
||||
4000.0,0.1,42050.0,1.95625449809703,19.514952149108,262.675214736028,62.0729275737883,0.725,0.759342615879705,116.865701684297,38.17621292184083
|
||||
4000.0,0.1,40600.0,2.4619611768912,14.8444101225498,262.675214736028,62.0729275737883,0.7,0.733158387745922,116.865701684297,36.54636141556835
|
||||
4000.0,0.1,0.0,0.0,0.0,262.675214736028,62.0729275737883,0.0,0.0,116.865701684297,0.0
|
||||
4000.0,0.15,58000.0,0.508376710865291,183.535093910855,263.331733156064,62.6168706187689,1.0,1.046062700507,175.298552526445,93.30496737075278
|
||||
4000.0,0.15,56550.0,0.508557778227161,168.353315696433,263.331733156064,62.6168706187689,0.975,1.01991113299433,175.298552526445,85.61738818775379
|
||||
4000.0,0.15,55100.0,0.515479501869442,150.886396013128,263.331733156064,62.6168706187689,0.95,0.993759565481654,175.298552526445,77.77884425572259
|
||||
4000.0,0.15,53650.0,0.526819807149964,135.101380841619,263.331733156064,62.6168706187689,0.925,0.967607997968979,175.298552526445,71.17408340067557
|
||||
4000.0,0.15,52200.0,0.555758111444936,117.342763698527,263.331733156064,62.6168706187689,0.9,0.941456430456304,175.298552526445,65.21419274482275
|
||||
4000.0,0.15,50750.0,0.603163986723064,98.6553333328164,263.331733156064,62.6168706187689,0.875,0.915304862943629,175.298552526445,59.50534416451433
|
||||
4000.0,0.15,49300.0,0.69259042623058,77.3477011375684,263.331733156064,62.6168706187689,0.85,0.889153295430954,175.298552526445,53.57027729882401
|
||||
4000.0,0.15,47850.0,0.841914795667452,57.15716419971,263.331733156064,62.6168706187689,0.825,0.863001727918279,175.298552526445,48.12146221812985
|
||||
4000.0,0.15,46400.0,1.05206836997687,41.7603409950361,263.331733156064,62.6168706187689,0.8,0.836850160405603,175.298552526445,43.93473388032589
|
||||
4000.0,0.15,44950.0,1.30150643971779,31.6106594905969,263.331733156064,62.6168706187689,0.775,0.810698592892928,175.298552526445,41.14147689073814
|
||||
4000.0,0.15,43500.0,1.58198593134005,24.8703737906756,263.331733156064,62.6168706187689,0.75,0.784547025380253,175.298552526445,39.34458144401711
|
||||
4000.0,0.15,42050.0,1.91314195786026,19.8776161794593,263.331733156064,62.6168706187689,0.725,0.758395457867578,175.298552526445,38.028701535165546
|
||||
4000.0,0.15,40600.0,2.40762299842655,15.1147622768858,263.331733156064,62.6168706187689,0.7,0.732243890354903,175.298552526445,36.390649273580294
|
||||
4000.0,0.15,0.0,0.0,0.0,263.331733156064,62.6168706187689,0.0,0.0,175.298552526445,0.0
|
||||
4000.0,0.2,58000.0,0.502168900435508,187.114078592016,264.250858944113,63.3840961442688,1.0,1.04424189146032,233.731403368594,93.9628711025559
|
||||
4000.0,0.2,56550.0,0.501751601103474,171.650832615857,264.250858944113,63.3840961442688,0.975,1.01813584417381,233.731403368594,86.12608009575068
|
||||
4000.0,0.2,55100.0,0.508189938401694,153.908131483308,264.250858944113,63.3840961442688,0.95,0.9920297968873,233.731403368594,78.21456385802212
|
||||
4000.0,0.2,53650.0,0.519052011049344,137.912781865048,264.250858944113,63.3840961442688,0.925,0.965923749600792,233.731403368594,71.58390677646265
|
||||
4000.0,0.2,52200.0,0.547479239939111,119.66833950462,264.250858944113,63.3840961442688,0.9,0.939817702314284,233.731403368594,65.51593155676484
|
||||
4000.0,0.2,50750.0,0.593837641984712,100.502751764912,264.250858944113,63.3840961442688,0.875,0.913711655027776,233.731403368594,59.6823171210502
|
||||
4000.0,0.2,49300.0,0.681342529901859,78.7155195007167,264.250858944113,63.3840961442688,0.85,0.887605607741268,233.731403368594,53.632231199157424
|
||||
4000.0,0.2,47850.0,0.827192207199755,58.1013211484694,264.250858944113,63.3840961442688,0.825,0.86149956045476,233.731403368594,48.06096008202421
|
||||
4000.0,0.2,46400.0,1.02979139836151,42.5414906100068,264.250858944113,63.3840961442688,0.8,0.835393513168252,233.731403368594,43.80886110366194
|
||||
4000.0,0.2,44950.0,1.26765700172921,32.3255071750987,264.250858944113,63.3840961442688,0.775,0.809287465881744,233.731403368594,40.97765550496168
|
||||
4000.0,0.2,43500.0,1.53603185614274,25.4910973063103,264.250858944113,63.3840961442688,0.75,0.783181418595236,233.731403368594,39.15513751052701
|
||||
4000.0,0.2,42050.0,1.86206441271866,20.2138617108206,264.250858944113,63.3840961442688,0.725,0.757075371308729,233.731403368594,37.63951253533537
|
||||
4000.0,0.2,40600.0,2.33409278241193,15.4982133670753,264.250858944113,63.3840961442688,0.7,0.730969324022221,233.731403368594,36.17426796037055
|
||||
4000.0,0.2,0.0,0.0,0.0,264.250858944113,63.3840961442688,0.0,0.0,233.731403368594,0.0
|
||||
4000.0,0.25,58000.0,0.494475248953783,191.734501623019,265.432592100177,64.3803604853571,1.0,1.04191476235198,292.164254210742,94.80796542307183
|
||||
4000.0,0.25,56550.0,0.493365083126142,175.872416132395,265.432592100177,64.3803604853571,0.975,1.01586689329318,292.164254210742,86.76930920475449
|
||||
4000.0,0.25,55100.0,0.499125808819755,157.858373934168,265.432592100177,64.3803604853571,0.95,0.989819024234382,292.164254210742,78.79118856886292
|
||||
4000.0,0.25,53650.0,0.509523423044994,141.535532357995,265.432592100177,64.3803604853571,0.925,0.963771155175582,292.164254210742,72.11566892954113
|
||||
4000.0,0.25,52200.0,0.537167924883246,122.702242161566,265.432592100177,64.3803604853571,0.9,0.937723286116782,292.164254210742,65.91170880044996
|
||||
4000.0,0.25,50750.0,0.582274081387425,102.892641336406,265.432592100177,64.3803604853571,0.875,0.911675417057983,292.164254210742,59.911718215681596
|
||||
4000.0,0.25,49300.0,0.667353118463615,80.476115534608,265.432592100177,64.3803604853571,0.85,0.885627547999183,292.164254210742,53.705986663858816
|
||||
4000.0,0.25,47850.0,0.808694238182032,59.3365047668264,265.432592100177,64.3803604853571,0.825,0.859579678940384,292.164254210742,47.98508951879319
|
||||
4000.0,0.25,46400.0,1.00186962694388,43.5736359433813,265.432592100177,64.3803604853571,0.8,0.833531809881584,292.164254210742,43.65510238718387
|
||||
4000.0,0.25,44950.0,1.22553591142411,33.2706443864228,265.432592100177,64.3803604853571,0.775,0.807483940822785,292.164254210742,40.77436949178212
|
||||
4000.0,0.25,43500.0,1.47888500326836,26.3330207379641,265.432592100177,64.3803604853571,0.75,0.781436071763985,292.164254210742,38.94350946012983
|
||||
4000.0,0.25,42050.0,1.79121279155016,20.8770024138194,265.432592100177,64.3803604853571,0.725,0.755388202705186,292.164254210742,37.39515377285688
|
||||
4000.0,0.25,40600.0,2.24542999254096,15.9862819365947,265.432592100177,64.3803604853571,0.7,0.729340333646386,292.164254210742,35.896076929645524
|
||||
4000.0,0.25,0.0,0.0,0.0,265.432592100177,64.3803604853571,0.0,0.0,292.164254210742,0.0
|
||||
4000.0,0.3,58000.0,0.485532677801374,197.394491551304,266.876932624255,65.6131378025166,1.0,1.03909151095035,350.597105052891,95.84147606614532
|
||||
4000.0,0.3,56550.0,0.48360563114096,181.054193388126,266.876932624255,65.6131378025166,0.975,1.01311422317659,350.597105052891,87.5588274641821
|
||||
4000.0,0.3,55100.0,0.488481730885005,162.804575019183,266.876932624255,65.6131378025166,0.95,0.987136935402833,350.597105052891,79.52706060136816
|
||||
4000.0,0.3,53650.0,0.498527594105241,145.971240863982,266.876932624255,65.6131378025166,0.925,0.961159647629074,350.597105052891,72.77069151647758
|
||||
4000.0,0.3,52200.0,0.524997145147183,126.483473437772,266.876932624255,65.6131378025166,0.9,0.935182359855315,350.597105052891,66.40346246312986
|
||||
4000.0,0.3,50750.0,0.568786919643188,105.83109792579,266.876932624255,65.6131378025166,0.875,0.909205072081557,350.597105052891,60.19534419166668
|
||||
4000.0,0.3,49300.0,0.651058929903836,82.6256711002017,266.876932624255,65.6131378025166,0.85,0.883227784307798,350.597105052891,53.79418100908362
|
||||
4000.0,0.3,47850.0,0.786726708471003,60.8800948269685,266.876932624255,65.6131378025166,0.825,0.857250496534039,350.597105052891,47.89599661462347
|
||||
4000.0,0.3,46400.0,0.968749806762913,44.8820304414574,266.876932624255,65.6131378025166,0.8,0.83127320876028,350.597105052891,43.47945831728904
|
||||
4000.0,0.3,44950.0,1.17618719502159,34.467582189139,266.876932624255,65.6131378025166,0.775,0.805295920986521,350.597105052891,40.54032881421952
|
||||
4000.0,0.3,43500.0,1.41427442105397,27.342512298392,266.876932624255,65.6131378025166,0.75,0.779318633212763,350.597105052891,38.6698157509694
|
||||
4000.0,0.3,42050.0,1.7082615092622,21.7155865051318,266.876932624255,65.6131378025166,0.725,0.753341345439004,350.597105052891,37.09590057777031
|
||||
4000.0,0.3,40600.0,2.14154137657687,16.6055717053225,266.876932624255,65.6131378025166,0.7,0.727364057665245,350.597105052891,35.56151888866227
|
||||
4000.0,0.3,0.0,0.0,0.0,266.876932624255,65.6131378025166,0.0,0.0,350.597105052891,0.0
|
||||
4000.0,0.35,58000.0,0.475456837401016,204.141883290552,268.583880516348,67.0916752949494,1.0,1.03578434646499,409.029955895039,97.06065421041316
|
||||
4000.0,0.35,56550.0,0.47277658919466,187.206355165262,268.583880516348,67.0916752949494,0.975,1.00988973780337,409.029955895039,88.50678207059669
|
||||
4000.0,0.35,55100.0,0.476535241522749,168.796656640343,268.583880516348,67.0916752949494,0.95,0.983995129141743,409.029955895039,80.4375555403384
|
||||
4000.0,0.35,53650.0,0.486357558404709,151.237415439444,268.583880516348,67.0916752949494,0.925,0.958100520480118,409.029955895039,73.55546011256662
|
||||
4000.0,0.35,52200.0,0.511244289102639,131.108869816639,268.583880516348,67.0916752949494,0.9,0.932205911818494,409.029955895039,67.02866094445804
|
||||
4000.0,0.35,50750.0,0.553861843741355,109.264491838343,268.583880516348,67.0916752949494,0.875,0.906311303156869,409.029955895039,60.517432905046896
|
||||
4000.0,0.35,49300.0,0.63294534978744,85.1316129863787,268.583880516348,67.0916752949494,0.85,0.880416694495244,409.029955895039,53.88365855963244
|
||||
4000.0,0.35,47850.0,0.761655798536187,62.752862602764,268.583880516348,67.0916752949494,0.825,0.854522085833619,409.029955895039,47.79608167613984
|
||||
4000.0,0.35,46400.0,0.930928272769655,46.509216683074,268.583880516348,67.0916752949494,0.8,0.828627477171994,409.029955895039,43.2967447546437
|
||||
4000.0,0.35,44950.0,1.12092406496459,35.9535859074632,268.583880516348,67.0916752949494,0.775,0.802732868510369,409.029955895039,40.30123966544725
|
||||
4000.0,0.35,43500.0,1.34214772117032,28.5745316319166,268.583880516348,67.0916752949494,0.75,0.776838259848744,409.029955895039,38.351242513286095
|
||||
4000.0,0.35,42050.0,1.61627594977978,22.7349539579851,268.583880516348,67.0916752949494,0.725,0.75094365118712,409.029955895039,36.74595930164193
|
||||
4000.0,0.35,40600.0,2.02665080752162,17.3504035569554,268.583880516348,67.0916752949494,0.7,0.725049042525495,409.029955895039,35.16320937952965
|
||||
4000.0,0.35,0.0,0.0,0.0,268.583880516348,67.0916752949494,0.0,0.0,409.029955895039,0.0
|
||||
5000.0,0.0,58000.0,0.518246696506667,162.250085387309,255.65,54.019881314929,1.0,1.06166235198407,0.0,84.08557075989754
|
||||
5000.0,0.0,56550.0,0.520357994792976,149.523156804776,255.65,54.019881314929,0.975,1.03512079318447,0.0,77.80557005004896
|
||||
5000.0,0.0,55100.0,0.524609481589099,135.569262000759,255.65,54.019881314929,0.95,1.00857923438487,0.0,71.12092025763492
|
||||
5000.0,0.0,53650.0,0.5368267262803,120.847121314339,255.65,54.019881314929,0.925,0.982037675585263,0.0,64.87396451557488
|
||||
5000.0,0.0,52200.0,0.559100659317848,106.631628146617,255.65,54.019881314929,0.9,0.955496116785662,0.0,59.617813600909166
|
||||
5000.0,0.0,50750.0,0.60284323239843,90.714670469783,255.65,54.019881314929,0.875,0.92895455798606,0.0,54.68672517196239
|
||||
5000.0,0.0,49300.0,0.678084139353396,73.4642188139315,255.65,54.019881314929,0.85,0.902412999186458,0.0,49.814921587714295
|
||||
5000.0,0.0,47850.0,0.815852899049915,55.1401506458041,255.65,54.019881314929,0.825,0.875871440386856,0.0,44.98625175842832
|
||||
5000.0,0.0,46400.0,1.02765242307153,40.0283700761439,255.65,54.019881314929,0.8,0.849329881587255,0.0,41.135251500353206
|
||||
5000.0,0.0,44950.0,1.30750823132573,29.4222992632827,255.65,54.019881314929,0.775,0.822788322787653,0.0,38.469898471271094
|
||||
5000.0,0.0,43500.0,1.62754845803272,22.6782115758849,255.65,54.019881314929,0.75,0.796246763988051,0.0,36.90988828127125
|
||||
5000.0,0.0,42050.0,2.00920504969854,17.7874094625612,255.65,54.019881314929,0.725,0.76970520518845,0.0,35.73855291323356
|
||||
5000.0,0.0,40600.0,2.53137262768456,13.7163011931135,255.65,54.019881314929,0.7,0.743163646388848,0.0,34.72106939332458
|
||||
5000.0,0.0,0.0,0.0,0.0,255.65,54.019881314929,0.0,0.0,0.0,0.0
|
||||
5000.0,0.05,58000.0,0.516752133377032,163.140244444615,255.778056334361,54.1145158994384,1.0,1.06139655590359,57.7057583324503,84.30306935640529
|
||||
5000.0,0.05,56550.0,0.519348214207269,149.959118413857,255.778056334361,54.1145158994384,0.975,1.034861642006,57.7057583324503,77.88100035233302
|
||||
5000.0,0.05,55100.0,0.52354921624391,135.9323215579,255.778056334361,54.1145158994384,0.95,1.00832672810841,57.7057583324503,71.1672604138537
|
||||
5000.0,0.05,53650.0,0.535656256196874,121.20968523407,255.778056334361,54.1145158994384,0.925,0.981791814210823,57.7057583324503,64.92672620728345
|
||||
5000.0,0.05,52200.0,0.557879248119083,106.935379836636,255.778056334361,54.1145158994384,0.9,0.955256900313234,57.7057583324503,59.657029300591034
|
||||
5000.0,0.05,50750.0,0.601373549085895,90.988630071994,255.778056334361,54.1145158994384,0.875,0.928721986415644,57.7057583324503,54.71815539285863
|
||||
5000.0,0.05,49300.0,0.676409044927178,73.6675888993647,255.778056334361,54.1145158994384,0.85,0.902187072518054,57.7057583324503,49.82942344950726
|
||||
5000.0,0.05,47850.0,0.813876312979595,55.2611344518302,255.778056334361,54.1145158994384,0.825,0.875652158620464,57.7057583324503,44.975728358725235
|
||||
5000.0,0.05,46400.0,1.02479297251044,40.124902133305,255.778056334361,54.1145158994384,0.8,0.849117244722874,57.7057583324503,41.11971772888013
|
||||
5000.0,0.05,44950.0,1.30272446539547,29.5149982537354,255.778056334361,54.1145158994384,0.775,0.822582330825284,57.7057583324503,38.449910321245675
|
||||
5000.0,0.05,43500.0,1.62097077598601,22.7534387908991,255.778056334361,54.1145158994384,0.75,0.796047416927694,57.7057583324503,36.882659333233896
|
||||
5000.0,0.05,42050.0,2.00014863712078,17.8538244868514,255.778056334361,54.1145158994384,0.725,0.769512503030105,57.7057583324503,35.71030271476944
|
||||
5000.0,0.05,40600.0,2.51826202008928,13.7757528719333,255.778056334361,54.1145158994384,0.7,0.742977589132515,57.7057583324503,34.69095525552545
|
||||
5000.0,0.05,0.0,0.0,0.0,255.778056334361,54.1145158994384,0.0,0.0,57.7057583324503,0.0
|
||||
5000.0,0.1,58000.0,0.514061195005615,164.53000982987,256.162225337444,54.3991297683344,1.0,1.0606003638621,115.411516664901,84.57849346742856
|
||||
5000.0,0.1,56550.0,0.516403351526352,151.233341263994,256.162225337444,54.3991297683344,0.975,1.03408535476554,115.411516664901,78.09740429125505
|
||||
5000.0,0.1,55100.0,0.52037921011584,137.069207099578,256.162225337444,54.3991297683344,0.95,1.00757034566899,115.411516664901,71.32796572168289
|
||||
5000.0,0.1,53650.0,0.532100729294331,122.302942562597,256.162225337444,54.3991297683344,0.925,0.981055336572438,115.411516664901,65.07748493240054
|
||||
5000.0,0.1,52200.0,0.554240267534791,107.855611882432,256.162225337444,54.3991297683344,0.9,0.954540327475886,115.411516664901,59.7779231848477
|
||||
5000.0,0.1,50750.0,0.597131775319073,91.7763464848068,256.162225337444,54.3991297683344,0.875,0.928025318379333,115.411516664901,54.802572708771045
|
||||
5000.0,0.1,49300.0,0.671621908208454,74.2457866475003,256.162225337444,54.3991297683344,0.85,0.901510309282781,115.411516664901,49.865096904631905
|
||||
5000.0,0.1,47850.0,0.80776230960516,55.6637293383272,256.162225337444,54.3991297683344,0.825,0.874995300186229,115.411516664901,44.96306257156369
|
||||
5000.0,0.1,46400.0,1.016187976604,40.4183748079322,256.162225337444,54.3991297683344,0.8,0.848480291089676,115.411516664901,41.07266651369471
|
||||
5000.0,0.1,44950.0,1.28869709034324,29.7833759864807,256.162225337444,54.3991297683344,0.775,0.821965281993124,115.411516664901,38.381749974376405
|
||||
5000.0,0.1,43500.0,1.60067732113231,22.9914708974933,256.162225337444,54.3991297683344,0.75,0.795450272896571,115.411516664901,36.801926045091044
|
||||
5000.0,0.1,42050.0,1.97378083969854,18.0491697188451,256.162225337444,54.3991297683344,0.725,0.768935263800019,115.411516664901,35.62510536352354
|
||||
5000.0,0.1,40600.0,2.48476694708568,13.9231822780183,256.162225337444,54.3991297683344,0.7,0.742420254703466,115.411516664901,34.59586312266898
|
||||
5000.0,0.1,0.0,0.0,0.0,256.162225337444,54.3991297683344,0.0,0.0,115.411516664901,0.0
|
||||
5000.0,0.15,58000.0,0.509665687846681,166.847026869279,256.80250700925,54.8758585840331,1.0,1.05927734954021,173.117274997351,85.03620471450475
|
||||
5000.0,0.15,56550.0,0.511582403647968,153.361047009971,256.80250700925,54.8758585840331,0.975,1.0327954158017,173.117274997351,78.45681305532999
|
||||
5000.0,0.15,55100.0,0.515201040467881,138.97416770803,256.80250700925,54.8758585840331,0.95,1.0063134820632,173.117274997351,71.59963580133484
|
||||
5000.0,0.15,53650.0,0.526284008552761,124.139105285384,256.80250700925,54.8758585840331,0.925,0.979831548324692,173.117274997351,65.33242594774514
|
||||
5000.0,0.15,52200.0,0.548288180075291,109.396571893106,256.80250700925,54.8758585840331,0.9,0.953349614586187,173.117274997351,59.98084730974682
|
||||
5000.0,0.15,50750.0,0.590209970057099,93.0925277401187,256.80250700925,54.8758585840331,0.875,0.926867680847682,173.117274997351,54.94413801003511
|
||||
5000.0,0.15,49300.0,0.663809295181086,75.2082030440106,256.80250700925,54.8758585840331,0.85,0.900385747109176,173.117274997351,49.92390425448068
|
||||
5000.0,0.15,47850.0,0.797710521235381,56.3395856202963,256.80250700925,54.8758585840331,0.825,0.873903813370671,173.117274997351,44.942680211351934
|
||||
5000.0,0.15,46400.0,1.00197401193305,40.9148193761549,256.80250700925,54.8758585840331,0.8,0.847421879632166,173.117274997351,40.99558571784202
|
||||
5000.0,0.15,44950.0,1.26567357092106,30.2369737876224,256.80250700925,54.8758585840331,0.775,0.820939945893661,173.117274997351,38.27013858762653
|
||||
5000.0,0.15,43500.0,1.56731641897143,23.4118194340459,256.80250700925,54.8758585840331,0.75,0.794458012155155,173.117274997351,36.69372899697455
|
||||
5000.0,0.15,42050.0,1.9298587367802,18.3867953502695,256.80250700925,54.8758585840331,0.725,0.76797607841665,173.117274997351,35.48391764810716
|
||||
5000.0,0.15,40600.0,2.42799850768839,14.1835499643512,256.80250700925,54.8758585840331,0.7,0.741494144678145,173.117274997351,34.437638147168435
|
||||
5000.0,0.15,0.0,0.0,0.0,256.80250700925,54.8758585840331,0.0,0.0,173.117274997351,0.0
|
||||
5000.0,0.2,58000.0,0.503682619646487,170.103179946096,257.698901349778,55.5482795233554,1.0,1.05743341970528,230.823033329801,85.6780152854474
|
||||
5000.0,0.2,56550.0,0.505010022911426,156.34762318493,257.698901349778,55.5482795233554,0.975,1.03099758421265,230.823033329801,78.95711676676851
|
||||
5000.0,0.2,55100.0,0.508167038876388,141.670991185465,257.698901349778,55.5482795233554,0.95,1.00456174872002,230.823033329801,71.99252808540062
|
||||
5000.0,0.2,53650.0,0.518368571739874,126.736775213638,257.698901349778,55.5482795233554,0.925,0.978125913227389,230.823033329801,65.696361154411
|
||||
5000.0,0.2,52200.0,0.540193858126767,111.573229634416,257.698901349778,55.5482795233554,0.9,0.951690077734756,230.823033329801,60.27117337987891
|
||||
5000.0,0.2,50750.0,0.58082043821956,94.9414649814655,257.698901349778,55.5482795233554,0.875,0.925254242242124,230.823033329801,55.1439432957418
|
||||
5000.0,0.2,49300.0,0.653209833004123,76.5545862467353,257.698901349778,55.5482795233554,0.85,0.898818406749492,230.823033329801,50.0062084979297
|
||||
5000.0,0.2,47850.0,0.783910839193015,57.2999926042574,257.698901349778,55.5482795233554,0.825,0.87238257125686,230.823033329801,44.918085288156966
|
||||
5000.0,0.2,46400.0,0.982401190970184,41.6218796168076,257.698901349778,55.5482795233554,0.8,0.845946735764228,230.823033329801,40.889384105969405
|
||||
5000.0,0.2,44950.0,1.23436798291207,30.8845483361624,257.698901349778,55.5482795233554,0.775,0.819510900271596,230.823033329801,38.12289763285911
|
||||
5000.0,0.2,43500.0,1.5231168603958,23.9732411175547,257.698901349778,55.5482795233554,0.75,0.793075064778964,230.823033329801,36.51404774448142
|
||||
5000.0,0.2,42050.0,1.87093761994391,18.8588917074703,257.698901349778,55.5482795233554,0.725,0.766639229286331,230.823033329801,35.283809965954426
|
||||
5000.0,0.2,40600.0,2.35143380383289,14.5519079497807,257.698901349778,55.5482795233554,0.7,0.740203393793699,230.823033329801,34.217848263378905
|
||||
5000.0,0.2,0.0,0.0,0.0,257.698901349778,55.5482795233554,0.0,0.0,230.823033329801,0.0
|
||||
5000.0,0.25,58000.0,0.496269569012698,174.310139200679,258.851408359027,56.4214379510871,1.0,1.05507674141852,288.528791662252,86.50481765566435
|
||||
5000.0,0.25,56550.0,0.496464296105077,160.450868675724,258.851408359027,56.4214379510871,0.975,1.02869982288306,288.528791662252,79.65812757654146
|
||||
5000.0,0.25,55100.0,0.499446311519522,145.189820087766,258.851408359027,56.4214379510871,0.95,1.00232290434759,288.528791662252,72.51452011301774
|
||||
5000.0,0.25,53650.0,0.508581518588864,130.117500739234,258.851408359027,56.4214379510871,0.925,0.97594598581213,288.528791662252,66.17535612094727
|
||||
5000.0,0.25,52200.0,0.53013046932598,114.426528276526,258.851408359027,56.4214379510871,0.9,0.949569067276667,288.528791662252,60.66098913857724
|
||||
5000.0,0.25,50750.0,0.569241427319018,97.3287721396932,258.851408359027,56.4214379510871,0.875,0.923192148741204,288.528791662252,55.40356917200643
|
||||
5000.0,0.25,49300.0,0.640269463105119,78.2384621958888,258.851408359027,56.4214379510871,0.85,0.896815230205741,288.528791662252,50.09369818433187
|
||||
5000.0,0.25,47850.0,0.766549266745674,58.566909883541,258.851408359027,56.4214379510871,0.825,0.870438311670278,288.528791662252,44.894421826788324
|
||||
5000.0,0.25,46400.0,0.957751001746161,42.5542026670322,258.851408359027,56.4214379510871,0.8,0.844061393134815,288.528791662252,40.75633023285925
|
||||
5000.0,0.25,44950.0,1.19568715192549,31.7336567136248,258.851408359027,56.4214379510871,0.775,0.817684474599352,288.528791662252,37.943525616095236
|
||||
5000.0,0.25,43500.0,1.46878284327374,24.7023528818067,258.851408359027,56.4214379510871,0.75,0.791307556063889,288.528791662252,36.28239210129131
|
||||
5000.0,0.25,42050.0,1.79847970184233,19.476505362586,258.851408359027,56.4214379510871,0.725,0.764930637528426,288.528791662252,35.02809955743421
|
||||
5000.0,0.25,40600.0,2.25744822074899,15.0341447328158,258.851408359027,56.4214379510871,0.7,0.738553718992963,288.528791662252,33.938803277577826
|
||||
5000.0,0.25,0.0,0.0,0.0,258.851408359027,56.4214379510871,0.0,0.0,288.528791662252,0.0
|
||||
5000.0,0.3,58000.0,0.487662021753793,179.468275106696,260.260028036999,57.5018848914076,1.0,1.0522176425886,346.234549994702,87.5198618791973
|
||||
5000.0,0.3,56550.0,0.486415677723434,165.5637012311,260.260028036999,57.5018848914076,0.975,1.02591220152388,346.234549994702,80.53277994072566
|
||||
5000.0,0.3,55100.0,0.489294715862642,149.53961475835,260.260028036999,57.5018848914076,0.95,0.999606760459169,346.234549994702,73.16894331339581
|
||||
5000.0,0.3,53650.0,0.497210226659682,134.310029846869,260.260028036999,57.5018848914076,0.925,0.973301319394454,346.234549994702,66.7803203828304
|
||||
5000.0,0.3,52200.0,0.518382091033499,117.966171682858,260.260028036999,57.5018848914076,0.9,0.946995878329739,346.234549994702,61.15155074817667
|
||||
5000.0,0.3,50750.0,0.555831972579993,100.251942339675,260.260028036999,57.5018848914076,0.875,0.920690437265024,346.234549994702,55.72323486563727
|
||||
5000.0,0.3,49300.0,0.625154691193909,80.306424242145,260.260028036999,57.5018848914076,0.85,0.894384996200309,346.234549994702,50.2039378479852
|
||||
5000.0,0.3,47850.0,0.746160611162508,60.1269160590895,260.260028036999,57.5018848914076,0.825,0.868079555135594,346.234549994702,44.86433643396704
|
||||
5000.0,0.3,46400.0,0.928393195741348,43.7297595932427,260.260028036999,57.5018848914076,0.8,0.841774114070879,346.234549994702,40.59841125777146
|
||||
5000.0,0.3,44950.0,1.14915440809038,32.861443769403,260.260028036999,57.5018848914076,0.775,0.815468673006164,346.234549994702,37.76287296382361
|
||||
5000.0,0.3,43500.0,1.40495722142123,25.626168079065,260.260028036999,57.5018848914076,0.75,0.789163231941449,346.234549994702,36.003669900036584
|
||||
5000.0,0.3,42050.0,1.71394150336082,20.2586663607693,260.260028036999,57.5018848914076,0.725,0.762857790876734,346.234549994702,34.72216907846221
|
||||
5000.0,0.3,40600.0,2.14906839885651,15.6355707659906,260.260028036999,57.5018848914076,0.7,0.736552349812019,346.234549994702,33.60191103127507
|
||||
5000.0,0.3,0.0,0.0,0.0,260.260028036999,57.5018848914076,0.0,0.0,346.234549994702,0.0
|
||||
5000.0,0.35,58000.0,0.477992679080351,185.614795451357,261.924760383694,58.7977254249342,1.0,1.04886848821832,403.940308327152,88.72251335474547
|
||||
5000.0,0.35,56550.0,0.475370462771992,171.484393631987,261.924760383694,58.7977254249342,0.975,1.02264677601286,403.940308327152,81.51861555901209
|
||||
5000.0,0.35,55100.0,0.477907872516205,154.761344679709,261.924760383694,58.7977254249342,0.95,0.996425063807402,403.940308327152,73.96166498362683
|
||||
5000.0,0.35,53650.0,0.484659200087829,139.314594418563,261.924760383694,58.7977254249342,0.925,0.970203351601944,403.940308327152,67.52009989146106
|
||||
5000.0,0.35,52200.0,0.505291171575943,122.181028947528,261.924760383694,58.7977254249342,0.9,0.943981639396486,403.940308327152,61.73699526125064
|
||||
5000.0,0.35,50750.0,0.541001583571571,103.693233504967,261.924760383694,58.7977254249342,0.875,0.917759927191029,403.940308327152,56.09820353184383
|
||||
5000.0,0.35,49300.0,0.608169538484932,82.7604256728757,261.924760383694,58.7977254249342,0.85,0.891538214985571,403.940308327152,50.332369886289335
|
||||
5000.0,0.35,47850.0,0.723175117926988,61.989703384996,261.924760383694,58.7977254249342,0.825,0.865316502780113,403.940308327152,44.82941105570349
|
||||
5000.0,0.35,46400.0,0.894678133453339,45.1829233542759,261.924760383694,58.7977254249342,0.8,0.839094790574655,403.940308327152,40.424173530568844
|
||||
5000.0,0.35,44950.0,1.09794357801275,34.181649826939,261.924760383694,58.7977254249342,0.775,0.812873078369197,403.940308327152,37.529522913368304
|
||||
5000.0,0.35,43500.0,1.33244623474888,26.7778106171551,261.924760383694,58.7977254249342,0.75,0.786651366163739,403.940308327152,35.67999293164689
|
||||
5000.0,0.35,42050.0,1.61977017962671,21.218800450405,261.924760383694,58.7977254249342,0.725,0.760429653958281,403.940308327152,34.36958021701582
|
||||
5000.0,0.35,40600.0,2.0294520043276,16.3628368561968,261.924760383694,58.7977254249342,0.7,0.734207941752823,403.940308327152,33.207592054294125
|
||||
5000.0,0.35,0.0,0.0,0.0,261.924760383694,58.7977254249342,0.0,0.0,403.940308327152,0.0
|
||||
6000.0,0.0,58000.0,0.519421974629505,146.994605171756,249.15,47.1809940960953,1.0,1.07542188384738,0.0,76.35222807819795
|
||||
6000.0,0.0,56550.0,0.522390341017192,136.109005418484,249.15,47.1809940960953,0.975,1.04853633675119,0.0,71.10202975607268
|
||||
6000.0,0.0,55100.0,0.526598698087967,124.487524313818,249.15,47.1809940960953,0.95,1.02165078965501,0.0,65.5549682318507
|
||||
6000.0,0.0,53650.0,0.537728139104616,111.096684704469,249.15,47.1809940960953,0.925,0.994765242558824,0.0,59.739813526826374
|
||||
6000.0,0.0,52200.0,0.55634468508304,98.5370676395621,249.15,47.1809940960953,0.9,0.967879695462639,0.0,54.82057386493839
|
||||
6000.0,0.0,50750.0,0.594812343494651,84.8301673978975,249.15,47.1809940960953,0.875,0.940994148366455,0.0,50.45803066898695
|
||||
6000.0,0.0,49300.0,0.658749085046626,70.33002629933,249.15,47.1809940960953,0.85,0.91410860127027,0.0,46.32984047598878
|
||||
6000.0,0.0,47850.0,0.777981532592966,54.210008964547,249.15,47.1809940960953,0.825,0.887223054174086,0.0,42.1743858561167
|
||||
6000.0,0.0,46400.0,0.978919894518656,39.4580930582098,249.15,47.1809940960953,0.8,0.860337507077901,0.0,38.626312294450045
|
||||
6000.0,0.0,44950.0,1.27203213569009,28.4183197959078,249.15,47.1809940960953,0.775,0.833451959981717,0.0,36.149016022712566
|
||||
6000.0,0.0,43500.0,1.62309360609651,21.4650660149825,249.15,47.1809940960953,0.75,0.806566412885532,0.0,34.839811403357594
|
||||
6000.0,0.0,42050.0,2.04901075732315,16.6026403188136,249.15,47.1809940960953,0.725,0.779680865789348,0.0,34.018988613216116
|
||||
6000.0,0.0,40600.0,2.61365991407012,12.8016103699634,249.15,47.1809940960953,0.7,0.752795318693164,0.0,33.459055859517704
|
||||
6000.0,0.0,0.0,0.0,0.0,249.15,47.1809940960953,0.0,0.0,0.0,0.0
|
||||
6000.0,0.05,58000.0,0.51854347292176,147.411856458091,249.274808561608,47.2636533672839,1.0,1.07515262546503,56.9692902316657,76.43945599762247
|
||||
6000.0,0.05,56550.0,0.521394409909503,136.501385666879,249.274808561608,47.2636533672839,0.975,1.04827380982841,56.9692902316657,71.17105943161187
|
||||
6000.0,0.05,55100.0,0.52550481611347,124.8544335046,249.274808561608,47.2636533672839,0.95,1.02139499419178,56.9692902316657,65.61160611978629
|
||||
6000.0,0.05,53650.0,0.536557136616859,111.410600251112,249.274808561608,47.2636533672839,0.925,0.994516178555157,56.9692902316657,59.77815265950217
|
||||
6000.0,0.05,52200.0,0.555067283055608,98.8345736352427,249.274808561608,47.2636533672839,0.9,0.967637362918531,56.9692902316657,54.8598382596736
|
||||
6000.0,0.05,50750.0,0.593392260774357,85.0864123936198,249.274808561608,47.2636533672839,0.875,0.940758547281905,56.9692902316657,50.48961861142932
|
||||
6000.0,0.05,49300.0,0.657195368081725,70.5162165438766,249.274808561608,47.2636533672839,0.85,0.913879731645279,56.9692902316657,46.3429308872836
|
||||
6000.0,0.05,47850.0,0.776029279771654,54.3441851185059,249.274808561608,47.2636533672839,0.825,0.887000916008653,56.9692902316657,42.17267883729157
|
||||
6000.0,0.05,46400.0,0.976289906106596,39.5509834458122,249.274808561608,47.2636533672839,0.8,0.860122100372027,56.9692902316657,38.61322591473553
|
||||
6000.0,0.05,44950.0,1.26773469405731,28.4966659519572,249.274808561608,47.2636533672839,0.775,0.833243284735401,56.9692902316657,36.12621209225782
|
||||
6000.0,0.05,43500.0,1.61654797284725,21.5353334936601,249.274808561608,47.2636533672839,0.75,0.806364469098775,56.9692902316657,34.81289970376572
|
||||
6000.0,0.05,42050.0,2.03949511551869,16.6648825708255,249.274808561608,47.2636533672839,0.725,0.77948565346215,56.9692902316657,33.98794660389115
|
||||
6000.0,0.05,40600.0,2.60080971040092,12.8514909917473,249.274808561608,47.2636533672839,0.7,0.752606837825524,56.9692902316657,33.424282564466324
|
||||
6000.0,0.05,0.0,0.0,0.0,249.274808561608,47.2636533672839,0.0,0.0,56.9692902316657,0.0
|
||||
6000.0,0.1,58000.0,0.51593294559035,148.664911279609,249.649234246432,47.5122514767502,1.0,1.07434606217843,113.938580463331,76.70112558241671
|
||||
6000.0,0.1,56550.0,0.518512989274105,137.666796989054,249.649234246432,47.5122514767502,0.975,1.04748741062397,113.938580463331,71.38202243058576
|
||||
6000.0,0.1,55100.0,0.522302392234581,125.935010293652,249.649234246432,47.5122514767502,0.95,1.02062875906951,113.938580463331,65.77615714246102
|
||||
6000.0,0.1,53650.0,0.53316050953024,112.356015049348,249.649234246432,47.5122514767502,0.925,0.993770107515046,113.938580463331,59.90379023249769
|
||||
6000.0,0.1,52200.0,0.551267581796574,99.7361184988789,249.649234246432,47.5122514767502,0.9,0.966911455960585,113.938580463331,54.981288862653514
|
||||
6000.0,0.1,50750.0,0.589339234790663,85.8055511150101,249.649234246432,47.5122514767502,0.875,0.940052804406124,113.938580463331,50.568577834911174
|
||||
6000.0,0.1,49300.0,0.652501701367449,71.0768539446014,249.649234246432,47.5122514767502,0.85,0.913194152851664,113.938580463331,46.37776812669809
|
||||
6000.0,0.1,47850.0,0.770183251363122,54.7559110875161,249.649234246432,47.5122514767502,0.825,0.886335501297203,113.938580463331,42.17208563273317
|
||||
6000.0,0.1,46400.0,0.968351353235641,39.8342696780011,249.649234246432,47.5122514767502,0.8,0.859476849742742,113.938580463331,38.57356894784583
|
||||
6000.0,0.1,44950.0,1.25516810155459,28.7329702282286,249.649234246432,47.5122514767502,0.775,0.832618198188282,113.938580463331,36.06470769339024
|
||||
6000.0,0.1,43500.0,1.59732133956316,21.7421347968869,249.649234246432,47.5122514767502,0.75,0.805759546633821,113.938580463331,34.72917587872618
|
||||
6000.0,0.1,42050.0,2.01219775433977,16.8441208754777,249.649234246432,47.5122514767502,0.725,0.77890089507936,113.938580463331,33.893702199463874
|
||||
6000.0,0.1,40600.0,2.56349539615701,12.9977845937861,249.649234246432,47.5122514767502,0.7,0.752042243524899,113.938580463331,33.31976096641118
|
||||
6000.0,0.1,0.0,0.0,0.0,249.649234246432,47.5122514767502,0.0,0.0,113.938580463331,0.0
|
||||
6000.0,0.15,58000.0,0.511666632756061,150.758337253728,250.273277054471,47.9286539563753,1.0,1.07300581445337,170.907870694997,77.13801078251763
|
||||
6000.0,0.15,56550.0,0.513801571809086,139.612977518912,250.273277054471,47.9286539563753,0.975,1.04618066909203,170.907870694997,71.73336729416359
|
||||
6000.0,0.15,55100.0,0.517087747546741,127.728380060473,250.273277054471,47.9286539563753,0.95,1.0193555237307,170.907870694997,66.04678034326405
|
||||
6000.0,0.15,53650.0,0.527594177261484,113.945886755664,250.273277054471,47.9286539563753,0.925,0.992530378369365,170.907870694997,60.11718637518479
|
||||
6000.0,0.15,52200.0,0.54508784018803,101.239779239551,250.273277054471,47.9286539563753,0.9,0.965705233008031,170.907870694997,55.18457260679981
|
||||
6000.0,0.15,50750.0,0.582704078485421,87.0124366179705,250.273277054471,47.9286539563753,0.875,0.938880087646697,170.907870694997,50.702501696245605
|
||||
6000.0,0.15,49300.0,0.644917072832505,72.0152639667671,250.273277054471,47.9286539563753,0.85,0.912054942285362,170.907870694997,46.4438732367076
|
||||
6000.0,0.15,47850.0,0.760616440723587,55.443324431916,250.273277054471,47.9286539563753,0.825,0.885229796924028,170.907870694997,42.17110409128704
|
||||
6000.0,0.15,46400.0,0.955247121055815,40.3125431622509,250.273277054471,47.9286539563753,0.8,0.858404651562694,170.907870694997,38.50844079817845
|
||||
6000.0,0.15,44950.0,1.23443206088574,29.1317686919852,250.273277054471,47.9286539563753,0.775,0.83157950620136,170.907870694997,35.96118926369397
|
||||
6000.0,0.15,43500.0,1.56572815453965,22.0929485185965,250.273277054471,47.9286539563753,0.75,0.804754360840025,170.907870694997,34.59155151236159
|
||||
6000.0,0.15,42050.0,1.9670599793759,17.1517038027952,250.273277054471,47.9286539563753,0.725,0.777929215478691,170.907870694997,33.73843012858787
|
||||
6000.0,0.15,40600.0,2.50279438630843,13.2438941140896,250.273277054471,47.9286539563753,0.7,0.751104070117357,170.907870694997,33.14674384160671
|
||||
6000.0,0.15,0.0,0.0,0.0,250.273277054471,47.9286539563753,0.0,0.0,170.907870694997,0.0
|
||||
6000.0,0.2,58000.0,0.505864891457361,153.700777797242,251.146936985726,48.5159855226555,1.0,1.07113786638299,227.877160926663,77.7518272773138
|
||||
6000.0,0.2,56550.0,0.507392989345275,142.345605149098,251.146936985726,48.5159855226555,0.975,1.04435941972341,227.877160926663,72.225162116763
|
||||
6000.0,0.2,55100.0,0.510034086417718,130.224684851585,251.146936985726,48.5159855226555,0.95,1.01758097306384,227.877160926663,66.4190281673134
|
||||
6000.0,0.2,53650.0,0.519990518043506,116.203031514792,251.146936985726,48.5159855226555,0.925,0.990802526404261,227.877160926663,60.42447455560255
|
||||
6000.0,0.2,52200.0,0.536745159875203,103.346528724363,251.146936985726,48.5159855226555,0.9,0.964024079744687,227.877160926663,55.470749082705474
|
||||
6000.0,0.2,50750.0,0.573647549349413,88.7218749112501,251.146936985726,48.5159855226555,0.875,0.937245633085112,227.877160926663,50.895086116523785
|
||||
6000.0,0.2,49300.0,0.634591892855428,73.3328971215598,251.146936985726,48.5159855226555,0.85,0.910467186425537,227.877160926663,46.536461992943
|
||||
6000.0,0.2,47850.0,0.747581910092109,56.4074168636116,251.146936985726,48.5159855226555,0.825,0.883688739765963,227.877160926663,42.1691644422606
|
||||
6000.0,0.2,46400.0,0.937205126358831,40.9940513762024,251.146936985726,48.5159855226555,0.8,0.856910293106388,227.877160926663,38.41983509999418
|
||||
6000.0,0.2,44950.0,1.20460278836965,29.7646651348364,251.146936985726,48.5159855226555,0.775,0.830131846446813,227.877160926663,35.85459861631283
|
||||
6000.0,0.2,43500.0,1.5225040511401,22.5956859684225,251.146936985726,48.5159855226555,0.75,0.803353399787239,227.877160926663,34.402023425212775
|
||||
6000.0,0.2,42050.0,1.90603560984566,17.5881147407626,251.146936985726,48.5159855226555,0.725,0.776574953127664,227.877160926663,33.52357300594488
|
||||
6000.0,0.2,40600.0,2.42080085784825,13.5934340955407,251.146936985726,48.5159855226555,0.7,0.749796506468089,227.877160926663,32.90699691958858
|
||||
6000.0,0.2,0.0,0.0,0.0,251.146936985726,48.5159855226555,0.0,0.0,227.877160926663,0.0
|
||||
6000.0,0.25,58000.0,0.498686027959403,157.503529780503,252.270214040197,49.2786533779784,1.0,1.0687504919372,284.846451158329,78.54480965582457
|
||||
6000.0,0.25,56550.0,0.499450656659723,145.875853827004,252.270214040197,49.2786533779784,0.975,1.04203172963877,284.846451158329,72.85779098469492
|
||||
6000.0,0.25,55100.0,0.501350186123495,133.417788537055,252.270214040197,49.2786533779784,0.95,1.01531296734034,284.846451158329,66.88903311523762
|
||||
6000.0,0.25,53650.0,0.510527450271479,119.160385753063,252.270214040197,49.2786533779784,0.925,0.988594205041908,284.846451158329,60.83464791187713
|
||||
6000.0,0.25,52200.0,0.526561585642671,106.045392962282,252.270214040197,49.2786533779784,0.9,0.961875442743478,284.846451158329,55.83943026831935
|
||||
6000.0,0.25,50750.0,0.56235489453584,90.9591973628607,252.270214040197,49.2786533779784,0.875,0.935156680445049,284.846451158329,51.151349840056184
|
||||
6000.0,0.25,49300.0,0.621788633876176,75.0338018194786,252.270214040197,49.2786533779784,0.85,0.908437918146618,284.846451158329,46.655165127869324
|
||||
6000.0,0.25,47850.0,0.731391381819095,57.6554094288205,252.270214040197,49.2786533779784,0.825,0.881719155848188,284.846451158329,42.1686695714907
|
||||
6000.0,0.25,46400.0,0.914474868477157,41.8936517333171,252.270214040197,49.2786533779784,0.8,0.855000393549759,284.846451158329,38.310691658852974
|
||||
6000.0,0.25,44950.0,1.16852411481809,30.5328814412811,252.270214040197,49.2786533779784,0.775,0.828281631251329,284.846451158329,35.67840825901869
|
||||
6000.0,0.25,43500.0,1.46795912647773,23.2706495400573,252.270214040197,49.2786533779784,0.75,0.801562868952899,284.846451158329,34.160362371391905
|
||||
6000.0,0.25,42050.0,1.83063475960272,18.1640745685555,252.270214040197,49.2786533779784,0.725,0.774844106654469,284.846451158329,33.25178628121348
|
||||
6000.0,0.25,40600.0,2.32024196895106,14.0514983283886,252.270214040197,49.2786533779784,0.7,0.748125344356039,284.846451158329,32.602876148172896
|
||||
6000.0,0.25,0.0,0.0,0.0,252.270214040197,49.2786533779784,0.0,0.0,284.846451158329,0.0
|
||||
6000.0,0.3,58000.0,0.490355368823204,162.17156541481,253.643108217884,50.2223799446227,1.0,1.06585415420823,341.815741389994,79.52169777161552
|
||||
6000.0,0.3,56550.0,0.490230015520132,150.194515838868,253.643108217884,50.2223799446227,0.975,1.03920780035303,341.815741389994,73.62985983072697
|
||||
6000.0,0.3,55100.0,0.491270347633714,137.307598486989,253.643108217884,50.2223799446227,0.95,1.01256144649782,341.815741389994,67.45515164145351
|
||||
6000.0,0.3,53650.0,0.499436382162378,122.840419870291,253.643108217884,50.2223799446227,0.925,0.985915092642614,341.815741389994,61.35097488332563
|
||||
6000.0,0.3,52200.0,0.514875974769656,109.329710607968,253.643108217884,50.2223799446227,0.9,0.959268738787408,341.815741389994,56.291241320561916
|
||||
6000.0,0.3,50750.0,0.549133428852494,93.7290481476368,253.643108217884,50.2223799446227,0.875,0.932622384932202,341.815741389994,51.4697535923923
|
||||
6000.0,0.3,49300.0,0.606806016429206,77.1385360951671,253.643108217884,50.2223799446227,0.85,0.905976031076996,341.815741389994,46.808127801088865
|
||||
6000.0,0.3,47850.0,0.712495760913284,59.1889680071433,253.643108217884,50.2223799446227,0.825,0.879329677221791,341.815741389994,42.17188879792159
|
||||
6000.0,0.3,46400.0,0.887450965694075,43.0247513456544,253.643108217884,50.2223799446227,0.8,0.852683323366585,341.815741389994,38.18235713044845
|
||||
6000.0,0.3,44950.0,1.12633670920937,31.4866362157395,253.643108217884,50.2223799446227,0.775,0.826036969511379,341.815741389994,35.464554219308596
|
||||
6000.0,0.3,43500.0,1.4034241986148,24.134415868178,253.643108217884,50.2223799446227,0.75,0.799390615656173,341.815741389994,33.87082324883402
|
||||
6000.0,0.3,42050.0,1.74296021254557,18.8911699676513,253.643108217884,50.2223799446227,0.725,0.772744261800967,341.815741389994,32.926557622052
|
||||
6000.0,0.3,40600.0,2.20412661882757,14.6262318459538,253.643108217884,50.2223799446227,0.7,0.746097907945762,341.815741389994,32.23806694481028
|
||||
6000.0,0.3,0.0,0.0,0.0,253.643108217884,50.2223799446227,0.0,0.0,341.815741389994,0.0
|
||||
6000.0,0.35,58000.0,0.481024129071741,167.733120980767,255.265619518787,51.3542451430885,1.0,1.06246138002961,398.78503162166,80.68367843625842
|
||||
6000.0,0.35,56550.0,0.479815230117078,155.374522056274,255.265619518787,51.3542451430885,0.975,1.03589984552887,398.78503162166,74.55106205476213
|
||||
6000.0,0.35,55100.0,0.480073596902173,141.88945996365,255.265619518787,51.3542451430885,0.95,1.00933831102813,398.78503162166,68.11738340725633
|
||||
6000.0,0.35,53650.0,0.486963945452877,127.295930681106,255.265619518787,51.3542451430885,0.925,0.982776776527389,398.78503162166,61.98852864456732
|
||||
6000.0,0.35,52200.0,0.501935998523042,113.225016032718,255.265619518787,51.3542451430885,0.9,0.956215242026649,398.78503162166,56.83171148016976
|
||||
6000.0,0.35,50750.0,0.534003617986606,97.1665008385878,255.265619518787,51.3542451430885,0.875,0.929653707525908,398.78503162166,51.88726299490447
|
||||
6000.0,0.35,49300.0,0.590090920144534,79.6211174648268,255.265619518787,51.3542451430885,0.85,0.903092173025168,398.78503162166,46.98369846775567
|
||||
6000.0,0.35,47850.0,0.691344390788991,60.9981721557301,255.265619518787,51.3542451430885,0.825,0.876530638524428,398.78503162166,42.17074416824522
|
||||
6000.0,0.35,46400.0,0.856586290593151,44.4067433965466,255.265619518787,51.3542451430885,0.8,0.849969104023688,398.78503162166,38.038207603369756
|
||||
6000.0,0.35,44950.0,1.07852868216672,32.6532715537887,255.265619518787,51.3542451430885,0.775,0.823407569522947,398.78503162166,35.21748993733977
|
||||
6000.0,0.35,43500.0,1.33152325107151,25.1885397904928,255.265619518787,51.3542451430885,0.75,0.796846035022207,398.78503162166,33.539126391581064
|
||||
6000.0,0.35,42050.0,1.64510575006291,19.7877084172638,255.265619518787,51.3542451430885,0.725,0.770284500521467,398.78503162166,32.552872897808925
|
||||
6000.0,0.35,40600.0,2.07601315096264,15.3242670915128,255.265619518787,51.3542451430885,0.7,0.743722966020726,398.78503162166,31.813380010844575
|
||||
6000.0,0.35,0.0,0.0,0.0,255.265619518787,51.3542451430885,0.0,0.0,398.78503162166,0.0
|
||||
|
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,168 @@
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
class BatterySim:
|
||||
"""
|
||||
混电飞机高压电池模型
|
||||
"""
|
||||
def __init__(self, capacity_kwh=50.0, nom_voltage=500.0, initial_soc=0.5):
|
||||
"""
|
||||
初始化电池参数
|
||||
:param capacity_kwh: 电池总能量 (kWh),默认 50 kWh
|
||||
:param nom_voltage: 额定电压 (V),默认 500 V
|
||||
:param initial_soc: 初始荷电状态 (0.0 到 1.0)
|
||||
"""
|
||||
# --- 基本物理参数 ---
|
||||
# 单体电池为 3.7V,根据额定电压计算串联数
|
||||
self.cells_in_series = int(nom_voltage / 3.7)
|
||||
|
||||
# 电池组电压安全极限 (工程极限)
|
||||
self.V_min = self.cells_in_series * 2.7 # 绝对放电截止电压 (约 364.5V)
|
||||
self.V_max = self.cells_in_series * 4.2 # 绝对充电截止电压 (约 567.0V)
|
||||
|
||||
# 容量与内阻标定
|
||||
self.capacity_Ah = (capacity_kwh * 1000) / nom_voltage # 安时容量 (约 100Ah)
|
||||
|
||||
# 电池内阻为 0.15 欧姆。
|
||||
# 在 SOC=50% 时,此内阻可将最大放电/充电安全功率限制在 300kW 左右。
|
||||
self.R_in = 0.15
|
||||
|
||||
# --- 状态变量 ---
|
||||
self.SOC = initial_soc
|
||||
self.V_t = 0.0 # 端电压 (V)
|
||||
self.I = 0.0 # 实际电流 (A),放电为正,充电为负
|
||||
|
||||
# --- OCV-SOC 查表曲线 Voc = f(SOC) ---
|
||||
self.soc_table = np.array([0.0, 0.1, 0.2, 0.5, 0.8, 0.9, 1.0])
|
||||
self.cell_ocv_table = np.array([2.8, 3.3, 3.4, 3.6, 3.9, 4.0, 4.15])
|
||||
self.Voc_table = self.cell_ocv_table * self.cells_in_series
|
||||
|
||||
def _get_ocv(self, soc):
|
||||
"""根据当前 SOC 线性插值获取开路电压"""
|
||||
return np.interp(soc, self.soc_table, self.Voc_table)
|
||||
|
||||
def step(self, dt, P_req_kw):
|
||||
"""
|
||||
单步执行电池仿真,包含过充/过放保护(功率限幅)
|
||||
:param dt: 仿真步长 (秒)
|
||||
:param P_req_kw: 外部请求功率 (kW)。正数表示放电,负数表示充电
|
||||
:return: (实际输出/吸收功率 kW, 端电压 V, 实际电流 A, 当前 SOC)
|
||||
"""
|
||||
# 1. 获取当前开路电压
|
||||
V_oc = self._get_ocv(self.SOC)
|
||||
|
||||
# 2. 计算工程安全极限 (基于电压边界)
|
||||
# 2.1 最大放电极限 (限制 V_t >= V_min)
|
||||
I_dis_max = (V_oc - self.V_min) / self.R_in
|
||||
P_dis_max_W = self.V_min * I_dis_max # 瓦特
|
||||
|
||||
# 2.2 最大充电极限 (限制 V_t <= V_max, 电流和功率为负数)
|
||||
I_cha_max = (V_oc - self.V_max) / self.R_in
|
||||
P_cha_max_W = self.V_max * I_cha_max # 瓦特
|
||||
|
||||
# SOC 保护限制 (防止 SOC 突破 0% 和 100%)
|
||||
if self.SOC <= 0.05:
|
||||
P_dis_max_W = 0.0 # 电量极低,禁止放电
|
||||
if self.SOC >= 0.98:
|
||||
P_cha_max_W = 0.0 # 电量极高,禁止充电
|
||||
|
||||
# 3. 保护逻辑:功率限幅 (Clipping)
|
||||
P_req_W = P_req_kw * 1000.0
|
||||
# 强制将需求功率限制在安全充放电区间内
|
||||
P_actual_W = max(P_cha_max_W, min(P_req_W, P_dis_max_W))
|
||||
|
||||
# 4. 根据实际功率求解电流 (一元二次方程)
|
||||
# R * I^2 - Voc * I + P_actual = 0
|
||||
discriminant = V_oc**2 - 4 * self.R_in * P_actual_W
|
||||
|
||||
if discriminant < 0:
|
||||
self.I = V_oc / (2 * self.R_in)
|
||||
P_actual_W = V_oc**2 / (4 * self.R_in)
|
||||
else:
|
||||
self.I = (V_oc - np.sqrt(discriminant)) / (2 * self.R_in)
|
||||
|
||||
# 5. 计算端电压
|
||||
self.V_t = V_oc - self.I * self.R_in
|
||||
|
||||
# 6. 安时积分更新 SOC
|
||||
delta_soc = (self.I * (dt / 3600.0)) / self.capacity_Ah
|
||||
self.SOC = self.SOC - delta_soc
|
||||
self.SOC = max(0.0, min(1.0, self.SOC))
|
||||
|
||||
P_actual_kw = P_actual_W / 1000.0
|
||||
return P_actual_kw, self.V_t, self.I, self.SOC
|
||||
|
||||
if __name__ == "__main__":
|
||||
import matplotlib
|
||||
matplotlib.use('Agg')
|
||||
|
||||
# ==========================================
|
||||
# 【测试示例】展示完整的充放电循环与边界保护
|
||||
# ==========================================
|
||||
plt.rcParams['font.family'] = 'serif'
|
||||
plt.rcParams['font.serif'] = ['DejaVu Serif', 'Times New Roman']
|
||||
plt.rcParams['axes.unicode_minus'] = True
|
||||
|
||||
battery = BatterySim(initial_soc=0.5)
|
||||
|
||||
dt = 0.5
|
||||
# 仿真总时长 1 小时,包含一个完整的充放电循环,且在边界处持续请求以验证保护机制
|
||||
time_array = np.arange(0, 3600, dt)
|
||||
|
||||
req_power_log = []
|
||||
act_power_log = []
|
||||
soc_log = []
|
||||
vt_log = []
|
||||
|
||||
for t in time_array:
|
||||
if t < 100:
|
||||
P_req = 0.0
|
||||
elif t < 1200:
|
||||
# 持续放电 150kW,将SOC从50%消耗至最低限制(5%)
|
||||
# 在触发限制后继续请求,以验证禁止放电保护生效
|
||||
P_req = 150.0
|
||||
elif t < 3300:
|
||||
# 持续充电 150kW,将SOC从5%一直充满至最高限制(98%)
|
||||
# 同样在触发满电后继续请求,验证禁止充电保护生效
|
||||
P_req = -150.0
|
||||
else:
|
||||
P_req = 0.0
|
||||
|
||||
P_act, V_t, I_act, soc = battery.step(dt, P_req)
|
||||
|
||||
req_power_log.append(P_req)
|
||||
act_power_log.append(P_act)
|
||||
vt_log.append(V_t)
|
||||
soc_log.append(soc * 100)
|
||||
|
||||
# 绘图展示
|
||||
fig, (ax1, ax2, ax3) = plt.subplots(3, 1, figsize=(10, 8), sharex=True)
|
||||
|
||||
ax1.plot(time_array, req_power_log, 'k--', linewidth=2, label='Requested Power (kW)')
|
||||
ax1.plot(time_array, act_power_log, 'r-', linewidth=2, label='Actual Power (kW)')
|
||||
ax1.set_ylabel('Power [kW]')
|
||||
ax1.set_title('Battery Power: Complete Cycle Protection Demo', fontweight='bold')
|
||||
ax1.legend()
|
||||
ax1.grid(True)
|
||||
|
||||
ax2.plot(time_array, vt_log, 'b-', linewidth=2)
|
||||
ax2.set_ylabel('Terminal Voltage [V]')
|
||||
ax2.axhline(battery.V_min, color='r', linestyle=':', label='V_min limit')
|
||||
ax2.axhline(battery.V_max, color='g', linestyle=':', label='V_max limit')
|
||||
ax2.set_title('Voltage Dynamics with Physical Limits', fontweight='bold')
|
||||
ax2.legend()
|
||||
ax2.grid(True)
|
||||
|
||||
ax3.plot(time_array, soc_log, 'g-', linewidth=2)
|
||||
ax3.axhline(5, color='r', linestyle=':', alpha=0.8, label='SOC Lower Limit (5%)')
|
||||
ax3.axhline(98, color='g', linestyle=':', alpha=0.8, label='SOC Upper Limit (98%)')
|
||||
ax3.set_ylabel('SOC [%]')
|
||||
ax3.set_xlabel('Time [s]')
|
||||
ax3.set_title('State of Charge (SOC) Evolution', fontweight='bold')
|
||||
ax3.legend()
|
||||
ax3.grid(True)
|
||||
|
||||
plt.tight_layout()
|
||||
plt.savefig('figures/battery_sim_output.png')
|
||||
print('Plot saved to figures/battery_sim_output.png')
|
||||
# plt.show()
|
||||
@@ -0,0 +1,275 @@
|
||||
"""
|
||||
GPR → NN 知识蒸馏脚本
|
||||
将训练好的高斯过程回归 (GPR) 代理模型的知识蒸馏到轻量级神经网络 (MLP) 中。
|
||||
|
||||
支持两种模式:
|
||||
1. 直接从 CSV 原始数据训练 NN (快速模式, 无需 GPR 依赖)
|
||||
2. 从 GPR 教师模型蒸馏 (完整模式, 需 botorch/gpytorch)
|
||||
|
||||
用法:
|
||||
python distill_gpr_to_nn.py # 从Model目录运行
|
||||
python Model/src/distill_gpr_to_nn.py # 从项目根目录运行
|
||||
|
||||
也可在代码中调用:
|
||||
from distill_gpr_to_nn import distill, distill_from_csv
|
||||
result = distill_from_csv(csv_path, nn_save_path, ...)
|
||||
result = distill(gpr_csv_path, gpr_pth_path, nn_save_path, ...)
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import csv as csv_mod
|
||||
import numpy as np
|
||||
import torch
|
||||
import torch.nn as nn
|
||||
|
||||
# 确保 src 目录在 path 中
|
||||
_this_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
if _this_dir not in sys.path:
|
||||
sys.path.insert(0, _this_dir)
|
||||
|
||||
from lightweight_model import EngineNNProxy
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 工具函数: 手写 StandardScaler (避免 sklearn import 导致的
|
||||
# numpy/scipy 递归问题)
|
||||
# ============================================================
|
||||
class SimpleScaler:
|
||||
"""轻量 Z-Score 归一化, 兼容 EngineNNProxy.set_normalization_params"""
|
||||
def __init__(self):
|
||||
self.mean_ = None
|
||||
self.scale_ = None
|
||||
|
||||
def fit(self, X):
|
||||
X = np.asarray(X, dtype=np.float64)
|
||||
self.mean_ = X.mean(axis=0)
|
||||
self.scale_ = X.std(axis=0)
|
||||
self.scale_[self.scale_ < 1e-12] = 1.0
|
||||
return self
|
||||
|
||||
def transform(self, X):
|
||||
return (np.asarray(X, dtype=np.float64) - self.mean_) / self.scale_
|
||||
|
||||
def fit_transform(self, X):
|
||||
self.fit(X)
|
||||
return self.transform(X)
|
||||
|
||||
def inverse_transform(self, X):
|
||||
return np.asarray(X, dtype=np.float64) * self.scale_ + self.mean_
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 模式一: 直接从 CSV 训练 (快速, 无需 sklearn/botorch)
|
||||
# ============================================================
|
||||
def distill_from_csv(csv_path, nn_save_path,
|
||||
epochs=3000, lr=1e-3, batch_size=256,
|
||||
hidden_size=64, verbose=True, progress_callback=None):
|
||||
"""
|
||||
直接从 CSV 原始发动机数据训练 NN 代理模型。
|
||||
|
||||
Returns
|
||||
-------
|
||||
dict with keys: loss_history, nn_model, X_train, Y_train, Y_nn,
|
||||
scaler_X, scaler_Y, rel_error_fuel, rel_error_power
|
||||
"""
|
||||
# 1. 读取 CSV
|
||||
if verbose:
|
||||
print(f"-> Loading CSV: {csv_path}")
|
||||
with open(csv_path, 'r', encoding='utf-8') as f:
|
||||
reader = csv_mod.reader(f)
|
||||
header = next(reader)
|
||||
rows = [r for r in reader]
|
||||
|
||||
col_idx = {name: i for i, name in enumerate(header)}
|
||||
data = np.array([[float(x) for x in r] for r in rows], dtype=np.float64)
|
||||
|
||||
X_cols = ['Altitude_m', 'Mach', 'RPM']
|
||||
Y_cols = ['WF_kg_h', 'Power_kW']
|
||||
X_raw = data[:, [col_idx[c] for c in X_cols]]
|
||||
Y_raw = data[:, [col_idx[c] for c in Y_cols]]
|
||||
|
||||
# 过滤零/非物理值
|
||||
valid = (Y_raw[:, 0] > 0.5) & (Y_raw[:, 1] > 0.5) & (X_raw[:, 2] > 500)
|
||||
X_phys = X_raw[valid].astype(np.float32)
|
||||
Y_phys = Y_raw[valid].astype(np.float32)
|
||||
if verbose:
|
||||
print(f"-> Valid samples: {len(X_phys)} / {len(data)}")
|
||||
|
||||
# 2. 归一化
|
||||
scaler_X = SimpleScaler()
|
||||
scaler_X.fit(X_phys)
|
||||
|
||||
Y_log = np.log1p(Y_phys.astype(np.float64))
|
||||
scaler_Y = SimpleScaler()
|
||||
scaler_Y.fit(Y_log)
|
||||
|
||||
return _train_nn(X_phys, Y_phys, scaler_X, scaler_Y, nn_save_path,
|
||||
epochs, lr, batch_size, hidden_size, verbose,
|
||||
progress_callback=progress_callback)
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 模式二: 从 GPR 教师模型蒸馏 (需 botorch/gpytorch/sklearn)
|
||||
# ============================================================
|
||||
def _generate_teacher_data(gpr_csv_path, gpr_pth_path,
|
||||
n_altitude=25, n_mach=6, n_rpm=30):
|
||||
"""
|
||||
加载 GPR 教师模型,在输入空间的密集网格上生成标注数据。
|
||||
"""
|
||||
from engine_gpr_class import EngineGPRModel
|
||||
|
||||
gpr = EngineGPRModel(csv_path=gpr_csv_path)
|
||||
success = gpr.load_model(pth_path=gpr_pth_path)
|
||||
if not success:
|
||||
raise RuntimeError(f"Failed to load GPR model from {gpr_pth_path}")
|
||||
|
||||
df = gpr.df
|
||||
H_range = np.linspace(df['Altitude_m'].min(), df['Altitude_m'].max(), n_altitude)
|
||||
Ma_range = np.linspace(df['Mach'].min(), df['Mach'].max(), n_mach)
|
||||
RPM_range = np.linspace(max(df['RPM'].min(), 1000), df['RPM'].max(), n_rpm)
|
||||
|
||||
H, Ma, RPM = np.meshgrid(H_range, Ma_range, RPM_range, indexing='ij')
|
||||
X_grid = np.column_stack([H.ravel(), Ma.ravel(), RPM.ravel()])
|
||||
|
||||
print(f"-> Querying GPR teacher on {len(X_grid)} grid points ...")
|
||||
Y_pred, _ = gpr.predict(X_grid) # [WF_kg_h, Power_kW]
|
||||
|
||||
valid = (Y_pred[:, 0] > 0.5) & (Y_pred[:, 1] > 0.5)
|
||||
X_valid = X_grid[valid].astype(np.float32)
|
||||
Y_valid = Y_pred[valid].astype(np.float32)
|
||||
print(f"-> Valid samples: {len(X_valid)} / {len(X_grid)}")
|
||||
|
||||
scaler_X = SimpleScaler()
|
||||
scaler_X.fit(X_valid)
|
||||
|
||||
Y_log = np.log1p(Y_valid.astype(np.float64))
|
||||
scaler_Y = SimpleScaler()
|
||||
scaler_Y.fit(Y_log)
|
||||
|
||||
return X_valid, Y_valid, scaler_X, scaler_Y
|
||||
|
||||
|
||||
def distill(gpr_csv_path, gpr_pth_path, nn_save_path,
|
||||
n_altitude=25, n_mach=6, n_rpm=30,
|
||||
epochs=3000, lr=1e-3, batch_size=512,
|
||||
hidden_size=64, verbose=True):
|
||||
"""
|
||||
从 GPR 教师模型蒸馏到 NN。需安装 botorch / gpytorch。
|
||||
"""
|
||||
X_phys, Y_phys, scaler_X, scaler_Y = _generate_teacher_data(
|
||||
gpr_csv_path, gpr_pth_path, n_altitude, n_mach, n_rpm
|
||||
)
|
||||
return _train_nn(X_phys, Y_phys, scaler_X, scaler_Y, nn_save_path,
|
||||
epochs, lr, batch_size, hidden_size, verbose)
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 通用 NN 训练核心
|
||||
# ============================================================
|
||||
def _train_nn(X_phys, Y_phys, scaler_X, scaler_Y, nn_save_path,
|
||||
epochs=3000, lr=1e-3, batch_size=256,
|
||||
hidden_size=64, verbose=True, progress_callback=None):
|
||||
"""训练 NN 并保存模型。"""
|
||||
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
||||
if verbose:
|
||||
print(f"-> Training device: {device}")
|
||||
|
||||
# 创建模型并移至设备
|
||||
nn_model = EngineNNProxy(hidden_size=hidden_size)
|
||||
nn_model.set_normalization_params(scaler_X, scaler_Y)
|
||||
nn_model = nn_model.to(device)
|
||||
|
||||
# 准备归一化数据
|
||||
X_norm = scaler_X.transform(X_phys).astype(np.float32)
|
||||
Y_log = np.log1p(Y_phys.astype(np.float64))
|
||||
Y_norm = scaler_Y.transform(Y_log).astype(np.float32)
|
||||
|
||||
X_t = torch.tensor(X_norm, dtype=torch.float32)
|
||||
Y_t = torch.tensor(Y_norm, dtype=torch.float32)
|
||||
|
||||
dataset = torch.utils.data.TensorDataset(X_t, Y_t)
|
||||
loader = torch.utils.data.DataLoader(dataset, batch_size=batch_size, shuffle=True)
|
||||
|
||||
# 训练
|
||||
optimizer = torch.optim.Adam(nn_model.net.parameters(), lr=lr)
|
||||
scheduler = torch.optim.lr_scheduler.CosineAnnealingLR(
|
||||
optimizer, T_max=epochs, eta_min=lr * 0.01)
|
||||
loss_fn = nn.MSELoss()
|
||||
|
||||
loss_history = []
|
||||
nn_model.train()
|
||||
|
||||
n_params = sum(p.numel() for p in nn_model.parameters())
|
||||
if verbose:
|
||||
print(f"-> Training NN ({hidden_size}x{hidden_size}, {n_params} params) "
|
||||
f"for {epochs} epochs on {len(X_phys)} samples ...")
|
||||
|
||||
for epoch in range(epochs):
|
||||
epoch_loss = 0.0
|
||||
n_batches = 0
|
||||
for xb, yb in loader:
|
||||
xb, yb = xb.to(device), yb.to(device)
|
||||
pred = nn_model.net(xb)
|
||||
loss = loss_fn(pred, yb)
|
||||
optimizer.zero_grad()
|
||||
loss.backward()
|
||||
optimizer.step()
|
||||
epoch_loss += loss.item()
|
||||
n_batches += 1
|
||||
|
||||
scheduler.step()
|
||||
avg_loss = epoch_loss / max(n_batches, 1)
|
||||
loss_history.append(avg_loss)
|
||||
|
||||
if verbose and (epoch + 1) % 500 == 0:
|
||||
print(f" Epoch {epoch+1:>5d}/{epochs} Loss: {avg_loss:.6f}")
|
||||
if progress_callback is not None and (epoch + 1) % 50 == 0:
|
||||
progress_callback(epoch + 1, epochs, avg_loss)
|
||||
|
||||
nn_model.eval()
|
||||
|
||||
# 验证精度(在 CPU 上做推理,避免显存占用)
|
||||
nn_model_cpu = nn_model.cpu()
|
||||
with torch.no_grad():
|
||||
X_phys_t = torch.tensor(X_phys, dtype=torch.float32)
|
||||
Y_nn = nn_model_cpu(X_phys_t).numpy()
|
||||
|
||||
rel_err_fuel = np.mean(
|
||||
np.abs(Y_nn[:, 0] - Y_phys[:, 0]) / np.maximum(Y_phys[:, 0], 1e-6)) * 100
|
||||
rel_err_power = np.mean(
|
||||
np.abs(Y_nn[:, 1] - Y_phys[:, 1]) / np.maximum(Y_phys[:, 1], 1e-6)) * 100
|
||||
|
||||
if verbose:
|
||||
print(f"-> Distillation complete!")
|
||||
print(f" Fuel Flow MAPE: {rel_err_fuel:.2f}%")
|
||||
print(f" Power MAPE: {rel_err_power:.2f}%")
|
||||
|
||||
# 保存(始终保存 CPU 版,推理时无需 GPU 环境)
|
||||
if nn_save_path:
|
||||
os.makedirs(os.path.dirname(os.path.abspath(nn_save_path)), exist_ok=True)
|
||||
torch.save(nn_model_cpu.state_dict(), nn_save_path)
|
||||
if verbose:
|
||||
print(f"-> Saved NN model to {nn_save_path}")
|
||||
|
||||
return {
|
||||
'loss_history': loss_history,
|
||||
'nn_model': nn_model_cpu,
|
||||
'X_train': X_phys,
|
||||
'Y_train': Y_phys,
|
||||
'Y_nn': Y_nn,
|
||||
'scaler_X': scaler_X,
|
||||
'scaler_Y': scaler_Y,
|
||||
'rel_error_fuel': rel_err_fuel,
|
||||
'rel_error_power': rel_err_power,
|
||||
}
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
model_root = os.path.join(os.path.dirname(os.path.abspath(__file__)), "..")
|
||||
csv_path = os.path.join(model_root, "data", "Cleaned_Engine_Data_Full.csv")
|
||||
nn_path = os.path.join(model_root, "data", "engine_nn_proxy.pth")
|
||||
|
||||
# 使用 CSV 直接训练模式 (无需 sklearn/botorch)
|
||||
result = distill_from_csv(csv_path, nn_path, epochs=3000)
|
||||
print(f"\nFinal training loss: {result['loss_history'][-1]:.6f}")
|
||||
@@ -0,0 +1,301 @@
|
||||
import sys
|
||||
import os
|
||||
|
||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
|
||||
import numpy as np
|
||||
import torch
|
||||
import matplotlib.pyplot as plt
|
||||
from tqdm import tqdm
|
||||
from src.lightweight_model import EngineNNProxy
|
||||
from src.mpc_controller import TurboShaftMPCController
|
||||
|
||||
class TurboshaftDynamicSim:
|
||||
"""
|
||||
涡轴发动机动态仿真类
|
||||
|
||||
包含功能:
|
||||
1. 基于 NN Proxy (轻量化神经网络) 的稳态代理模型
|
||||
2. 一阶燃油执行机构动态 (First-order Actuator Dynamics)
|
||||
3. 转子动力学积分 (Rotor Dynamics)
|
||||
4. MPC (模型预测控制) 用于功率跟随
|
||||
"""
|
||||
def __init__(self, nn_pth_path="data/engine_nn_proxy.pth",
|
||||
tau_fuel=0.15, K_inertia=100.0,
|
||||
mpc_horizon=15, mpc_dt=0.02, min_fuel=10.0, max_fuel=400.0,
|
||||
mpc_overshoot_limit=0.05):
|
||||
print("-> 正在加载 NN 稳态代理模型...")
|
||||
self.engine_model = EngineNNProxy()
|
||||
|
||||
if not os.path.exists(nn_pth_path):
|
||||
raise FileNotFoundError(f"Missing NN model file: {nn_pth_path}. Please run scripts/distill_gpr_to_nn.py first.")
|
||||
|
||||
self.engine_model.load_state_dict(torch.load(nn_pth_path, map_location='cpu'))
|
||||
self.engine_model.eval()
|
||||
print("-> NN Model Loaded (CPU Mode for Sim Loop)")
|
||||
|
||||
self.tau_fuel = tau_fuel
|
||||
self.K_inertia = K_inertia
|
||||
self.max_fuel = max_fuel
|
||||
self.max_power_ref = 300.0
|
||||
|
||||
self.mpc = TurboShaftMPCController(
|
||||
tau_fuel=tau_fuel, K_inertia=K_inertia, dt=mpc_dt, horizon=mpc_horizon,
|
||||
min_fuel=min_fuel, max_fuel=max_fuel, overshoot_limit=mpc_overshoot_limit
|
||||
)
|
||||
|
||||
self.H_env = 0.0
|
||||
self.Ma_env = 0.0
|
||||
self.N_current = 0.0
|
||||
self.Wf_act_current = 0.0
|
||||
self.power_generated = 0.0
|
||||
self.Wf_cmd = 0.0
|
||||
|
||||
def _solve_steady_rpm(self, target_val, target_type='power'):
|
||||
"""数值反解给定功率/燃油下的稳态转速"""
|
||||
from scipy.optimize import brentq
|
||||
low_bound, high_bound = 0.0, 60000.0
|
||||
|
||||
def objective(n):
|
||||
# 构造输入: [H, Ma, N]
|
||||
current_input = torch.tensor([[self.H_env, self.Ma_env, n]], dtype=torch.float32)
|
||||
with torch.no_grad():
|
||||
pred_mean = self.engine_model(current_input).numpy()
|
||||
|
||||
# 输出: [0]=Fuel, [1]=Power
|
||||
val = pred_mean[0, 1] if target_type == 'power' else pred_mean[0, 0]
|
||||
return val - target_val
|
||||
|
||||
try:
|
||||
f_low = objective(low_bound)
|
||||
f_high = objective(high_bound)
|
||||
if f_low * f_high > 0:
|
||||
print(f"[Warn] 目标值超出模型范围 [{low_bound}, {high_bound}] RPM 对应的输出。将使用最接近的边界。")
|
||||
return low_bound if abs(f_low) < abs(f_high) else high_bound
|
||||
|
||||
n_solution = brentq(objective, low_bound, high_bound)
|
||||
return n_solution
|
||||
except Exception as e:
|
||||
print(f"[Error] 稳态求解失败: {e}")
|
||||
return (low_bound + high_bound) / 2.0
|
||||
|
||||
def set_steady_state_by_power(self, H_env, Ma_env, Power_target):
|
||||
"""设定初始稳态工况点"""
|
||||
self.H_env = H_env
|
||||
self.Ma_env = Ma_env
|
||||
self.N_current = self._solve_steady_rpm(Power_target, target_type='power')
|
||||
|
||||
# 计算该稳态下的燃油消耗
|
||||
current_input = torch.tensor([[self.H_env, self.Ma_env, self.N_current]], dtype=torch.float32)
|
||||
with torch.no_grad():
|
||||
pred_mean = self.engine_model(current_input).numpy()
|
||||
|
||||
self.power_generated = pred_mean[0, 1]
|
||||
self.Wf_act_current = pred_mean[0, 0]
|
||||
self.Wf_cmd = self.Wf_act_current
|
||||
|
||||
print(f"-> 稳态(Power)已配置: H={H_env}, Ma={Ma_env}, Target_P={Power_target:.1f} kW => N={self.N_current:.1f} RPM, Wf={self.Wf_cmd:.2f} kg/h")
|
||||
self.mpc.reset(initial_output=self.Wf_cmd, initial_N=self.N_current)
|
||||
return self.N_current
|
||||
|
||||
def compute_control_law(self, dt, target_power, precalc_params=None):
|
||||
"""调用 MPC 更新控制指令"""
|
||||
self.Wf_cmd = self.mpc.compute(
|
||||
current_N=self.N_current,
|
||||
current_Wfact=self.Wf_act_current,
|
||||
target_power=target_power,
|
||||
precalc_params=precalc_params
|
||||
)
|
||||
return self.Wf_cmd
|
||||
|
||||
def step(self, dt, target_power=None):
|
||||
"""
|
||||
执行单步动态仿真 (High-Performance Optimized)
|
||||
|
||||
加速策略:
|
||||
- 聚合 GPR 预测请求: 将 MPC 所需的梯度计算点与当前物理状态点合并为一个 Batch (Size=2)
|
||||
- 减少 GPU I/O 次数: 从每步 3 次减少为 1 次
|
||||
"""
|
||||
|
||||
# --- 0. 统一 GPU 批次预测 (Batch Prediction) ---
|
||||
# 构造输入: [Row 0: 当前状态点, Row 1: 用于梯度计算的微扰点]
|
||||
delta_N = 5.0
|
||||
|
||||
# 判断模型类型: NN 模型使用 forward,GPR 模型使用 predict
|
||||
if hasattr(self.engine_model, 'predict') and not hasattr(self.engine_model, 'forward'):
|
||||
# GPR 模型
|
||||
inputs = np.array([
|
||||
[self.H_env, self.Ma_env, self.N_current],
|
||||
[self.H_env, self.Ma_env, self.N_current + delta_N]
|
||||
])
|
||||
pred_mean, _ = self.engine_model.predict(inputs)
|
||||
else:
|
||||
# NN 模型
|
||||
import torch
|
||||
inputs = torch.tensor([
|
||||
[self.H_env, self.Ma_env, self.N_current],
|
||||
[self.H_env, self.Ma_env, self.N_current + delta_N]
|
||||
], dtype=torch.float32)
|
||||
with torch.no_grad():
|
||||
pred_mean = self.engine_model(inputs).numpy()
|
||||
|
||||
# 核心加速点:一次 GPU 调用获取所有信息
|
||||
# pred_mean 形如 [[Wf0, Pow0], [Wf1, Pow1]]
|
||||
|
||||
# 提取结果
|
||||
Wf_req_current = pred_mean[0, 0]
|
||||
Power_current = pred_mean[0, 1]
|
||||
|
||||
Wf_req_pert = pred_mean[1, 0]
|
||||
Power_pert = pred_mean[1, 1]
|
||||
|
||||
# --- 1. 闭环控制计算 ---
|
||||
if target_power is not None:
|
||||
# 在 Python 端快速计算梯度,避免在 MPC 内部再次调用模型
|
||||
k_wf = (Wf_req_pert - Wf_req_current) / delta_N
|
||||
k_p = (Power_pert - Power_current) / delta_N
|
||||
|
||||
# 使用预计算好的参数,MPC 内部将不再调用 engine_model.predict
|
||||
params = (Wf_req_current, Power_current, k_wf, k_p)
|
||||
self.compute_control_law(dt, target_power, precalc_params=params)
|
||||
|
||||
# --- 2. 燃油执行机构动态 (一阶惯性) ---
|
||||
dWf_act_dt = (self.Wf_cmd - self.Wf_act_current) / self.tau_fuel
|
||||
Wf_act_next = self.Wf_act_current + dWf_act_dt * dt
|
||||
|
||||
# --- 3. 调用NN代理模型推算当前气动热力参数 ---
|
||||
current_input = torch.tensor([[self.H_env, self.Ma_env, self.N_current]], dtype=torch.float32)
|
||||
with torch.no_grad():
|
||||
pred_mean = self.engine_model(current_input).numpy()
|
||||
|
||||
# [0]: Fuel Flow (kg/h), [1]: Power (kW)
|
||||
Wf_req_current = pred_mean[0, 0]
|
||||
Power_current = pred_mean[0, 1]
|
||||
self.power_generated = Power_current
|
||||
|
||||
# --- 4. 转子动力学积分 (供油盈余 -> 加速) ---
|
||||
dN_dt = self.K_inertia * (self.Wf_act_current - Wf_req_current)
|
||||
N_next = self.N_current + dN_dt * dt
|
||||
|
||||
# 更新状态
|
||||
self.Wf_act_current = Wf_act_next
|
||||
self.N_current = N_next
|
||||
|
||||
return self.N_current, self.Wf_act_current, Wf_req_current, Power_current
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# ==========================================
|
||||
# 涡轴发动机动态响应测试脚本
|
||||
# 模拟复杂剖面: 包含阶跃、正弦、斜坡指令及变高度/马赫数干扰
|
||||
# ==========================================
|
||||
import matplotlib
|
||||
matplotlib.use('Agg')
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
plt.rcParams['font.family'] = 'serif'
|
||||
plt.rcParams['font.serif'] = ['DejaVu Serif', 'Times New Roman']
|
||||
plt.rcParams['axes.unicode_minus'] = True
|
||||
|
||||
sim = TurboshaftDynamicSim(mpc_dt=0.02)
|
||||
|
||||
# 初始状态
|
||||
P_initial_target = 100.0
|
||||
sim.set_steady_state_by_power(H_env=0.0, Ma_env=0.0, Power_target=P_initial_target)
|
||||
|
||||
dt = 0.02
|
||||
t_end = 60.0
|
||||
time_array = np.arange(0, t_end, dt)
|
||||
|
||||
N_log, Wf_act_log, Wf_cmd_log, Power_log, Power_target_log = [], [], [], [], []
|
||||
H_env_log, Ma_env_log = [], []
|
||||
|
||||
print("-> 开始极限工况仿真测试 (大动态指令 + 连续外界干扰)...")
|
||||
|
||||
for t in tqdm(time_array, desc="Simulating"):
|
||||
# --- 1. 生成复杂功率指令 (Setpoint) ---
|
||||
if t < 10.0:
|
||||
# 阶跃测试
|
||||
target_p = 100.0 if t < 3 else 220.0 if t < 7 else 80.0
|
||||
elif t < 25.0:
|
||||
# 正弦跟踪 (0.2Hz)
|
||||
target_p = 140.0 + 50.0 * np.sin(2 * np.pi * 0.2 * (t - 10.0))
|
||||
elif t < 40.0:
|
||||
# 锯齿波测试
|
||||
cycle = (t - 25.0) % 5.0
|
||||
target_p = 80.0 + (80.0 / 5.0) * cycle
|
||||
else:
|
||||
# 极限大范围跳变
|
||||
target_p = 170.0 if t < 48.0 else 40.0
|
||||
|
||||
# --- 2. 生成环境扰动 (Disturbance) ---
|
||||
if t < 15.0:
|
||||
h_env, ma_env = 0.0, 0.0
|
||||
elif t < 30.0:
|
||||
# 爬升阶段: 0->3000m
|
||||
h_env = 0.0 + (3000.0 / 15.0) * (t - 15.0)
|
||||
ma_env = 0.0 + (0.2 / 15.0) * (t - 15.0)
|
||||
elif t < 45.0:
|
||||
h_env, ma_env = 3000.0, 0.2
|
||||
else:
|
||||
# 突发机动
|
||||
h_env, ma_env = 500.0, 0.4
|
||||
|
||||
sim.H_env = h_env
|
||||
sim.Ma_env = ma_env
|
||||
|
||||
# 执行单步仿真
|
||||
N_cur, Wf_act_cur, Wf_req, Power_cur = sim.step(dt, target_power=target_p)
|
||||
|
||||
N_log.append(N_cur)
|
||||
Wf_act_log.append(Wf_act_cur)
|
||||
Wf_cmd_log.append(sim.Wf_cmd)
|
||||
Power_log.append(Power_cur)
|
||||
Power_target_log.append(target_p)
|
||||
H_env_log.append(h_env)
|
||||
Ma_env_log.append(ma_env)
|
||||
|
||||
# ==========================================
|
||||
# 绘图逻辑
|
||||
# ==========================================
|
||||
fig, axes = plt.subplots(4, 1, figsize=(14, 12), gridspec_kw={'height_ratios': [2.5, 2, 2, 1.5]})
|
||||
fig.suptitle('Turboshaft Engine: MPC Extreme Stress Test\nSine Tracking + Continuous Disturbances',
|
||||
fontsize=14, fontweight='bold')
|
||||
|
||||
# Plot 1: Power Tracking (核心表现)
|
||||
axes[0].plot(time_array, Power_target_log, 'k--', linewidth=2, label='Target Power (Command)')
|
||||
axes[0].plot(time_array, Power_log, 'g-', linewidth=2, label='Actual Power (MPC)')
|
||||
axes[0].set_ylabel('Shaft Power [kW]', fontweight='bold')
|
||||
axes[0].set_title('Performance: Complex Trajectory Tracking', fontweight='bold')
|
||||
axes[0].grid(True, linestyle=':', alpha=0.7)
|
||||
axes[0].legend(loc='upper right')
|
||||
|
||||
# Plot 2: Rotor Speed
|
||||
axes[1].plot(time_array, N_log, 'b-', linewidth=2, label='Engine Speed (N)')
|
||||
axes[1].set_ylabel('Rotor Speed [RPM]', fontweight='bold')
|
||||
axes[1].set_title('State: Rotor Speed Response', fontweight='bold')
|
||||
axes[1].grid(True, linestyle=':', alpha=0.7)
|
||||
axes[1].legend(loc='upper right')
|
||||
|
||||
# Plot 3: Fuel Flow (Control Input)
|
||||
axes[2].plot(time_array, Wf_cmd_log, 'r--', linewidth=1.5, label='Fuel Command (MPC Output)')
|
||||
axes[2].plot(time_array, Wf_act_log, 'm-', linewidth=2, label='Actual Fuel Actuator')
|
||||
axes[2].set_ylabel('Fuel Flow [kg/h]', fontweight='bold')
|
||||
axes[2].set_title('Control Effort: Actuator Dynamics', fontweight='bold')
|
||||
axes[2].grid(True, linestyle=':', alpha=0.7)
|
||||
axes[2].legend(loc='upper right')
|
||||
|
||||
# Plot 4: Environmental Disturbances
|
||||
ax4_1 = axes[3]
|
||||
ax4_2 = ax4_1.twinx()
|
||||
ax4_1.plot(time_array, H_env_log, 'c-', linewidth=2, label='Altitude (m)')
|
||||
ax4_2.plot(time_array, Ma_env_log, 'y-', linewidth=2, label='Mach Number')
|
||||
ax4_1.set_xlabel('Time [s]', fontweight='bold')
|
||||
ax4_1.set_ylabel('Altitude [m]', color='c', fontweight='bold')
|
||||
ax4_2.set_ylabel('Mach', color='y', fontweight='bold')
|
||||
axes[3].set_title('Disturbances: Flight Conditions', fontweight='bold')
|
||||
axes[3].grid(True, linestyle=':', alpha=0.7)
|
||||
|
||||
plt.tight_layout(rect=[0, 0, 1, 0.96])
|
||||
plt.savefig('figures/engine_mpc_stress_test.png', dpi=200)
|
||||
print('-> 仿真完成!极限制图已保存至: figures/engine_mpc_stress_test.png')
|
||||
@@ -0,0 +1,297 @@
|
||||
import torch
|
||||
import pandas as pd
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
from matplotlib.colors import LogNorm
|
||||
from botorch.models import SingleTaskGP
|
||||
from botorch.fit import fit_gpytorch_mll
|
||||
from gpytorch.mlls import ExactMarginalLogLikelihood
|
||||
from gpytorch.means import LinearMean
|
||||
from gpytorch.priors import GammaPrior
|
||||
from sklearn.preprocessing import StandardScaler
|
||||
import warnings
|
||||
import os
|
||||
|
||||
warnings.filterwarnings("ignore")
|
||||
|
||||
# ==========================================
|
||||
# 【全局绘图设置】学术规范
|
||||
# ==========================================
|
||||
plt.rcParams['font.family'] = 'serif'
|
||||
plt.rcParams['font.serif'] = ['DejaVu Serif', 'Times New Roman']
|
||||
plt.rcParams['mathtext.fontset'] = 'stix'
|
||||
plt.rcParams['axes.unicode_minus'] = True
|
||||
|
||||
class EngineGPRModel:
|
||||
"""
|
||||
涡轴发动机 GPR 代理模型类
|
||||
支持: 训练、加载已有模型、预测推断、单马赫数切面可视化
|
||||
"""
|
||||
def __init__(self, csv_path="data/Cleaned_Engine_Data_Full.csv"):
|
||||
self.csv_path = csv_path
|
||||
self.df = None
|
||||
self.valid_X_cols = []
|
||||
self.scaler_X = StandardScaler()
|
||||
self.scaler_Y = StandardScaler()
|
||||
self.model = None
|
||||
# 自动检测并使用 GPU
|
||||
self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
||||
print(f"Using device: {self.device}")
|
||||
|
||||
def _prepare_data(self):
|
||||
"""数据预处理:读取、筛选、Log变换、标准化"""
|
||||
self.df = pd.read_csv(self.csv_path, encoding='utf-8')
|
||||
X_df = self.df[['Altitude_m', 'Mach', 'RPM']]
|
||||
|
||||
# 剔除无效特征
|
||||
self.valid_X_cols = [col for col in X_df.columns if X_df[col].nunique() > 1]
|
||||
X_numpy = self.df[self.valid_X_cols].values
|
||||
|
||||
if 'WF_kg_h' not in self.df.columns:
|
||||
raise ValueError("Column 'WF_kg_h' not found.")
|
||||
|
||||
Y_numpy = self.df[['WF_kg_h', 'Power_kW']].values
|
||||
|
||||
# Log1p 变换:保证非负性,并线性化指数规律
|
||||
Y_numpy = np.log1p(Y_numpy)
|
||||
|
||||
# Z-Score 归一化
|
||||
X_scaled = self.scaler_X.fit_transform(X_numpy)
|
||||
Y_scaled = self.scaler_Y.fit_transform(Y_numpy)
|
||||
|
||||
# 转换为 Tensor 并移动到 GPU (如果可用)
|
||||
return torch.tensor(X_scaled, dtype=torch.double).to(self.device), torch.tensor(Y_scaled, dtype=torch.double).to(self.device)
|
||||
|
||||
def _init_model(self, train_X, train_Y):
|
||||
"""内部方法:统一初始化模型结构(包含 Mean 和 Prior 设置)"""
|
||||
mean_module = LinearMean(input_size=train_X.shape[-1], batch_shape=torch.Size([train_Y.shape[-1]]))
|
||||
model = SingleTaskGP(train_X, train_Y, mean_module=mean_module)
|
||||
|
||||
# 统一施加 GammaPrior 防止结构不匹配
|
||||
# 这一步非常关键:加载模型时,模型结构必须与训练时完全一致,包括 Prior
|
||||
if hasattr(model.covar_module, 'base_kernel'):
|
||||
kernel = model.covar_module.base_kernel
|
||||
else:
|
||||
kernel = model.covar_module
|
||||
|
||||
if hasattr(kernel, 'lengthscale'):
|
||||
kernel.lengthscale_prior = GammaPrior(4.0, 1.0)
|
||||
|
||||
return model
|
||||
|
||||
def train(self, save_path=None):
|
||||
"""训练 GPR 模型 (Log-Space + 平滑约束)"""
|
||||
print(f"{'='*30}\n🚀 GP Training (Log-Space)\n{'='*30}")
|
||||
|
||||
train_X, train_Y = self._prepare_data()
|
||||
|
||||
# 使用统一初始化方法
|
||||
self.model = self._init_model(train_X, train_Y)
|
||||
self.model.to(self.device)
|
||||
|
||||
# 仅在训练开始前设定初始值,引导优化方向
|
||||
if hasattr(self.model.covar_module, 'base_kernel'):
|
||||
kernel = self.model.covar_module.base_kernel
|
||||
else:
|
||||
kernel = self.model.covar_module
|
||||
|
||||
if hasattr(kernel, 'lengthscale'):
|
||||
kernel.lengthscale = 2.0
|
||||
|
||||
print("-> Optimizing hyperparameters...")
|
||||
mll = ExactMarginalLogLikelihood(self.model.likelihood, self.model)
|
||||
fit_gpytorch_mll(mll)
|
||||
print("-> Training completed.")
|
||||
|
||||
if save_path:
|
||||
torch.save(self.model.state_dict(), save_path)
|
||||
print(f"-> Model saved to {save_path}")
|
||||
|
||||
def load_model(self, pth_path="data/engine_gpr_model.pth"):
|
||||
"""加载已训练的模型"""
|
||||
print(f"Loading model from {pth_path}...")
|
||||
try:
|
||||
train_X, train_Y = self._prepare_data()
|
||||
# 必须使用完全相同的结构初始化,否则 load_state_dict 会报错
|
||||
self.model = self._init_model(train_X, train_Y)
|
||||
self.model.to(self.device)
|
||||
|
||||
# 使用 strict=False 忽略 Prior 缓冲区的差异(例如 _transformed_loc 等内部参数)
|
||||
# 这些参数通常不影响模型预测,只影响后续继续训练时的约束
|
||||
state_dict = torch.load(pth_path, map_location=self.device)
|
||||
self.model.load_state_dict(state_dict, strict=True)
|
||||
self.model.eval()
|
||||
print("-> Model loaded successfully.")
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"-> Load failed: {e}")
|
||||
return False
|
||||
|
||||
def _predict_log_space(self, test_X_real: np.ndarray):
|
||||
"""预测 Log 空间下的均值和标准差"""
|
||||
if self.model is None: raise ValueError("Model not initialized.")
|
||||
|
||||
self.model.eval()
|
||||
|
||||
# Determine device from model parameters
|
||||
try:
|
||||
device = next(self.model.parameters()).device
|
||||
except StopIteration:
|
||||
device = torch.device('cpu')
|
||||
|
||||
test_X_scaled = torch.tensor(self.scaler_X.transform(test_X_real), dtype=torch.double, device=device)
|
||||
|
||||
with torch.no_grad():
|
||||
posterior = self.model.posterior(test_X_scaled)
|
||||
mu_scaled = posterior.mean.detach().cpu().numpy()
|
||||
var_scaled = posterior.variance.detach().cpu().numpy()
|
||||
|
||||
# 反归一化
|
||||
mu_log_real = self.scaler_Y.inverse_transform(mu_scaled)
|
||||
var_log_real = var_scaled * self.scaler_Y.var_
|
||||
return mu_log_real, np.sqrt(var_log_real)
|
||||
|
||||
def predict(self, test_X_real: np.ndarray):
|
||||
"""预测物理值 (expm1 还原)"""
|
||||
mu_log, std_log = self._predict_log_space(test_X_real)
|
||||
|
||||
# 中位数点估计 (Median of LogNormal)
|
||||
pred_mean = np.expm1(mu_log)
|
||||
# 近似方差
|
||||
var_log = std_log ** 2
|
||||
pred_var = (np.expm1(var_log)) * np.exp(2*mu_log + var_log)
|
||||
|
||||
return pred_mean, pred_var
|
||||
|
||||
def visualize(self, target_mach=0.0):
|
||||
"""可视化:生成方差热力图、切面曲线、均值云图"""
|
||||
if self.model is None: raise ValueError("Model not initialized.")
|
||||
print(f"Generating Plots for Mach = {target_mach}")
|
||||
|
||||
# 确定绘图范围 (训练数据 Range)
|
||||
H_min, H_max = self.df['Altitude_m'].min(), self.df['Altitude_m'].max()
|
||||
RPM_min, RPM_max = self.df['RPM'].min(), self.df['RPM'].max()
|
||||
|
||||
if H_min == H_max: H_min, H_max = H_min-1, H_max+1
|
||||
if RPM_min == RPM_max: RPM_min, RPM_max = RPM_min-100, RPM_max+100
|
||||
|
||||
H_grid, RPM_grid = np.meshgrid(np.linspace(H_min, H_max, 60), np.linspace(RPM_min, RPM_max, 60), indexing='ij')
|
||||
|
||||
test_X_dict = {'Altitude_m': H_grid.flatten(), 'RPM': RPM_grid.flatten()}
|
||||
if 'Mach' in self.valid_X_cols:
|
||||
test_X_dict['Mach'] = np.full_like(H_grid.flatten(), target_mach)
|
||||
|
||||
test_X_real = np.column_stack([test_X_dict[col] for col in self.valid_X_cols])
|
||||
|
||||
# 预测并重塑 (60x60)
|
||||
pred_mean, pred_var = self.predict(test_X_real)
|
||||
wf_mean, pow_mean = pred_mean[:, 0].reshape(60, 60), pred_mean[:, 1].reshape(60, 60)
|
||||
wf_var, pow_var = pred_var[:, 0].reshape(60, 60), pred_var[:, 1].reshape(60, 60)
|
||||
|
||||
# 筛选绘图用的真实数据点
|
||||
tol = 1e-3
|
||||
plot_df = self.df[(self.df['Mach'] >= target_mach - tol) & (self.df['Mach'] <= target_mach + tol)] if 'Mach' in self.valid_X_cols else self.df
|
||||
|
||||
# 1. 方差热力图 (Log Scale)
|
||||
fig, axes = plt.subplots(1, 2, figsize=(14, 5.5))
|
||||
for ax, var_data, title in zip(axes, [wf_var, pow_var], ['Fuel Flow Variance', 'Shaft Power Variance']):
|
||||
log_var = np.log10(np.maximum(var_data, 1e-16))
|
||||
cf = ax.contourf(RPM_grid, H_grid, log_var, levels=50, cmap='jet', alpha=0.9)
|
||||
if not plot_df.empty: ax.scatter(plot_df['RPM'], plot_df['Altitude_m'], c='white', edgecolors='black', s=25, label='Data')
|
||||
ax.set_title(f"{title} (Log10)"); ax.set_xlabel('RPM'); ax.set_ylabel('Altitude')
|
||||
plt.colorbar(cf, ax=ax)
|
||||
plt.tight_layout()
|
||||
plt.savefig(f'figures/gpr_mach_{target_mach}_variance.png')
|
||||
print(f"Saved figures/gpr_mach_{target_mach}_variance.png")
|
||||
plt.close()
|
||||
|
||||
# 2. 高度切面图 (95% CI)
|
||||
fig, axes = plt.subplots(1, 2, figsize=(14, 5.5))
|
||||
colors = ['#1f77b4', '#ff7f0e', '#2ca02c']
|
||||
RPM_1D = np.linspace(RPM_min, RPM_max, 100)
|
||||
|
||||
for idx, alt in enumerate([0.0, 3000.0, 6000.0]):
|
||||
d_1D = {'Altitude_m': np.full_like(RPM_1D, alt), 'RPM': RPM_1D}
|
||||
if 'Mach' in self.valid_X_cols: d_1D['Mach'] = np.full_like(RPM_1D, target_mach)
|
||||
X_1D = np.column_stack([d_1D[c] for c in self.valid_X_cols])
|
||||
|
||||
# Log空间预测 -> 计算物理置信区间 (保证下界非负)
|
||||
mu_log, std_log = self._predict_log_space(X_1D)
|
||||
mean = np.expm1(mu_log)
|
||||
lower = np.expm1(mu_log - 2*std_log)
|
||||
upper = np.expm1(mu_log + 2*std_log)
|
||||
|
||||
for ax, i in zip(axes, [0, 1]):
|
||||
ax.plot(RPM_1D, mean[:, i], color=colors[idx], label=f'Alt={int(alt)}m')
|
||||
ax.fill_between(RPM_1D, lower[:, i], upper[:, i], color=colors[idx], alpha=0.2)
|
||||
|
||||
for ax, title, ylab in zip(axes, ['Fuel Flow', 'Shaft Power'], ['kg/h', 'kW']):
|
||||
ax.set_title(title); ax.set_ylabel(ylab); ax.set_xlabel('RPM')
|
||||
ax.legend(); ax.grid(True, alpha=0.5)
|
||||
plt.tight_layout()
|
||||
plt.savefig(f'figures/gpr_mach_{target_mach}_section.png')
|
||||
print(f"Saved figures/gpr_mach_{target_mach}_section.png")
|
||||
plt.close()
|
||||
|
||||
# 3. 均值云图
|
||||
fig, axes = plt.subplots(1, 2, figsize=(14, 5.5))
|
||||
for ax, mean_data, title in zip(axes, [wf_mean, pow_mean], ['Fuel Flow Mean', 'Shaft Power Mean']):
|
||||
cf = ax.contourf(RPM_grid, H_grid, mean_data, levels=50, cmap='viridis', alpha=0.9)
|
||||
if not plot_df.empty: ax.scatter(plot_df['RPM'], plot_df['Altitude_m'], c='red', s=20, edgecolors='white', label='Data')
|
||||
ax.set_title(title); ax.set_xlabel('RPM'); ax.set_ylabel('Altitude')
|
||||
plt.colorbar(cf, ax=ax)
|
||||
plt.tight_layout()
|
||||
plt.savefig(f'figures/gpr_mach_{target_mach}_mean.png')
|
||||
print(f"Saved figures/gpr_mach_{target_mach}_mean.png")
|
||||
plt.close()
|
||||
|
||||
if __name__ == "__main__":
|
||||
import matplotlib
|
||||
matplotlib.use('Agg')
|
||||
print("Using Agg backend for plotting.")
|
||||
|
||||
engine_model = EngineGPRModel()
|
||||
|
||||
# 智能选择加载或训练
|
||||
model_path = "data/engine_gpr_model.pth"
|
||||
if os.path.exists(model_path):
|
||||
success = engine_model.load_model(model_path)
|
||||
if not success:
|
||||
# 如果加载失败(结构不匹配),则重新训练
|
||||
engine_model.train(save_path=model_path)
|
||||
else:
|
||||
# 如果模型不存在,则训练并保存
|
||||
engine_model.train(save_path=model_path)
|
||||
|
||||
# ==========================================
|
||||
# 【使用示例】
|
||||
# ==========================================
|
||||
print("\n" + "="*50)
|
||||
print("💡 预测使用示例 (Prediction Example)")
|
||||
print("="*50)
|
||||
# 假设默认特征组合为: [Altitude_m, Mach, RPM]
|
||||
sample_inputs = np.array([
|
||||
[0.0, 0.0, 15000.0], # 测试点 1: 海平面静止, 15000 RPM
|
||||
[3000.0, 0.2, 22000.0] # 测试点 2: 3000米, 0.2马赫, 22000 RPM
|
||||
])
|
||||
|
||||
|
||||
mean_preds, var_preds = engine_model.predict(sample_inputs)
|
||||
|
||||
for i, (X_in, Y_mean, Y_var) in enumerate(zip(sample_inputs, mean_preds, var_preds)):
|
||||
# 格式化输出
|
||||
x_str = "[" + ", ".join([f"{val:8.2f}" for val in X_in]) + " ]"
|
||||
mean_str = "[" + ", ".join([f"{val:10.4f}" for val in Y_mean]) + " ]"
|
||||
var_str = "[" + ", ".join([f"{val:10.4f}" for val in Y_var]) + " ]"
|
||||
|
||||
print(f"[测试点 {i+1}]")
|
||||
print(f" -> 输入特征 {engine_model.valid_X_cols}: {x_str}")
|
||||
print(f" -> 预测均值 [WF (kg/h), Power_kW]: {mean_str}")
|
||||
print(f" -> 预测方差 [WF (kg/h), Power_kW]: {var_str}\n")
|
||||
|
||||
# ==========================================
|
||||
# 循环调用绘图方法,分别输出所需的马赫数切面图
|
||||
# ==========================================
|
||||
target_machs = [0.0, 0.1, 0.2, 0.3, 0.4]
|
||||
for m in target_machs:
|
||||
engine_model.visualize(target_mach=m)
|
||||
@@ -0,0 +1,88 @@
|
||||
class IncrementalPIDController:
|
||||
"""
|
||||
增量式 PID 控制器 (支持自动归一化缩放)
|
||||
适用于发动机燃油控制等具有保持特性的执行机构
|
||||
"""
|
||||
def __init__(self, kp, ki, kd, dt, output_min, output_max, input_scale=1.0, output_scale=1.0):
|
||||
"""
|
||||
初始化 PID 控制器
|
||||
|
||||
如果提供了 scale 参数,则 kp/ki/kd 被视为归一化域的参数。
|
||||
内部运算逻辑:
|
||||
norm_error = (setpoint - measurement) / input_scale
|
||||
norm_output += PID(norm_error, kp, ki, kd)
|
||||
physical_output = norm_output * output_scale
|
||||
|
||||
:param kp: 比例系数 (建议使用归一化参数)
|
||||
:param ki: 积分系数
|
||||
:param kd: 微分系数
|
||||
:param dt: 控制周期 (s)
|
||||
:param output_min: 执行机构输出下限 (物理量)
|
||||
:param output_max: 执行机构输出上限 (物理量)
|
||||
:param input_scale: 输入测量值的量程基准 (例如额定功率 1000.0)
|
||||
:param output_scale: 输出控制量的量程基准 (例如最大燃油 600.0)
|
||||
"""
|
||||
self.kp = kp
|
||||
self.ki = ki
|
||||
self.kd = kd
|
||||
self.dt = dt
|
||||
|
||||
# 记录缩放因子
|
||||
self.input_scale = input_scale
|
||||
self.output_scale = output_scale
|
||||
|
||||
# 将物理限制转换为内部的归一化限制
|
||||
self.out_min_norm = output_min / output_scale
|
||||
self.out_max_norm = output_max / output_scale
|
||||
|
||||
# 历史误差状态 (归一化误差)
|
||||
self.e_k1 = 0.0 # e(k-1)
|
||||
self.e_k2 = 0.0 # e(k-2)
|
||||
|
||||
# 当前实际的控制输出 (归一化值 [0~1] 或 [-1~1])
|
||||
self.current_output_norm = 0.0
|
||||
|
||||
def reset(self, initial_output=0.0):
|
||||
"""
|
||||
重置控制器状态,用于初始化或开闭环的无扰切换
|
||||
:param initial_output: 当前执行机构的实际位置(物理量,如燃油流量)
|
||||
"""
|
||||
self.e_k1 = 0.0
|
||||
self.e_k2 = 0.0
|
||||
# 将物理初始值转换为归一化内部状态
|
||||
self.current_output_norm = initial_output / self.output_scale
|
||||
|
||||
def compute(self, setpoint, measurement):
|
||||
"""
|
||||
计算下一拍的控制量
|
||||
:param setpoint: 目标设定值 (物理量)
|
||||
:param measurement: 当前测量值 (物理量)
|
||||
:return: 经过限幅的绝对控制指令 (物理量)
|
||||
"""
|
||||
# 1. 计算归一化误差 e(k)
|
||||
# 误差除以输入量程,使得误差在 -1~1 之间 (对于阶跃通常更小)
|
||||
e_k = (setpoint - measurement) / self.input_scale
|
||||
|
||||
# 2. 计算归一化控制增量 delta_u
|
||||
p_term = self.kp * (e_k - self.e_k1)
|
||||
i_term = self.ki * e_k * self.dt
|
||||
# 微分项除以dt可能会很大,归一化的时间常数有助于平滑
|
||||
d_term = self.kd * (e_k - 2 * self.e_k1 + self.e_k2) / self.dt
|
||||
|
||||
delta_u_norm = p_term + i_term + d_term
|
||||
|
||||
# 3. 更新当前归一化输出量
|
||||
self.current_output_norm += delta_u_norm
|
||||
|
||||
# 4. 绝对位置限幅 (在归一化域进行)
|
||||
if self.current_output_norm > self.out_max_norm:
|
||||
self.current_output_norm = self.out_max_norm
|
||||
elif self.current_output_norm < self.out_min_norm:
|
||||
self.current_output_norm = self.out_min_norm
|
||||
|
||||
# 5. 更新历史误差
|
||||
self.e_k2 = self.e_k1
|
||||
self.e_k1 = e_k
|
||||
|
||||
# 6. 返回物理量输出
|
||||
return self.current_output_norm * self.output_scale
|
||||
@@ -0,0 +1,70 @@
|
||||
import torch
|
||||
import torch.nn as nn
|
||||
import numpy as np
|
||||
|
||||
class EngineNNProxy(nn.Module):
|
||||
"""
|
||||
轻量级神经网络代理模型,用于替代笨重的 GPR 模型。
|
||||
结构: 简单的 MLP (多层感知机)
|
||||
输入: [Altitude, Mach, RPM] (未归一化)
|
||||
输出: [FuelFlow, Power] (未归一化)
|
||||
"""
|
||||
def __init__(self, hidden_size=64):
|
||||
super(EngineNNProxy, self).__init__()
|
||||
|
||||
# 定义网络结构
|
||||
# 对应 distill_gpr_to_nn.py 中的索引访问:
|
||||
# 0: Linear
|
||||
# 1: ReLU / Tanh
|
||||
# 2: Linear
|
||||
# 3: ReLU / Tanh
|
||||
# 4: Linear (Output)
|
||||
self.net = nn.Sequential(
|
||||
nn.Linear(3, hidden_size), # 0
|
||||
nn.Tanh(), # 1: Tanh 通常比 ReLU 更适合平滑的物理函数拟合
|
||||
nn.Linear(hidden_size, hidden_size), # 2
|
||||
nn.Tanh(), # 3
|
||||
nn.Linear(hidden_size, 2) # 4: 输出 2 个物理量 (Fuel, Power)
|
||||
)
|
||||
|
||||
# 归一化参数 (注册为 buffer 以便随模型保存)
|
||||
# 初始化为默认值,防止未调用 set_normalization_params 时报错
|
||||
self.register_buffer('x_mean', torch.zeros(3))
|
||||
self.register_buffer('x_scale', torch.ones(3))
|
||||
self.register_buffer('y_mean', torch.zeros(2))
|
||||
self.register_buffer('y_scale', torch.ones(2))
|
||||
|
||||
def set_normalization_params(self, scaler_X, scaler_Y):
|
||||
"""
|
||||
从 sklearn StandardScaler 中提取参数
|
||||
scaler_X: 用于输入的归一化器
|
||||
scaler_Y: 用于输出 (Log1p Space) 的归一化器
|
||||
"""
|
||||
if scaler_X is not None:
|
||||
self.x_mean.copy_(torch.tensor(scaler_X.mean_, dtype=torch.float32))
|
||||
self.x_scale.copy_(torch.tensor(scaler_X.scale_, dtype=torch.float32))
|
||||
|
||||
if scaler_Y is not None:
|
||||
self.y_mean.copy_(torch.tensor(scaler_Y.mean_, dtype=torch.float32))
|
||||
self.y_scale.copy_(torch.tensor(scaler_Y.scale_, dtype=torch.float32))
|
||||
|
||||
def forward(self, x):
|
||||
"""
|
||||
前向传播: 物理输入 -> 物理输出
|
||||
包含: 归一化 -> NN推理 -> 反归一化 -> expm1
|
||||
"""
|
||||
# 1. 输入归一化 (Z-Score)
|
||||
# 确保输入 x 与 buffer 在同一设备
|
||||
x = x.to(self.x_mean.device)
|
||||
x_norm = (x - self.x_mean) / self.x_scale
|
||||
|
||||
# 2. 神经网络推理 (预测 Log Normalized Z-Score)
|
||||
y_norm_pred = self.net(x_norm)
|
||||
|
||||
# 3. 输出反归一化 (Z-Score Inverse)
|
||||
y_log1p_pred = y_norm_pred * self.y_scale + self.y_mean
|
||||
|
||||
# 4. 指数还原 (Inverse Log1p)
|
||||
y_phys_pred = torch.expm1(y_log1p_pred)
|
||||
|
||||
return y_phys_pred
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,298 @@
|
||||
import numpy as np
|
||||
|
||||
|
||||
# ==============================================================================
|
||||
# Pure-Python projected gradient descent for box-constrained optimization
|
||||
# (替代 scipy.optimize.minimize SLSQP,避免 Fortran ABI 兼容性问题)
|
||||
# ==============================================================================
|
||||
def _minimize_box(objective, x0, bounds, lr=1.0, max_iter=80, ftol=1e-6):
|
||||
"""
|
||||
Projected gradient descent with Armijo backtracking line search.
|
||||
For small-to-medium MPC horizons (H ≤ 30) this is fast enough.
|
||||
"""
|
||||
n = len(x0)
|
||||
lb = np.array([b[0] for b in bounds], dtype=np.float64)
|
||||
ub = np.array([b[1] for b in bounds], dtype=np.float64)
|
||||
x = np.clip(np.array(x0, dtype=np.float64), lb, ub)
|
||||
|
||||
eps = 1e-5 # finite-difference step
|
||||
f_prev = objective(x)
|
||||
|
||||
for _it in range(max_iter):
|
||||
# Approximate gradient via central differences
|
||||
grad = np.empty(n, dtype=np.float64)
|
||||
for i in range(n):
|
||||
x_p = x.copy(); x_p[i] += eps
|
||||
x_m = x.copy(); x_m[i] -= eps
|
||||
grad[i] = (objective(x_p) - objective(x_m)) / (2 * eps)
|
||||
|
||||
# Backtracking line search (Armijo condition)
|
||||
step = lr
|
||||
for _ in range(12):
|
||||
x_new = np.clip(x - step * grad, lb, ub)
|
||||
f_new = objective(x_new)
|
||||
if f_new < f_prev - 1e-4 * step * np.dot(grad, x - x_new):
|
||||
break
|
||||
step *= 0.5
|
||||
else:
|
||||
x_new = np.clip(x - step * grad, lb, ub)
|
||||
f_new = objective(x_new)
|
||||
|
||||
if abs(f_prev - f_new) < ftol:
|
||||
x = x_new
|
||||
break
|
||||
x = x_new
|
||||
f_prev = f_new
|
||||
|
||||
class _Result:
|
||||
pass
|
||||
res = _Result()
|
||||
res.x = x
|
||||
res.fun = f_prev
|
||||
res.success = True
|
||||
return res
|
||||
|
||||
# ==============================================================================
|
||||
# 1. 涡轴发动机 MPC 控制器 (基于 Scipy SLSQP 高速求解)
|
||||
# ==============================================================================
|
||||
class TurboShaftMPCController:
|
||||
def __init__(self, tau_fuel, K_inertia, dt=0.02, horizon=15,
|
||||
min_fuel=10.0, max_fuel=600.0, overshoot_limit=0.05):
|
||||
"""
|
||||
初始化高速 MPC 控制器 (基于 Scipy SLSQP)
|
||||
替代 GEKKO 以消除文件 I/O 开销,提升单步推理速度 50x 以上。
|
||||
|
||||
:param overshoot_limit: 超调量硬约束 (0.05 = 5%)
|
||||
"""
|
||||
self.dt = dt
|
||||
self.H = horizon
|
||||
self.tau_fuel = tau_fuel
|
||||
self.K_inertia = K_inertia
|
||||
self.min_fuel = min_fuel
|
||||
self.max_fuel = max_fuel
|
||||
|
||||
# 权重参数 (与 GEKKO 版本保持一致)
|
||||
self.W_power = 200.0 # Power Setpoint Weight
|
||||
self.W_dcost = 1.5 # Delta Control Weight (DCOST)
|
||||
|
||||
# 超调量约束
|
||||
self.overshoot_limit = overshoot_limit # 5% 硬约束
|
||||
|
||||
# 超调惩罚权重 (使用很大的值使约束"硬"化)
|
||||
self.W_overshoot_penalty = 1e6
|
||||
|
||||
# 状态缓存
|
||||
self.last_u = 100.0
|
||||
self.last_N = 0.0
|
||||
|
||||
def reset(self, initial_output, initial_N):
|
||||
self.last_u = initial_output
|
||||
self.last_N = initial_N
|
||||
|
||||
def compute(self, current_N, current_Wfact, target_power, engine_model=None, H_env=0, Ma_env=0, precalc_params=None, **kwargs):
|
||||
"""
|
||||
计算 MPC 控制律
|
||||
:param precalc_params: (必须) 元组 (Wf_req_0, Power_0, k_wf, k_p)。
|
||||
FastMPC 必须配合 Batch Prediction 使用。
|
||||
"""
|
||||
if precalc_params is not None:
|
||||
Wf_req_0, Power_0, k_wf, k_p = precalc_params
|
||||
else:
|
||||
raise ValueError("FastMPC 必须配合 Batch Prediction 使用 (提供 precalc_params)")
|
||||
|
||||
N0 = current_N
|
||||
Wf_act0 = current_Wfact
|
||||
N_ref = N0 # 用于线性化的参考点
|
||||
|
||||
# --- 构建线性预测模型 ---
|
||||
# State x = [N, Wf_act]
|
||||
# x_{k+1} = A x_k + B u_k + d
|
||||
# N_{k+1} = N_k + dt * K * (Wf_act_k - (Wf_req_0 + k_wf*(N_k - N0)))
|
||||
# = (1 - dt*K*k_wf) N_k + (dt*K) Wf_act_k + dt*K*(k_wf*N0 - Wf_req_0)
|
||||
# Wf_act_{k+1} = Wf_act_k + dt * (u_k - Wf_act_k) / tau
|
||||
# = (1 - dt/tau) Wf_act_k + (dt/tau) u_k
|
||||
|
||||
dt = self.dt
|
||||
K = self.K_inertia
|
||||
tau = self.tau_fuel
|
||||
|
||||
A = np.array([
|
||||
[1 - dt * K * k_wf, dt * K],
|
||||
[0, 1 - dt / tau]
|
||||
])
|
||||
B = np.array([0, dt / tau])
|
||||
d = np.array([dt * K * (k_wf * N_ref - Wf_req_0), 0])
|
||||
|
||||
# Power Output: P = P0 + k_p * (N - N0)
|
||||
# = k_p * N + (P0 - k_p * N0)
|
||||
C_p = k_p
|
||||
D_p = Power_0 - k_p * N_ref
|
||||
|
||||
# --- 超调量硬约束 ---
|
||||
# 升功率时: P_k <= target_power * (1 + overshoot_limit)
|
||||
# 降功率时: P_k >= target_power * (1 - overshoot_limit)
|
||||
P_max = target_power * (1 + self.overshoot_limit)
|
||||
P_min = target_power * (1 - self.overshoot_limit)
|
||||
|
||||
# 判断是升功率还是降功率
|
||||
is_ramping_up = target_power > Power_0
|
||||
|
||||
# --- 优化目标函数 ---
|
||||
# Variables: U = [u_0, ..., u_{H-1}]
|
||||
# x_0 is fixed.
|
||||
# Cost = sum_{k=1 to H} W_power * (P_k - P_target)^2 + sum_{k=0 to H-1} W_dcost * (u_k - u_{k-1})^2
|
||||
# + W_overshoot_penalty * (违反约束的惩罚)
|
||||
|
||||
def objective(U):
|
||||
cost = 0.0
|
||||
x_k = np.array([N0, Wf_act0])
|
||||
u_prev = self.last_u # Use last commanded u for the first delta
|
||||
|
||||
for k in range(self.H):
|
||||
u_k = U[k]
|
||||
|
||||
# Dynamics Step
|
||||
x_k = A @ x_k + B * u_k + d
|
||||
|
||||
# Output
|
||||
P_k = C_p * x_k[0] + D_p
|
||||
|
||||
# Cost Accumulation
|
||||
cost += self.W_power * (P_k - target_power) ** 2
|
||||
cost += self.W_dcost * (u_k - u_prev) ** 2
|
||||
|
||||
# 超调惩罚: 如果违反约束,添加巨大惩罚
|
||||
if is_ramping_up:
|
||||
if P_k > P_max:
|
||||
cost += self.W_overshoot_penalty * (P_k - P_max) ** 2
|
||||
else:
|
||||
if P_k < P_min:
|
||||
cost += self.W_overshoot_penalty * (P_min - P_k) ** 2
|
||||
|
||||
u_prev = u_k
|
||||
|
||||
return cost
|
||||
|
||||
# --- 求解 ---
|
||||
# 初始猜测: 保持上一次的输入
|
||||
U0 = np.full(self.H, float(self.last_u), dtype=np.float64)
|
||||
|
||||
# 约束: lb <= u <= ub
|
||||
bounds = [(self.min_fuel, self.max_fuel) for _ in range(self.H)]
|
||||
|
||||
# 使用纯Python投影梯度下降求解带约束优化 (替代 SLSQP)
|
||||
res = _minimize_box(objective, U0, bounds, lr=5.0, max_iter=60, ftol=1e-3)
|
||||
|
||||
# 更新状态
|
||||
u_opt = res.x[0]
|
||||
self.last_u = u_opt
|
||||
|
||||
return u_opt
|
||||
|
||||
|
||||
# ==============================================================================
|
||||
# 2. 驱动电机 MPC 控制器 (基于 Scipy SLSQP 高速求解)
|
||||
# ==============================================================================
|
||||
class MotorMPCController:
|
||||
def __init__(self, J, B_visc, dt=0.02, horizon=10, W_speed=100.0, W_dcost=1.0, overshoot_limit=0.05):
|
||||
"""
|
||||
初始化高速电机 MPC 控制器 (基于 Scipy SLSQP)
|
||||
替代 GEKKO 以消除文件 I/O 开销,提升单步推理速度 50x 以上。
|
||||
|
||||
:param overshoot_limit: 超调量硬约束 (0.05 = 5%)
|
||||
"""
|
||||
self.dt = dt
|
||||
self.H = horizon
|
||||
self.J = J
|
||||
self.B_visc = B_visc
|
||||
|
||||
# 权重参数 (可调)
|
||||
self.W_speed = W_speed # 转速跟踪权重
|
||||
self.W_dcost = W_dcost # 控制变化惩罚
|
||||
|
||||
# 超调量约束
|
||||
self.overshoot_limit = overshoot_limit # 5% 硬约束
|
||||
|
||||
# 超调惩罚权重 (使用很大的值使约束"硬"化)
|
||||
self.W_overshoot_penalty = 1e6
|
||||
|
||||
# 状态缓存
|
||||
self.last_T_cmd = 0.0
|
||||
|
||||
def reset(self, initial_w=0.0):
|
||||
"""重新初始化状态"""
|
||||
self.last_T_cmd = 0.0
|
||||
|
||||
def compute(self, current_w, target_w, t_load, t_ext, t_lim_upper, t_lim_lower):
|
||||
"""
|
||||
执行单步 MPC 优化计算
|
||||
:param current_w: 当前实际转速 (rad/s)
|
||||
:param target_w: 目标转速 (rad/s)
|
||||
:param t_load: 当前气动负载转矩 (Nm)
|
||||
:param t_ext: 当前外部轴系转矩 (Nm)
|
||||
:param t_lim_upper: 当前母线电压下,电机能发出的【正向转矩上限】(发电极限)
|
||||
:param t_lim_lower: 当前母线电压下,电机能发出的【负向转矩下限】(驱动极限)
|
||||
:return: 最优转矩指令 (Nm)
|
||||
"""
|
||||
w0 = current_w
|
||||
|
||||
dt = self.dt
|
||||
J = self.J
|
||||
B = self.B_visc
|
||||
|
||||
# --- 离散线性模型 ---
|
||||
# w_{k+1} = w_k + dt * (-(T_cmd + T_ext + T_load + B*w_k) / J)
|
||||
# = (1 - dt*B/J) * w_k - dt/J * T_cmd - dt/J * (T_ext + T_load)
|
||||
a = 1 - dt * B / J
|
||||
b = -dt / J
|
||||
d = -dt / J * (t_ext + t_load)
|
||||
|
||||
# --- 超调量硬约束 ---
|
||||
# 升速时: w_k <= target_w * (1 + overshoot_limit)
|
||||
# 降速时: w_k >= target_w * (1 - overshoot_limit)
|
||||
w_max = target_w * (1 + self.overshoot_limit)
|
||||
w_min = target_w * (1 - self.overshoot_limit)
|
||||
|
||||
# 判断是升速还是降速
|
||||
is_ramping_up = target_w > w0
|
||||
|
||||
# --- 优化目标函数 ---
|
||||
# Cost = sum_{k=1 to H} W_speed * (w_k - target_w)^2 + sum_{k=0 to H-1} W_dcost * (T_k - T_{k-1})^2
|
||||
# + W_overshoot_penalty * (违反约束的惩罚)
|
||||
|
||||
def objective(U):
|
||||
cost = 0.0
|
||||
w_k = w0
|
||||
T_prev = self.last_T_cmd
|
||||
|
||||
for k in range(self.H):
|
||||
T_k = U[k]
|
||||
w_k = a * w_k + b * T_k + d # 动力学迭代
|
||||
cost += self.W_speed * (w_k - target_w) ** 2
|
||||
cost += self.W_dcost * (T_k - T_prev) ** 2
|
||||
|
||||
# 超调惩罚: 如果违反约束,添加巨大惩罚
|
||||
if is_ramping_up:
|
||||
if w_k > w_max:
|
||||
cost += self.W_overshoot_penalty * (w_k - w_max) ** 2
|
||||
else:
|
||||
if w_k < w_min:
|
||||
cost += self.W_overshoot_penalty * (w_min - w_k) ** 2
|
||||
|
||||
T_prev = T_k
|
||||
|
||||
return cost
|
||||
|
||||
# 初始猜测
|
||||
U0 = np.full(self.H, float(self.last_T_cmd), dtype=np.float64)
|
||||
|
||||
# 约束: 转矩边界
|
||||
bounds = [(t_lim_lower, t_lim_upper) for _ in range(self.H)]
|
||||
|
||||
# 求解 (使用纯Python投影梯度下降,替代 SLSQP)
|
||||
res = _minimize_box(objective, U0, bounds, lr=50.0, max_iter=120, ftol=1e-5)
|
||||
|
||||
T_opt = res.x[0]
|
||||
self.last_T_cmd = T_opt
|
||||
|
||||
return T_opt
|
||||
@@ -0,0 +1,251 @@
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
from tqdm import tqdm
|
||||
|
||||
from engine_dynamic_sim import TurboshaftDynamicSim
|
||||
from motor_sim import MotorSim
|
||||
from battery_sim import BatterySim
|
||||
|
||||
class SeriesHybridSystem:
|
||||
"""
|
||||
串联式混合动力系统总成
|
||||
"""
|
||||
def __init__(self, mpc_overshoot_limit: float = 0.05):
|
||||
self.genset = TurboshaftDynamicSim(mpc_overshoot_limit=mpc_overshoot_limit)
|
||||
self.drive_motor = MotorSim(
|
||||
P_rate=300e3,
|
||||
w_rate=575.95,
|
||||
J=1.0,
|
||||
mpc_W_speed=40,
|
||||
mpc_W_dcost=5,
|
||||
mpc_overshoot_limit=mpc_overshoot_limit, # 超调量硬约束 (5%)
|
||||
)
|
||||
self.battery = BatterySim(capacity_kwh=50.0, initial_soc=0.6)
|
||||
|
||||
self.bus_voltage = self.battery._get_ocv(self.battery.SOC)
|
||||
self.motor_actual_power_kw = 0.0
|
||||
|
||||
# 滞环控制状态
|
||||
self._genset_low_power_mode = False # 发动机低功率模式标志
|
||||
self._hysteresis_rpm = 100 # 滞环带宽 RPM
|
||||
|
||||
def energy_management_strategy(self, p_drive_req_kw, soc, speed_error_rpm=0.0):
|
||||
"""
|
||||
功率跟随策略 (Power Following Control) - 增强版
|
||||
核心思想:
|
||||
- 使用滞环控制避免频繁切换
|
||||
- 当转速持续高于目标时,降低发动机功率
|
||||
- 当转速持续低于目标时,增加发动机功率
|
||||
"""
|
||||
P_eng_max = 300.0
|
||||
P_eng_min = 20.0
|
||||
SOC_TARGET = 0.60
|
||||
K_soc = 30.0 # kW / ΔSOC
|
||||
K_speed = 1.5 # kW / RPM
|
||||
p_dyn_reserve = P_eng_max * 0.3 # 90 kW 基础储备
|
||||
|
||||
# 滞环控制逻辑
|
||||
# 进入低功率模式:转速高于目标 + 电机发电
|
||||
if speed_error_rpm < -self._hysteresis_rpm and p_drive_req_kw < 0:
|
||||
self._genset_low_power_mode = True
|
||||
# 退出低功率模式:转速低于目标 - 滞环带宽
|
||||
elif speed_error_rpm > self._hysteresis_rpm:
|
||||
self._genset_low_power_mode = False
|
||||
|
||||
# 根据模式计算目标功率
|
||||
if self._genset_low_power_mode:
|
||||
# 低功率模式:发动机降到最低
|
||||
target_engine_power = P_eng_min
|
||||
elif speed_error_rpm > 0:
|
||||
# 加速模式
|
||||
p_speed_comp = min(speed_error_rpm * K_speed, 250.0)
|
||||
target_engine_power = p_drive_req_kw + p_dyn_reserve + p_speed_comp
|
||||
else:
|
||||
# 减速/稳态模式
|
||||
p_speed_comp = max(speed_error_rpm * K_speed, -250.0)
|
||||
target_engine_power = p_drive_req_kw + p_dyn_reserve + p_speed_comp
|
||||
|
||||
# SOC补偿
|
||||
soc_error = SOC_TARGET - soc
|
||||
if soc < 0.2 or soc > 0.85:
|
||||
K_soc_effective = 0
|
||||
else:
|
||||
K_soc_effective = K_soc
|
||||
p_charge_req = soc_error * K_soc_effective
|
||||
target_engine_power += p_charge_req
|
||||
|
||||
# 极限状态越界保护
|
||||
if soc < 0.15:
|
||||
target_engine_power = P_eng_max
|
||||
elif soc > 0.95:
|
||||
target_engine_power = P_eng_min
|
||||
|
||||
# 限制输出范围
|
||||
target_engine_power = max(P_eng_min, min(P_eng_max, target_engine_power))
|
||||
|
||||
return target_engine_power
|
||||
|
||||
def step(self, dt, target_prop_speed, prop_load_torque):
|
||||
"""
|
||||
全系统单步动力学仿真
|
||||
"""
|
||||
# 1. 需求端:驱动电机电功率请求
|
||||
motor_state = self.drive_motor.step(
|
||||
dt=dt,
|
||||
n_setpoint=target_prop_speed,
|
||||
p_bus_actual_kw=self.motor_actual_power_kw,
|
||||
v_bus=self.bus_voltage,
|
||||
t_load=prop_load_torque,
|
||||
t_ext=0.0
|
||||
)
|
||||
p_drive_req = motor_state['p_bus_req_kw']
|
||||
actual_rpm = motor_state['n_rpm']
|
||||
|
||||
# 计算转速误差(用于EMS)
|
||||
speed_error_rpm = target_prop_speed - actual_rpm
|
||||
|
||||
# 2. 决策端:EMS 目标功率计算(加入转速误差反馈)
|
||||
target_engine_pwr = self.energy_management_strategy(p_drive_req, self.battery.SOC, speed_error_rpm)
|
||||
|
||||
# 3. 发电端:涡轴发动机响应并输出电能
|
||||
N_eng, Wf_act, Wf_req, P_eng_out = self.genset.step(dt, target_power=target_engine_pwr)
|
||||
# GPR模型输出的 P_eng_out > 0 表示发动机输出功率(发电)
|
||||
p_gen_elec = P_eng_out # 正值表示发电功率
|
||||
|
||||
# 4. 汇流端:电池功率补偿与直流母线状态更新
|
||||
# 功率平衡:电机需求 = 发动机发电 + 电池补充
|
||||
# p_batt_req > 0 表示电池放电,p_batt_req < 0 表示电池充电
|
||||
p_batt_req = p_drive_req - p_gen_elec
|
||||
p_batt_actual, v_bus, i_batt, soc = self.battery.step(dt, p_batt_req)
|
||||
|
||||
# 5. 状态记忆:为打破代数环,保留关键变量至下一拍
|
||||
self.bus_voltage = v_bus
|
||||
|
||||
# 电机实际获得的功率 = 发电功率 + 电池放电功率
|
||||
# 注意:允许负值存在,表示电机在发电模式(制动)
|
||||
# 这样电机控制器才能正确产生制动转矩
|
||||
self.motor_actual_power_kw = p_gen_elec + p_batt_actual
|
||||
|
||||
return {
|
||||
'soc': soc * 100.0,
|
||||
'bus_voltage': v_bus,
|
||||
'prop_speed_rpm': motor_state['n_rpm'],
|
||||
'target_engine_pwr': target_engine_pwr,
|
||||
'p_engine_out_kw': P_eng_out,
|
||||
'p_drive_req_kw': p_drive_req,
|
||||
'p_motor_actual_kw': self.motor_actual_power_kw,
|
||||
'p_batt_actual_kw': p_batt_actual,
|
||||
'wf_kg_h': Wf_act,
|
||||
'engine_rpm': N_eng
|
||||
}
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import os
|
||||
import matplotlib
|
||||
matplotlib.use('Agg') # 非交互后端
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
plt.rcParams['font.family'] = 'serif'
|
||||
plt.rcParams['axes.unicode_minus'] = True
|
||||
|
||||
print("-> 初始化串联混电系统...")
|
||||
system = SeriesHybridSystem()
|
||||
system.genset.set_steady_state_by_power(H_env=0.0, Ma_env=0.0, Power_target=50.0)
|
||||
|
||||
dt = 0.02
|
||||
t_end = 180.0
|
||||
time_array = np.arange(0, t_end, dt)
|
||||
|
||||
log = {k: [] for k in ['soc', 'bus_voltage', 'prop_speed_rpm', 'target_prop_rpm', 'target_engine_pwr',
|
||||
'p_engine_out_kw', 'p_drive_req_kw', 'p_motor_actual_kw',
|
||||
'p_batt_actual_kw', 'wf_kg_h']}
|
||||
|
||||
print("-> 开始全系统闭环步进仿真 (总时长 3 分钟)...")
|
||||
for t in tqdm(time_array, desc='Simulating', unit='step'):
|
||||
# 3分钟测试剖面
|
||||
if t < 15.0:
|
||||
target_rpm, load_torque = 1500.0, 50.0 # 地面滑行
|
||||
elif t < 60.0:
|
||||
target_rpm, load_torque = 3000.0, 200.0 # 暴力拉升
|
||||
elif t < 120.0:
|
||||
target_rpm, load_torque = 2800.0, 150.0 # 重载巡航
|
||||
else:
|
||||
target_rpm, load_torque = 1800.0, 60.0 # 降落滑行
|
||||
|
||||
res = system.step(dt, target_rpm, load_torque)
|
||||
res['target_prop_rpm'] = target_rpm
|
||||
for k in log.keys():
|
||||
log[k].append(res[k])
|
||||
|
||||
print("-> 仿真完成,正在绘制系统响应曲线...")
|
||||
|
||||
# 绘图逻辑
|
||||
fig, axes = plt.subplots(4, 1, figsize=(14, 12), sharex=True)
|
||||
fig.suptitle('Series Hybrid Electric System Dynamics (Load Following EMS)', fontweight='bold', fontsize=14)
|
||||
|
||||
# 1. 转速响应
|
||||
axes[0].plot(time_array, log['target_prop_rpm'], 'k--', lw=1.5, label='Target Speed')
|
||||
axes[0].plot(time_array, log['prop_speed_rpm'], 'b-', lw=1.5, label='Actual Speed')
|
||||
axes[0].set_ylabel('Speed [RPM]')
|
||||
axes[0].set_title('Drive Motor Speed Response')
|
||||
axes[0].grid(True, linestyle=':', alpha=0.7)
|
||||
axes[0].legend()
|
||||
|
||||
# 2. 功率分配流向
|
||||
axes[1].plot(time_array, log['p_drive_req_kw'], 'k--', lw=1.5, label='Drive Motor Request')
|
||||
axes[1].plot(time_array, log['p_engine_out_kw'], 'r-', lw=1.5, label='Engine Output (Turbo Shaft)')
|
||||
axes[1].plot(time_array, log['p_batt_actual_kw'], 'g-', lw=1.5, label='Battery Output')
|
||||
axes[1].set_ylabel('Power [kW]')
|
||||
axes[1].set_title('System Power Flow (Energy Management)')
|
||||
axes[1].axhline(0, color='gray', lw=1)
|
||||
axes[1].grid(True, linestyle=':', alpha=0.7)
|
||||
axes[1].legend()
|
||||
|
||||
# 3. 电池状态
|
||||
axes[2].plot(time_array, log['bus_voltage'], 'm-', lw=1.5, label='DC Bus Voltage')
|
||||
axes[2].set_ylabel('Voltage [V]')
|
||||
axes[2].set_title('DC Bus Electrical State')
|
||||
axes[2].grid(True, linestyle=':', alpha=0.7)
|
||||
axes[2].legend(loc='upper left')
|
||||
|
||||
ax2_soc = axes[2].twinx()
|
||||
ax2_soc.plot(time_array, log['soc'], 'c--', lw=2, label='Battery SOC')
|
||||
ax2_soc.set_ylabel('SOC [%]')
|
||||
ax2_soc.legend(loc='upper right')
|
||||
|
||||
# 4. 燃油消耗
|
||||
axes[3].plot(time_array, log['wf_kg_h'], 'tab:orange', lw=1.5, label='Engine Fuel Flow')
|
||||
axes[3].set_ylabel('Fuel Flow [kg/h]')
|
||||
axes[3].set_xlabel('Time [s]')
|
||||
axes[3].set_title('Turboshaft Engine Fuel Consumption')
|
||||
axes[3].grid(True, linestyle=':', alpha=0.7)
|
||||
axes[3].legend()
|
||||
|
||||
plt.tight_layout(rect=[0, 0, 1, 0.96])
|
||||
|
||||
# 保存到 ../figures 目录
|
||||
figures_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), 'figures')
|
||||
if not os.path.exists(figures_dir):
|
||||
os.makedirs(figures_dir)
|
||||
save_path = os.path.join(figures_dir, 'series_hybrid_system_3min_test.png')
|
||||
|
||||
plt.savefig(save_path, dpi=300)
|
||||
print(f"-> 绘图已保存: {save_path}")
|
||||
|
||||
# 保存数据到dat文件
|
||||
data_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), 'data')
|
||||
if not os.path.exists(data_dir):
|
||||
os.makedirs(data_dir)
|
||||
dat_path = os.path.join(data_dir, 'series_hybrid_data.dat')
|
||||
|
||||
with open(dat_path, 'w', encoding='utf-8') as f:
|
||||
f.write('# Time(s)\tTarget_RPM\tActual_RPM\tError_RPM\tSOC\tEngine_Power\tDrive_Req\tBatt_Power\n')
|
||||
for i in range(len(time_array)):
|
||||
err = log['target_prop_rpm'][i] - log['prop_speed_rpm'][i]
|
||||
f.write(f'{time_array[i]:.3f}\t{log["target_prop_rpm"][i]:.1f}\t'
|
||||
f'{log["prop_speed_rpm"][i]:.1f}\t{err:.1f}\t{log["soc"][i]:.2f}\t'
|
||||
f'{log["p_engine_out_kw"][i]:.2f}\t{log["p_drive_req_kw"][i]:.2f}\t'
|
||||
f'{log["p_batt_actual_kw"][i]:.2f}\n')
|
||||
print(f"-> 数据已保存: {dat_path}")
|
||||
# plt.show()
|
||||
@@ -1,212 +1,516 @@
|
||||
# 🎛️ 自动控制原理AI+数智平台
|
||||
# 自动控制理论AI+数智平台
|
||||
|
||||
> 交互式控制系统分析与设计工具 | 时域·频域·根轨迹·AI问答
|
||||
> 交互式控制系统分析与设计工具 | 时域·频域·根轨迹·算例演示·AI问答
|
||||
|
||||
一个基于 Gradio 构建的现代化自动控制原理学习平台,集成了系统分析工具和 AI 智能问答功能。
|
||||
[](https://www.python.org/)
|
||||
[](https://gradio.app/)
|
||||
[](LICENSE)
|
||||
|
||||
## ✨ 核心功能
|
||||
## 项目简介
|
||||
|
||||
### 📊 1. 时域分析 (Time Domain Analysis)
|
||||
自动控制理论AI+数智平台是一个基于 Gradio 构建的现代化自动控制原理学习平台,集成了系统分析工具、完整混动模型算例演示,和AI智能问答功能。本项目为西北工业大学2025年校级本科生建设项目成果。
|
||||
|
||||
- **阶跃响应分析**:观察系统对单位阶跃输入的响应
|
||||
- **脉冲响应分析**:观察系统对单位脉冲输入的响应
|
||||
- **性能指标计算**:
|
||||
- 上升时间 (Rise Time)
|
||||
- 峰值时间 (Peak Time)
|
||||
- 超调量 (Overshoot)
|
||||
- 调节时间 (Settling Time)
|
||||
- 稳态值 (Steady State Value)
|
||||
平台旨在为自动控制理论课程提供交互式、数智化的学习环境,使学生能够直观理解控制系统的时域响应、频域特性、根轨迹分析等核心概念,并通过完整的混合动力系统算例演示,将理论知识与工程实践相结合。
|
||||
|
||||
**知识要点**:
|
||||
- 二阶系统标准形式
|
||||
- 阻尼比与自然频率参数说明
|
||||
- 时域性能指标公式
|
||||
- 稳态误差分析
|
||||
---
|
||||
|
||||
### 🌊 2. 频域分析 (Frequency Domain Analysis)
|
||||
## 核心功能
|
||||
|
||||
- **Bode 图绘制**:幅频特性和相频特性
|
||||
- **Nyquist 图绘制**:极坐标频率响应
|
||||
- **稳定裕度计算**:
|
||||
- 增益裕度 (Gain Margin, GM)
|
||||
- 相位裕度 (Phase Margin, PM)
|
||||
- 增益交越频率
|
||||
- 相角交越频率
|
||||
- **稳定性评估**:自动判断系统稳定性
|
||||
本平台提供五大核心功能模块,涵盖经典控制理论分析与现代控制系统设计:
|
||||
|
||||
**知识要点**:
|
||||
- 增益裕度与相位裕度定义
|
||||
- 稳定性判断准则
|
||||
- 频域指标与时域性能的关系
|
||||
- Bode 图读数技巧
|
||||
### 1. 时域分析 (Time Domain Analysis)
|
||||
|
||||
### 🎯 3. 根轨迹分析 (Root Locus Analysis)
|
||||
时域分析是研究控制系统在时间域内对输入信号响应特性的方法,是自动控制理论的基础分析方法之一。
|
||||
|
||||
- **根轨迹绘制**:自动绘制完整根轨迹图
|
||||
- **增益调节**:对数滑块精确调节增益 K
|
||||
- **极点跟踪**:实时显示当前增益下的闭环极点位置
|
||||
- **动态视角**:自动调整坐标范围,聚焦关键区域
|
||||
**主要功能:**
|
||||
- **阶跃响应分析**:观察系统对单位阶跃输入的响应,这是控制系统分析中最常用的测试信号
|
||||
- **脉冲响应分析**:观察系统对单位脉冲(δ函数)输入的响应,用于分析系统的固有特性
|
||||
- **性能指标计算**:自动计算并显示系统的关键时域性能指标
|
||||
|
||||
**知识要点**:
|
||||
- 根轨迹法基本原理
|
||||
- 幅值条件与相角条件
|
||||
- 根轨迹的基本性质(起点、终点、渐近线、分离点)
|
||||
- s 平面稳定性区域
|
||||
- 阻尼比等值线
|
||||
**计算的性能指标:**
|
||||
| 指标 | 符号 | 定义 | 物理意义 |
|
||||
|------|------|------|----------|
|
||||
| 上升时间 | $t_r$ | 响应从稳态值的10%上升到90%所需时间 | 反映系统响应速度 |
|
||||
| 峰值时间 | $t_p$ | 响应达到第一个峰值的时间 | 反映系统阻尼特性 |
|
||||
| 超调量 | $\sigma\%$ | 峰值超过稳态值的百分比 | 反映系统振荡程度 |
|
||||
| 调节时间 | $t_s$ | 响应进入并保持在稳态值±2%区间的时间 | 反映系统 settling 速度 |
|
||||
| 稳态值 | $y(\infty)$ | 时间趋于无穷时系统的输出值 | 反映系统最终行为 |
|
||||
|
||||
### 🤖 4. AI 智能问答 (Q&A)
|
||||
**二阶系统标准形式:**
|
||||
|
||||
二阶系统是自动控制理论中最重要的系统类型,其标准传递函数为:
|
||||
|
||||
$$G(s) = \frac{\omega_n^2}{s^2 + 2\zeta\omega_n s + \omega_n^2}$$
|
||||
|
||||
其中:
|
||||
- $\omega_n$ — 自然频率(rad/s),表示系统无阻尼时的固有振荡频率
|
||||
- $\zeta$ — 阻尼比,表示系统阻尼程度的相对量
|
||||
|
||||
**阻尼比与系统响应关系:**
|
||||
|
||||
| 阻尼比范围 | 系统类型 | 响应特性 |
|
||||
|------------|----------|----------|
|
||||
| $\zeta = 0$ | 无阻尼 | 持续等幅振荡 |
|
||||
| $0 < \zeta < 1$ | 欠阻尼 | 振荡衰减,响应快速 |
|
||||
| $\zeta = 1$ | 临界阻尼 | 最快无振荡响应 |
|
||||
| $\zeta > 1$ | 过阻尼 | 无振荡,但响应较慢 |
|
||||
|
||||
**稳态误差分析:**
|
||||
|
||||
稳态误差是系统长期运行后实际输出与期望输出之间的差值,是评价系统控制精度的重要指标。对于单位反馈系统:
|
||||
|
||||
$$e_{ss} = \lim_{t\to\infty} e(t) = \lim_{s\to0} \frac{R(s)}{1+G(s)H(s)}$$
|
||||
|
||||
---
|
||||
|
||||
### 2. 频域分析 (Frequency Domain Analysis)
|
||||
|
||||
频域分析通过研究系统对不同频率正弦信号的响应特性来分析系统性能,是经典控制理论的核心方法之一。
|
||||
|
||||
**主要功能:**
|
||||
- **Bode 图绘制**:同时显示幅频特性曲线和相频特性曲线
|
||||
- **Nyquist 图绘制**:以极坐标形式展示系统频率响应
|
||||
- **稳定裕度计算**:定量评估系统的相对稳定性
|
||||
|
||||
**Bode 图(波特图):**
|
||||
|
||||
Bode 图包含两个子图:
|
||||
- **幅频特性图**:显示增益(单位:dB)随频率变化的关系
|
||||
- **相频特性图**:显示相位(单位:度)随频率变化的关系
|
||||
|
||||
对数频率特性的优点:
|
||||
1. 可以将频率范围压缩,便于观察宽频带内的特性
|
||||
2. 幅值相乘转化为对数相加,简化串联系统计算
|
||||
3. 渐近线近似作图简便实用
|
||||
|
||||
**Nyquist 稳定判据:**
|
||||
|
||||
Nyquist 图是基于复变函数理论的稳定性判据。对于闭环系统:
|
||||
|
||||
$$T(s) = \frac{G(s)}{1 + G(s)}$$
|
||||
|
||||
稳定性条件:当 $\omega$ 从 $-\infty$ 变化到 $+\infty$ 时,$G(j\omega)H(j\omega)$ 轨迹顺时针包围 $(-1, j0)$ 点 $P$ 圈,其中 $P$ 为开环不稳定极点数。
|
||||
|
||||
**稳定裕度(Stability Margins):**
|
||||
|
||||
| 裕度类型 | 定义 | 计算公式 | 经验要求 |
|
||||
|----------|------|----------|----------|
|
||||
| 增益裕度 GM | 相角为 $-180°$ 时,闭环增益还能增大多少 | $GM = \frac{1}{|G(j\omega_g)|}$ | $GM > 1.0$(即 $GM_{dB} > 0$) |
|
||||
| 相位裕度 PM | 增益为1(0dB)时,相位还能滞后多少 | $PM = 180° + \angle G(j\omega_c)$ | $PM > 45°$ |
|
||||
|
||||
**稳定性判断准则:**
|
||||
- $GM > 0$ dB 且 $PM > 0°$ → **系统稳定**
|
||||
- $GM < 0$ dB 或 $PM < 0°$ → **系统不稳定**
|
||||
|
||||
**频域指标与时域性能的关系:**
|
||||
|
||||
| 频域指标 | 时域对应 | 经验公式 |
|
||||
|----------|----------|----------|
|
||||
| 带宽 $\omega_b$ | 上升时间 $t_r$ | $t_r \approx \frac{1.8}{\omega_b}$ |
|
||||
| 相位裕度 PM | 超调量 $\sigma\%$ | $\sigma\% \approx 100 \times e^{-\pi PM/(90-PM)}$ |
|
||||
| 增益裕度 GM | 稳定余量 | GM 越大,系统对不确定性越不敏感 |
|
||||
|
||||
---
|
||||
|
||||
### 3. 根轨迹分析 (Root Locus Analysis)
|
||||
|
||||
根轨迹法是一种图解方法,用于分析系统闭环极点随增益 K 变化的轨迹,是控制系统设计的核心工具。
|
||||
|
||||
**主要功能:**
|
||||
- **完整根轨迹绘制**:自动绘制开环增益从0到无穷变化时的闭环极点轨迹
|
||||
- **增益调节**:通过滑块精确调节增益 K,实时观察极点位置变化
|
||||
- **极点跟踪**:显示当前增益下闭环极点的精确位置
|
||||
- **动态坐标**:自动调整坐标系范围,聚焦关键区域
|
||||
|
||||
**根轨迹的基本规则:**
|
||||
|
||||
1. **起点与终点**:
|
||||
- 起点(K=0):开环传递函数的极点($n$ 个)
|
||||
- 终点(K→∞):开环传递函数的零点($m$ 个),剩余 $n-m$ 个趋向无穷
|
||||
|
||||
2. **渐近线**:
|
||||
- 当 $K \to \infty$ 时,根轨迹趋向 $n-m$ 条渐近线
|
||||
- 渐近线与实轴的夹角:$\phi_a = \frac{(2k+1)180°}{n-m}$
|
||||
|
||||
3. **分离点与会合点**:
|
||||
- 根轨迹在实轴上相邻两分支之间的某点分离或会合
|
||||
- 分离点坐标可通过求解 $\frac{dK}{ds} = 0$ 得到
|
||||
|
||||
4. **与虚轴的交点**:
|
||||
- 根轨迹与虚轴的交点对应的增益和频率可通过劳斯判据确定
|
||||
|
||||
**s平面稳定性区域:**
|
||||
|
||||
| 极点位置 | 系统状态 | 物理意义 |
|
||||
|----------|----------|----------|
|
||||
| 左半平面(Re(s) < 0) | 稳定 | 响应最终衰减 |
|
||||
| 虚轴(Re(s) = 0) | 临界稳定 | 持续振荡 |
|
||||
| 右半平面(Re(s) > 0) | 不稳定 | 响应发散 |
|
||||
|
||||
**阻尼比等值线:**
|
||||
|
||||
在 s 平面上,阻尼比 $\zeta$ 等于常数的曲线是通过原点的射线。对于二阶系统:
|
||||
|
||||
$$\zeta = \cos(\theta)$$
|
||||
|
||||
其中 $\theta$ 是该射线与负实轴的夹角。阻尼比越大,射线越接近负实轴,系统响应越平稳但越缓慢。
|
||||
|
||||
---
|
||||
|
||||
### 4. 算例演示 (Case Demo)
|
||||
|
||||
算例演示模块是本平台的特色功能,通过完整的串联式混合动力系统模型,展示控制系统设计在实际工程中的应用。
|
||||
|
||||
**模块架构(四阶段设计):**
|
||||
|
||||
```
|
||||
阶段零:模型训练
|
||||
├── GPR模型训练/加载(高斯过程回归)
|
||||
└── NN模型训练(知识蒸馏)
|
||||
|
||||
阶段一:发动机控制器设计
|
||||
├── PID控制器
|
||||
└── MPC控制器(模型预测控制)
|
||||
|
||||
阶段二:电机控制器设计
|
||||
├── PID控制器
|
||||
└── MPC控制器(模型预测控制)
|
||||
|
||||
阶段三:能量管理策略设计
|
||||
├── 规则型能量管理(基于SOC滞环)
|
||||
└── 完整混动系统仿真
|
||||
```
|
||||
|
||||
**发动机模型(Engine Model):**
|
||||
|
||||
基于高斯过程回归(GPR)和神经网络(NN)代理模型的涡轴发动机动态仿真:
|
||||
|
||||
- **输入变量**:高度 $H$ (m)、马赫数 $Ma$、转速 $N$ (RPM)
|
||||
- **输出变量**:燃油流量 $W_f$ (kg/h)、输出功率 $P$ (kW)
|
||||
|
||||
**发动机动态特性:**
|
||||
$$\tau_f \frac{dW_f}{dt} + W_f = W_{f,cmd}$$
|
||||
$$T \frac{dN}{dt} = K(W_f - W_{f,eq}(N))$$
|
||||
|
||||
其中 $\tau_f$ 是燃油执行机构时间常数,$K$ 是转子惯性增益。
|
||||
|
||||
**电机模型(Motor Model):**
|
||||
|
||||
永磁同步电机(PMSM)离散时间动力学模型:
|
||||
|
||||
- **d/q轴电流控制**:$i_d = 0$ 控制(MTPA)
|
||||
- **转矩方程**:$T_e = 1.5n_p[\psi_f + (L_d - L_q)i_d]i_q$
|
||||
- **机械方程**:$J\frac{d\omega}{dt} = T_e - T_L - B\omega$
|
||||
|
||||
**电池模型(Battery Model):**
|
||||
|
||||
等效电路模型,包含:
|
||||
- **开路电压** OCV:与 SOC 相关的非线性查表
|
||||
- **内阻**:$R_{in} = 0.15 \Omega$
|
||||
- **SOC 更新**:安时积分法
|
||||
|
||||
$$SOC_{k+1} = SOC_k - \frac{I_k \cdot \Delta t}{C_{capacity}}$$
|
||||
|
||||
**能量管理策略(EMS):**
|
||||
|
||||
基于规则的功率跟随策略,配合 SOC 滞环控制:
|
||||
|
||||
| SOC 区间 | 工作模式 | 控制策略 |
|
||||
|----------|----------|----------|
|
||||
| $SOC < SOC_{low}$ | 充电模式 | 发动机输出固定功率 $P_{charge}$ |
|
||||
| $SOC > SOC_{high}$ | 功率跟随 | 发动机输出 = 电机需求 + 储备功率 + SOC补偿 |
|
||||
| 滞环区间内 | 保持 | 维持前一模式 |
|
||||
|
||||
**MPC控制器(模型预测控制):**
|
||||
|
||||
滚动时域优化控制器,核心思想:
|
||||
|
||||
1. **预测模型**:利用系统线性化模型预测未来 H 步状态
|
||||
2. **优化目标**:$\min \sum_{k=1}^{H} [\|w_k - w_{ref}\|^2_{Q} + \|\Delta u_k\|^2_{R}]$
|
||||
3. **约束处理**:执行机构限幅、超调量硬约束
|
||||
|
||||
本平台使用纯 Python 实现的投影梯度下降求解器,替代传统的 SLSQP / GEKKO 方案,避免 Fortran ABI 兼容性问题。
|
||||
|
||||
**PID控制器(增量式):**
|
||||
|
||||
增量式 PID 控制器公式:
|
||||
|
||||
$$\Delta u(k) = k_p[e(k) - e(k-1)] + k_i e(k) + k_d[e(k) - 2e(k-1) + e(k-2)]$$
|
||||
|
||||
特点:
|
||||
- 计算增量而非绝对量,避免积分饱和
|
||||
- 支持输入/输出量程归一化,便于参数调节
|
||||
|
||||
---
|
||||
|
||||
### 5. AI 智能问答 (Q&A)
|
||||
|
||||
AI 问答模块集成了 DeepSeek API,提供24小时在线的自动控制理论学习助手。
|
||||
|
||||
**主要功能:**
|
||||
- **专业教学助手**:精通自动控制原理的 AI 教授
|
||||
- **流式响应**:实时显示 AI 回复过程
|
||||
- **流式响应**:实时逐字显示 AI 回复,支持多轮对话
|
||||
- **LaTeX 公式渲染**:完美支持数学公式显示
|
||||
- **上下文记忆**:支持多轮对话
|
||||
- **上下文记忆**:支持多轮连续对话,理解对话上下文
|
||||
|
||||
**支持的 API**:
|
||||
- DeepSeek API(推荐,国内网络友好)
|
||||
- Google Gemini API
|
||||
**支持的 API:**
|
||||
| API 提供商 | 模型选择 | 特点 |
|
||||
|------------|----------|------|
|
||||
| DeepSeek | deepseek-chat / deepseek-coder | 国内访问,中文优化 |
|
||||
|
||||
## 🚀 快速开始
|
||||
**提问技巧:**
|
||||
|
||||
### 环境要求
|
||||
✅ **推荐的问题类型:**
|
||||
- 概念解释:"请解释传递函数的定义和物理意义"
|
||||
- 公式推导:"如何推导二阶系统的超调量公式?"
|
||||
- 例题讲解:"如何用劳斯判据判断这个系统的稳定性?"
|
||||
- 参数分析:"PID控制器中三个参数分别如何影响系统响应?"
|
||||
|
||||
- Python 3.8+
|
||||
- pip 包管理器
|
||||
❌ **应避免的问题:**
|
||||
- 过于宽泛:"帮我做作业"(建议具体描述问题)
|
||||
- 缺乏上下文:"这个对吗?"(请提供具体系统参数)
|
||||
|
||||
### 安装步骤
|
||||
---
|
||||
|
||||
1. **克隆项目**
|
||||
## 系统要求
|
||||
|
||||
### 运行环境
|
||||
|
||||
| 项目 | 要求 |
|
||||
|------|------|
|
||||
| Python 版本 | 3.10+ |
|
||||
| 操作系统 | Windows / Linux / macOS |
|
||||
| 内存 | 建议 8GB 以上 |
|
||||
| 显卡 | 可选(用于 GPR 训练加速,CPU 模式也可运行) |
|
||||
|
||||
### 浏览器要求
|
||||
|
||||
推荐使用以下浏览器的最新版本以获得最佳体验:
|
||||
- Google Chrome 90+
|
||||
- Microsoft Edge 90+
|
||||
- Mozilla Firefox 88+
|
||||
- Apple Safari 14+
|
||||
|
||||
---
|
||||
|
||||
## 快速开始
|
||||
|
||||
### 方式一:使用 pip 安装(推荐)
|
||||
|
||||
**1. 克隆项目**
|
||||
|
||||
```bash
|
||||
git clone <your-repo-url>
|
||||
cd AutoControl
|
||||
cd AutoControlCourse
|
||||
```
|
||||
|
||||
2. **安装依赖**
|
||||
**2. 创建虚拟环境(推荐)**
|
||||
|
||||
```bash
|
||||
pip install gradio numpy control matplotlib aiohttp
|
||||
```
|
||||
# 使用 venv
|
||||
python -m venv my_gradio_env
|
||||
source my_gradio_env/bin/activate # Linux/macOS
|
||||
# 或
|
||||
my_gradio_env\Scripts\activate # Windows
|
||||
|
||||
或使用 conda:
|
||||
|
||||
```bash
|
||||
conda create -n autocontrol python=3.9
|
||||
# 或使用 conda
|
||||
conda create -n autocontrol python=3.10
|
||||
conda activate autocontrol
|
||||
pip install gradio numpy control matplotlib aiohttp
|
||||
```
|
||||
|
||||
3. **配置 API 密钥**
|
||||
**3. 安装依赖**
|
||||
|
||||
编辑 `app.py` 文件开头的配置区域:
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
**4. 配置 API 密钥**
|
||||
|
||||
编辑 `config.py` 文件中的 API 配置区域:
|
||||
|
||||
```python
|
||||
# ==================== API 配置 ====================
|
||||
API_KEY = "your-api-key-here" # 填入您的 DeepSeek API 密钥
|
||||
API_BASE_URL = "https://api.deepseek.com/v1"
|
||||
API_MODEL = "deepseek-chat"
|
||||
API_TYPE = "deepseek" # 或 "gemini"
|
||||
API_TYPE = "deepseek"
|
||||
# ==================================================
|
||||
```
|
||||
|
||||
**获取 DeepSeek API 密钥**:
|
||||
- 访问 https://platform.deepseek.com/api_keys
|
||||
- 注册并创建 API 密钥
|
||||
- 复制密钥到配置文件
|
||||
**获取 DeepSeek API 密钥:**
|
||||
1. 访问 https://platform.deepseek.com/api_keys
|
||||
2. 注册并登录账号
|
||||
3. 点击"创建新密钥"
|
||||
4. 复制生成的密钥并填入配置
|
||||
|
||||
4. **运行应用**
|
||||
**5. 运行应用**
|
||||
|
||||
```bash
|
||||
python app.py
|
||||
```
|
||||
|
||||
或使用 conda 环境:
|
||||
**6. 访问应用**
|
||||
|
||||
```bash
|
||||
conda run -n autocontrol python app.py
|
||||
```
|
||||
|
||||
5. **访问应用**
|
||||
|
||||
浏览器自动打开,或手动访问:
|
||||
浏览器将自动打开,或手动访问:
|
||||
```
|
||||
http://localhost:7860
|
||||
```
|
||||
|
||||
## 📖 使用指南
|
||||
### 方式二:使用 Docker(可选)
|
||||
|
||||
### 输入系统传递函数
|
||||
```bash
|
||||
# 构建镜像
|
||||
docker build -t autocontrol-course .
|
||||
|
||||
在任意标签页的输入框中输入传递函数的分子和分母系数:
|
||||
|
||||
**示例 1:一阶系统**
|
||||
```
|
||||
分子: 1
|
||||
分母: 1,1
|
||||
传递函数: G(s) = 1/(s+1)
|
||||
# 运行容器
|
||||
docker run -p 7860:7860 \
|
||||
-e API_KEY="your-api-key" \
|
||||
autocontrol-course
|
||||
```
|
||||
|
||||
**示例 2:二阶系统**
|
||||
---
|
||||
|
||||
## 项目结构
|
||||
|
||||
```
|
||||
分子: 4
|
||||
分母: 1,2,4
|
||||
传递函数: G(s) = 4/(s²+2s+4)
|
||||
AutoControlCourse/
|
||||
├── app.py # Gradio 主入口,事件绑定与界面布局
|
||||
├── ui_components.py # 各功能标签页的 UI 组件定义
|
||||
├── analysis_functions.py # 时域/频域/根轨迹分析核心计算函数
|
||||
├── case_demo_functions.py # 算例演示模块(混动模型四阶段仿真)
|
||||
├── chatbot.py # AI 智能问答(DeepSeek API 集成)
|
||||
├── user_stats.py # 在线人数统计与数据持久化
|
||||
├── config.py # 全局配置(API密钥、服务器端口等)
|
||||
├── requirements.txt # Python 依赖列表
|
||||
│
|
||||
├── Model/ # 混动模型核心代码
|
||||
│ ├── src/
|
||||
│ │ ├── lightweight_model.py # NN代理模型(MLP,用于替代GPR)
|
||||
│ │ ├── engine_gpr_class.py # GPR高斯过程回归模型
|
||||
│ │ ├── distill_gpr_to_nn.py # 知识蒸馏脚本(GPR→NN)
|
||||
│ │ ├── engine_dynamic_sim.py # 涡轴发动机动态仿真
|
||||
│ │ ├── motor_sim.py # PMSM永磁同步电机仿真
|
||||
│ │ ├── battery_sim.py # 电池等效电路仿真
|
||||
│ │ ├── mpc_controller.py # MPC模型预测控制器
|
||||
│ │ ├── increPID.py # 增量式PID控制器
|
||||
│ │ └── series_hybrid_sim.py # 串联混动系统总成
|
||||
│ └── data/
|
||||
│ ├── Cleaned_Engine_Data_Full.csv # 发动机标定数据
|
||||
│ ├── engine_gpr_model.pth # GPR模型权重
|
||||
│ └── engine_nn_proxy.pth # NN代理模型权重
|
||||
│
|
||||
└── assets/ # 静态资源
|
||||
├── styles.css # 自定义CSS样式
|
||||
└── knowledge_cards_html.py # 各模块知识卡片HTML内容
|
||||
```
|
||||
|
||||
**示例 3:三阶系统**
|
||||
```
|
||||
分子: 1
|
||||
分母: 1,6,11,6
|
||||
传递函数: G(s) = 1/(s³+6s²+11s+6)
|
||||
---
|
||||
|
||||
## 技术栈
|
||||
|
||||
### 前端框架
|
||||
- **Gradio 4.44.1**:快速构建机器学习 Web 界面的 Python 库
|
||||
- **Custom CSS**:现代化样式定制,支持响应式布局
|
||||
|
||||
### 核心计算库
|
||||
| 库名 | 版本 | 用途 |
|
||||
|------|------|------|
|
||||
| NumPy | 1.26.4 | 数值计算基础库 |
|
||||
| python-control | 0.9.4 | 控制系统分析工具箱 |
|
||||
| Matplotlib | 3.9.4 | 图表绑制 |
|
||||
| PyTorch | 2.4.1 | 神经网络推理(CPU模式) |
|
||||
|
||||
### AI 集成
|
||||
| 库名 | 用途 |
|
||||
|------|------|
|
||||
| aiohttp | 异步HTTP请求,流式响应 |
|
||||
| DeepSeek API | AI问答后端服务 |
|
||||
|
||||
### 其他依赖
|
||||
| 库名 | 用途 |
|
||||
|------|------|
|
||||
| pandas | 数据处理(发动机CSV数据读取) |
|
||||
| scikit-learn | 数据归一化预处理 |
|
||||
| psutil | 系统资源监控(CPU/内存/显存) |
|
||||
|
||||
---
|
||||
|
||||
## 算例演示模块详解
|
||||
|
||||
### 阶段零:模型训练
|
||||
|
||||
**GPR 模型训练/加载:**
|
||||
|
||||
高斯过程回归是一种非参数概率模型,适合小样本、高维插值。
|
||||
|
||||
```python
|
||||
# 运行模式
|
||||
mode = "load" # 加载已有模型(推荐)
|
||||
mode = "train" # 从头训练(需要 botorch/gpytorch)
|
||||
```
|
||||
|
||||
**输入格式**:
|
||||
- 系数从最高次项到常数项
|
||||
- 用逗号分隔(支持中文或英文逗号)
|
||||
- 支持小数和负数
|
||||
- 例如:`1, 2.5, -3, 4` 表示 s³ + 2.5s² - 3s + 4
|
||||
**NN 模型训练(知识蒸馏):**
|
||||
|
||||
### 调节系统增益
|
||||
将 GPR 模型的知识蒸馏到轻量级 MLP 中,用于实时控制仿真。
|
||||
|
||||
频域分析和根轨迹分析都支持增益调节:
|
||||
关键参数:
|
||||
- **训练轮数 (Epochs)**:越多越精确,推荐 3000
|
||||
- **学习率 (LR)**:推荐 1e-3 ~ 5e-3
|
||||
- **隐藏层宽度**:推荐 64(平衡精度与速度)
|
||||
|
||||
- **对数滑块**:log₁₀(K) 范围 -1 到 3
|
||||
- -1 对应 K = 0.1
|
||||
- 0 对应 K = 1
|
||||
- 1 对应 K = 10
|
||||
- 2 对应 K = 100
|
||||
- 3 对应 K = 1000
|
||||
### 阶段一:发动机控制器设计
|
||||
|
||||
- **实时显示**:下方数字框显示实际增益值
|
||||
- **松开更新**:滑块松开后才更新图表,避免卡顿
|
||||
**PID 控制参数:**
|
||||
- **Kp(比例增益)**:增大可加快响应,但过大导致振荡
|
||||
- **Ki(积分增益)**:消除稳态误差,过大导致超调
|
||||
- **Kd(微分增益)**:抑制振荡,改善动态特性
|
||||
|
||||
### AI 问答技巧
|
||||
**MPC 控制参数:**
|
||||
- **预测时域 (Horizon)**:前看步数,越长越激进
|
||||
- **功率跟踪权重 W_power**:越高则功率跟踪越紧
|
||||
- **控制增量权重 W_dcost**:越高则控制变化越平缓
|
||||
- **超调限制**:5% 硬约束
|
||||
|
||||
**高效提问方式**:
|
||||
### 阶段二:电机控制器设计
|
||||
|
||||
✅ **好的问题**:
|
||||
- "请解释 PID 控制器的三个参数如何影响系统性能?"
|
||||
- "如何根据 Bode 图判断系统的稳定裕度?"
|
||||
- "为什么阻尼比为 0.707 时系统响应最佳?"
|
||||
- "推导二阶系统的超调量公式"
|
||||
**仿真设置:**
|
||||
- 仿真时长:5~60秒可调
|
||||
- 仿真步长:0.02s / 0.05s / 0.1s
|
||||
- 目标转速:500~5000 RPM
|
||||
- 负载转矩:10~400 Nm
|
||||
|
||||
❌ **避免的问题**:
|
||||
- "帮我做作业"(太模糊)
|
||||
- "这个对吗?"(缺少上下文)
|
||||
- "答案是什么?"(没有提供问题描述)
|
||||
**负载扰动测试:**
|
||||
在仿真60%时刻自动施加150%负载扰动,检验控制器抗扰能力。
|
||||
|
||||
**公式显示**:
|
||||
AI 回复中的数学公式会自动渲染,支持以下格式:
|
||||
- 行内公式:`$公式$` 或 `\(公式\)`
|
||||
- 块级公式:`$$公式$$` 或 `\[公式\]`
|
||||
### 阶段三:能量管理策略设计
|
||||
|
||||
## 🎨 界面特色
|
||||
**SOC 滞环控制参数:**
|
||||
|
||||
| 参数 | 含义 | 推荐值 |
|
||||
|------|------|--------|
|
||||
| SOC目标值 | 功率跟随模式下的补偿基准 | 60% |
|
||||
| SOC下限阈值 | 低于此值进入充电模式 | 30% |
|
||||
| SOC上限阈值 | 高于此值退出充电模式 | 70% |
|
||||
|
||||
**功率规则参数:**
|
||||
|
||||
| 参数 | 含义 | 推荐值 |
|
||||
|------|------|--------|
|
||||
| 发动机最小功率 | 最低运转功率 | 20 kW |
|
||||
| 发动机最大功率 | 峰值输出功率 | 300 kW |
|
||||
| 充电模式功率 | 充电时发动机输出 | 200 kW |
|
||||
| SOC补偿增益 | SOC偏差修正力度 | 50 kW/ΔSOC |
|
||||
|
||||
---
|
||||
|
||||
## 界面特色
|
||||
|
||||
### 现代化设计
|
||||
|
||||
- **渐变色标题**:紫色渐变视觉效果
|
||||
- **卡片式布局**:分组清晰,层次分明
|
||||
- **可滚动知识卡片**:长文档不占据过多空间
|
||||
- **可折叠章节**:按需展开知识点
|
||||
- **可滚动知识卡片**:长文档不占用过多屏幕空间
|
||||
- **可折叠章节**:按需展开,节省视线
|
||||
|
||||
### 响应式交互
|
||||
|
||||
@@ -220,63 +524,15 @@ AI 回复中的数学公式会自动渲染,支持以下格式:
|
||||
- **嵌入式公式**:页面内直接显示 LaTeX 公式
|
||||
- **表格对比**:性能指标、稳定准则表格化
|
||||
- **颜色编码**:稳定/不稳定用绿/红色标识
|
||||
- **图标辅助**:emoji 增强视觉识别
|
||||
- **图标辅助**:Emoji 增强视觉识别
|
||||
|
||||
## 🛠️ 技术栈
|
||||
---
|
||||
|
||||
### 前端框架
|
||||
- **Gradio 4.x**:快速构建机器学习 Web 界面
|
||||
- **Custom CSS**:现代化样式定制
|
||||
|
||||
### 计算库
|
||||
- **NumPy**:数值计算
|
||||
- **python-control**:控制系统分析
|
||||
- **Matplotlib**:图表绘制
|
||||
|
||||
### AI 集成
|
||||
- **aiohttp**:异步 HTTP 请求
|
||||
- **DeepSeek API**:智能问答后端
|
||||
- **流式响应**:提升用户体验
|
||||
|
||||
## 📁 项目结构
|
||||
|
||||
```
|
||||
AutoControl/
|
||||
├── app.py # 主应用程序
|
||||
├── README.md # 项目文档
|
||||
├── API_CONFIG.md # API 配置详细说明(可选)
|
||||
├── QUICK_START.md # 快速入门指南(可选)
|
||||
└── requirements.txt # 依赖列表(可选)
|
||||
```
|
||||
|
||||
## 🔧 高级配置
|
||||
|
||||
### 切换到 Gemini API
|
||||
|
||||
如果您想使用 Google Gemini API:
|
||||
|
||||
```python
|
||||
API_KEY = "your-gemini-api-key"
|
||||
API_BASE_URL = "https://generativelanguage.googleapis.com/v1beta"
|
||||
API_MODEL = "gemini-1.5-flash"
|
||||
API_TYPE = "gemini"
|
||||
```
|
||||
|
||||
### 自定义系统提示词
|
||||
|
||||
修改 `chat_with_ai` 函数中的 `system_prompt`:
|
||||
|
||||
```python
|
||||
system_prompt = """
|
||||
你是一位[角色定义]。
|
||||
请用[语言风格]来回答有关[领域]的问题。
|
||||
[其他要求...]
|
||||
"""
|
||||
```
|
||||
## 高级配置
|
||||
|
||||
### 调整图表样式
|
||||
|
||||
在 `matplotlib` 绘图代码中修改:
|
||||
在 `analysis_functions.py` 中的 matplotlib 绑图代码里修改:
|
||||
|
||||
```python
|
||||
# 修改图表大小
|
||||
@@ -289,48 +545,156 @@ ax.plot(x, y, color='#667eea', linewidth=2)
|
||||
ax.grid(True, alpha=0.3, linestyle='--')
|
||||
```
|
||||
|
||||
## 📚 参考资料
|
||||
### 自定义系统提示词
|
||||
|
||||
修改 `chatbot.py` 中的 `system_prompt`:
|
||||
|
||||
```python
|
||||
system_prompt = """
|
||||
你是一位精通自动控制原理的专家教授。
|
||||
请用清晰、准确、专业的中文来回答问题。
|
||||
重要规则:
|
||||
1. 当需要表达数学公式时,必须使用 LaTeX 格式
|
||||
2. 行内公式使用 $公式$ 或 \\(公式\\)
|
||||
3. 独立公式使用 $$公式$$ 或 \\[公式\\]
|
||||
"""
|
||||
```
|
||||
|
||||
### 自定义工况模板
|
||||
|
||||
修改 `case_demo_functions.py` 中的 `_profile_points` 函数:
|
||||
|
||||
```python
|
||||
def _profile_points(profile_name):
|
||||
if profile_name == "我的自定义工况":
|
||||
return [
|
||||
(0., 1500., 50.), # (时间, 目标转速, 负载转矩)
|
||||
(10., 3000., 200.),
|
||||
(30., 2800., 150.),
|
||||
(50., 1800., 60.)
|
||||
]
|
||||
# ... 其他工况
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 常见问题
|
||||
|
||||
### Q1: 运行时提示 "psutil 未安装"
|
||||
|
||||
不影响主要功能,仅系统资源监控不可用。忽略此提示或执行:
|
||||
|
||||
```bash
|
||||
pip install psutil
|
||||
```
|
||||
|
||||
### Q2: 算例演示提示 "engine_nn_proxy.pth not found"
|
||||
|
||||
需要先完成**阶段零**的 NN 模型训练(约2~5分钟)。
|
||||
|
||||
### Q3: GPR 训练失败,提示缺少 botorch/gpytorch
|
||||
|
||||
GPR 训练需要额外依赖。安装方法:
|
||||
|
||||
```bash
|
||||
pip install botorch gpytorch scikit-learn
|
||||
```
|
||||
|
||||
或直接选择 "load" 模式加载已有模型。
|
||||
|
||||
### Q4: AI 问答返回 "API_KEY 未配置"
|
||||
|
||||
请在 `config.py` 中填入有效的 DeepSeek API 密钥。
|
||||
|
||||
### Q5: 图表显示中文乱码
|
||||
|
||||
本平台图表使用英文标签以避免中文显示问题。如需修改,编辑 `analysis_functions.py` 中的 `plt.title()`、`plt.xlabel()` 等。
|
||||
|
||||
---
|
||||
|
||||
## 参考资料
|
||||
|
||||
### 经典教材
|
||||
- 《自动控制原理》- 胡寿松
|
||||
- 《现代控制工程》- Katsuhiko Ogata
|
||||
- 《反馈控制理论》- John Doyle
|
||||
|
||||
1. 胡寿松.《自动控制原理》(第七版). 科学出版社, 2019.
|
||||
2. Katsuhiko Ogata. *Modern Control Engineering* (5th Edition). Prentice Hall, 2010.
|
||||
3. Richard C. Dorf, Robert H. Bishop. *Modern Control Systems* (14th Edition). Pearson, 2021.
|
||||
4. John Doyle, Bruce Francis, Allen Tannenbaum. *Feedback Control Theory*. Macmillan, 1992.
|
||||
|
||||
### 在线资源
|
||||
|
||||
- [python-control 官方文档](https://python-control.readthedocs.io/)
|
||||
- [DeepSeek API 文档](https://platform.deepseek.com/docs)
|
||||
- [Gradio 官方文档](https://www.gradio.app/docs)
|
||||
- [Gradio 官方文档](https://gradio.app/docs)
|
||||
- [PyTorch 文档](https://pytorch.org/docs/)
|
||||
|
||||
## 🤝 贡献指南
|
||||
---
|
||||
|
||||
## 贡献指南
|
||||
|
||||
欢迎提交 Issue 和 Pull Request!
|
||||
|
||||
### 贡献方向
|
||||
|
||||
- 🐛 修复 Bug
|
||||
- ✨ 添加新功能(如状态空间分析)
|
||||
- ✨ 添加新功能(如状态空间分析模块)
|
||||
- 📝 改进文档
|
||||
- 🎨 优化界面设计
|
||||
- 🧪 添加测试用例
|
||||
|
||||
## 📄 许可证
|
||||
### 开发环境设置
|
||||
|
||||
```bash
|
||||
# 克隆仓库
|
||||
git clone <your-repo-url>
|
||||
cd AutoControlCourse
|
||||
|
||||
# 创建开发分支
|
||||
git checkout -b feature/your-feature-name
|
||||
|
||||
# 安装开发依赖
|
||||
pip install -r requirements.txt
|
||||
pip install pytest black flake8
|
||||
|
||||
# 代码格式化
|
||||
black .
|
||||
|
||||
# 运行测试
|
||||
pytest
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 更新日志
|
||||
|
||||
详细更新日志请参阅 [CHANGELOG.md](CHANGELOG.md)。
|
||||
|
||||
---
|
||||
|
||||
## 许可证
|
||||
|
||||
本项目采用 MIT 许可证。详见 [LICENSE](LICENSE) 文件。
|
||||
|
||||
## 🙏 致谢
|
||||
---
|
||||
|
||||
## 致谢
|
||||
|
||||
- **Gradio**:提供优秀的 Web 界面框架
|
||||
- **python-control**:强大的控制系统分析库
|
||||
- **DeepSeek**:高质量的 AI 服务
|
||||
- 所有贡献者和使用者
|
||||
|
||||
## 📞 联系方式
|
||||
---
|
||||
|
||||
- 项目地址:[GitHub Repository URL]
|
||||
- 问题反馈:[Issues URL]
|
||||
- 邮箱:[your-email@example.com]
|
||||
## 联系方式
|
||||
|
||||
- **项目负责人**:魏鹏飞
|
||||
- **电子邮件**:pengfeiwei@nwpu.edu.cn
|
||||
- **机构**:西北工业大学
|
||||
- **项目地址**:https://github.com/your-repo
|
||||
|
||||
---
|
||||
|
||||
**⭐ 如果这个项目对您有帮助,请给它一个 Star!**
|
||||
**⭐ 如果这个项目对您的学习有帮助,请给它一个 Star!**
|
||||
|
||||
最后更新:2025年10月15日
|
||||
最后更新:2026年4月7日
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import os
|
||||
import gradio as gr
|
||||
import time
|
||||
from functools import partial
|
||||
@@ -10,6 +11,8 @@ from analysis_functions import (
|
||||
frequency_domain_analysis,
|
||||
root_locus_analysis
|
||||
)
|
||||
# ===== 算例演示模块函数导入(四阶段设计)=====
|
||||
from case_demo_functions import run_distillation_demo, run_gpr_training, run_engine_design, run_motor_design, run_hybrid_demo
|
||||
from chatbot import chat_with_ai
|
||||
from user_stats import get_online_status_html, update_user_activity
|
||||
from ui_components import (
|
||||
@@ -17,11 +20,102 @@ from ui_components import (
|
||||
create_time_domain_tab,
|
||||
create_frequency_domain_tab,
|
||||
create_root_locus_tab,
|
||||
create_case_demo_tab,
|
||||
create_chatbot_tab
|
||||
)
|
||||
|
||||
|
||||
# ===== 系统资源监控 =====
|
||||
def get_system_monitor_html():
|
||||
"""获取 CPU / 内存 / GPU 使用率的 HTML 小组件"""
|
||||
try:
|
||||
import psutil
|
||||
cpu_pct = psutil.cpu_percent(interval=0)
|
||||
mem = psutil.virtual_memory()
|
||||
mem_pct = mem.percent
|
||||
mem_used_gb = mem.used / (1024 ** 3)
|
||||
mem_total_gb = mem.total / (1024 ** 3)
|
||||
except ImportError:
|
||||
return "<div style='text-align:center;color:#999;font-size:0.8em;'>psutil 未安装,无法监控系统资源</div>"
|
||||
|
||||
# GPU 信息 — 优先用 nvidia-smi(不依赖 PyTorch CUDA 版本),再用 torch.cuda 兜底
|
||||
gpu_html = ""
|
||||
try:
|
||||
import subprocess as _sp
|
||||
_r = _sp.run(
|
||||
['nvidia-smi', '--query-gpu=name,memory.used,memory.total,utilization.gpu',
|
||||
'--format=csv,noheader,nounits'],
|
||||
capture_output=True, text=True, timeout=3
|
||||
)
|
||||
if _r.returncode == 0 and _r.stdout.strip():
|
||||
_parts = [p.strip() for p in _r.stdout.strip().split('\n')[0].split(',')]
|
||||
_gpu_mem_used = float(_parts[1]) / 1024 # MiB → GiB
|
||||
_gpu_mem_total = float(_parts[2]) / 1024
|
||||
_gpu_util = float(_parts[3])
|
||||
_gc = '#ff6b6b' if _gpu_util > 80 else '#ffd93d' if _gpu_util > 50 else '#6bcb77'
|
||||
gpu_html = (
|
||||
f"<div style='display:inline-flex;align-items:center;gap:6px;'>"
|
||||
f"<span>🎮 GPU</span>"
|
||||
f"<div style='width:90px;height:8px;background:#444;border-radius:4px;overflow:hidden;'>"
|
||||
f"<div style='width:{min(_gpu_util, 100):.0f}%;height:100%;background:{_gc};'></div>"
|
||||
f"</div>"
|
||||
f"<span>{_gpu_util:.0f}% {_gpu_mem_used:.1f}/{_gpu_mem_total:.0f} GB</span>"
|
||||
f"</div>"
|
||||
)
|
||||
else:
|
||||
raise RuntimeError("nvidia-smi no output")
|
||||
except Exception:
|
||||
try:
|
||||
import torch as _torch
|
||||
if _torch.cuda.is_available():
|
||||
_mem_alloc = _torch.cuda.memory_allocated(0) / (1024 ** 3)
|
||||
_mem_total = _torch.cuda.get_device_properties(0).total_memory / (1024 ** 3)
|
||||
_util = _mem_alloc / max(_mem_total, 0.01) * 100
|
||||
_gc = '#ff6b6b' if _util > 80 else '#ffd93d' if _util > 50 else '#6bcb77'
|
||||
gpu_html = (
|
||||
f"<div style='display:inline-flex;align-items:center;gap:6px;'>"
|
||||
f"<span>🎮 GPU</span>"
|
||||
f"<div style='width:90px;height:8px;background:#444;border-radius:4px;overflow:hidden;'>"
|
||||
f"<div style='width:{min(_util, 100):.0f}%;height:100%;background:{_gc};'></div>"
|
||||
f"</div>"
|
||||
f"<span>{_mem_alloc:.1f}/{_mem_total:.0f} GB</span>"
|
||||
f"</div>"
|
||||
)
|
||||
else:
|
||||
gpu_html = "<div style='display:inline-flex;align-items:center;gap:4px;'><span>🎮 GPU N/A</span></div>"
|
||||
except Exception:
|
||||
gpu_html = "<div style='display:inline-flex;align-items:center;gap:4px;'><span>🎮 GPU N/A</span></div>"
|
||||
|
||||
cpu_color = '#ff6b6b' if cpu_pct > 80 else '#ffd93d' if cpu_pct > 50 else '#6bcb77'
|
||||
mem_color = '#ff6b6b' if mem_pct > 80 else '#ffd93d' if mem_pct > 50 else '#6bcb77'
|
||||
|
||||
html = (
|
||||
f"<div style='display:flex;justify-content:center;gap:20px;flex-wrap:wrap;"
|
||||
f"font-size:0.82em;color:#ddd;padding:4px 10px;'>"
|
||||
# CPU
|
||||
f"<div style='display:inline-flex;align-items:center;gap:6px;'>"
|
||||
f"<span>🖥️ CPU</span>"
|
||||
f"<div style='width:90px;height:8px;background:#444;border-radius:4px;overflow:hidden;'>"
|
||||
f"<div style='width:{min(cpu_pct, 100):.0f}%;height:100%;background:{cpu_color};'></div>"
|
||||
f"</div>"
|
||||
f"<span>{cpu_pct:.0f}%</span>"
|
||||
f"</div>"
|
||||
# Memory
|
||||
f"<div style='display:inline-flex;align-items:center;gap:6px;'>"
|
||||
f"<span>💾 RAM</span>"
|
||||
f"<div style='width:90px;height:8px;background:#444;border-radius:4px;overflow:hidden;'>"
|
||||
f"<div style='width:{min(mem_pct, 100):.0f}%;height:100%;background:{mem_color};'></div>"
|
||||
f"</div>"
|
||||
f"<span>{mem_used_gb:.1f}/{mem_total_gb:.0f} GB ({mem_pct:.0f}%)</span>"
|
||||
f"</div>"
|
||||
# GPU
|
||||
f"{gpu_html}"
|
||||
f"</div>"
|
||||
)
|
||||
return html
|
||||
|
||||
# 加载外部CSS文件
|
||||
with open("assets/styles.css", "r", encoding="utf-8") as f:
|
||||
with open(os.path.join(os.path.dirname(__file__), "assets", "styles.css"), "r", encoding="utf-8") as f:
|
||||
custom_css = f.read()
|
||||
|
||||
# --- 主应用界面 ---
|
||||
@@ -33,23 +127,8 @@ with gr.Blocks(title="自动控制理论学习网站 - AI+数智平台", css=cus
|
||||
# 创建头部信息和在线计数器
|
||||
online_counter = create_header()
|
||||
|
||||
# 创建共享的输入组件
|
||||
with gr.Row():
|
||||
with gr.Column(scale=1):
|
||||
with gr.Group():
|
||||
gr.HTML("<div class='card-title'>📊 通用系统参数</div>")
|
||||
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="💡 分母阶数通常高于或等于分子阶数"
|
||||
)
|
||||
# 系统资源监控(始终可见)
|
||||
system_monitor = gr.HTML(value=get_system_monitor_html, elem_id="system-monitor")
|
||||
|
||||
# 创建功能选项卡
|
||||
with gr.Tabs() as tabs:
|
||||
@@ -59,7 +138,10 @@ with gr.Blocks(title="自动控制理论学习网站 - AI+数智平台", css=cus
|
||||
freq_domain_ui = create_frequency_domain_tab()
|
||||
with gr.TabItem("🎯 根轨迹 (Root Locus)", id=2):
|
||||
root_locus_ui = create_root_locus_tab()
|
||||
with gr.TabItem("🤖 智能问答 (Q&A)", id=3):
|
||||
# ===== 新增:算例演示 Tab(位于根轨迹与智能问答之间) =====
|
||||
with gr.TabItem("🧪 算例演示 (Case Demo)", id=3):
|
||||
case_demo_ui = create_case_demo_tab()
|
||||
with gr.TabItem("🤖 智能问答 (Q&A)", id=4):
|
||||
chatbot_ui = create_chatbot_tab()
|
||||
|
||||
# 2. 绑定事件逻辑
|
||||
@@ -74,13 +156,13 @@ with gr.Blocks(title="自动控制理论学习网站 - AI+数智平台", css=cus
|
||||
# --- 时域分析事件 ---
|
||||
time_domain_ui["confirm_button"].click(
|
||||
fn=display_transfer_function,
|
||||
inputs=[num_input, den_input],
|
||||
inputs=[time_domain_ui["num_input"], time_domain_ui["den_input"]],
|
||||
outputs=[time_domain_ui["tf_display"]]
|
||||
).then(lambda: get_online_status_html(), outputs=online_counter)
|
||||
|
||||
time_domain_ui["analyze_button"].click(
|
||||
fn=time_domain_analysis,
|
||||
inputs=[num_input, den_input],
|
||||
inputs=[time_domain_ui["num_input"], time_domain_ui["den_input"]],
|
||||
outputs=[time_domain_ui["output_plot"], time_domain_ui["output_metrics"]]
|
||||
).then(lambda: get_online_status_html(), outputs=online_counter)
|
||||
|
||||
@@ -90,7 +172,7 @@ with gr.Blocks(title="自动控制理论学习网站 - AI+数智平台", css=cus
|
||||
fig, metrics, tf_latex, stability = frequency_domain_analysis(num, den, k)
|
||||
return fig, metrics, tf_latex, stability, k, get_online_status_html()
|
||||
|
||||
freq_inputs = [num_input, den_input, freq_domain_ui["log_k_slider"]]
|
||||
freq_inputs = [freq_domain_ui["num_input"], freq_domain_ui["den_input"], freq_domain_ui["log_k_slider"]]
|
||||
freq_outputs = [
|
||||
freq_domain_ui["plot_output"],
|
||||
freq_domain_ui["metrics_display"],
|
||||
@@ -110,7 +192,7 @@ with gr.Blocks(title="自动控制理论学习网站 - AI+数智平台", css=cus
|
||||
fig, poles, k_val = root_locus_analysis(num, den, log_k)
|
||||
return fig, poles, k_val, get_online_status_html()
|
||||
|
||||
rl_inputs = [root_locus_ui["log_k_slider"], num_input, den_input]
|
||||
rl_inputs = [root_locus_ui["log_k_slider"], root_locus_ui["num_input"], root_locus_ui["den_input"]]
|
||||
rl_outputs = [
|
||||
root_locus_ui["plot_output"],
|
||||
root_locus_ui["poles_display"],
|
||||
@@ -123,26 +205,172 @@ with gr.Blocks(title="自动控制理论学习网站 - AI+数智平台", css=cus
|
||||
outputs=rl_outputs
|
||||
)
|
||||
|
||||
# 当输入框变化时,也更新频域和根轨迹(如果它们是当前可见的)
|
||||
def update_all_on_tf_change(num, den, log_k_freq, log_k_rl):
|
||||
# 更新频域
|
||||
k_freq = 10**log_k_freq
|
||||
fig_freq, metrics, tf_latex, stability = frequency_domain_analysis(num, den, k_freq)
|
||||
# 频域:当传递函数输入框变化时自动更新
|
||||
freq_domain_ui["num_input"].change(
|
||||
fn=update_frequency_analysis_wrapper,
|
||||
inputs=freq_inputs, outputs=freq_outputs
|
||||
)
|
||||
freq_domain_ui["den_input"].change(
|
||||
fn=update_frequency_analysis_wrapper,
|
||||
inputs=freq_inputs, outputs=freq_outputs
|
||||
)
|
||||
|
||||
# 更新根轨迹
|
||||
fig_rl, poles, k_val_rl = root_locus_analysis(num, den, log_k_rl)
|
||||
# 根轨迹:当传递函数输入框变化时自动更新
|
||||
root_locus_ui["num_input"].change(
|
||||
fn=update_rl_view_wrapper,
|
||||
inputs=rl_inputs, outputs=rl_outputs
|
||||
)
|
||||
root_locus_ui["den_input"].change(
|
||||
fn=update_rl_view_wrapper,
|
||||
inputs=rl_inputs, outputs=rl_outputs
|
||||
)
|
||||
|
||||
return (
|
||||
fig_freq, metrics, tf_latex, stability, k_freq,
|
||||
fig_rl, poles, k_val_rl,
|
||||
get_online_status_html()
|
||||
# ===== 算例演示事件绑定(四阶段)=====
|
||||
|
||||
# --- 阶段零-A:GPR 模型训练 ---
|
||||
def run_gpr_wrapper(mode, sid, progress=gr.Progress(track_tqdm=True)):
|
||||
update_user_activity(sid)
|
||||
fig, summary = run_gpr_training(mode=mode, progress=progress)
|
||||
return fig, summary, get_online_status_html()
|
||||
|
||||
case_demo_ui["gpr_run_button"].click(
|
||||
fn=run_gpr_wrapper,
|
||||
inputs=[case_demo_ui["gpr_mode"], session_id],
|
||||
outputs=[case_demo_ui["gpr_plot"], case_demo_ui["gpr_summary"], online_counter]
|
||||
)
|
||||
|
||||
# --- 阶段零-B:NN 模型训练(蒸馏)---
|
||||
def run_distillation_wrapper(epochs, lr, hidden, sid, progress=gr.Progress(track_tqdm=True)):
|
||||
update_user_activity(sid)
|
||||
fig, summary = run_distillation_demo(epochs, lr, hidden, progress=progress)
|
||||
return fig, summary, get_online_status_html()
|
||||
|
||||
case_demo_ui["distill_run_button"].click(
|
||||
fn=run_distillation_wrapper,
|
||||
inputs=[
|
||||
case_demo_ui["distill_epochs"], case_demo_ui["distill_lr"],
|
||||
case_demo_ui["distill_hidden"],
|
||||
session_id
|
||||
],
|
||||
outputs=[case_demo_ui["distill_plot"], case_demo_ui["distill_summary"], online_counter]
|
||||
)
|
||||
|
||||
# --- 阶段一:发动机控制器设计 ---
|
||||
def run_engine_design_wrapper(sim_time, dt, init_power, target_power,
|
||||
controller_type,
|
||||
kp, ki, kd, tau_fuel, K_inertia,
|
||||
mpc_horizon, mpc_W_power, mpc_W_dcost, mpc_overshoot,
|
||||
sid, progress=gr.Progress(track_tqdm=True)):
|
||||
update_user_activity(sid)
|
||||
fig, summary = run_engine_design(
|
||||
sim_time, dt, init_power, target_power,
|
||||
controller_type,
|
||||
kp, ki, kd, tau_fuel, K_inertia,
|
||||
mpc_horizon, mpc_W_power, mpc_W_dcost, mpc_overshoot / 100.0,
|
||||
progress=progress
|
||||
)
|
||||
return fig, summary, get_online_status_html()
|
||||
|
||||
tf_change_inputs = [num_input, den_input, freq_domain_ui["log_k_slider"], root_locus_ui["log_k_slider"]]
|
||||
tf_change_outputs = freq_outputs[:-1] + rl_outputs[:-1] + [online_counter]
|
||||
case_demo_ui["eng_run_button"].click(
|
||||
fn=run_engine_design_wrapper,
|
||||
inputs=[
|
||||
case_demo_ui["eng_sim_time"], case_demo_ui["eng_dt"],
|
||||
case_demo_ui["eng_init_power"], case_demo_ui["eng_target_power"],
|
||||
case_demo_ui["eng_controller_type"],
|
||||
case_demo_ui["eng_kp"], case_demo_ui["eng_ki"], case_demo_ui["eng_kd"],
|
||||
case_demo_ui["eng_tau_fuel"], case_demo_ui["eng_K_inertia"],
|
||||
case_demo_ui["eng_mpc_horizon"], case_demo_ui["eng_mpc_W_power"],
|
||||
case_demo_ui["eng_mpc_W_dcost"], case_demo_ui["eng_mpc_overshoot"],
|
||||
session_id
|
||||
],
|
||||
outputs=[case_demo_ui["eng_plot"], case_demo_ui["eng_summary"], online_counter]
|
||||
)
|
||||
|
||||
num_input.change(fn=update_all_on_tf_change, inputs=tf_change_inputs, outputs=tf_change_outputs)
|
||||
den_input.change(fn=update_all_on_tf_change, inputs=tf_change_inputs, outputs=tf_change_outputs)
|
||||
# --- 阶段二:电机控制器设计 ---
|
||||
def run_motor_design_wrapper(sim_time, dt, target_rpm, load_torque,
|
||||
controller_type,
|
||||
kp, ki, kd, J,
|
||||
mpc_W_speed, mpc_W_dcost, mpc_overshoot,
|
||||
sid, progress=gr.Progress(track_tqdm=True)):
|
||||
update_user_activity(sid)
|
||||
fig, summary = run_motor_design(
|
||||
sim_time, dt, target_rpm, load_torque,
|
||||
controller_type,
|
||||
kp, ki, kd, J,
|
||||
mpc_W_speed, mpc_W_dcost, mpc_overshoot / 100.0,
|
||||
progress=progress
|
||||
)
|
||||
return fig, summary, get_online_status_html()
|
||||
|
||||
case_demo_ui["mot_run_button"].click(
|
||||
fn=run_motor_design_wrapper,
|
||||
inputs=[
|
||||
case_demo_ui["mot_sim_time"], case_demo_ui["mot_dt"],
|
||||
case_demo_ui["mot_target_rpm"], case_demo_ui["mot_load_torque"],
|
||||
case_demo_ui["mot_controller_type"],
|
||||
case_demo_ui["mot_kp"], case_demo_ui["mot_ki"], case_demo_ui["mot_kd"],
|
||||
case_demo_ui["mot_J"],
|
||||
case_demo_ui["mot_mpc_W_speed"], case_demo_ui["mot_mpc_W_dcost"],
|
||||
case_demo_ui["mot_mpc_overshoot"],
|
||||
session_id
|
||||
],
|
||||
outputs=[case_demo_ui["mot_plot"], case_demo_ui["mot_summary"], online_counter]
|
||||
)
|
||||
|
||||
# --- 阶段三:能量管理策略设计(自动引用前两阶段控制器参数)---
|
||||
def run_hybrid_demo_wrapper(sim_time, dt, initial_soc, initial_engine_power,
|
||||
profile,
|
||||
eng_ctrl_type, eng_kp, eng_ki, eng_kd,
|
||||
eng_mpc_horizon, eng_mpc_W_power, eng_mpc_W_dcost, eng_mpc_overshoot,
|
||||
mot_ctrl_type, mot_kp, mot_ki, mot_kd, mot_J,
|
||||
mot_mpc_W_speed, mot_mpc_W_dcost, mot_mpc_overshoot,
|
||||
soc_target, soc_low, soc_high,
|
||||
p_eng_min, p_eng_max, p_charge, k_soc,
|
||||
power_reserve, battery_capacity, sid,
|
||||
progress=gr.Progress(track_tqdm=True)):
|
||||
update_user_activity(sid)
|
||||
fig, summary, table_data = run_hybrid_demo(
|
||||
sim_time, dt, initial_soc, initial_engine_power, profile,
|
||||
eng_ctrl_type, eng_kp, eng_ki, eng_kd,
|
||||
eng_mpc_horizon, eng_mpc_W_power, eng_mpc_W_dcost, eng_mpc_overshoot / 100.0,
|
||||
mot_ctrl_type, mot_kp, mot_ki, mot_kd, mot_J,
|
||||
mot_mpc_W_speed, mot_mpc_W_dcost, mot_mpc_overshoot / 100.0,
|
||||
soc_target, soc_low, soc_high,
|
||||
p_eng_min, p_eng_max, p_charge, k_soc,
|
||||
power_reserve, battery_capacity,
|
||||
progress=progress
|
||||
)
|
||||
return fig, summary, table_data, get_online_status_html()
|
||||
|
||||
case_demo_ui["hybrid_run_button"].click(
|
||||
fn=run_hybrid_demo_wrapper,
|
||||
inputs=[
|
||||
case_demo_ui["sim_time"], case_demo_ui["dt"],
|
||||
case_demo_ui["initial_soc"], case_demo_ui["initial_engine_power"],
|
||||
case_demo_ui["profile"],
|
||||
# 发动机控制器参数
|
||||
case_demo_ui["eng_controller_type"],
|
||||
case_demo_ui["eng_kp"], case_demo_ui["eng_ki"], case_demo_ui["eng_kd"],
|
||||
case_demo_ui["eng_mpc_horizon"], case_demo_ui["eng_mpc_W_power"],
|
||||
case_demo_ui["eng_mpc_W_dcost"], case_demo_ui["eng_mpc_overshoot"],
|
||||
# 电机控制器参数
|
||||
case_demo_ui["mot_controller_type"],
|
||||
case_demo_ui["mot_kp"], case_demo_ui["mot_ki"], case_demo_ui["mot_kd"],
|
||||
case_demo_ui["mot_J"],
|
||||
case_demo_ui["mot_mpc_W_speed"], case_demo_ui["mot_mpc_W_dcost"],
|
||||
case_demo_ui["mot_mpc_overshoot"],
|
||||
# 能量管理策略参数
|
||||
case_demo_ui["soc_target"], case_demo_ui["soc_low"], case_demo_ui["soc_high"],
|
||||
case_demo_ui["p_eng_min"], case_demo_ui["p_eng_max"],
|
||||
case_demo_ui["p_charge"], case_demo_ui["k_soc"],
|
||||
case_demo_ui["power_reserve"], case_demo_ui["battery_capacity"],
|
||||
session_id
|
||||
],
|
||||
outputs=[
|
||||
case_demo_ui["hybrid_plot"], case_demo_ui["hybrid_summary"],
|
||||
case_demo_ui["hybrid_table"], online_counter
|
||||
]
|
||||
)
|
||||
|
||||
# --- 聊天机器人事件 ---
|
||||
async def chat_wrapper(message, history, sid):
|
||||
@@ -174,14 +402,13 @@ with gr.Blocks(title="自动控制理论学习网站 - AI+数智平台", css=cus
|
||||
)
|
||||
|
||||
# --- 页面加载和定时器事件 ---
|
||||
def on_page_load(sid):
|
||||
update_user_activity(sid)
|
||||
return get_online_status_html()
|
||||
|
||||
demo.load(fn=on_page_load, inputs=[session_id], outputs=[online_counter])
|
||||
demo.load(fn=lambda: get_online_status_html(), outputs=[online_counter])
|
||||
|
||||
gr.Timer(10).tick(fn=get_online_status_html, outputs=online_counter)
|
||||
|
||||
# 系统资源监控定时刷新(每 3 秒)
|
||||
gr.Timer(3).tick(fn=get_system_monitor_html, outputs=system_monitor)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
demo.queue().launch(
|
||||
|
||||
+1674
-1
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -16,4 +16,4 @@ API_TYPE = "deepseek" # 当前支持 "deepseek"
|
||||
# ==================== Gradio 应用启动配置 ====================
|
||||
SERVER_NAME = "0.0.0.0" # 监听所有网络接口
|
||||
SERVER_PORT = 7860 # 指定一个端口
|
||||
SHARE = False # 是否创建Gradio的公开分享链接
|
||||
SHARE = True # 是否创建Gradio的公开分享链接
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
[
|
||||
{
|
||||
"name": "常规-起飞巡航",
|
||||
"figure_ok": true,
|
||||
"summary_ok": true,
|
||||
"table_len": 8,
|
||||
"summary_head": "### 算例结果解读",
|
||||
"soc_min": 60.0,
|
||||
"soc_max": 62.05,
|
||||
"first_row": [
|
||||
0.0,
|
||||
1500.0,
|
||||
0.0,
|
||||
50.0,
|
||||
-0.65,
|
||||
60.0
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "高机动-高负载",
|
||||
"figure_ok": true,
|
||||
"summary_ok": true,
|
||||
"table_len": 8,
|
||||
"summary_head": "### 算例结果解读",
|
||||
"soc_min": 55.0,
|
||||
"soc_max": 61.41,
|
||||
"first_row": [
|
||||
0.0,
|
||||
1920.0,
|
||||
0.0,
|
||||
80.0,
|
||||
-30.65,
|
||||
55.0
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "经济巡航-低负载",
|
||||
"figure_ok": true,
|
||||
"summary_ok": true,
|
||||
"table_len": 8,
|
||||
"summary_head": "### 算例结果解读",
|
||||
"soc_min": 70.0,
|
||||
"soc_max": 76.3,
|
||||
"first_row": [
|
||||
0.0,
|
||||
1275.0,
|
||||
0.0,
|
||||
40.0,
|
||||
9.35,
|
||||
70.0
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "边界输入-自动裁剪",
|
||||
"figure_ok": true,
|
||||
"summary_ok": true,
|
||||
"table_len": 8,
|
||||
"summary_head": "### 算例结果解读",
|
||||
"soc_min": 10.0,
|
||||
"soc_max": 26.51,
|
||||
"first_row": [
|
||||
0.0,
|
||||
2400.0,
|
||||
0.0,
|
||||
260.0,
|
||||
-210.65,
|
||||
10.0
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -1,4 +1,4 @@
|
||||
{
|
||||
"total_users": 15,
|
||||
"last_saved_at": 1760890996.5595384
|
||||
"total_users": 37,
|
||||
"last_saved_at": 1775561044.8460488
|
||||
}
|
||||
+22
-5
@@ -1,7 +1,24 @@
|
||||
# requirements.txt
|
||||
|
||||
gradio
|
||||
numpy
|
||||
control
|
||||
matplotlib
|
||||
aiohttp
|
||||
# ===== PyTorch:GPU (CUDA 12.1) 版本,如无 NVIDIA GPU 可改为 cpu =====
|
||||
--extra-index-url https://download.pytorch.org/whl/cu121
|
||||
|
||||
gradio==4.44.1
|
||||
gradio-client==1.3.0
|
||||
pydantic==2.10.6
|
||||
pydantic-core==2.27.2
|
||||
huggingface_hub==0.23.0
|
||||
numpy==1.26.4
|
||||
control==0.9.4
|
||||
matplotlib==3.9.4
|
||||
aiohttp==3.13.5
|
||||
pillow==10.4.0
|
||||
# ===== 新增:混动模型(Model)运行依赖 =====
|
||||
torch==2.4.1+cu121
|
||||
botorch==0.14.0
|
||||
gpytorch==1.14
|
||||
pyro-ppl==1.9.1
|
||||
pandas==2.3.3
|
||||
scipy>=1.10
|
||||
scikit-learn==1.7.1
|
||||
psutil>=5.9
|
||||
|
||||
+336
-2
@@ -1,8 +1,13 @@
|
||||
import gradio as gr
|
||||
import gradio as gr
|
||||
from assets.knowledge_cards_html import (
|
||||
TIME_DOMAIN_KNOWLEDGE,
|
||||
FREQUENCY_DOMAIN_KNOWLEDGE,
|
||||
ROOT_LOCUS_KNOWLEDGE
|
||||
ROOT_LOCUS_KNOWLEDGE,
|
||||
ENGINE_CONTROL_KNOWLEDGE,
|
||||
MOTOR_CONTROL_KNOWLEDGE,
|
||||
GPR_KNOWLEDGE,
|
||||
NN_KNOWLEDGE,
|
||||
EMS_KNOWLEDGE,
|
||||
)
|
||||
|
||||
def create_header():
|
||||
@@ -66,6 +71,20 @@ def create_time_domain_tab():
|
||||
ui_dict = {}
|
||||
with gr.Row():
|
||||
with gr.Column(scale=1):
|
||||
with gr.Group():
|
||||
gr.HTML("<div class='card-title'>📊 传递函数设定</div>")
|
||||
ui_dict["num_input"] = gr.Textbox(
|
||||
label="分子系数 (Numerator)",
|
||||
value="1",
|
||||
placeholder="例如: 1 或 1,2,3",
|
||||
info="💡 用逗号分隔,从最高次项到常数项"
|
||||
)
|
||||
ui_dict["den_input"] = gr.Textbox(
|
||||
label="分母系数 (Denominator)",
|
||||
value="1,6,11,6",
|
||||
placeholder="例如: 1,2,1",
|
||||
info="💡 分母阶数通常 ≥ 分子阶数"
|
||||
)
|
||||
with gr.Group():
|
||||
gr.HTML("<div class='card-title'>🔧 系统模型</div>")
|
||||
ui_dict["tf_display"] = gr.Markdown(label="当前传递函数", elem_classes="output-display")
|
||||
@@ -116,6 +135,20 @@ def create_frequency_domain_tab():
|
||||
ui_dict = {}
|
||||
with gr.Row():
|
||||
with gr.Column(scale=1):
|
||||
with gr.Group():
|
||||
gr.HTML("<div class='card-title'>📊 传递函数设定</div>")
|
||||
ui_dict["num_input"] = gr.Textbox(
|
||||
label="分子系数 (Numerator)",
|
||||
value="1",
|
||||
placeholder="例如: 1 或 1,2,3",
|
||||
info="💡 用逗号分隔,从最高次项到常数项"
|
||||
)
|
||||
ui_dict["den_input"] = gr.Textbox(
|
||||
label="分母系数 (Denominator)",
|
||||
value="1,6,11,6",
|
||||
placeholder="例如: 1,2,1",
|
||||
info="💡 分母阶数通常 ≥ 分子阶数"
|
||||
)
|
||||
with gr.Group():
|
||||
gr.HTML("<div class='card-title'>🎚️ 调整系统增益</div>")
|
||||
ui_dict["log_k_slider"] = gr.Slider(minimum=-4, maximum=4, value=1, step=0.01, label="对数增益 log₁₀(K)", info="💡 拖动滑块查看实时变化")
|
||||
@@ -127,6 +160,8 @@ def create_frequency_domain_tab():
|
||||
gr.HTML("<div class='card-title'>📊 稳定裕度分析</div>")
|
||||
ui_dict["metrics_display"] = gr.Textbox(label="Stability Margins", lines=4, interactive=False, elem_classes="output-metrics")
|
||||
ui_dict["stability_display"] = gr.Markdown(elem_classes="stability-result")
|
||||
with gr.Row():
|
||||
ui_dict["analyze_button"] = gr.Button("🚀 开始分析", variant="primary", scale=1, elem_classes="primary-btn")
|
||||
with gr.Column(scale=2):
|
||||
ui_dict["plot_output"] = gr.Plot(label="频域响应图", elem_classes="plot-container")
|
||||
# 知识卡片
|
||||
@@ -163,6 +198,20 @@ def create_root_locus_tab():
|
||||
ui_dict = {}
|
||||
with gr.Row():
|
||||
with gr.Column(scale=1):
|
||||
with gr.Group():
|
||||
gr.HTML("<div class='card-title'>📊 传递函数设定</div>")
|
||||
ui_dict["num_input"] = gr.Textbox(
|
||||
label="分子系数 (Numerator)",
|
||||
value="1",
|
||||
placeholder="例如: 1 或 1,2,3",
|
||||
info="💡 用逗号分隔,从最高次项到常数项"
|
||||
)
|
||||
ui_dict["den_input"] = gr.Textbox(
|
||||
label="分母系数 (Denominator)",
|
||||
value="1,6,11,6",
|
||||
placeholder="例如: 1,2,1",
|
||||
info="💡 分母阶数通常 ≥ 分子阶数"
|
||||
)
|
||||
with gr.Group():
|
||||
gr.HTML("<div class='card-title'>🎚️ 调整系统增益</div>")
|
||||
ui_dict["log_k_slider"] = gr.Slider(minimum=-4, maximum=4, value=1, step=0.01, label="对数增益 log₁₀(K)", info="💡 拖动滑块观察极点移动")
|
||||
@@ -170,6 +219,8 @@ def create_root_locus_tab():
|
||||
with gr.Group():
|
||||
gr.HTML("<div class='card-title'>📍 闭环极点位置</div>")
|
||||
ui_dict["poles_display"] = gr.Textbox(label="Closed-Loop Pole Locations", lines=6, interactive=False, elem_classes="output-metrics")
|
||||
with gr.Row():
|
||||
ui_dict["analyze_button"] = gr.Button("🚀 开始分析", variant="primary", scale=1, elem_classes="primary-btn")
|
||||
with gr.Column(scale=2):
|
||||
ui_dict["plot_output"] = gr.Plot(label="根轨迹图")
|
||||
gr.HTML(f"""
|
||||
@@ -200,6 +251,288 @@ def create_root_locus_tab():
|
||||
""")
|
||||
return ui_dict
|
||||
|
||||
def create_case_demo_tab():
|
||||
"""创建算例演示选项卡 — 四阶段交互设计(蒸馏→发动机→电机→能量管理)"""
|
||||
ui_dict = {}
|
||||
|
||||
# === MathJax re-render helper (reused across tabs) ===
|
||||
def _mathjax_script(div_id):
|
||||
return f"""
|
||||
<script>
|
||||
(function() {{
|
||||
function renderMath() {{
|
||||
setTimeout(function() {{
|
||||
if (typeof MathJax !== 'undefined' && MathJax.typesetPromise) {{
|
||||
MathJax.typesetPromise([document.getElementById('{div_id}')])
|
||||
.catch(function(err) {{ console.log('MathJax error:', err); }});
|
||||
}} else {{ setTimeout(renderMath, 500); }}
|
||||
}}, 300);
|
||||
}}
|
||||
if (document.readyState === 'loading') {{
|
||||
document.addEventListener('DOMContentLoaded', renderMath);
|
||||
}} else {{ renderMath(); }}
|
||||
}})();
|
||||
</script>"""
|
||||
|
||||
with gr.Tabs():
|
||||
# ========== 阶段零:模型训练(GPR + NN 两个子标签页)==========
|
||||
with gr.TabItem("🧬 模型训练", id="distill_tab"):
|
||||
gr.HTML("""<div style='background:linear-gradient(135deg,#f3e5f5,#e1bee7);padding:10px 16px;
|
||||
border-radius:8px;margin-bottom:10px;font-size:0.92em;color:#6a1b9a;'>
|
||||
<b>阶段零</b>:模型训练包含两步——先训练/验证 GPR 高斯过程代理模型,
|
||||
再将其知识蒸馏为轻量 NN(MLP)用于后续实时控制仿真。</div>""")
|
||||
with gr.Tabs():
|
||||
# ----- 子标签页 A: GPR 模型训练 -----
|
||||
with gr.TabItem("📈 GPR 模型训练", id="gpr_sub_tab"):
|
||||
with gr.Row():
|
||||
with gr.Column(scale=1):
|
||||
with gr.Group():
|
||||
gr.HTML("<div class='card-title'>🔬 GPR 训练设置</div>")
|
||||
ui_dict["gpr_mode"] = gr.Radio(
|
||||
choices=["load", "train"], value="load",
|
||||
label="运行模式",
|
||||
info="load: 加载已有权重 | train: 从头训练(需 botorch)")
|
||||
ui_dict["gpr_run_button"] = gr.Button(
|
||||
"🚀 运行 GPR 训练 / 加载", variant="primary",
|
||||
elem_classes="primary-btn")
|
||||
with gr.Group():
|
||||
gr.HTML("<div class='card-title'>📝 GPR 结果</div>")
|
||||
ui_dict["gpr_summary"] = gr.Markdown()
|
||||
with gr.Column(scale=2):
|
||||
ui_dict["gpr_plot"] = gr.Plot(label="GPR 模型结果")
|
||||
gr.HTML(f"""
|
||||
<div id="gpr-knowledge" style="max-height:600px;overflow-y:auto;padding-right:8px;">
|
||||
{GPR_KNOWLEDGE}
|
||||
</div>
|
||||
{_mathjax_script('gpr-knowledge')}
|
||||
""")
|
||||
|
||||
# ----- 子标签页 B: NN 模型训练 -----
|
||||
with gr.TabItem("🧠 NN 模型训练", id="nn_sub_tab"):
|
||||
with gr.Row():
|
||||
with gr.Column(scale=1):
|
||||
with gr.Group():
|
||||
gr.HTML("<div class='card-title'>🧪 NN 训练参数</div>")
|
||||
ui_dict["distill_epochs"] = gr.Slider(minimum=500, maximum=8000, value=3000, step=100,
|
||||
label="训练轮数 (Epochs)", info="越多越精确,但耗时更长")
|
||||
ui_dict["distill_lr"] = gr.Slider(minimum=1e-4, maximum=1e-2, value=3e-3, step=1e-4,
|
||||
label="学习率 (LR)", info="推荐 1e-3 ~ 5e-3")
|
||||
ui_dict["distill_hidden"] = gr.Slider(minimum=16, maximum=256, value=64, step=16,
|
||||
label="隐藏层宽度", info="MLP每层神经元数")
|
||||
ui_dict["distill_run_button"] = gr.Button("🚀 开始 NN 训练", variant="primary",
|
||||
elem_classes="primary-btn")
|
||||
with gr.Group():
|
||||
gr.HTML("<div class='card-title'>📝 NN 训练结果</div>")
|
||||
ui_dict["distill_summary"] = gr.Markdown()
|
||||
with gr.Column(scale=2):
|
||||
ui_dict["distill_plot"] = gr.Plot(label="NN 训练结果 (Loss + Parity)")
|
||||
gr.HTML(f"""
|
||||
<div id="nn-knowledge" style="max-height:600px;overflow-y:auto;padding-right:8px;">
|
||||
{NN_KNOWLEDGE}
|
||||
</div>
|
||||
{_mathjax_script('nn-knowledge')}
|
||||
""")
|
||||
|
||||
# ========== 阶段一:发动机控制器设计 ==========
|
||||
with gr.TabItem("🔧 发动机控制器设计", id="engine_tab"):
|
||||
gr.HTML("""<div style='background:linear-gradient(135deg,#fff3e0,#ffe0b2);padding:10px 16px;
|
||||
border-radius:8px;margin-bottom:10px;font-size:0.92em;color:#e65100;'>
|
||||
<b>阶段一</b>:选择 PID 或 MPC 控制器,调整参数,运行阶跃响应测试,观察功率跟踪性能。</div>""")
|
||||
with gr.Row():
|
||||
with gr.Column(scale=1):
|
||||
with gr.Group():
|
||||
gr.HTML("<div class='card-title'>🎯 控制器选择</div>")
|
||||
ui_dict["eng_controller_type"] = gr.Radio(
|
||||
choices=["PID", "MPC"], value="PID", label="控制器类型",
|
||||
info="PID: 经典三参数 | MPC: 模型预测控制")
|
||||
with gr.Group(visible=True) as eng_pid_group:
|
||||
gr.HTML("<div class='card-title'>🎛️ PID 参数</div>")
|
||||
ui_dict["eng_kp"] = gr.Slider(minimum=0.1, maximum=20, value=4.652, step=0.01,
|
||||
label="比例增益 Kp", info="增大加快响应,过大导致振荡")
|
||||
ui_dict["eng_ki"] = gr.Slider(minimum=0.0, maximum=20, value=7.078, step=0.01,
|
||||
label="积分增益 Ki", info="消除稳态误差,过大导致超调")
|
||||
ui_dict["eng_kd"] = gr.Slider(minimum=0.0, maximum=5, value=0.222, step=0.001,
|
||||
label="微分增益 Kd", info="抑制振荡,改善动态特性")
|
||||
ui_dict["eng_pid_group"] = eng_pid_group
|
||||
with gr.Group(visible=False) as eng_mpc_group:
|
||||
gr.HTML("<div class='card-title'>🎛️ MPC 参数</div>")
|
||||
ui_dict["eng_mpc_horizon"] = gr.Slider(minimum=3, maximum=30, value=15, step=1,
|
||||
label="预测时域 (Horizon)", info="MPC前看步数")
|
||||
ui_dict["eng_mpc_W_power"] = gr.Slider(minimum=1, maximum=500, value=200, step=1,
|
||||
label="功率跟踪权重 W_power")
|
||||
ui_dict["eng_mpc_W_dcost"] = gr.Slider(minimum=0.01, maximum=20, value=1.5, step=0.01,
|
||||
label="控制增量权重 W_Δcost")
|
||||
ui_dict["eng_mpc_overshoot"] = gr.Slider(minimum=1, maximum=30, value=5, step=1,
|
||||
label="超调限制 (%)")
|
||||
ui_dict["eng_mpc_group"] = eng_mpc_group
|
||||
with gr.Group():
|
||||
gr.HTML("<div class='card-title'>⚙️ 发动机模型参数</div>")
|
||||
ui_dict["eng_tau_fuel"] = gr.Slider(minimum=0.05, maximum=1.0, value=0.15, step=0.01,
|
||||
label="燃油执行机构时间常数 τ (s)")
|
||||
ui_dict["eng_K_inertia"] = gr.Slider(minimum=10, maximum=500, value=100, step=5,
|
||||
label="转子惯性增益 K")
|
||||
with gr.Group():
|
||||
gr.HTML("<div class='card-title'>🧪 仿真设置</div>")
|
||||
ui_dict["eng_sim_time"] = gr.Slider(minimum=5, maximum=60, value=30, step=1,
|
||||
label="仿真时长 (s)")
|
||||
ui_dict["eng_dt"] = gr.Dropdown(choices=[0.02, 0.05, 0.1], value=0.02,
|
||||
label="仿真步长 (s)")
|
||||
ui_dict["eng_init_power"] = gr.Slider(minimum=20, maximum=250, value=100, step=5,
|
||||
label="初始功率 (kW)")
|
||||
ui_dict["eng_target_power"] = gr.Slider(minimum=20, maximum=300, value=200, step=5,
|
||||
label="目标功率 (kW)")
|
||||
ui_dict["eng_run_button"] = gr.Button("🚀 运行发动机仿真", variant="primary",
|
||||
elem_classes="primary-btn")
|
||||
with gr.Group():
|
||||
gr.HTML("<div class='card-title'>📝 设计结果</div>")
|
||||
ui_dict["eng_summary"] = gr.Markdown()
|
||||
with gr.Column(scale=2):
|
||||
ui_dict["eng_plot"] = gr.Plot(label="发动机控制器阶跃响应")
|
||||
gr.HTML(f"""
|
||||
<div id="engine-knowledge" style="max-height:600px;overflow-y:auto;padding-right:8px;">
|
||||
{ENGINE_CONTROL_KNOWLEDGE}
|
||||
</div>
|
||||
{_mathjax_script('engine-knowledge')}
|
||||
""")
|
||||
|
||||
# Radio toggle PID/MPC visibility
|
||||
ui_dict["eng_controller_type"].change(
|
||||
fn=lambda ct: (gr.update(visible=(ct == "PID")), gr.update(visible=(ct == "MPC"))),
|
||||
inputs=[ui_dict["eng_controller_type"]],
|
||||
outputs=[eng_pid_group, eng_mpc_group],
|
||||
)
|
||||
|
||||
# ========== 阶段二:电机控制器设计 ==========
|
||||
with gr.TabItem("⚡ 电机控制器设计", id="motor_tab"):
|
||||
gr.HTML("""<div style='background:linear-gradient(135deg,#e3f2fd,#bbdefb);padding:10px 16px;
|
||||
border-radius:8px;margin-bottom:10px;font-size:0.92em;color:#1565c0;'>
|
||||
<b>阶段二</b>:选择 PID 或 MPC 控制器,运行转速跟踪 + 负载扰动测试。
|
||||
在仿真60%时刻自动施加50%负载扰动,检验抗扰能力。</div>""")
|
||||
with gr.Row():
|
||||
with gr.Column(scale=1):
|
||||
with gr.Group():
|
||||
gr.HTML("<div class='card-title'>🎯 控制器选择</div>")
|
||||
ui_dict["mot_controller_type"] = gr.Radio(
|
||||
choices=["PID", "MPC"], value="PID", label="控制器类型",
|
||||
info="PID: 经典三参数 | MPC: 模型预测控制")
|
||||
with gr.Group(visible=True) as mot_pid_group:
|
||||
gr.HTML("<div class='card-title'>🎛️ PID 参数</div>")
|
||||
ui_dict["mot_kp"] = gr.Slider(minimum=0.1, maximum=50, value=5.0, step=0.1,
|
||||
label="比例增益 Kp", info="增大加快转速响应")
|
||||
ui_dict["mot_ki"] = gr.Slider(minimum=0.0, maximum=100, value=2.0, step=0.1,
|
||||
label="积分增益 Ki", info="消除转速稳态偏差")
|
||||
ui_dict["mot_kd"] = gr.Slider(minimum=0.0, maximum=5, value=0.5, step=0.01,
|
||||
label="微分增益 Kd", info="抑制转速振荡")
|
||||
ui_dict["mot_pid_group"] = mot_pid_group
|
||||
with gr.Group(visible=False) as mot_mpc_group:
|
||||
gr.HTML("<div class='card-title'>🎛️ MPC 参数</div>")
|
||||
ui_dict["mot_mpc_W_speed"] = gr.Slider(minimum=1, maximum=500, value=200, step=1,
|
||||
label="转速跟踪权重 W_speed")
|
||||
ui_dict["mot_mpc_W_dcost"] = gr.Slider(minimum=0.01, maximum=20, value=0.3, step=0.01,
|
||||
label="控制增量权重 W_Δcost")
|
||||
ui_dict["mot_mpc_overshoot"] = gr.Slider(minimum=1, maximum=30, value=5, step=1,
|
||||
label="超调限制 (%)")
|
||||
ui_dict["mot_mpc_group"] = mot_mpc_group
|
||||
with gr.Group():
|
||||
gr.HTML("<div class='card-title'>⚙️ 电机模型参数</div>")
|
||||
ui_dict["mot_J"] = gr.Slider(minimum=0.1, maximum=5.0, value=1.0, step=0.1,
|
||||
label="转动惯量 J (kg·m²)", info="越大响应越慢但越平稳")
|
||||
with gr.Group():
|
||||
gr.HTML("<div class='card-title'>🧪 仿真设置</div>")
|
||||
ui_dict["mot_sim_time"] = gr.Slider(minimum=5, maximum=60, value=30, step=1,
|
||||
label="仿真时长 (s)")
|
||||
ui_dict["mot_dt"] = gr.Dropdown(choices=[0.02, 0.05, 0.1], value=0.02,
|
||||
label="仿真步长 (s)")
|
||||
ui_dict["mot_target_rpm"] = gr.Slider(minimum=500, maximum=5000, value=2000, step=50,
|
||||
label="目标转速 (RPM)")
|
||||
ui_dict["mot_load_torque"] = gr.Slider(minimum=10, maximum=400, value=80, step=5,
|
||||
label="负载转矩 (Nm)")
|
||||
ui_dict["mot_run_button"] = gr.Button("🚀 运行电机仿真", variant="primary",
|
||||
elem_classes="primary-btn")
|
||||
with gr.Group():
|
||||
gr.HTML("<div class='card-title'>📝 设计结果</div>")
|
||||
ui_dict["mot_summary"] = gr.Markdown()
|
||||
with gr.Column(scale=2):
|
||||
ui_dict["mot_plot"] = gr.Plot(label="电机控制器阶跃响应")
|
||||
gr.HTML(f"""
|
||||
<div id="motor-knowledge" style="max-height:600px;overflow-y:auto;padding-right:8px;">
|
||||
{MOTOR_CONTROL_KNOWLEDGE}
|
||||
</div>
|
||||
{_mathjax_script('motor-knowledge')}
|
||||
""")
|
||||
|
||||
# Radio toggle PID/MPC visibility
|
||||
ui_dict["mot_controller_type"].change(
|
||||
fn=lambda ct: (gr.update(visible=(ct == "PID")), gr.update(visible=(ct == "MPC"))),
|
||||
inputs=[ui_dict["mot_controller_type"]],
|
||||
outputs=[mot_pid_group, mot_mpc_group],
|
||||
)
|
||||
|
||||
# ========== 阶段三:能量管理策略设计 ==========
|
||||
with gr.TabItem("🔋 能量管理策略设计", id="ems_tab"):
|
||||
gr.HTML("""<div style='background:linear-gradient(135deg,#e8f5e9,#c8e6c9);padding:10px 16px;
|
||||
border-radius:8px;margin-bottom:10px;font-size:0.92em;color:#2e7d32;'>
|
||||
<b>阶段三</b>:设计基于规则的能量管理策略(自动引用前两阶段的控制器参数)。<br>
|
||||
<b>策略原理</b>:SOC < 下限阈值 → 进入<b>充电模式</b>;
|
||||
SOC > 上限阈值 → 退出充电,进入<b>功率跟随模式</b>。
|
||||
下限~上限之间为<b>滞环区间</b>,防止模式频繁切换。</div>""")
|
||||
with gr.Row():
|
||||
with gr.Column(scale=1):
|
||||
with gr.Group():
|
||||
gr.HTML("<div class='card-title'>📊 SOC规则参数(滞环控制)</div>")
|
||||
ui_dict["soc_target"] = gr.Slider(minimum=30, maximum=80, value=60, step=1,
|
||||
label="SOC目标值 (%)", info="功率跟随模式下的SOC补偿基准")
|
||||
ui_dict["soc_low"] = gr.Slider(minimum=15, maximum=50, value=30, step=1,
|
||||
label="SOC下限阈值 (%)", info="低于此值→进入充电模式")
|
||||
ui_dict["soc_high"] = gr.Slider(minimum=50, maximum=90, value=70, step=1,
|
||||
label="SOC上限阈值 (%)", info="高于此值→退出充电模式")
|
||||
with gr.Group():
|
||||
gr.HTML("<div class='card-title'>⚡ 功率规则参数</div>")
|
||||
ui_dict["p_eng_min"] = gr.Slider(minimum=10, maximum=100, value=20, step=5,
|
||||
label="发动机最小功率 (kW)")
|
||||
ui_dict["p_eng_max"] = gr.Slider(minimum=100, maximum=350, value=300, step=10,
|
||||
label="发动机最大功率 (kW)")
|
||||
ui_dict["p_charge"] = gr.Slider(minimum=50, maximum=300, value=200, step=10,
|
||||
label="充电模式发动机功率 (kW)", info="进入充电模式后发动机固定输出")
|
||||
ui_dict["k_soc"] = gr.Slider(minimum=0, maximum=200, value=50, step=5,
|
||||
label="SOC补偿增益 (kW/ΔSOC)", info="跟随模式下对SOC偏差的修正力度")
|
||||
ui_dict["power_reserve"] = gr.Slider(minimum=0, maximum=50, value=10, step=1,
|
||||
label="动态功率储备 (%)", info="发动机额外预留功率百分比")
|
||||
with gr.Group():
|
||||
gr.HTML("<div class='card-title'>🔧 系统与仿真参数</div>")
|
||||
ui_dict["battery_capacity"] = gr.Slider(minimum=10, maximum=200, value=50, step=5,
|
||||
label="电池容量 (kWh)")
|
||||
ui_dict["initial_soc"] = gr.Slider(minimum=10, maximum=95, value=60, step=1,
|
||||
label="初始SOC (%)")
|
||||
ui_dict["initial_engine_power"] = gr.Slider(minimum=20, maximum=250, value=50, step=5,
|
||||
label="初始发动机功率 (kW)")
|
||||
ui_dict["profile"] = gr.Dropdown(
|
||||
choices=["起飞-巡航-降落", "高机动阶跃", "经济巡航"],
|
||||
value="起飞-巡航-降落", label="工况模板")
|
||||
ui_dict["sim_time"] = gr.Slider(minimum=20, maximum=180, value=60, step=5,
|
||||
label="仿真时长 (s)")
|
||||
ui_dict["dt"] = gr.Dropdown(choices=[0.02, 0.05, 0.1], value=0.02,
|
||||
label="仿真步长 (s)")
|
||||
ui_dict["hybrid_run_button"] = gr.Button("🚀 运行混动系统仿真", variant="primary",
|
||||
size="lg", elem_classes="primary-btn")
|
||||
with gr.Group():
|
||||
gr.HTML("<div class='card-title'>📝 结果摘要</div>")
|
||||
ui_dict["hybrid_summary"] = gr.Markdown()
|
||||
with gr.Column(scale=2):
|
||||
ui_dict["hybrid_plot"] = gr.Plot(label="混动系统响应图")
|
||||
ui_dict["hybrid_table"] = gr.Dataframe(
|
||||
headers=["时间(s)", "目标转速", "实际转速", "发动机功率(kW)",
|
||||
"电池功率(kW)", "SOC(%)", "EMS模式"],
|
||||
label="关键时刻数据", interactive=False
|
||||
)
|
||||
gr.HTML(f"""
|
||||
<div id="ems-knowledge" style="max-height:600px;overflow-y:auto;padding-right:8px;">
|
||||
{EMS_KNOWLEDGE}
|
||||
</div>
|
||||
{_mathjax_script('ems-knowledge')}
|
||||
""")
|
||||
return ui_dict
|
||||
|
||||
def create_chatbot_tab():
|
||||
"""创建AI问答选项卡的UI组件"""
|
||||
ui_dict = {}
|
||||
@@ -229,3 +562,4 @@ def create_chatbot_tab():
|
||||
label="💡 试试这些问题:"
|
||||
)
|
||||
return ui_dict
|
||||
|
||||
|
||||
Reference in New Issue
Block a user