PID 配置改为通过 HTTP API 存取,移除 rosbridge 推送

- 页面初始化时 GET /api/pid/config 加载已保存的配置
- 点击保存通过 POST /api/pid/config 持久化到后端
- 新增「加载配置」按钮支持手动从后端重新拉取
- 移除 PID_CONFIG_TOPIC 及 rosbridge 发布逻辑
This commit is contained in:
2026-06-04 14:17:16 +08:00
parent e71d4fa716
commit 2f2e444978
2 changed files with 81 additions and 18 deletions
-2
View File
@@ -9,8 +9,6 @@ export const MJPEG_MANUAL_URL = 'http://192.168.0.11/stream?topic=/vision/result
// ROS 话题
export const CMD_WHEEL_TOPIC = '/cmd_wheel'
export const CMD_GIMBAL_TOPIC = '/cmd_gimbal'
export const PID_CONFIG_TOPIC = '/pid_config'
// 键盘控制参数
export const MAX_LINEAR = 0.5 // m/s
export const MAX_ANGULAR = 1.0 // rad/s
+81 -16
View File
@@ -44,27 +44,62 @@
<button class="btn-laser" @click="toggleLaser">
激光: {{ laserOn ? 'ON' : 'OFF' }}
</button>
<button class="btn-publish" @click="publishParams">发布参数</button>
<button class="btn-load" :disabled="loading" @click="loadConfig">
{{ loading ? '加载中...' : '加载配置' }}
</button>
<button class="btn-publish" :disabled="saving" @click="saveConfig">
{{ saving ? '保存中...' : '保存配置' }}
</button>
</div>
</div>
</template>
<script setup>
import { reactive, ref } from 'vue'
import { HTTP_API_BASE, ROSBRIDGE_URL, PID_CONFIG_TOPIC } from '../config.js'
import { reactive, ref, onMounted } from 'vue'
import { HTTP_API_BASE, ROSBRIDGE_URL } from '../config.js'
import { useRosbridge } from '../composables/useRosbridge.js'
const { connected, connect, publish } = useRosbridge()
const { connected, connect } = useRosbridge()
connect(ROSBRIDGE_URL)
const laserOn = ref(false)
const loading = ref(false)
const saving = ref(false)
const params = reactive({
const defaults = {
visualYaw: { kp: 0, ki: 0, kd: 0 },
visualPitch: { kp: 0, ki: 0, kd: 0 },
angleYaw: { kp: 0, ki: 0, kd: 0 },
anglePitch: { kp: 0, ki: 0, kd: 0 },
})
}
const params = reactive(structuredClone(defaults))
function snakeToCamel(key) {
return key.replace(/_([a-z])/g, (_, c) => c.toUpperCase())
}
async function loadConfig() {
loading.value = true
try {
const res = await fetch(`${HTTP_API_BASE}/api/pid/config`)
if (!res.ok) throw new Error(`HTTP ${res.status}`)
const data = await res.json()
for (const [snakeKey, val] of Object.entries(data)) {
const camelKey = snakeToCamel(snakeKey)
if (params[camelKey]) {
params[camelKey].kp = val.kp ?? 0
params[camelKey].ki = val.ki ?? 0
params[camelKey].kd = val.kd ?? 0
}
}
console.log('PID 配置已加载:', data)
} catch (e) {
console.error('加载 PID 配置失败:', e)
} finally {
loading.value = false
}
}
async function switchMode(mode) {
try {
@@ -79,18 +114,37 @@ async function switchMode(mode) {
}
}
function publishParams() {
publish(PID_CONFIG_TOPIC, 'std_msgs/String', {
data: JSON.stringify({
visual_yaw: params.visualYaw,
visual_pitch: params.visualPitch,
angle_yaw: params.angleYaw,
angle_pitch: params.anglePitch,
}),
})
console.log('PID 参数已发布:', params)
async function saveConfig() {
const payload = {
visual_yaw: params.visualYaw,
visual_pitch: params.visualPitch,
angle_yaw: params.angleYaw,
angle_pitch: params.anglePitch,
}
saving.value = true
try {
const res = await fetch(`${HTTP_API_BASE}/api/pid/config`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload),
})
if (!res.ok) {
const err = await res.json().catch(() => ({}))
throw new Error(err.message || `HTTP ${res.status}`)
}
console.log('PID 配置已保存')
} catch (e) {
console.error('保存 PID 配置失败:', e)
} finally {
saving.value = false
}
}
onMounted(() => {
loadConfig()
})
async function toggleLaser() {
try {
const action = laserOn.value ? 'off' : 'on'
@@ -146,6 +200,16 @@ async function toggleLaser() {
.conn-status { font-size: 13px; color: #e94560; }
.conn-status.ok { color: #4ecca3; }
.btn-load {
padding: 10px 28px;
border: 1px solid #0f3460; border-radius: 4px;
background: #16213e; color: #a0a0b0;
font-size: 15px; font-weight: 600; cursor: pointer;
transition: background 0.2s, color 0.2s;
}
.btn-load:hover { background: #1a1a3e; color: #e0e0e0; }
.btn-load:disabled { opacity: 0.5; cursor: not-allowed; }
.btn-publish {
padding: 10px 28px;
border: none; border-radius: 4px;
@@ -154,6 +218,7 @@ async function toggleLaser() {
transition: background 0.2s;
}
.btn-publish:hover { background: #3bb08a; }
.btn-publish:disabled { opacity: 0.5; cursor: not-allowed; }
.btn-laser {
padding: 10px 28px;