Compare commits

..

95 Commits

Author SHA1 Message Date
lyq
d11bb73beb 使能imu 2026-03-20 11:15:59 +08:00
lyq
e6f549cc2a BMS查询改成远程帧 2026-03-19 15:22:13 +08:00
lyq
15b9046d8b VID 透传改成200ms持续发布 2026-03-19 15:20:13 +08:00
lyq
a5bd401f9c VID 透传 2026-03-19 10:21:26 +08:00
lyq
3391fa4d60 README 2026-03-12 16:46:57 +08:00
lyq
e1efdb45ab sh 2026-03-12 16:17:55 +08:00
lyq
8a06e6b9a1 优化点云处理性能 2026-03-12 16:11:32 +08:00
lyq
0fc2f051f4 GPU 2026-03-11 17:22:18 +08:00
lyq
b3ee1a647d fix bug 2026-03-11 14:46:50 +08:00
lyq
d3e57eb77e gpu_processing 2026-03-11 13:59:03 +08:00
lyq
1c81a127af sh 2026-03-09 19:08:52 +08:00
lyq
37d350dd82 format launch file 2026-03-09 19:08:43 +08:00
lyq
7d3ecde581 提升雷达数据处理性能 2026-03-09 13:39:01 +08:00
lyq
1960fc8805 检查栅格数据过期 2026-03-09 13:06:23 +08:00
lyq
96dde92d9e fu_node 260306 2026-03-06 14:58:55 +08:00
lyq
0dd6687c09 提高遥控车速 2026-03-06 13:24:48 +08:00
lyq
4cdddde818 some routes 2026-03-06 13:24:28 +08:00
lyq
86d2d7d514 0228_2 2026-02-28 17:19:29 +08:00
lyq
11a7ee57aa 0228 2026-02-28 17:00:02 +08:00
lyq
c55105c9bf 从配置文件读取串口名 2026-02-28 13:25:32 +08:00
lyq
101bc924aa start_all scipt 2026-02-26 14:09:01 +08:00
lyq
92beb100b8 更改控制通道 2026-02-25 13:39:57 +08:00
lyq
09fa75aa90 8 Channels print 2026-02-25 13:09:02 +08:00
lyq
d701062b3b can_filter 2026-02-12 17:01:41 +08:00
lyq
eabf181280 云卓T12通讯遥控器CAN 2026-02-10 13:42:29 +08:00
lyq
347f980794 format task node 2026-02-09 13:50:34 +08:00
lyq
a8ed715631 修复遥控接收器松了还在发遥控指令BUG 2026-02-02 17:35:28 +08:00
lyq
3cdea52783 遇障停车bug 2026-02-02 17:32:55 +08:00
lyq
689c10bd91 修正先订阅topic再获取vid bug 2026-02-02 14:13:33 +08:00
lyq
93afcdebbb 提高代码健壮性 2026-02-02 13:59:53 +08:00
lyq
26d7ce5bf6 修正前进后退档位上报相反的问题 2026-02-02 13:19:41 +08:00
lyq
ee5f90c9ff docs: 完善 README 文档,补充项目架构、功能模块、配置说明等完整信息 2026-01-30 10:50:35 +08:00
lyq
47f280b2a0 readme 2026-01-30 09:47:41 +08:00
lyq
7049668465 sh 2026-01-30 09:39:00 +08:00
lyq
7cf7201361 readme 2026-01-30 09:37:06 +08:00
lyq
381788f467 修改启动方式 2026-01-30 09:30:02 +08:00
lyq
0939e19f3b launch包 2026-01-30 09:07:15 +08:00
lyq
d7ae466462 0129 2026-01-29 17:06:08 +08:00
lyq
02f0b42d36 修改绕障逻辑 2026-01-29 09:00:35 +08:00
lyq
7dc03a3c47 使能绕障 2026-01-27 10:28:46 +08:00
lyq
316e1e50eb RsSDK 路径 2026-01-27 10:28:28 +08:00
lyq
853d0155fe 删除DetectLine相关 2026-01-27 10:22:50 +08:00
lyq
20b6002099 优化点云处理流程 2026-01-27 09:49:42 +08:00
lyq
45a853b86c 删除pub_gps包 2026-01-26 15:18:13 +08:00
lyq
61fd82ee18 调整打印 2026-01-26 15:17:55 +08:00
lyq
86871a4ab8 修复清扫部件初始化bug 2026-01-26 15:17:36 +08:00
lyq
5211cd55dc 修复使能可视化栅格但是不打印的bug 2026-01-23 14:45:24 +08:00
lyq
ae9b7c1704 修改远控逻辑 2026-01-22 15:54:01 +08:00
lyq
71e63419b8 B6门口 2026-01-22 15:53:42 +08:00
lyq
098e67d798 修改远控逻辑 2026-01-21 16:44:29 +08:00
lyq
4e6b05eb3f 关闭sub节点发布remote_mc_ctrl 2026-01-21 16:43:45 +08:00
lyq
8edaa28967 园区大圈2 2026-01-21 16:42:47 +08:00
lyq
886b6b6de3 解决打印的 MD5 和实际上传的 MD5 不一致。 2026-01-21 16:40:50 +08:00
lyq
466a615378 更新gitignore 2026-01-21 13:29:42 +08:00
lyq
0c429ac416 优化日志文件结构 2026-01-21 13:29:22 +08:00
lyq
58656ed633 园区大圈 2026-01-21 10:21:09 +08:00
lyq
707b5e0c66 修复路径上传vid为空bug 2026-01-21 10:20:58 +08:00
lyq
c52bce7aed 修复日志输出转义bug 2026-01-21 10:20:01 +08:00
lyq
06adb527c8 持久化日志并格式化代码 2026-01-20 14:18:54 +08:00
lyq
885277d97a 修改启动脚本,增加vehicle_params_node 2026-01-20 10:22:20 +08:00
lyq
605bedc3e0 添加高性能异步日志系统 2026-01-19 17:01:23 +08:00
lyq
9c73d52dce 修改task_manager节点获取vid和话题的方式 2026-01-19 14:36:36 +08:00
lyq
cec7a19971 修改远控节点获取vid及远控话题的方式 2026-01-19 10:17:00 +08:00
lyq
caeb6cbc2b 修改sub节点获取vid的方式,以及topic的方式 2026-01-15 17:05:43 +08:00
lyq
19182ffe53 合并gps上报功能,去除原有的pub_gps节点 2026-01-15 09:38:48 +08:00
lyq
180bf5df50 调整mqtt节点架构 2026-01-15 09:02:54 +08:00
lyq
d3246d551d 调整mqtt_node架构 2026-01-15 09:01:56 +08:00
lyq
43b8299e6a 合并定位信息上报节点至mqtt上报节点 2026-01-14 16:44:15 +08:00
lyq
977fab0f9a 添加部分打印信息 2026-01-13 17:29:29 +08:00
lyq
603dc42acf 修改mqtt上报节点的配置获取 2026-01-13 17:24:17 +08:00
lyq
cc09a445de 拆分节点逻辑与业务逻辑 2026-01-13 16:14:55 +08:00
lyq
3568ef7ff9 修改md5文件变量类型重定义 2026-01-13 15:16:58 +08:00
lyq
a115de4977 修改目录 2026-01-13 14:47:12 +08:00
lyq
9cc4998c71 修改配置文件和路径文件 2026-01-13 14:05:25 +08:00
lyq
d24ea2ece9 分离mqtt和任务管理;增加mqtt断线重连 2026-01-13 14:04:17 +08:00
lyq
d69cc29ec9 调整打印信息 2026-01-13 13:59:44 +08:00
lyq
d5b01517a0 调整优先级 2026-01-13 13:59:43 +08:00
lyq
cf5a698eb9 修改滚刷推杆不下沉的bug 2026-01-13 13:59:43 +08:00
lyq
0195ddb3f8 260106 2026-01-06 10:18:25 +08:00
lyq
f445d3718b 调整整体程序架构,进行功能区分 2026-01-05 15:47:58 +08:00
lyq
f0349d21f9 修改远控节点配置文件 2026-01-04 16:51:53 +08:00
lyq
4e62bf4e66 修正三方库 2025-12-30 11:36:49 +08:00
lyq
53f104fff0 修正paho库报错 2025-12-30 11:34:07 +08:00
lyq
f8dcfa68b5 修正三方库报错 2025-12-30 11:30:52 +08:00
lyq
673a5e4adc 修改远控看门狗逻辑 2025-12-30 11:25:32 +08:00
lyq
3ce0c0b16e remote ctrl 2025-12-30 09:45:05 +08:00
lyq
5ddb2662c6 remote_ctrl 2025-12-19 15:20:59 +08:00
lyq
e5bd3f9c90 新采集的路线1204 2025-12-04 15:00:06 +08:00
lyq
e798a7c15f 调整一些打印 2025-12-04 14:59:41 +08:00
lyq
9e7ae8f7fd bug:brake 搞反了应该1的 2025-12-04 14:59:04 +08:00
lyq
fdde0c6e24 降低打印输出频率 2025-11-26 09:45:13 +08:00
lyq
b5686a81b0 fix : mqtt 死锁 2025-11-18 13:36:06 +08:00
lyq
048cefc202 humble分支 修改rtk串口号 2025-11-06 14:13:35 +08:00
lyq
b555b84e53 手柄控制脚本增加mqtt上报 2025-11-06 14:11:47 +08:00
lyq
4fde924479 humble分支 修改rtk串口号 2025-11-06 14:11:09 +08:00
867 changed files with 105286 additions and 19184 deletions

4
.clang-format Normal file
View File

@ -0,0 +1,4 @@
BasedOnStyle: Google
IndentWidth: 4
ColumnLimit: 120
BreakBeforeBraces: Allman

21
.cmake-format.yaml Normal file
View File

@ -0,0 +1,21 @@
# 一行不要太短,避免过度折行
line_width: 120
# CMake 社区默认习惯
tab_size: 2
# 只有参数很多时才换行
max_pargs_hwrap: 4
# 括号跟最后一个参数同一行(关键)
dangle_parens: false
# if/while/function 后不要加空格
separate_ctrl_name_with_space: false
# 风格统一
command_case: lower
keyword_case: upper
# 不做奇怪的 markup
enable_markup: false

3
.gitignore vendored
View File

@ -2,4 +2,5 @@ build
install
log
.vscode
deb_build
deb_build
nodes_log

145
README.md
View File

@ -1,148 +1,37 @@
# 清扫车 ROS2 控制与定位消息接口
# ZXOS
## 1. 文档概述
清扫车 ROS2 控制与定位消息接口
智行智驾低速自主驾驶体系 -- 车端ROS2固件ZXOS。该固件适配ZX200/ZX800自主智能清扫车。
## 2. 依赖环境
### 2.1 系统环境
* **ROS2 版本**Foxy
* **Ubuntu 版本**20.04
* **Ubuntu 版本**Ubuntu 22.04.5 LTS (Jammy Jellyfish)
* **ROS2 版本**ROS 2 Humble
* **CUDA 版本**12.2 (V12.2.140)
* **GCC/G++**gcc-11.4.0 / g++-11.4.0
* **Python 版本**Python 3.10.12
* **CMake 版本**3.22.1
### 2.2 .deb 的安装、启动与卸载
## 3. 启动
在目标机器上执行安装:
### 3.1 单遥控
```bash
sudo dpkg -i controller_XXXX_arm64.deb
./radio_ctrl.sh
```
安装完成后主要文件路径:
### 3.1 单远控
工作空间:/opt/controller/
启动脚本:/opt/controller/start_all.sh
CAN 配置脚本:/opt/controller/can.sh
日志文件:/var/log/controller/controller.log
systemd 服务:
CAN 配置服务:/etc/systemd/system/controller-can.service
ROS2 节点服务:/etc/systemd/system/controller.service
安装后CAN 配置服务会先运行,确保 can0 接口可用,然后 ROS2 节点服务会启动。
手动启动 ROS2 节点:
```bash
sudo systemctl start controller.service
./remote_ctrl.sh
```
重启服务:
### 3.1 全部节点
```bash
sudo systemctl restart controller.service
./start_all.sh
```
启动 CAN 配置服务(通常自动执行,不需要手动):
```bash
sudo systemctl start controller-can.service
```
查看运行状态
```bash
sudo systemctl status controller.service
sudo systemctl status controller-can.service
```
实时查看最新日志:
```bash
tail -f /var/log/controller/controller.log
```
也可以使用 journalctl 查看 systemd 输出:
```bash
sudo journalctl -u controller.service -f
```
旧日志会自动轮转,由 logrotate 管理,每天生成一个历史日志,历史日志会压缩 .gz默认保留最近 14 天日志
轮转后的文件示例:
```bash
/var/log/controller/controller.log # 当天日志
/var/log/controller/controller.log-20250923.gz # 历史压缩日志
```
停止服务
```bash
sudo systemctl stop controller.service
sudo systemctl stop controller-can.service
```
禁用开机自启
```bash
sudo systemctl disable controller.service
sudo systemctl disable controller-can.service
```
卸载 deb 包
```bash
sudo dpkg -r controller
```
卸载包后 日志文件会保留,便于调试。
## 3. 消息msg文件详情
### 3.1 McCtrl.msg车辆控制指令消息
#### 字段定义
| 字段类型 | 字段名称 | 取值范围 / 说明 | 功能描述 |
| -------- | ------------------------------- | ----------------------------------------------- | ------------------------------------------------------------ |
| uint8 | brake | 0不刹、1 | 电磁刹控制0 表示解除电磁刹1 表示激活电磁刹 |
| uint8 | gear | 0空挡、1后退、2前进、3保留 | 车辆挡位控制3 为预留挡位暂未使用 |
| uint8 | rpm | 0-4000 | 电机转速指令数值直接对应实际电机转速rpm |
| float32 | angle | \[-40.0, 40.0] | 轮端转向角度控制,单位为度(°),[-左、+右] |
| uint16 | angle\_speed | 120-1500 | 转向角速度控制,单位为 rpm |
| bool | sweep | true清扫、false不清扫 | 清扫 |
#### 对应 Topic
* **Topic**`/auto_mc_ctrl`
### 3.2 Rtk.msgRTK 定位信息消息)
#### 字段定义
| 字段类型 | 字段名称 | 取值范围 / 说明 | 功能描述 |
| -------- | ---------- | ----------------------------------------- | ------------------------------------------------------------ |
| float64 | lat | 无固定范围(符合 WGS84 坐标系经纬度格式) | 车辆所在位置的纬度 |
| float64 | lon | 无固定范围(符合 WGS84 坐标系经纬度格式) | 车辆所在位置的经度 |
| float32 | head | 0-360 | 车辆航向角单位0° 表示正北方向,顺时针递增 |
| float32 | speed | | |
| int32 | p\_quality | 0-9 | 定位解状态<br /> 0初始化 1单点定位 2码差分 3无效PPS 4固定解 5浮点解 6正在估算 7人工输入固定值 8模拟模式 9WAAS差分;<br /> 固定解是最优解 |
| int32 | h\_quality | 0-9 | 定向解状态<br /> 0初始化 1单点定位 2码差分 3无效PPS 4固定解 5浮点解 6正在估算 7人工输入固定值 8模拟模式 9WAAS差分;<br /> 固定解是最优解 |
#### 对应 Topic
* **Topic**`/rtk_message`

View File

@ -1,18 +1,17 @@
{
"mqtt": {
"vid": "V060003",
"external_net_address": "36.153.162.171",
"external_net_port": 19683,
"username": "zxwl",
"password": "zxwl1234@",
"info_topic": "/zxwl/sweeper/{vid}/info",
"fault_topic": "/zxwl/sweeper/{vid}/fault",
"gps_topic": "/zxwl/sweeper/{vid}/gps",
"remote_topic": "/zxwl/sweeper/{vid}/ctrl",
"upload_url": "https://qsc.ntiov.com:8443/api/sys/route/upload",
"download_url_pre": "http://36.153.162.171:9510/api/ccp-web/file/",
"inter_net_address": "tcp://192.168.4.196",
"inter_net_port": 11883,
"external_net_address": "tcp://36.153.162.171",
"external_net_port": 19683,
"mqtt_user": "zxwl",
"mqtt_password": "zxwl1234@",
"pub_gps_topic": "/zxwl/vehicle/V060003/gps",
"remote_topic": "/zxwl/vehicle/V060003/ctrl",
"mqtt_topic_push_status": "/zxwl/vehicle/V060003/task/status",
"mqtt_topic_sub_task": "/zxwl/vehicle/V060003/task"
"mqtt_topic_push_status": "/zxwl/sweeper/{vid}/task/status",
"mqtt_topic_sub_task": "/zxwl/sweeper/{vid}/task"
},
"detect_line_tolerance": 3.06,
"detect_head_tolerance": 2,

Binary file not shown.

View File

@ -1,96 +1,100 @@
32.0311468570
120.91525671300
358.096008
32.0310917570
120.91525467400
349.971985
0.000000
32.0311563730
120.91525624100
354.798004
32.0311007180
120.91525281000
347.497009
0.000000
32.0311655490
120.91525493600
347.576996
32.0311098440
120.91525041500
345.182007
0.000000
32.0311743100
120.91525172600
332.431000
32.0311188070
120.91524761800
346.235992
0.000000
32.0311818630
120.91524556200
313.209991
32.0311277000
120.91524564100
354.537994
0.000000
32.0311872560
120.91523692500
291.302002
32.0311374250
120.91524478800
357.682007
0.000000
32.0311895010
120.91522644400
273.058014
32.0311464090
120.91524462200
0.736000
0.000000
32.0311897810
120.91521522700
268.415009
32.0311554610
120.91524524600
10.159000
0.000000
32.0311893590
120.91520456100
264.153992
32.0311641680
120.91524787300
22.878000
0.000000
32.0311880140
120.91519349600
256.733002
32.0311729890
120.91525282200
26.490000
0.000000
32.0311854800
120.91518299200
247.852005
32.0311815850
120.91525809100
32.991001
0.000000
32.0311813510
120.91517328200
235.455994
32.0311895440
120.91526488500
38.161999
0.000000
32.0311754410
120.91516488300
219.582001
32.0311965870
120.91527158500
42.695000
0.000000
32.0311677300
120.91515878500
201.425995
32.0312034590
120.91527970700
51.610001
0.000000
32.0311588910
120.91515602500
183.102005
32.0312087060
120.91528835600
59.937000
0.000000
32.0311498140
120.91515571600
178.761002
32.0312130590
120.91529852200
66.385002
0.000000
32.0311408050
120.91515620700
172.496002
32.0312169790
120.91530905400
69.073997
0.000000
32.0311313060
120.91515857400
158.169998
32.0312201740
120.91531981700
74.775002
0.000000
32.0311232530
120.91516330100
142.091995
32.0312224930
120.91533104600
79.578003
0.000000
32.0311168570
120.91517109100
123.244003
32.0312241310
120.91534217100
85.223999
0.000000
32.0311126890
120.91518064100
104.664001
32.0312249230
120.91535273500
85.499001
0.000000
32.0311106850
120.91519129000
97.190002
32.0312258660
120.91536327800
83.461998
0.000000
32.0311099930
120.91520212400
89.829002
32.0312269000
120.91537477100
84.094002
0.000000
32.0311102590
120.91521279400
85.438004
32.0312278010
120.91538624100
86.753998
0.000000
32.0312285410
120.91539710300
85.632004
0.000000

View File

@ -1,194 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
PKG_NAME="controller"
PKG_VERSION="$(date +%Y%m%d%H%M)"
ARCH="arm64"
MAINTAINER="LYQ<liyq@ntiov.com>"
DESCRIPTION="Binary package of remote controller nodes for robot (ROS2 foxy)."
INSTALL_DIR="/opt/${PKG_NAME}"
WORKDIR="$(pwd)/deb_build"
INSTALL_SRC="$(pwd)/install"
# 清理工作目录
rm -rf "${WORKDIR}"
mkdir -p "${WORKDIR}/${INSTALL_DIR}"
mkdir -p "${WORKDIR}/DEBIAN"
# 复制 ROS2 install 文件
cp -a "${INSTALL_SRC}/." "${WORKDIR}/${INSTALL_DIR}/"
# control 文件
cat > "${WORKDIR}/DEBIAN/control" <<EOF
Package: ${PKG_NAME}
Version: ${PKG_VERSION}
Section: misc
Priority: optional
Architecture: ${ARCH}
Essential: no
Maintainer: ${MAINTAINER}
Depends: ros-foxy-ros-base, logrotate
Description: ${DESCRIPTION}
EOF
# ============================
# 创建 can.sh (root 执行)
# ============================
cat > "${WORKDIR}/${INSTALL_DIR}/can.sh" <<'EOF'
#!/bin/bash
# Script: can.sh
# Description: Configures CAN interface can0 on startup
if [[ $EUID -ne 0 ]]; then
echo "This script must be run as root"
exit 1
fi
if ip link show can0 &> /dev/null; then
ip link set can0 down
fi
modprobe can
modprobe can_raw
modprobe mttcan
ip link set can0 type can bitrate 500000
ip link set up can0
if [[ $? -ne 0 ]]; then
echo "Error configuring CAN interface can0"
exit 1
fi
echo "CAN interface can0 configured successfully"
exit 0
EOF
chmod +x "${WORKDIR}/${INSTALL_DIR}/can.sh"
# ============================
# 创建 start_all.sh (aiec 用户执行)
# ============================
cat > "${WORKDIR}/${INSTALL_DIR}/start_all.sh" <<EOF
#!/bin/bash
set -e
# 加载 ROS2 系统环境
source /opt/ros/foxy/setup.bash
# 加载打包的工作空间环境
source ${INSTALL_DIR}/local_setup.bash
# 启动多个节点
ros2 run radio_ctrl radio_ctrl_node &
ros2 run mc mc_node &
ros2 run ctrl_arbiter ctrl_arbiter_node &
ros2 run mqtt_report mqtt_report_node &
# ros2 run rtk rtk_node &
# ros2 run pub_gps pub_gps_node &
wait
EOF
chmod +x "${WORKDIR}/${INSTALL_DIR}/start_all.sh"
# ============================
# systemd 服务目录
# ============================
mkdir -p "${WORKDIR}/etc/systemd/system"
# CAN 配置服务 (root 执行)
cat > "${WORKDIR}/etc/systemd/system/${PKG_NAME}-can.service" <<EOF
[Unit]
Description=Configure CAN interface can0
After=network.target
[Service]
Type=oneshot
ExecStart=${INSTALL_DIR}/can.sh
RemainAfterExit=yes
User=root
[Install]
WantedBy=multi-user.target
EOF
# ROS2 节点服务 (aiec 用户执行,日志写文件)
cat > "${WORKDIR}/etc/systemd/system/${PKG_NAME}.service" <<EOF
[Unit]
Description=Remote Controller Nodes
After=network.target ${PKG_NAME}-can.service
Requires=${PKG_NAME}-can.service
[Service]
Type=simple
User=aiec
Environment="ROS_DISTRO=foxy"
ExecStart=${INSTALL_DIR}/start_all.sh
Restart=on-failure
RestartSec=2
StandardOutput=append:/var/log/${PKG_NAME}/${PKG_NAME}.log
StandardError=append:/var/log/${PKG_NAME}/${PKG_NAME}.log
[Install]
WantedBy=multi-user.target
EOF
# ============================
# logrotate 配置
# ============================
mkdir -p "${WORKDIR}/etc/logrotate.d"
cat > "${WORKDIR}/etc/logrotate.d/${PKG_NAME}" <<EOF
/var/log/${PKG_NAME}/${PKG_NAME}.log {
daily
rotate 14
compress
missingok
notifempty
copytruncate
dateext
dateformat -%Y%m%d
}
EOF
# ============================
# postinst 启用服务
# ============================
cat > "${WORKDIR}/DEBIAN/postinst" <<EOF
#!/bin/bash
set -e
# 创建日志目录
mkdir -p /var/log/${PKG_NAME}
chown aiec:aiec /var/log/${PKG_NAME}
systemctl daemon-reload
systemctl enable ${PKG_NAME}-can.service
systemctl enable ${PKG_NAME}.service
exit 0
EOF
chmod 755 "${WORKDIR}/DEBIAN/postinst"
# ============================
# postrm 停用服务
# ============================
cat > "${WORKDIR}/DEBIAN/postrm" <<EOF
#!/bin/bash
set -e
systemctl stop ${PKG_NAME}.service || true
systemctl disable ${PKG_NAME}.service || true
systemctl stop ${PKG_NAME}-can.service || true
systemctl disable ${PKG_NAME}-can.service || true
systemctl daemon-reload
exit 0
EOF
chmod 755 "${WORKDIR}/DEBIAN/postrm"
# ============================
# 构建 deb 包
# ============================
dpkg-deb --build "${WORKDIR}" "${PKG_NAME}_${PKG_VERSION}_${ARCH}.deb"
echo "生成 ${PKG_NAME}_${PKG_VERSION}_${ARCH}.deb"

View File

@ -2,6 +2,6 @@
sudo ./can.sh
sudo chmod 777 /dev/ttyTHS0
sudo chmod 777 /dev/ttyTHS1
sudo ip route add 36.153.162.0/24 via 192.168.5.1 dev eth4
# sudo ip route add 36.153.162.0/24 via 192.168.5.1 dev eth4

View File

@ -5,7 +5,12 @@ set -e
source install/setup.bash
# 启动节点
ros2 run radio_ctrl radio_ctrl_node &
ros2 run vehicle_params vehicle_params_node &
sleep 0.2
# ros2 run radio_ctrl radio_ctrl_node &
# sleep 0.2
ros2 run can_radio_ctrl can_radio_ctrl_node &
sleep 0.2
ros2 run mc mc_node &
@ -14,4 +19,7 @@ sleep 0.2
ros2 run ctrl_arbiter ctrl_arbiter_node &
sleep 0.2
ros2 run mqtt_report mqtt_report_node &
sleep 0.2
wait

23
remote_ctrl.sh Executable file
View File

@ -0,0 +1,23 @@
#!/bin/bash
set -e
# 加载工作空间环境
source install/setup.bash
# 启动节点
ros2 run vehicle_params vehicle_params_node &
sleep 0.2
ros2 run remote_ctrl remote_ctrl_node &
sleep 0.2
ros2 run mc mc_node &
sleep 0.2
ros2 run ctrl_arbiter ctrl_arbiter_node &
sleep 0.2
ros2 run mqtt_report mqtt_report_node &
sleep 0.2
wait

View File

@ -1,190 +0,0 @@
#!/bin/bash
###############################################################################
# ros2_nodes.sh
# 一键启动 / 停止 / 重启 / 状态查询 6 个 ROS 2 节点(或仅核心 4 节点)
# 用法:
# ./ros2_nodes.sh start # 默认启动全部 6 节点
# ./ros2_nodes.sh start all # 同上
# ./ros2_nodes.sh start core # 仅启动 4 个核心节点
# ./ros2_nodes.sh stop # 停止
# ./ros2_nodes.sh restart [core] # 重启(可选 core / all
# ./ros2_nodes.sh status # 查看状态
# ./ros2_nodes.sh rotate # 手动轮换日志
###############################################################################
##== 基本路径与环境 ===========================================================
WORKSPACE_PATH="/home/nvidia/Downloads/sweeper_whu"
source "$WORKSPACE_PATH/install/setup.bash"
##== 日志目录与轮换配置 =======================================================
LOG_DIR="/var/log/ros2"
MAX_LOG_SIZE="10M" # 单个日志大小
MAX_LOG_FILES=5 # 保留文件数
##== 节点命令列表 ==============================================================
# 1) 全量 6 节点(键名 = 节点标识 , 值 = 启动命令)
declare -A NODES_ALL=(
["mc"]="ros2 run mc mc_node"
["radio_ctrl"]="ros2 run radio_ctrl radio_ctrl_node"
["ctrl_arbiter"]="ros2 run ctrl_arbiter ctrl_arbiter_node"
["mqtt_report"]="ros2 run mqtt_report mqtt_report_node"
["rtk"]="ros2 run rtk rtk_node"
["pub_gps"]="ros2 run pub_gps pub_gps_node"
)
# 2) 核心节点名称数组(便于 core 模式筛选)
CORE_NAMES=(mc radio_ctrl ctrl_arbiter mqtt_report)
##== 函数 =====================================================================
# 预启动环境准备CAN、USB 权限、日志目录与 logrotate
setup_environment() {
echo "[INFO] 设置 CAN0 波特率为 500K..."
sudo ip link set can0 down 2>/dev/null
sudo ip link set can0 type can bitrate 500000
sudo ip link set can0 up
echo "[INFO] CAN0 配置完成。"
echo "[INFO] 设置 /dev/ttyUSB0 权限为 777..."
sudo chmod 777 /dev/ttyUSB0
echo "[INFO] ttyUSB0 权限设置完成。"
echo "[INFO] 设置 /dev/ttyTHS1 权限为 777..."
sudo chmod 777 /dev/ttyTHS1
echo "[INFO] ttyTHS1 权限设置完成。"
# 日志目录
echo "[INFO] 创建日志目录: $LOG_DIR"
sudo mkdir -p "$LOG_DIR"
sudo chown -R nvidia:nvidia "$LOG_DIR"
# logrotate 配置
local LOGROTATE_CONF="/etc/logrotate.d/ros2_nodes"
echo "[INFO] 配置 logrotate: $LOGROTATE_CONF"
sudo bash -c "cat > $LOGROTATE_CONF" <<EOF
$LOG_DIR/*.log {
su nvidia nvidia
daily
maxsize $MAX_LOG_SIZE
rotate $MAX_LOG_FILES
missingok
notifempty
compress
delaycompress
sharedscripts
copytruncate
}
EOF
}
# 启动节点start_nodes [core|all]
start_nodes() {
local mode=${1:-all} # 默认 all
setup_environment
# 选择节点集合
local names=()
if [[ "$mode" == "core" ]]; then
names=("${CORE_NAMES[@]}")
else
names=("${!NODES_ALL[@]}")
fi
echo "[INFO] 启动模式: $mode"
echo "[INFO] 节点列表: ${names[*]}"
echo "[INFO] 每个节点启动间隔 0.1s"
for name in "${names[@]}"; do
echo "[START] $name"
local log_file="${LOG_DIR}/${name}.log"
#=====================================================================
${NODES_ALL[$name]} >> "$log_file" 2>&1 &
# gnome-terminal --title="$name" \
# -- bash -c "source $WORKSPACE_PATH/install/setup.bash && ${NODES_ALL[$name]}; exec bash" &
#=====================================================================
local pid=$!
echo $pid > "/tmp/$name.pid"
echo "[INFO] $name PID: $pid | 日志: $log_file"
sleep 0.1 # 每个节点之间暂停 0.1 秒
done
echo "[INFO] 所有节点已启动 (${mode})."
}
# 停止全部正在运行的节点
stop_nodes() {
echo "[INFO] 停止 ROS 2 节点..."
for pidfile in /tmp/*.pid; do
[ -e "$pidfile" ] || continue
local name=$(basename "$pidfile" .pid)
local pid=$(cat "$pidfile")
if ps -p "$pid" > /dev/null 2>&1; then
kill -SIGINT "$pid" && echo "[STOP] $name (PID $pid) - 发送 SIGINT"
local timeout=5
while kill -0 "$pid" 2>/dev/null && [ $timeout -gt 0 ]; do
sleep 0.5; ((timeout--))
done
if kill -0 "$pid" 2>/dev/null; then
kill -9 "$pid" && echo "[STOP] $name (PID $pid) - 强制终止"
fi
fi
rm -f "$pidfile"
done
echo "[INFO] 所有节点已停止。"
}
# 手动触发日志轮换
rotate_logs() {
echo "[INFO] 手动轮换日志..."
sudo logrotate -f /etc/logrotate.d/ros2_nodes
echo "[INFO] 日志轮换完成。"
}
# 查看节点运行状态
show_status() {
echo "[INFO] 节点状态:"
for name in "${!NODES_ALL[@]}"; do
if [ -f "/tmp/$name.pid" ]; then
local pid=$(cat "/tmp/$name.pid")
if ps -p "$pid" > /dev/null 2>&1; then
echo "[RUNNING] $name (PID $pid)"
else
echo "[DEAD] $name (PID $pid)"
fi
else
echo "[STOPPED] $name"
fi
done
}
##== 主入口 ===================================================================
case "$1" in
start)
# 用法: ./ros2_nodes.sh start [core|all]
start_nodes "${2:-all}"
;;
stop)
stop_nodes
;;
restart)
stop_nodes
sleep 1
start_nodes "${2:-all}"
;;
rotate)
rotate_logs
;;
status)
show_status
;;
*)
echo "Usage: $0 {start|stop|restart|rotate|status} [core|all]"
echo " core : 仅启动 4 个核心节点 (mc radio_ctrl ctrl_arbiter mqtt_report)"
echo " all : 启动全部 6 个节点 (默认)"
;;
esac

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,332 @@
32.0310062300
120.91508837100
192.574005
0.000000
32.0309966680
120.91508582400
191.985992
0.000000
32.0309878290
120.91508368100
190.095993
0.000000
32.0309782290
120.91508183300
182.136002
0.000000
32.0309691320
120.91508170900
177.313004
0.000000
32.0309598680
120.91508247300
172.324997
0.000000
32.0309505220
120.91508425100
168.134995
0.000000
32.0309415740
120.91508691000
166.386993
0.000000
32.0309324890
120.91508851300
172.783997
0.000000
32.0309229090
120.91509012000
168.578995
0.000000
32.0309140780
120.91509229000
166.811005
0.000000
32.0309051460
120.91509472400
165.830994
0.000000
32.0308963060
120.91509693900
169.735001
0.000000
32.0308867260
120.91509924600
168.291000
0.000000
32.0308772720
120.91510142700
169.839996
0.000000
32.0308683980
120.91510326300
170.018005
0.000000
32.0308594670
120.91510533100
166.720001
0.000000
32.0308507300
120.91510801800
162.283005
0.000000
32.0308414490
120.91511150600
160.276001
0.000000
32.0308322270
120.91511521300
160.251007
0.000000
32.0308230440
120.91511922500
157.701004
0.000000
32.0308141650
120.91512387100
154.352005
0.000000
32.0308054470
120.91512915300
148.410995
0.000000
32.0307974410
120.91513576500
138.578003
0.000000
32.0307907500
120.91514307500
132.796997
0.000000
32.0307850720
120.91515141400
121.928001
0.000000
32.0307805000
120.91516066300
116.037003
0.000000
32.0307766080
120.91517127500
107.122002
0.000000
32.0307745290
120.91518162500
96.809998
0.000000
32.0307739520
120.91519245000
88.552002
0.000000
32.0307747490
120.91520329000
77.658997
0.000000
32.0307772880
120.91521349200
64.290001
0.000000
32.0307823290
120.91522328700
47.359001
0.000000
32.0307894970
120.91523096000
36.080002
0.000000
32.0307976360
120.91523738300
30.979000
0.000000
32.0308055610
120.91524256000
26.162001
0.000000
32.0308139090
120.91524678200
15.933000
0.000000
32.0308233950
120.91524910900
4.803000
0.000000
32.0308331110
120.91524969200
358.704010
0.000000
32.0308422060
120.91524933500
356.233002
0.000000
32.0308512330
120.91524834200
353.705994
0.000000
32.0308602030
120.91524716700
354.881989
0.000000
32.0308699110
120.91524640300
354.579987
0.000000
32.0308790400
120.91524550800
354.855011
0.000000
32.0308881120
120.91524480900
357.506012
0.000000
32.0308971240
120.91524413800
355.522003
0.000000
32.0309061540
120.91524343500
355.557007
0.000000
32.0309151310
120.91524259400
355.384003
0.000000
32.0309248150
120.91524175100
355.596985
0.000000
32.0309338400
120.91524100100
355.588989
0.000000
32.0309435560
120.91524009100
355.132996
0.000000
32.0309532770
120.91523905600
353.201996
0.000000
32.0309623680
120.91523783100
353.092987
0.000000
32.0309713470
120.91523671000
356.117004
0.000000
32.0309803210
120.91523592700
353.936005
0.000000
32.0309893530
120.91523464500
351.126007
0.000000
32.0309989390
120.91523284100
352.040985
0.000000
32.0310085870
120.91523110700
348.987000
0.000000
32.0310174600
120.91522884000
345.084015
0.000000
32.0310268560
120.91522583600
340.417999
0.000000
32.0310353180
120.91522201400
335.906006
0.000000
32.0310433100
120.91521715800
324.356995
0.000000
32.0310510080
120.91521017700
316.306000
0.000000
32.0310578080
120.91520196700
308.945007
0.000000
32.0310631970
120.91519342700
298.385986
0.000000
32.0310669850
120.91518381600
287.634003
0.000000
32.0310690180
120.91517322400
275.351990
0.000000
32.0310692190
120.91516232300
265.686005
0.000000
32.0310684190
120.91515169800
262.846008
0.000000
32.0310667670
120.91514114000
252.485992
0.000000
32.0310635690
120.91513059500
244.078995
0.000000
32.0310590500
120.91512108200
235.897003
0.000000
32.0310532920
120.91511179600
229.807999
0.000000
32.0310467450
120.91510366600
222.167007
0.000000
32.0310397350
120.91509674500
213.647995
0.000000
32.0310320550
120.91509095600
206.363998
0.000000
32.0310232240
120.91508615500
199.858994
0.000000
32.0310140310
120.91508258800
195.602997
0.000000
32.0310051760
120.91508022200
187.149994
0.000000
32.0309962010
120.91507896700
180.582993
0.000000
32.0309871640
120.91507898300
176.052002
0.000000
32.0309775250
120.91507982600
175.110992
0.000000
32.0309685520
120.91508080400
174.738007
0.000000

View File

@ -0,0 +1,100 @@
32.0309685520
120.91508080400
174.738007
0.000000
32.0309594760
120.91508193400
170.802002
0.000000
32.0309504680
120.91508341600
174.061005
0.000000
32.0309413970
120.91508461300
175.490997
0.000000
32.0309322910
120.91508506600
178.044998
0.000000
32.0309227710
120.91508524700
178.255997
0.000000
32.0309134700
120.91508573500
175.113998
0.000000
32.0309043040
120.91508663600
172.272003
0.000000
32.0308953330
120.91508869600
165.223007
0.000000
32.0308868920
120.91509233900
145.375000
0.000000
32.0308803380
120.91509975500
119.100998
0.000000
32.0308771860
120.91511044800
88.364998
0.000000
32.0308801960
120.91512096200
38.959000
0.000000
32.0308889470
120.91512500000
358.279999
0.000000
32.0308980650
120.91512459800
354.290009
0.000000
32.0309072300
120.91512317000
348.907990
0.000000
32.0309161820
120.91512084500
348.226990
0.000000
32.0309250920
120.91511863300
348.507996
0.000000
32.0309340350
120.91511645900
347.182007
0.000000
32.0309428210
120.91511396100
341.677002
0.000000
32.0309514190
120.91510961900
327.466003
0.000000
32.0309580580
120.91510225800
290.079987
0.000000
32.0309583760
120.91509116000
240.046997
0.000000
32.0309517360
120.91508382200
191.212997
0.000000
32.0309609090
120.91508219100
175.347000
0.000000

View File

@ -0,0 +1,72 @@
32.0309150690
120.91506536800
177.654007
0.000000
32.0309060550
120.91506541700
178.863998
0.000000
32.0308966140
120.91506616000
161.466995
0.000000
32.0308891770
120.91507222500
118.348999
0.000000
32.0308869110
120.91508264700
88.599998
0.000000
32.0308874270
120.91509340300
85.597000
0.000000
32.0308877380
120.91510406400
92.059998
0.000000
32.0308873680
120.91511488600
78.463997
0.000000
32.0308919650
120.91512440800
27.441999
0.000000
32.0309008020
120.91512683500
359.238007
0.000000
32.0309098920
120.91512631500
355.177002
0.000000
32.0309188450
120.91512515300
351.442993
0.000000
32.0309272450
120.91512120700
309.044006
0.000000
32.0309305690
120.91511117100
264.268005
0.000000
32.0309294050
120.91510059200
259.207001
0.000000
32.0309264150
120.91509008900
223.201996
0.000000
32.0309182090
120.91508508500
176.380997
0.000000
32.0309275230
120.91508596900
206.153000
0.000000

View File

@ -0,0 +1,68 @@
32.0309247030
120.91507181700
175.167999
0.000000
32.0309153960
120.91507298400
169.643997
0.000000
32.0309064620
120.91507499500
172.268997
0.000000
32.0308971460
120.91507587000
177.580002
0.000000
32.0308879100
120.91507735600
152.240005
0.000000
32.0308810980
120.91508470900
102.825996
0.000000
32.0308796330
120.91509556100
94.540001
0.000000
32.0308790170
120.91510617400
84.416000
0.000000
32.0308824190
120.91511639600
37.883999
0.000000
32.0308908460
120.91512016300
353.354004
0.000000
32.0308998390
120.91511894700
353.295013
0.000000
32.0309090620
120.91511812300
358.222992
0.000000
32.0309183710
120.91511749800
346.201996
0.000000
32.0309261310
120.91511212000
297.071991
0.000000
32.0309276550
120.91510141900
249.197006
0.000000
32.0309219690
120.91509306000
200.531006
0.000000
32.0309129310
120.91509103000
176.186005
0.000000

View File

@ -0,0 +1,308 @@
32.0309270710
120.91508380700
174.522003
0.000000
32.0309177630
120.91508508700
170.716995
0.000000
32.0309083630
120.91508691600
167.014008
0.000000
32.0308991500
120.91509013100
158.218994
0.000000
32.0308909680
120.91509463700
151.005997
0.000000
32.0308825810
120.91510033500
147.225006
0.000000
32.0308741660
120.91510631000
156.934006
0.000000
32.0308652190
120.91510999400
166.878998
0.000000
32.0308561900
120.91511247100
165.128998
0.000000
32.0308470540
120.91511526000
164.408005
0.000000
32.0308384050
120.91511818800
165.382996
0.000000
32.0308288240
120.91512052600
167.072998
0.000000
32.0308193630
120.91512325900
164.526993
0.000000
32.0308099890
120.91512646200
160.466995
0.000000
32.0308016850
120.91513058700
151.772003
0.000000
32.0307940750
120.91513631900
140.869995
0.000000
32.0307872200
120.91514318900
132.024994
0.000000
32.0307816190
120.91515177200
123.033997
0.000000
32.0307767850
120.91516175300
111.536003
0.000000
32.0307737970
120.91517181200
104.806999
0.000000
32.0307716670
120.91518215100
100.636002
0.000000
32.0307703680
120.91519282400
89.806000
0.000000
32.0307709200
120.91520367800
81.512001
0.000000
32.0307728420
120.91521413600
69.341003
0.000000
32.0307771010
120.91522443200
52.085999
0.000000
32.0307837600
120.91523281900
41.723999
0.000000
32.0307914160
120.91523974900
31.273001
0.000000
32.0307994650
120.91524466500
21.080000
0.000000
32.0308081020
120.91524794900
11.581000
0.000000
32.0308169840
120.91524990900
6.804000
0.000000
32.0308266650
120.91525087500
2.044000
0.000000
32.0308363640
120.91525102500
357.092987
0.000000
32.0308454740
120.91525076200
0.180000
0.000000
32.0308545400
120.91525048300
358.631012
0.000000
32.0308642580
120.91525064500
1.479000
0.000000
32.0308733660
120.91525116000
3.574000
0.000000
32.0308823780
120.91525174100
1.308000
0.000000
32.0308915670
120.91525213700
3.472000
0.000000
32.0309013400
120.91525273600
1.245000
0.000000
32.0309103910
120.91525290600
1.489000
0.000000
32.0309201180
120.91525361800
1.429000
0.000000
32.0309291640
120.91525371800
359.424011
0.000000
32.0309388660
120.91525320500
356.106995
0.000000
32.0309478980
120.91525251700
352.549988
0.000000
32.0309576240
120.91525108400
350.079010
0.000000
32.0309665940
120.91524933800
352.509003
0.000000
32.0309755100
120.91524791200
351.528015
0.000000
32.0309844990
120.91524603700
348.252014
0.000000
32.0309940620
120.91524366200
346.699005
0.000000
32.0310034720
120.91524080400
344.282990
0.000000
32.0310120850
120.91523778100
340.821014
0.000000
32.0310205650
120.91523415800
335.459015
0.000000
32.0310285570
120.91522924400
325.936005
0.000000
32.0310358980
120.91522309900
322.156006
0.000000
32.0310433430
120.91521577300
312.940002
0.000000
32.0310496090
120.91520717900
303.739990
0.000000
32.0310549300
120.91519746200
298.476013
0.000000
32.0310588260
120.91518787300
291.746002
0.000000
32.0310619800
120.91517768500
284.023010
0.000000
32.0310634770
120.91516693600
275.184998
0.000000
32.0310638860
120.91515611400
264.816010
0.000000
32.0310623280
120.91514564900
253.266998
0.000000
32.0310587730
120.91513498100
240.110001
0.000000
32.0310535320
120.91512525600
233.132004
0.000000
32.0310479220
120.91511694700
226.000000
0.000000
32.0310409290
120.91510900500
220.576004
0.000000
32.0310339060
120.91510237400
214.026001
0.000000
32.0310256190
120.91509629900
203.143997
0.000000
32.0310169390
120.91509284600
191.787994
0.000000
32.0310074340
120.91509122200
179.445999
0.000000
32.0309977060
120.91509169800
172.662994
0.000000
32.0309887870
120.91509335300
167.395004
0.000000
32.0309799010
120.91509565100
168.294998
0.000000
32.0309702280
120.91509780900
172.145996
0.000000
32.0309611820
120.91509877900
176.160995
0.000000
32.0309514570
120.91509948100
176.261993
0.000000
32.0309423130
120.91510028200
174.684998
0.000000

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,632 @@
32.0309059220
120.91507453600
17.753000
0.000000
32.0309148270
120.91507776600
17.525999
0.000000
32.0309236310
120.91508057300
17.218000
0.000000
32.0309327390
120.91508386700
17.608000
0.000000
32.0309416330
120.91508699800
17.511000
0.000000
32.0309504650
120.91509028100
18.521000
0.000000
32.0309595190
120.91509363200
17.833000
0.000000
32.0309684230
120.91509729700
20.240999
0.000000
32.0309774410
120.91510135000
21.204000
0.000000
32.0309859680
120.91510527100
21.841999
0.000000
32.0309943390
120.91510941700
23.318001
0.000000
32.0310032190
120.91511407400
27.270000
0.000000
32.0310116700
120.91511970300
30.927000
0.000000
32.0310201800
120.91512568400
31.695000
0.000000
32.0310284370
120.91513180500
32.013000
0.000000
32.0310366160
120.91513795800
33.563999
0.000000
32.0310447580
120.91514428000
34.560001
0.000000
32.0310521640
120.91515038300
35.237000
0.000000
32.0310601020
120.91515715000
36.064999
0.000000
32.0310674000
120.91516351500
38.910999
0.000000
32.0310741240
120.91517079600
43.208000
0.000000
32.0310807950
120.91517838600
43.783001
0.000000
32.0310872180
120.91518587100
44.694000
0.000000
32.0310936010
120.91519343700
45.299999
0.000000
32.0311007320
120.91520131400
38.423000
0.000000
32.0311083860
120.91520835100
38.085999
0.000000
32.0311161270
120.91521541400
37.209000
0.000000
32.0311232950
120.91522199300
37.362000
0.000000
32.0311310550
120.91522896000
35.877998
0.000000
32.0311382810
120.91523533600
35.492001
0.000000
32.0311461850
120.91524203800
35.508999
0.000000
32.0311535190
120.91524821200
38.588001
0.000000
32.0311604720
120.91525511500
40.641998
0.000000
32.0311671790
120.91526228800
43.164001
0.000000
32.0311739140
120.91527055200
46.932999
0.000000
32.0311802090
120.91527889700
49.226002
0.000000
32.0311864270
120.91528781800
51.997002
0.000000
32.0311919750
120.91529620400
53.888000
0.000000
32.0311970510
120.91530500100
58.710999
0.000000
32.0312017590
120.91531489700
64.824997
0.000000
32.0312055030
120.91532550700
70.234001
0.000000
32.0312085640
120.91533638200
74.036003
0.000000
32.0312109030
120.91534742100
78.997002
0.000000
32.0312123390
120.91535796700
83.719002
0.000000
32.0312131810
120.91536929700
86.478996
0.000000
32.0312136050
120.91538077100
88.044998
0.000000
32.0312137320
120.91539148000
89.156998
0.000000
32.0312138820
120.91540299500
88.689003
0.000000
32.0312141080
120.91541366300
87.801003
0.000000
32.0312143330
120.91542426200
87.367996
0.000000
32.0312147380
120.91543489800
87.220001
0.000000
32.0312150710
120.91544615700
88.532997
0.000000
32.0312151700
120.91545780100
89.377998
0.000000
32.0312153040
120.91546932300
87.929001
0.000000
32.0312155460
120.91547994300
87.074997
0.000000
32.0312160640
120.91549141800
86.186996
0.000000
32.0312166750
120.91550289300
85.649002
0.000000
32.0312173150
120.91551347800
86.931999
0.000000
32.0312177400
120.91552505000
86.444000
0.000000
32.0312183350
120.91553650500
85.163002
0.000000
32.0312191160
120.91554711300
86.652000
0.000000
32.0312195390
120.91555856800
86.635002
0.000000
32.0312200820
120.91557008600
86.950996
0.000000
32.0312206390
120.91558155400
86.192001
0.000000
32.0312212560
120.91559215900
86.212997
0.000000
32.0312218250
120.91560365700
86.130997
0.000000
32.0312224570
120.91561511900
86.133003
0.000000
32.0312230080
120.91562663800
87.842003
0.000000
32.0312232550
120.91563816300
89.364998
0.000000
32.0312233280
120.91564881200
89.200996
0.000000
32.0312234440
120.91566023400
88.639999
0.000000
32.0312236340
120.91567083200
87.695000
0.000000
32.0312240270
120.91568233400
87.403000
0.000000
32.0312243780
120.91569294900
87.195000
0.000000
32.0312248570
120.91570442700
85.874001
0.000000
32.0312254770
120.91571499700
86.217003
0.000000
32.0312261490
120.91572650800
85.580002
0.000000
32.0312267750
120.91573709100
85.873001
0.000000
32.0312274030
120.91574857800
86.735001
0.000000
32.0312278540
120.91576005600
87.473000
0.000000
32.0312282120
120.91577064300
87.811996
0.000000
32.0312284600
120.91578219900
88.080002
0.000000
32.0312287020
120.91579362400
88.499001
0.000000
32.0312288700
120.91580507900
88.637001
0.000000
32.0312291280
120.91581668800
88.600998
0.000000
32.0312295050
120.91582823300
86.709000
0.000000
32.0312298770
120.91583972000
86.411003
0.000000
32.0312304810
120.91585115000
85.708000
0.000000
32.0312311600
120.91586174700
87.033997
0.000000
32.0312313880
120.91587237100
89.141998
0.000000
32.0312313680
120.91588313400
85.974998
0.000000
32.0312322530
120.91589430000
84.378998
0.000000
32.0312331030
120.91590550400
85.447998
0.000000
32.0312337200
120.91591623100
86.781998
0.000000
32.0312341560
120.91592685600
86.746002
0.000000
32.0312347330
120.91593756900
86.496002
0.000000
32.0312353150
120.91594891900
86.263000
0.000000
32.0312359390
120.91595981500
85.277000
0.000000
32.0312366530
120.91597135300
84.977997
0.000000
32.0312375340
120.91598281000
84.515999
0.000000
32.0312384120
120.91599336000
85.305000
0.000000
32.0312389410
120.91600396900
86.956001
0.000000
32.0312393590
120.91601538600
87.115997
0.000000
32.0312398990
120.91602678000
86.516998
0.000000
32.0312404200
120.91603735900
85.605003
0.000000
32.0312410700
120.91604866000
85.514999
0.000000
32.0312418440
120.91605932200
84.931000
0.000000
32.0312425240
120.91607070600
86.876999
0.000000
32.0312429500
120.91608222000
87.763000
0.000000
32.0312431370
120.91609374700
87.617996
0.000000
32.0312436760
120.91610519700
86.650002
0.000000
32.0312441960
120.91611580500
86.314003
0.000000
32.0312448280
120.91612729300
85.889999
0.000000
32.0312455840
120.91613880200
85.323997
0.000000
32.0312463040
120.91615025300
85.443001
0.000000
32.0312469720
120.91616173100
87.385002
0.000000
32.0312472400
120.91617322400
87.737000
0.000000
32.0312476780
120.91618465800
86.783997
0.000000
32.0312482210
120.91619618400
86.132004
0.000000
32.0312488670
120.91620773300
85.084000
0.000000
32.0312495330
120.91621909100
84.349998
0.000000
32.0312503240
120.91622970500
86.352997
0.000000
32.0312508580
120.91624118300
87.614998
0.000000
32.0312511870
120.91625269600
87.379997
0.000000
32.0312516130
120.91626412400
87.073997
0.000000
32.0312521140
120.91627474700
87.023003
0.000000
32.0312526240
120.91628616900
86.621002
0.000000
32.0312531820
120.91629766400
86.105003
0.000000
32.0312538090
120.91630916400
85.706001
0.000000
32.0312543880
120.91632068200
87.724998
0.000000
32.0312546460
120.91633132800
88.665001
0.000000
32.0312547180
120.91634203600
88.679001
0.000000
32.0312549880
120.91635345100
87.136002
0.000000
32.0312553720
120.91636404200
87.433998
0.000000
32.0312558060
120.91637468500
86.809998
0.000000
32.0312563790
120.91638608600
85.931000
0.000000
32.0312570560
120.91639749100
85.924004
0.000000
32.0312575200
120.91640896300
85.889999
0.000000
32.0312581010
120.91642048400
87.275002
0.000000
32.0312584050
120.91643203800
88.722000
0.000000
32.0312585420
120.91644358800
87.987000
0.000000
32.0312588670
120.91645506400
87.643997
0.000000
32.0312593360
120.91646658100
87.431000
0.000000
32.0312598290
120.91647806800
86.720001
0.000000
32.0312603720
120.91648865300
85.902000
0.000000
32.0312610920
120.91649982200
85.807999
0.000000
32.0312616930
120.91651066200
85.612999
0.000000
32.0312624190
120.91652205000
85.580002
0.000000
32.0312628980
120.91653348800
87.941002
0.000000
32.0312631520
120.91654499600
88.758003
0.000000
32.0312632690
120.91655563300
88.308998
0.000000
32.0312635020
120.91656705500
87.642998
0.000000
32.0312639160
120.91657851900
86.695999
0.000000
32.0312644430
120.91659004000
86.541000
0.000000
32.0312651230
120.91660065700
85.900002
0.000000
32.0312657190
120.91661207400
87.696999
0.000000
32.0312659540
120.91662364000
89.132004
0.000000
32.0312662160
120.91663460400
74.685997
0.000000

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,296 @@
32.0309031720
120.91507456700
358.903015
0.000000
32.0309122700
120.91507465100
1.824000
0.000000
32.0309218300
120.91507536900
5.379000
0.000000
32.0309309300
120.91507646200
9.029000
0.000000
32.0309399620
120.91507767700
8.762000
0.000000
32.0309491970
120.91507969400
12.384000
0.000000
32.0309588180
120.91508216100
13.471000
0.000000
32.0309675640
120.91508480500
17.896000
0.000000
32.0309766450
120.91508880400
22.101999
0.000000
32.0309848880
120.91509322200
26.379999
0.000000
32.0309930520
120.91509823000
30.480000
0.000000
32.0310012620
120.91510437600
33.999001
0.000000
32.0310087320
120.91511028400
34.645000
0.000000
32.0310163110
120.91511626500
36.090000
0.000000
32.0310240180
120.91512326500
37.971001
0.000000
32.0310317340
120.91513052000
39.084000
0.000000
32.0310391000
120.91513778100
41.595001
0.000000
32.0310459690
120.91514589500
51.403000
0.000000
32.0310509040
120.91515476500
65.014999
0.000000
32.0310540470
120.91516559800
83.711998
0.000000
32.0310540770
120.91517649900
98.914001
0.000000
32.0310514290
120.91518685500
114.102997
0.000000
32.0310469800
120.91519624200
130.358994
0.000000
32.0310399570
120.91520416900
143.240005
0.000000
32.0310318070
120.91521042600
154.128006
0.000000
32.0310236210
120.91521480300
156.352997
0.000000
32.0310153520
120.91521894700
156.727997
0.000000
32.0310068890
120.91522295900
162.268997
0.000000
32.0309976280
120.91522578700
167.934006
0.000000
32.0309887430
120.91522755900
171.403000
0.000000
32.0309798350
120.91522898000
172.026993
0.000000
32.0309701240
120.91523061000
173.535004
0.000000
32.0309608820
120.91523161700
174.781998
0.000000
32.0309511450
120.91523278100
173.095001
0.000000
32.0309414590
120.91523408100
172.738007
0.000000
32.0309317890
120.91523561300
172.759995
0.000000
32.0309220880
120.91523714100
171.729996
0.000000
32.0309124620
120.91523885800
171.533005
0.000000
32.0309035530
120.91524062100
170.462006
0.000000
32.0308939330
120.91524243500
173.511993
0.000000
32.0308849020
120.91524366900
174.072998
0.000000
32.0308758540
120.91524473900
174.837006
0.000000
32.0308668250
120.91524554200
175.477005
0.000000
32.0308571550
120.91524639000
176.475998
0.000000
32.0308481530
120.91524702000
181.354996
0.000000
32.0308390220
120.91524675200
181.582001
0.000000
32.0308293150
120.91524646800
181.154007
0.000000
32.0308195650
120.91524630200
181.212997
0.000000
32.0308105960
120.91524531800
190.882996
0.000000
32.0308017000
120.91524309800
196.507996
0.000000
32.0307927000
120.91523864000
215.287994
0.000000
32.0307854930
120.91523117700
234.037994
0.000000
32.0307810700
120.91522120300
251.423996
0.000000
32.0307787600
120.91521000500
261.298004
0.000000
32.0307778120
120.91519940900
266.550995
0.000000
32.0307773010
120.91518860600
267.316986
0.000000
32.0307770810
120.91517787700
274.162994
0.000000
32.0307783650
120.91516734800
287.984009
0.000000
32.0307823320
120.91515692700
303.756989
0.000000
32.0307878050
120.91514836000
312.296997
0.000000
32.0307945510
120.91514116000
327.027008
0.000000
32.0308022350
120.91513533100
327.855988
0.000000
32.0308099090
120.91512965100
327.330994
0.000000
32.0308180980
120.91512338900
326.914001
0.000000
32.0308265120
120.91511760300
333.226013
0.000000
32.0308350690
120.91511249800
332.450012
0.000000
32.0308436950
120.91510715800
331.259003
0.000000
32.0308516230
120.91510207100
330.828003
0.000000
32.0308596170
120.91509688700
329.868988
0.000000
32.0308675160
120.91509126400
328.059998
0.000000
32.0308754470
120.91508499700
326.908997
0.000000
32.0308839230
120.91507948100
331.130005
0.000000
32.0308927370
120.91507461700
346.996002
0.000000
32.0309016030
120.91507282800
355.095001
0.000000

View File

View File

@ -0,0 +1,8 @@
32.0308500220
120.91511424200
0.000000
0.000000
0.0000000000
0.00000000000
0.000000
0.000000

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,4 @@
32.0937184760
120.79454789700
84.724998
0.000000

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,4 @@
32.0309222090
120.91505759600
170.675995
0.000000

View File

@ -0,0 +1,100 @@
32.0310917570
120.91525467400
349.971985
0.000000
32.0311007180
120.91525281000
347.497009
0.000000
32.0311098440
120.91525041500
345.182007
0.000000
32.0311188070
120.91524761800
346.235992
0.000000
32.0311277000
120.91524564100
354.537994
0.000000
32.0311374250
120.91524478800
357.682007
0.000000
32.0311464090
120.91524462200
0.736000
0.000000
32.0311554610
120.91524524600
10.159000
0.000000
32.0311641680
120.91524787300
22.878000
0.000000
32.0311729890
120.91525282200
26.490000
0.000000
32.0311815850
120.91525809100
32.991001
0.000000
32.0311895440
120.91526488500
38.161999
0.000000
32.0311965870
120.91527158500
42.695000
0.000000
32.0312034590
120.91527970700
51.610001
0.000000
32.0312087060
120.91528835600
59.937000
0.000000
32.0312130590
120.91529852200
66.385002
0.000000
32.0312169790
120.91530905400
69.073997
0.000000
32.0312201740
120.91531981700
74.775002
0.000000
32.0312224930
120.91533104600
79.578003
0.000000
32.0312241310
120.91534217100
85.223999
0.000000
32.0312249230
120.91535273500
85.499001
0.000000
32.0312258660
120.91536327800
83.461998
0.000000
32.0312269000
120.91537477100
84.094002
0.000000
32.0312278010
120.91538624100
86.753998
0.000000
32.0312285410
120.91539710300
85.632004
0.000000

View File

@ -0,0 +1,128 @@
32.0375316490
120.83905455600
19.548000
0.000000
32.0375403970
120.83905791600
16.787001
0.000000
32.0375494470
120.83906089500
18.728001
0.000000
32.0375580940
120.83906417800
16.931999
0.000000
32.0375668750
120.83906710200
15.215000
0.000000
32.0375755620
120.83906983700
17.690001
0.000000
32.0375843330
120.83907369500
25.292999
0.000000
32.0375926950
120.83907818200
23.892000
0.000000
32.0376012720
120.83908249100
21.660999
0.000000
32.0376100410
120.83908622800
11.699000
0.000000
32.0376194030
120.83908569000
329.757996
0.000000
32.0376258540
120.83907768600
291.979004
0.000000
32.0376286530
120.83906747200
285.864014
0.000000
32.0376314910
120.83905694000
287.569000
0.000000
32.0376341150
120.83904660600
285.967987
0.000000
32.0376366350
120.83903616600
284.270996
0.000000
32.0376389630
120.83902574200
287.441986
0.000000
32.0376417030
120.83901534800
285.648010
0.000000
32.0376440920
120.83900490600
284.085999
0.000000
32.0376444520
120.83899417800
243.916000
0.000000
32.0376382760
120.83898617500
203.432007
0.000000
32.0376294760
120.83898193300
202.016998
0.000000
32.0376210860
120.83897814100
200.774002
0.000000
32.0376121740
120.83897428200
198.322998
0.000000
32.0376032490
120.83897076800
197.960007
0.000000
32.0375944910
120.83896752100
199.412003
0.000000
32.0375855500
120.83896370400
201.190994
0.000000
32.0375771870
120.83895939500
205.367996
0.000000
32.0375687840
120.83895461400
215.358994
0.000000
32.0375626420
120.83894625600
251.973999
0.000000
32.0375611770
120.83893579000
269.428009
0.000000
32.0375613250
120.83892499100
278.270996
0.000000

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,220 @@
32.0375256980
120.83908732700
288.496002
0.000000
32.0375279710
120.83907656500
287.195007
0.000000
32.0375310130
120.83906577800
288.477997
0.000000
32.0375337750
120.83905559000
286.726990
0.000000
32.0375365390
120.83904455000
285.257996
0.000000
32.0375388070
120.83903429200
283.579010
0.000000
32.0375411100
120.83902311000
283.385986
0.000000
32.0375435310
120.83901196400
285.466003
0.000000
32.0375461980
120.83900175600
288.773987
0.000000
32.0375491970
120.83899086500
287.556000
0.000000
32.0375518980
120.83898059400
286.817993
0.000000
32.0375547370
120.83897050800
292.147003
0.000000
32.0375583880
120.83895991400
291.039001
0.000000
32.0375618000
120.83894918400
289.423004
0.000000
32.0375646410
120.83893908500
287.746002
0.000000
32.0375674900
120.83892903200
289.576996
0.000000
32.0375704910
120.83891904100
288.720001
0.000000
32.0375734540
120.83890807500
286.674988
0.000000
32.0375763220
120.83889719100
286.394989
0.000000
32.0375789620
120.83888608000
286.623993
0.000000
32.0375817910
120.83887600100
289.453003
0.000000
32.0375850130
120.83886510700
288.670013
0.000000
32.0375878220
120.83885502900
287.022003
0.000000
32.0375903110
120.83884482800
284.981995
0.000000
32.0375935440
120.83883389200
291.226013
0.000000
32.0375969360
120.83882308700
286.811005
0.000000
32.0375988100
120.83881185200
266.934998
0.000000
32.0375965090
120.83880142900
229.272995
0.000000
32.0375890820
120.83879537000
202.175003
0.000000
32.0375797620
120.83879350400
161.380005
0.000000
32.0375721170
120.83879915700
133.274002
0.000000
32.0375660230
120.83880714800
117.611000
0.000000
32.0375624140
120.83881710100
112.405998
0.000000
32.0375589100
120.83882748900
110.486000
0.000000
32.0375557660
120.83883746900
110.531998
0.000000
32.0375523070
120.83884829300
106.041000
0.000000
32.0375498350
120.83885851700
106.042999
0.000000
32.0375472140
120.83886961000
104.768997
0.000000
32.0375454970
120.83888001200
103.069000
0.000000
32.0375427810
120.83889109100
110.514999
0.000000
32.0375397100
120.83890105200
108.686996
0.000000
32.0375364590
120.83891194800
111.352997
0.000000
32.0375329920
120.83892275500
110.000999
0.000000
32.0375299460
120.83893369500
107.347000
0.000000
32.0375271450
120.83894477800
105.801003
0.000000
32.0375246820
120.83895591900
106.535004
0.000000
32.0375221830
120.83896611500
104.922997
0.000000
32.0375197880
120.83897730800
102.987999
0.000000
32.0375178320
120.83898773700
98.748001
0.000000
32.0375187530
120.83899896600
56.189999
0.000000
32.0375261200
120.83900626900
10.275000
0.000000
32.0375356410
120.83900514400
324.920990
0.000000
32.0375413680
120.83899695300
285.876007
0.000000
32.0375428460
120.83898625700
275.144012
0.000000
32.0375436860
120.83897525300
276.519989
0.000000

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

54
run.sh
View File

@ -1,54 +0,0 @@
#!/bin/bash
source install/setup.bash # ros workspace
{
gnome-terminal --title="radio" --tab "XXD_ros" -- bash -c "ros2 run radio_ctrl radio_ctrl_node"
}&
sleep 0.2s
{
gnome-terminal --title="mc" --tab "XXD_ros" -- bash -c "ros2 run mc mc_node"
}&
sleep 0.2s
{
gnome-terminal --title="ctrl_arbiter" --tab "XXD_ros" -- bash -c "ros2 run ctrl_arbiter ctrl_arbiter_node"
}&
sleep 0.2s
{
gnome-terminal --title="report" --tab "XXD_ros" -- bash -c "ros2 run mqtt_report mqtt_report_node"
}&
sleep 0.2s
{
gnome-terminal --title="lidar" --tab "XXD_ros" -- bash -c "ros2 launch rslidar_sdk start_double.launch.py"
}&
sleep 0.1s
{
gnome-terminal --title="rtk" --tab "XXD_ros" -- bash -c "ros2 run rtk rtk_node"
}&
sleep 0.1s
{
gnome-terminal --title="route" --tab "XXD_ros" -- bash -c "ros2 run route route_node"
}&
sleep 0.1s
{
gnome-terminal --title="sub" --tab "XXD_ros" -- bash -c "ros2 run sub sub_node"
}&
sleep 0.1s
{
gnome-terminal --title="task_manager" --tab "XXD_ros" -- bash -c "ros2 run task_manager task_manager_node"
}&
sleep 0.1s
{
gnome-terminal --title="pl" --tab "XXD_ros" -- bash -c "ros2 run pl pl_node"
}&
sleep 0.1s
{
gnome-terminal --title="fu" --tab "XXD_ros" -- bash -c "ros2 launch fu fu.launch.py"
}
sleep 0.1s
{
gnome-terminal --title="pub_gps" --tab "XXD_ros" -- bash -c "ros2 run pub_gps pub_gps_node"
}

View File

@ -1,28 +0,0 @@
from launch import LaunchDescription
from launch_ros.actions import Node
from ament_index_python.packages import get_package_share_directory
def generate_launch_description():
rviz_config = get_package_share_directory("rslidar_sdk") + "/rviz/rviz2.rviz"
config_file = "" # your config file path
return LaunchDescription(
[
Node(
namespace="rslidar_sdk",
package="rslidar_sdk",
executable="rslidar_sdk_node",
output="screen",
parameters=[{"config_path": config_file}],
),
# Node(
# namespace="rviz2",
# package="rviz2",
# executable="rviz2",
# arguments=["-d", rviz_config],
# ),
]
)

View File

@ -16,13 +16,10 @@ if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
endif()
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
add_compile_options(-w) #
add_compile_options(-w) #
endif()
include_directories(
include/fu
${catkin_INCLUDE_DIRS}
)
include_directories(include/fu ${catkin_INCLUDE_DIRS})
# find dependencies
find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)
@ -30,19 +27,23 @@ find_package(std_msgs REQUIRED)
find_package(sweeper_interfaces REQUIRED)
find_package(sensor_msgs REQUIRED)
find_package(mc REQUIRED)
find_package(logger REQUIRED)
include_directories(include)
add_executable(fu_node src/fu_node.cpp src/jsoncpp.cpp)
ament_target_dependencies(fu_node rclcpp std_msgs sweeper_interfaces sensor_msgs mc)
install(TARGETS
ament_target_dependencies(
fu_node
DESTINATION lib/${PROJECT_NAME}
)
rclcpp
std_msgs
sweeper_interfaces
sensor_msgs
mc
logger)
install(DIRECTORY launch config
DESTINATION share/${PROJECT_NAME})
install(TARGETS fu_node DESTINATION lib/${PROJECT_NAME})
install(DIRECTORY launch config DESTINATION share/${PROJECT_NAME})
if(BUILD_TESTING)
find_package(ament_lint_auto REQUIRED)
@ -53,6 +54,6 @@ if(BUILD_TESTING)
# uncomment the line when this package is not in a git repo
#set(ament_cmake_cpplint_FOUND TRUE)
ament_lint_auto_find_test_dependencies()
endif()
endif()
ament_package()

View File

@ -1,7 +1,7 @@
FU:
ros__parameters:
# 遇障停车功能 False or True
enable_obstacle_stop: False
enable_obstacle_stop: True
# 绕障功能 False or True
enable_obstacle_avoid: False
@ -29,4 +29,19 @@ FU:
# 右侧扩展检测区域 int
right_area_extend: 2
# 路点到达容差(米)
waypoint_tolerance: 0.1
# 横向偏移量(栅格数)
lateral_offset: 2
# 平行前进距离(栅格数)
parallel_distance: 3
# 可绕过的最大障碍物宽度(栅格数)
avoid_able_width: 6
# 绕过所需最小空间(栅格数)
min_free_space: 6

File diff suppressed because it is too large Load Diff

View File

@ -21,19 +21,19 @@ find_package(rclcpp REQUIRED)
find_package(std_msgs REQUIRED)
find_package(sweeper_interfaces REQUIRED)
# find_package(mc REQUIRED)
find_package(logger REQUIRED)
include_directories(
include/pl
${catkin_INCLUDE_DIRS}
)
include_directories(include/pl ${catkin_INCLUDE_DIRS})
add_executable(pl_node src/pl_node.cpp src/pl.cpp src/jsoncpp.cpp)
ament_target_dependencies(pl_node rclcpp std_msgs sweeper_interfaces)
install(TARGETS
ament_target_dependencies(
pl_node
DESTINATION lib/${PROJECT_NAME}
)
rclcpp
std_msgs
sweeper_interfaces
logger)
install(TARGETS pl_node DESTINATION lib/${PROJECT_NAME})
if(BUILD_TESTING)
find_package(ament_lint_auto REQUIRED)
@ -44,6 +44,6 @@ if(BUILD_TESTING)
# uncomment the line when this package is not in a git repo
#set(ament_cmake_cpplint_FOUND TRUE)
ament_lint_auto_find_test_dependencies()
endif()
endif()
ament_package()

View File

@ -13,6 +13,7 @@
<depend>std_msgs</depend>
<depend>sweeper_interfaces</depend>
<depend>mc</depend>
<depend>logger</depend>
<test_depend>ament_lint_auto</test_depend>
<test_depend>ament_lint_common</test_depend>

View File

@ -1,21 +1,24 @@
#include "pl.hpp"
#include <iostream>
#include <unistd.h>
#include <string.h>
#include <math.h>
#include <string.h>
#include <unistd.h>
#include <iostream>
#include "logger/logger.h"
using namespace std;
#define WRC_MAX_POINTS_IN_PATH 2000
#define Lat_Origin 32.045062 // 地面平面坐标系原点的纬度
#define Lon_Origin 118.845200366 // 地面平面坐标系原点的经度
#define Lat_Origin 32.045062 // 地面平面坐标系原点的纬度
#define Lon_Origin 118.845200366 // 地面平面坐标系原点的经度
#define Re 6378137
#define Rn 6356755
#define deg_rad (0.01745329252) // Transfer from angle degree to rad
#define deg_rad (0.01745329252) // Transfer from angle degree to rad
#define R_LATI (6378137)
#define R_LONT (5407872) // 这个需要根据所在区域的纬度进行换算R_LONT = R_LATI*cos(所在地的纬度转化为弧度)
#define R_LONT (5407872) // 这个需要根据所在区域的纬度进行换算R_LONT = R_LATI*cos(所在地的纬度转化为弧度)
float nl_radius;
int nl_within_radius;
@ -39,18 +42,19 @@ TaskStatus task_status = TaskStatus::PENDING;
double ntzx_GPS_length(double lonti1, double lati1, double lonti2, double lati2)
{
double x, y, length;
x = (R_LONT) * (lonti2 - lonti1) * deg_rad; // 弧长公式
x = (R_LONT) * (lonti2 - lonti1) * deg_rad; // 弧长公式
y = (R_LATI) * (lati2 - lati1) * deg_rad;
length = sqrt(x * x + y * y);
return length;
}
// Cur_navAngle指定y轴正方向.Cur_lontiCur_lati为原点x_diff,y_diff是Dest_lonti,Dest_lati在该坐标系的直角坐标:m
int ntzx_GPS_posit(double Cur_navAngle, double Cur_lonti, double Cur_lati, double Dest_lonti, double Dest_lati, double *x_diff, double *y_diff)
int ntzx_GPS_posit(double Cur_navAngle, double Cur_lonti, double Cur_lati, double Dest_lonti, double Dest_lati,
double* x_diff, double* y_diff)
{
double Navi_rad, x, y;
float k1, k2, k3, k4; // 旋转矩阵的四个参数对应cos(theta),-sin(theta),sin(theta),cos(theta);
Navi_rad = Cur_navAngle * deg_rad; // 角度转化为弧度
float k1, k2, k3, k4; // 旋转矩阵的四个参数对应cos(theta),-sin(theta),sin(theta),cos(theta);
Navi_rad = Cur_navAngle * deg_rad; // 角度转化为弧度
// 以当前位置为原点以正北为y正轴以正东为x正轴
x = (Dest_lonti - Cur_lonti) * deg_rad * R_LONT;
y = (Dest_lati - Cur_lati) * deg_rad * R_LATI;
@ -66,31 +70,30 @@ int ntzx_GPS_posit(double Cur_navAngle, double Cur_lonti, double Cur_lati, doubl
}
// Find_Nearest_Point
int Road_Planning_Find_Nearest_Point(int start_index, WRC_MC_NAV_INFO Cur_GPS_info, WRC_GPS_Point *Road_info)
int Road_Planning_Find_Nearest_Point(int start_index, WRC_MC_NAV_INFO Cur_GPS_info, WRC_GPS_Point* Road_info)
{
if (start_index < 0)
{
return -1;
}
int Nearest_point_index = start_index; // 初始化为起始索引
int Nearest_point_index = start_index; // 初始化为起始索引
double min_distance = ntzx_GPS_length(Cur_GPS_info.Longitude_degree, Cur_GPS_info.Latitude_degree,
Road_info[start_index].LongitudeInfo,
Road_info[start_index].LatitudeInfo);
Road_info[start_index].LongitudeInfo, Road_info[start_index].LatitudeInfo);
// 从 start_index + 1 开始搜索
for (int i = 1; i < GpsPointNum; i++)
{
int current_index = (start_index + i) % GpsPointNum; // 环绕访问
int current_index = (start_index + i) % GpsPointNum; // 环绕访问
double current_distance = ntzx_GPS_length(Cur_GPS_info.Longitude_degree, Cur_GPS_info.Latitude_degree,
Road_info[current_index].LongitudeInfo,
Road_info[current_index].LatitudeInfo);
double current_distance =
ntzx_GPS_length(Cur_GPS_info.Longitude_degree, Cur_GPS_info.Latitude_degree,
Road_info[current_index].LongitudeInfo, Road_info[current_index].LatitudeInfo);
if (current_distance < min_distance)
{
min_distance = current_distance;
Nearest_point_index = current_index; // 更新最近点的索引
Nearest_point_index = current_index; // 更新最近点的索引
// 如果距离小于 0.8 m提前退出
if (min_distance < 0.8)
@ -100,7 +103,7 @@ int Road_Planning_Find_Nearest_Point(int start_index, WRC_MC_NAV_INFO Cur_GPS_in
}
}
return Nearest_point_index; // 返回最近点的索引
return Nearest_point_index; // 返回最近点的索引
}
/*
int Road_Planning_Find_Nearest_Point(int start_index, WRC_MC_NAV_INFO Cur_GPS_info, WRC_GPS_Point *Road_info)
@ -112,13 +115,15 @@ int Road_Planning_Find_Nearest_Point(int start_index, WRC_MC_NAV_INFO Cur_GPS_in
}
int Nearest_point_index = 0;
double aft_distance = 0, pre_distance = 0;
pre_distance = ntzx_GPS_length(Cur_GPS_info.Longitude_degree, Cur_GPS_info.Latitude_degree, Road_info[start_index].LongitudeInfo, Road_info[start_index].LatitudeInfo);
pre_distance = ntzx_GPS_length(Cur_GPS_info.Longitude_degree, Cur_GPS_info.Latitude_degree,
Road_info[start_index].LongitudeInfo, Road_info[start_index].LatitudeInfo);
int start = start_index + 1;
for (int i = start; i < GpsPointNum; i++)
{
aft_distance = ntzx_GPS_length(Cur_GPS_info.Longitude_degree, Cur_GPS_info.Latitude_degree, Road_info[i].LongitudeInfo, Road_info[i].LatitudeInfo);
aft_distance = ntzx_GPS_length(Cur_GPS_info.Longitude_degree, Cur_GPS_info.Latitude_degree,
Road_info[i].LongitudeInfo, Road_info[i].LatitudeInfo);
// printf("i: %d , aft_distance: %lf \t",i,aft_distance);
if (aft_distance < pre_distance)
{
@ -152,7 +157,7 @@ int Road_Planning_Find_Aim_Point(int start_index, int dest_num)
return (dest_index);
}
int star_find_nearest_point(double lon, double lat, WRC_GPS_Point *Road_info)
int star_find_nearest_point(double lon, double lat, WRC_GPS_Point* Road_info)
{
double dis = 10000;
int point = 0;
@ -164,7 +169,7 @@ int star_find_nearest_point(double lon, double lat, WRC_GPS_Point *Road_info)
dis = dis_temp;
point = i;
}
printf("i: %d , dis_temp: %lf", i, dis_temp);
LOG_DEBUG("i: %d , dis_temp: %lf", i, dis_temp);
}
return point;
}
@ -174,8 +179,7 @@ Direction straight_or_turn(double cur_direction, double des_direction, int thres
{
double diff = std::fmod(std::fabs(cur_direction - des_direction), 360.0);
if (diff > 180)
diff = 360 - diff;
if (diff > 180) diff = 360 - diff;
// std::cout << "diff : " << diff << std::endl;
@ -211,13 +215,8 @@ void PL_ProcThread()
// double head_raw = g_NavInfo.Yaw_rad;
road_pos = Road_Planning_Find_Nearest_Point(des_pos - 3, g_NavInfo, GPSPointQueue);
des_pos = Road_Planning_Find_Aim_Point(road_pos, 3); // 找到当前点后第 3 个点,作为目标点
direction_pos = Road_Planning_Find_Aim_Point(road_pos, 6); // 找到当前点后第 6 个点,判断直行/转弯
printf("当前位置: %d\n", road_pos);
printf("目标位置: %d\n", des_pos);
// printf("direction_pos: %d\n", direction_pos);
printf("\n");
des_pos = Road_Planning_Find_Aim_Point(road_pos, 3); // 找到当前点后第 3 个点,作为目标点
direction_pos = Road_Planning_Find_Aim_Point(road_pos, 6); // 找到当前点后第 6 个点,判断直行/转弯
drive_mode = straight_or_turn(g_rtk.direction, GPSPointQueue[direction_pos].Heading, 12);
@ -229,6 +228,12 @@ void PL_ProcThread()
double target_lat = GPSPointQueue[des_pos].LatitudeInfo;
double target_head = GPSPointQueue[des_pos].Heading;
LOG_INFO_THROTTLE(1000, "当前位置: %d 经度: %.6f 纬度: %.6f 朝向: %.1f", road_pos, current_lon, current_lat,
current_head);
LOG_INFO_THROTTLE(1000, "目标位置: %d 经度: %.6f 纬度: %.6f 朝向: %.1f", des_pos, target_lon, target_lat,
target_head);
LOG_INFO_THROTTLE(1000, "############################################################");
// 计算当前定位点与目标点距离
double distance = ntzx_GPS_length(current_lon, current_lat, target_lon, target_lat);
int nl_within_head = (abs(target_head - current_head) < 30) ? 1 : 0;
@ -238,16 +243,15 @@ void PL_ProcThread()
// cout << " * * * * * * * * * * * * * * * * * * * * *" << endl;
// cout << endl;
// cout << "--- -target_head " << target_head << "--- current_head " << current_head << " " << abs(target_head - current_head) << endl;
// cout << endl;
// cout << "--- -distance " << distance << "- -nl_radius " << nl_radius << endl;
// cout << "--- -target_head " << target_head << "--- current_head " << current_head << " " <<
// abs(target_head - current_head) << endl; cout << endl; cout << "--- -distance " << distance << "- -nl_radius
// " << nl_radius << endl;
// cout << endl;
// cout << " * * * * * * * * * * * * * * * * * * * * *" << endl;
if (road_pos >= (GpsPointNum - 1))
{
x = 0.0;
y = 1.0;
pl_speed = 0;
@ -260,10 +264,8 @@ void PL_ProcThread()
double x_cm_tmp = 0;
double y_cm_tmp = 0;
ntzx_GPS_posit(g_rtk.direction, g_rtk.lon, g_rtk.lat,
GPSPointQueue[des_pos].LongitudeInfo,
GPSPointQueue[des_pos].LatitudeInfo,
&x_cm_tmp, &y_cm_tmp);
ntzx_GPS_posit(g_rtk.direction, g_rtk.lon, g_rtk.lat, GPSPointQueue[des_pos].LongitudeInfo,
GPSPointQueue[des_pos].LatitudeInfo, &x_cm_tmp, &y_cm_tmp);
x = x_cm_tmp;
y = y_cm_tmp;
@ -277,20 +279,20 @@ void PL_ProcThread()
return;
}
void *pl_thread(void *args)
void* pl_thread(void* args)
{
(void)args;
sleep(3);
memset(GPSPointQueue, 0, sizeof(GPSPointQueue));
FILE *fp_gps = fopen("gps_load_now.txt", "r");
FILE* fp_gps = fopen("gps_load_now.txt", "r");
if (NULL == fp_gps)
{
printf("open route file error\n");
LOG_ERROR("open route file error");
return NULL;
}
std::cout << "have opened " << "gps_load_now.txt" << std::endl;
LOG_INFO("have opened gps_load_now.txt");
char mystring[200];
memset(mystring, '\0', 200);
@ -318,11 +320,10 @@ void *pl_thread(void *args)
}
GpsPointNum = i / 4;
printf("point_num:%d\n", GpsPointNum);
LOG_INFO("point_num:%d", GpsPointNum);
fclose(fp_gps);
std::cout << std::endl;
printf("#################### auto drive on! ####################\n");
LOG_INFO("#################### auto drive on! ####################");
PL_ProcThread();
return NULL;

View File

@ -1,22 +1,24 @@
#include <arpa/inet.h>
#include <pthread.h>
#include <sys/socket.h>
#include <unistd.h>
#include <chrono> // 新增:用于时间戳处理
#include <cstring>
#include <fstream>
#include <iostream>
#include "json.h"
#include "logger/logger.h"
#include "pl.hpp"
#include "rclcpp/rclcpp.hpp"
#include "sweeper_interfaces/msg/rtk.hpp"
#include "sweeper_interfaces/msg/pl.hpp"
#include "sweeper_interfaces/msg/route.hpp"
#include "sweeper_interfaces/msg/rtk.hpp"
#include "sweeper_interfaces/msg/task.hpp"
#include "json.h"
#include <pthread.h>
#include <iostream>
#include <fstream>
#include <unistd.h>
#include "pl.hpp"
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <cstring>
#include <chrono> // 新增:用于时间戳处理
using namespace std;
using namespace std::chrono; // 新增:时间戳命名空间
using namespace std::chrono; // 新增:时间戳命名空间
pthread_t pl_thread_t;
int is_start = 0;
@ -25,38 +27,43 @@ static int sock = -1;
// 新增全局变量记录最后接收RTK数据的时间戳
system_clock::time_point last_rtk_time;
// 新增超时阈值0.5秒)
const duration<double> rtk_timeout = duration<double>(0.2);
const duration<double> rtk_timeout = duration<double>(0.5);
class pl_node : public rclcpp::Node
{
public:
public:
pl_node(std::string name) : Node(name)
{
RCLCPP_INFO(this->get_logger(), "%s节点已经启动.", name.c_str());
LOG_INFO("%s节点已经启动.", name.c_str());
// 初始化最后接收时间为当前时间(避免初始状态直接超时)
last_rtk_time = system_clock::now();
// 创建订阅者订阅话题
msg_subscribe_ = this->create_subscription<sweeper_interfaces::msg::Rtk>("rtk_message", 10, std::bind(&pl_node::msg_callback, this, std::placeholders::_1));
task_subscribe_ = this->create_subscription<sweeper_interfaces::msg::Task>("task_message/download", 10, std::bind(&pl_node::task_callback, this, std::placeholders::_1));
msg_subscribe_ = this->create_subscription<sweeper_interfaces::msg::Rtk>(
"rtk_message", 10, std::bind(&pl_node::msg_callback, this, std::placeholders::_1));
task_subscribe_ = this->create_subscription<sweeper_interfaces::msg::Task>(
"task_message/download", 10, std::bind(&pl_node::task_callback, this, std::placeholders::_1));
// 创建发布者
msg_publisher_ = this->create_publisher<sweeper_interfaces::msg::Pl>("pl_message", 10);
task_publisher_ = this->create_publisher<sweeper_interfaces::msg::Task>("task_message/upload", 10);
// 创建定时器,定时发布
timer_pl = this->create_wall_timer(std::chrono::milliseconds(500), std::bind(&pl_node::timer_callback_pl, this));
timer_task = this->create_wall_timer(std::chrono::milliseconds(200), std::bind(&pl_node::timer_callback_task, this));
timer_pl =
this->create_wall_timer(std::chrono::milliseconds(500), std::bind(&pl_node::timer_callback_pl, this));
timer_task =
this->create_wall_timer(std::chrono::milliseconds(200), std::bind(&pl_node::timer_callback_task, this));
}
private:
private:
// 收到话题数据的回调函数
void msg_callback(const sweeper_interfaces::msg::Rtk::SharedPtr msg)
{
// 新增:更新最后接收时间戳
last_rtk_time = system_clock::now();
// RCLCPP_INFO(this->get_logger(), "lat:'%.9lf',lon:'%.9lf',head:'%lf',speed:'%lf',p_quality:'%d',h_quality:'%d'",
// LOG_INFO(
// "lat:'%.9lf',lon:'%.9lf',head:'%lf',speed:'%lf',p_quality:'%d',h_quality:'%d'",
// msg->lat, msg->lon, msg->head, msg->speed, msg->p_quality, msg->h_quality);
g_rtk.reliability = 1;
@ -75,19 +82,19 @@ private:
if (is_start == 0 && msg->task_status == 1)
{
pthread_create(&pl_thread_t, NULL, pl_thread, NULL);
cout << " started" << endl;
LOG_INFO("started");
is_start = 1;
task_status = TaskStatus::PENDING;
}
else if (is_start == 1 && msg->task_status == 0)
{
pthread_cancel(pl_thread_t);
cout << "pl_thread_t is canceled " << endl;
LOG_INFO("pl_thread_t is canceled");
is_start = 0;
task_status = TaskStatus::COMPLETED;
}
// RCLCPP_INFO(this->get_logger(), " ==================================== is_start : %d", is_start);
// RCLCPP_INFO(this->get_logger(), " ==================================== task_status : %d", msg->task_status);
// LOG_INFO(" ==================================== is_start : %d", is_start);
// LOG_INFO(" ==================================== task_status : %d", msg->task_status);
}
void timer_callback_pl()
@ -98,12 +105,12 @@ private:
if (is_start == 1)
{
if (sock < 0) // 首次连接
if (sock < 0) // 首次连接
{
struct sockaddr_in serv_addr;
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
RCLCPP_ERROR(this->get_logger(), "Socket creation error");
LOG_ERROR("Socket creation error");
return;
}
@ -112,31 +119,31 @@ private:
if (inet_pton(AF_INET, "192.168.5.1", &serv_addr.sin_addr) <= 0)
{
RCLCPP_ERROR(this->get_logger(), "Invalid address/ Address not supported");
LOG_ERROR("Invalid address/ Address not supported");
close(sock);
return;
}
if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
if (connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0)
{
RCLCPP_ERROR(this->get_logger(), "Connection Failed");
LOG_ERROR("Connection Failed");
close(sock);
sock = -1;
return;
}
}
const char *message = "Status: RUNNING";
if (send(sock, message, strlen(message), 0) < 0) // 发送失败则重建连接
const char* message = "Status: RUNNING";
if (send(sock, message, strlen(message), 0) < 0) // 发送失败则重建连接
{
close(sock);
sock = -1;
return timer_callback_pl(); // 重试
return timer_callback_pl(); // 重试
}
}
else if (sock >= 0)
{
close(sock); // 停止时关闭连接
close(sock); // 停止时关闭连接
sock = -1;
}
@ -144,18 +151,18 @@ private:
sweeper_interfaces::msg::Pl message;
message.x = x;
message.y = y;
// 修改同时判断RTK信号质量和超时情况
if (g_rtk.reliability == 0 || time_since_last > rtk_timeout)
{
message.speed = 0;
if (time_since_last > rtk_timeout)
{
RCLCPP_ERROR(this->get_logger(), "RTK数据超时(%.2fs),停车!!!", time_since_last.count());
LOG_ERROR("RTK数据超时(%.2fs),停车!!!", time_since_last.count());
}
else
{
RCLCPP_ERROR(this->get_logger(), "RTK信号差停车");
LOG_ERROR("RTK信号差停车");
}
}
else
@ -163,17 +170,18 @@ private:
message.reliability = g_rtk.reliability;
// message.drive_mode = drive_mode;
if (drive_mode == Direction::STRAIGHT_D) // 直行
if (drive_mode == Direction::STRAIGHT_D) // 直行
message.drive_mode = 0;
else if (drive_mode == Direction::LEFT_TURN || drive_mode == Direction::RIGHT_TURN) // 转弯
else if (drive_mode == Direction::LEFT_TURN || drive_mode == Direction::RIGHT_TURN) // 转弯
message.drive_mode = 1;
message.enter_range = nl_within_radius;
message.is_start = is_start;
// RCLCPP_INFO(this->get_logger(), " ==================================== message.is_start : %d", message.is_start);
// LOG_INFO(" ==================================== message.is_start : %d",
// message.is_start);
// 日志打印
// RCLCPP_INFO(this->get_logger(), "x:'%lf',y:'%lf',speed:'%lf',drive_mode:'%d'",
// LOG_INFO("x:'%lf',y:'%lf',speed:'%lf',drive_mode:'%d'",
// message.x, message.y, message.speed, message.drive_mode);
// 发布消息
msg_publisher_->publish(message);
@ -207,24 +215,28 @@ void initConfig()
std::ifstream in("config.json", std::ios::binary);
if (!in.is_open())
{
std::cout << "read config file error" << std::endl;
LOG_ERROR("read config file error");
return;
}
if (reader.parse(in, root))
{
nl_radius = root["detect_line_tolerance"].as<double>();
}
in.close(); // 关闭文件流
in.close(); // 关闭文件流
}
int main(int argc, char **argv)
int main(int argc, char** argv)
{
initConfig();
rclcpp::init(argc, argv);
// 初始化日志系统
logger::Logger::Init("pl", "./nodes_log");
/*创建对应节点的共享指针对象*/
auto node = std::make_shared<pl_node>("pl_node");
/* 运行节点,并检测退出信号*/
rclcpp::spin(node);
rclcpp::shutdown();
// 关闭日志系统
logger::Logger::Shutdown();
// pthread_join(pl_thread_t, NULL);
return 0;

View File

@ -21,23 +21,20 @@ find_package(rclcpp REQUIRED)
find_package(std_msgs REQUIRED)
find_package(sweeper_interfaces REQUIRED)
find_package(CURL REQUIRED)
find_package(logger REQUIRED)
include_directories(include/route ${catkin_INCLUDE_DIRS})
include_directories(
include/route
${catkin_INCLUDE_DIRS}
)
add_executable(route_node
src/route_node.cpp
src/md5.cpp
src/jsoncpp.cpp)
ament_target_dependencies(route_node rclcpp std_msgs sweeper_interfaces CURL)
install(TARGETS
add_executable(route_node src/route_node.cpp src/md5.cpp src/jsoncpp.cpp)
ament_target_dependencies(
route_node
DESTINATION lib/${PROJECT_NAME}
)
rclcpp
std_msgs
sweeper_interfaces
CURL
logger)
install(TARGETS route_node DESTINATION lib/${PROJECT_NAME})
if(BUILD_TESTING)
find_package(ament_lint_auto REQUIRED)
@ -48,5 +45,5 @@ if(BUILD_TESTING)
# uncomment the line when this package is not in a git repo
#set(ament_cmake_cpplint_FOUND TRUE)
ament_lint_auto_find_test_dependencies()
endif()
endif()
ament_package()

View File

@ -12,6 +12,7 @@
<depend>rclcpp</depend>
<depend>std_msgs</depend>
<depend>sweeper_interfaces</depend>
<depend>logger</depend>
<test_depend>ament_lint_auto</test_depend>
<test_depend>ament_lint_common</test_depend>

View File

@ -1,25 +1,28 @@
#include <curl/curl.h>
#include <pthread.h>
#include <unistd.h>
#include <chrono>
#include <cstdio>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <mutex>
#include <sstream>
#include "json.h"
#include "logger/logger.h"
#include "md5.h"
#include "rclcpp/rclcpp.hpp"
#include "sweeper_interfaces/msg/rtk.hpp"
#include "sweeper_interfaces/msg/sub.hpp"
#include <curl/curl.h>
#include "md5.h"
#include "json.h"
#include <pthread.h>
#include <iostream>
#include <unistd.h>
#include <cstdio>
#include <chrono>
#include "sweeper_interfaces/msg/vehicle_identity.hpp"
#include <fstream>
#include <sstream>
#include <iomanip>
#include <mutex>
std::mutex collect_mutex; // 互斥锁,用于保护 isCollecting 变量
std::mutex collect_mutex; // 互斥锁,用于保护 isCollecting 变量
#define deg_rad (0.01745329252) // Transfer from angle degree to rad
#define deg_rad (0.01745329252) // Transfer from angle degree to rad
#define R_LATI (6378137)
#define R_LONT (5407872) // 这个需要根据所在区域的纬度进行换算R_LONT = R_LATI*cos(所在地的纬度转化为弧度)
#define R_LONT (5407872) // 这个需要根据所在区域的纬度进行换算R_LONT = R_LATI*cos(所在地的纬度转化为弧度)
using namespace std;
/* 存储接收RTK的GPS点信息 */
struct struct_rtk
@ -40,83 +43,95 @@ struct_rtk last_g_rtk = {};
string vid;
string upload_URL;
std::string destinationFilePath1 = "./gps_load_now.txt";
void *route_thread(void *args);
void* route_thread(void* args);
string calculate_md5(string filename)
{
MD5 md5;
ifstream file;
file.open(filename, ios::binary);
md5.update(file);
cout << md5.toString() << endl;
LOG_INFO("%s", md5.toString().c_str());
return md5.toString();
}
bool upload_file(string filename)
{
CURL *curl;
CURL* curl;
CURLcode ret;
curl = curl_easy_init();
struct curl_httppost *post = NULL;
struct curl_httppost *last = NULL;
curl_formadd(&post, &last, CURLFORM_PTRNAME, "vid", CURLFORM_PTRCONTENTS, vid.c_str(), CURLFORM_END); // form-data key(path) 和 value(device_cover)
struct curl_httppost* post = NULL;
struct curl_httppost* last = NULL;
// 只计算一次MD5值
string md5_value = calculate_md5(filename);
curl_formadd(&post, &last, CURLFORM_PTRNAME, "vid", CURLFORM_PTRCONTENTS, vid.c_str(),
CURLFORM_END); // form-data key(path) 和 value(device_cover)
curl_formadd(&post, &last, CURLFORM_COPYNAME, "file", CURLFORM_FILE, filename.c_str(), CURLFORM_END);
curl_formadd(&post, &last, CURLFORM_COPYNAME, "md5", CURLFORM_COPYCONTENTS, calculate_md5(filename).c_str(), CURLFORM_END);
curl_formadd(&post, &last, CURLFORM_COPYNAME, "md5", CURLFORM_COPYCONTENTS, md5_value.c_str(), CURLFORM_END);
curl_easy_setopt(curl, CURLOPT_URL, upload_URL.c_str());
curl_easy_setopt(curl, CURLOPT_HTTPPOST, post);
ret = curl_easy_perform(curl);
if (ret != CURLE_OK)
{
fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(ret));
LOG_ERROR("curl_easy_perform() failed: %s", curl_easy_strerror(ret));
return false;
}
curl_formfree(post);
curl_easy_cleanup(curl);
cout << "上传成功" << endl;
LOG_INFO("上传成功");
return true;
}
void copyFileAndOverwrite(const std::string &sourceFilePath, const std::string &destinationFilePath)
void copyFileAndOverwrite(const std::string& sourceFilePath, const std::string& destinationFilePath)
{
std::ifstream src(sourceFilePath, std::ios::binary);
std::ofstream dst(destinationFilePath, std::ios::binary);
if (!src)
{
std::cerr << "无法打开源文件: " << sourceFilePath << std::endl;
LOG_ERROR("无法打开源文件: %s", sourceFilePath.c_str());
return;
}
if (!dst)
{
std::cerr << "无法打开目标文件: " << destinationFilePath << std::endl;
LOG_ERROR("无法打开目标文件: %s", destinationFilePath.c_str());
return;
}
dst << src.rdbuf(); // 将源文件内容复制到目标文件
dst << src.rdbuf(); // 将源文件内容复制到目标文件
if (!dst)
{
std::cerr << "复制文件时出错" << std::endl;
LOG_ERROR("复制文件时出错");
}
}
class route_node : public rclcpp::Node
{
public:
public:
route_node(std::string name) : Node(name)
{
RCLCPP_INFO(this->get_logger(), "%s节点已经启动.", name.c_str());
LOG_INFO("%s节点已经启动.", name.c_str());
// 创建一个订阅者订阅话题
sub_subscribe_ = this->create_subscription<sweeper_interfaces::msg::Sub>("gather", 10, std::bind(&route_node::sub_callback, this, std::placeholders::_1));
sub_subscribe_ = this->create_subscription<sweeper_interfaces::msg::Sub>(
"gather", 10, std::bind(&route_node::sub_callback, this, std::placeholders::_1));
msg_subscribe_ = this->create_subscription<sweeper_interfaces::msg::Rtk>("rtk_message", 10, std::bind(&route_node::msg_callback, this, std::placeholders::_1));
msg_subscribe_ = this->create_subscription<sweeper_interfaces::msg::Rtk>(
"rtk_message", 10, std::bind(&route_node::msg_callback, this, std::placeholders::_1));
// identitytransient_local确保晚启动也能拿到
identity_sub_ = this->create_subscription<sweeper_interfaces::msg::VehicleIdentity>(
"/vehicle/identity", rclcpp::QoS(1).transient_local().reliable(),
std::bind(&route_node::identityCallback, this, std::placeholders::_1));
}
private:
private:
// 收到话题数据的回调函数
void msg_callback(const sweeper_interfaces::msg::Rtk::SharedPtr msg)
{
if (msg->p_quality < 4 || msg->h_quality < 4)
{
g_rtk.reliability = 0;
RCLCPP_INFO(this->get_logger(), "rtk信号差!");
LOG_INFO("rtk信号差!");
}
if (first_flag)
{
@ -133,52 +148,60 @@ private:
if (!isCollecting)
{
cout << "等待采集...." << endl;
LOG_INFO("等待采集.....");
}
else
{
cout << "平台采集中" << endl;
LOG_INFO("平台采集中.....");
}
}
void sub_callback(const sweeper_interfaces::msg::Sub::SharedPtr msg)
{
if (msg->get_route && !isCollecting)
{
std::lock_guard<std::mutex> lock(collect_mutex); // 加锁
std::lock_guard<std::mutex> lock(collect_mutex); // 加锁
isCollecting = true;
cout << "平台开始采集" << endl;
LOG_INFO("平台开始采集");
pthread_create(&route_thread_t, NULL, route_thread, NULL);
}
else if (!msg->get_route && isCollecting)
{
isCollecting = false;
cout << "平台结束采集" << endl;
LOG_INFO("平台结束采集");
pthread_cancel(route_thread_t);
if (upload_file(filename))
{
cout << "上传成功" << endl;
LOG_INFO("上传成功");
}
else
{
cout << "上传失败" << endl;
LOG_INFO("上传失败");
}
}
}
void identityCallback(const sweeper_interfaces::msg::VehicleIdentity::SharedPtr msg)
{
vid = msg->vid;
LOG_INFO("Identity: VID=%s", msg->vid.c_str());
}
// 声明订阅者
rclcpp::Subscription<sweeper_interfaces::msg::Sub>::SharedPtr sub_subscribe_;
rclcpp::Subscription<sweeper_interfaces::msg::Rtk>::SharedPtr msg_subscribe_;
rclcpp::Subscription<sweeper_interfaces::msg::VehicleIdentity>::SharedPtr identity_sub_;
};
double ntzx_GPS_length(double lonti1, double lati1, double lonti2, double lati2)
{
double x, y, length;
x = (R_LONT) * (lonti2 - lonti1) * deg_rad; // 弧长公式
x = (R_LONT) * (lonti2 - lonti1) * deg_rad; // 弧长公式
y = (R_LATI) * (lati2 - lati1) * deg_rad;
length = sqrt(x * x + y * y);
return length;
}
void *route_thread(void *args)
void* route_thread(void* args)
{
(void)args;
filename = "";
@ -193,12 +216,12 @@ void *route_thread(void *args)
oss << "routes/gps_load_" << timestamp << ".txt";
filename = oss.str();
FILE *fp_routes = fopen(filename.c_str(), "w");
FILE* fp_routes = fopen(filename.c_str(), "w");
usleep(5000);
while (1)
{
double distance = ntzx_GPS_length(last_g_rtk.lon, last_g_rtk.lat, g_rtk.lon, g_rtk.lat);
if (distance >= 1.0) // 每隔1米采样一次
if (distance >= 1.0) // 每隔1米采样一次
{
fprintf(fp_routes, "%.10lf\n%.11lf\n%lf\n%lf\n", g_rtk.lat, g_rtk.lon, g_rtk.head, 0.0);
fflush(fp_routes);
@ -206,7 +229,7 @@ void *route_thread(void *args)
last_g_rtk.lat = g_rtk.lat;
last_g_rtk.lon = g_rtk.lon;
last_g_rtk.head = g_rtk.head;
printf("hit!\n");
LOG_DEBUG("hit!");
}
}
}
@ -218,27 +241,29 @@ void init_main()
std::ifstream in("config.json", std::ios::binary);
if (!in.is_open())
{
std::cout << "read config file error" << std::endl;
LOG_ERROR("read config file error");
return;
}
if (reader.parse(in, root))
{
vid = root["mqtt"]["vid"].asString();
upload_URL = root["mqtt"]["upload_url"].asString();
cout << "vid:" << vid << endl;
}
in.close(); // 关闭文件流
in.close(); // 关闭文件流
}
int main(int argc, char **argv)
int main(int argc, char** argv)
{
init_main();
rclcpp::init(argc, argv);
/*初始化日志系统*/
logger::Logger::Init("route", "./nodes_log");
/*创建对应节点的共享指针对象*/
auto node = std::make_shared<route_node>("route_node");
/* 运行节点,并检测退出信号*/
rclcpp::spin(node);
rclcpp::shutdown();
/*关闭日志系统*/
logger::Logger::Shutdown();
// pthread_join(route_thread_t, NULL);
return 0;
}

View File

@ -11,6 +11,7 @@ find_package(ament_index_cpp REQUIRED)
find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)
find_package(std_msgs REQUIRED)
find_package(logger REQUIRED)
# src .cpp
file(GLOB SRC_FILES src/*.cpp)
@ -18,15 +19,19 @@ file(GLOB SRC_FILES src/*.cpp)
#
add_executable(mc_node ${SRC_FILES})
ament_target_dependencies(mc_node ament_index_cpp rclcpp std_msgs sweeper_interfaces)
ament_target_dependencies(
mc_node
ament_index_cpp
rclcpp
std_msgs
sweeper_interfaces
logger)
# Set include directories for the target
target_include_directories(
mc_node
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>)
target_include_directories(mc_node PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>)
target_compile_features(mc_node PUBLIC c_std_99 cxx_std_17)
target_compile_features(mc_node PUBLIC c_std_99 cxx_std_17)
# Install target
install(TARGETS mc_node DESTINATION lib/${PROJECT_NAME})

108
src/base/mc/VID透传.md Normal file
View File

@ -0,0 +1,108 @@
# CAN 协议定义 — VID 透传报文
## 1 报文基本信息
| 项目 | 内容 |
|-----|-----|
| 报文名称 | VID_Transmit |
| 报文功能 | 透传设备 VID |
| CAN ID | 0x180 |
| 帧类型 | Standard Frame |
| DLC | 8 |
| 发送方式 | 按需发送 |
| 发送节点 | MCU |
| 接收节点 | VCU / 上位机 |
---
## 2 数据格式
| Byte | 信号名称 | 类型 | 说明 |
|-----|----------|------|------|
| Byte0 | VID_CHAR1 | ASCII | VID 第1个字符 |
| Byte1 | VID_CHAR2 | ASCII | VID 第2个字符 |
| Byte2 | VID_CHAR3 | ASCII | VID 第3个字符 |
| Byte3 | VID_CHAR4 | ASCII | VID 第4个字符 |
| Byte4 | VID_CHAR5 | ASCII | VID 第5个字符 |
| Byte5 | VID_CHAR6 | ASCII | VID 第6个字符 |
| Byte6 | VID_CHAR7 | ASCII | VID 第7个字符 |
| Byte7 | XOR_CHECK | uint8 | Byte0~Byte6 异或校验 |
---
## 3 校验规则
XOR 校验计算方式:
`CHECK = Byte0 ^ Byte1 ^ Byte2 ^ Byte3 ^ Byte4 ^ Byte5 ^ Byte6`
校验值存放在:
`Byte7`
接收端校验规则:
`(Byte0 ^ Byte1 ^ Byte2 ^ Byte3 ^ Byte4 ^ Byte5 ^ Byte6) == Byte7`
成立则数据有效。
---
## 4 数据编码说明
VID 使用 **7 位 ASCII 字符**编码。
常见字符范围:
| 字符 | ASCII HEX |
|-----|-----------|
| 0 ~ 9 | 0x30 ~ 0x39 |
| A ~ Z | 0x41 ~ 0x5A |
---
## 5 报文示例
示例 VID
`V060003`
ASCII 编码:
`56 30 36 30 30 30 33`
计算 XOR
`56 ^ 30 ^ 36 ^ 30 ^ 30 ^ 30 ^ 33 = 03`
最终 CAN 报文:
| ID | DLC | DATA |
|----|-----|------|
| 0x180 | 8 | 56 30 36 30 30 30 33 03 |
---
## 6 接收端解析流程
1. 接收 CAN 报文
2. 计算 Byte0~Byte6 XOR
3. 与 Byte7 比较
4. 校验通过则解析 ASCII 字符串
字符串提取:
`VID = Byte0~Byte6`
示例:
`V060003`
---
## 7 约束说明
- VID 固定 **7 字符**
- 不包含字符串结束符 `\0`
- 必须为 **ASCII 可打印字符**
- CAN DLC 固定为 **8**

View File

@ -1,30 +1,29 @@
#ifndef CAN_STRUCT_H
#define CAN_STRUCT_H
#include <cstdint>
#include <array>
#include <string.h>
#include <array>
#include <cstdint>
#include <iostream>
#include "can_driver.h"
#pragma pack(push, 1) // 禁止结构体补齐确保8字节紧密排列
#pragma pack(push, 1) // 禁止结构体补齐确保8字节紧密排列
struct can_BMS_query_0x100
{
// 报文ID与控制标志定义
static constexpr uint32_t CMD_ID = 0x100; // 标准帧ID
static constexpr bool EXT_FLAG = false; // 11位标准帧
static constexpr bool RTR_FLAG = false; // 普通数据帧(非远程帧)
static constexpr uint8_t DLC = 8; // 数据长度为8字节
static constexpr uint32_t CMD_ID = 0x100; // 标准帧ID
static constexpr bool EXT_FLAG = false; // 11位标准帧
static constexpr bool RTR_FLAG = true; // 普通数据帧(非远程帧)
static constexpr uint8_t DLC = 8; // 数据长度为8字节
// 数据区主机查询时通常发送全0
uint8_t data[8];
// 构造函数初始化数据为0
can_BMS_query_0x100()
{
memset(data, 0, sizeof(data));
}
can_BMS_query_0x100() { memset(data, 0, sizeof(data)); }
// 生成CAN帧
CANFrame toFrame() const
@ -42,19 +41,16 @@ struct can_BMS_query_0x100
struct can_BMS_query_0x101
{
// 报文ID与控制标志定义
static constexpr uint32_t CMD_ID = 0x101; // 标准帧ID
static constexpr bool EXT_FLAG = false; // 11位标准帧
static constexpr bool RTR_FLAG = false; // 普通数据帧(非远程帧)
static constexpr uint8_t DLC = 8; // 数据长度为8字节
static constexpr uint32_t CMD_ID = 0x101; // 标准帧ID
static constexpr bool EXT_FLAG = false; // 11位标准帧
static constexpr bool RTR_FLAG = true; // 普通数据帧(非远程帧)
static constexpr uint8_t DLC = 8; // 数据长度为8字节
// 数据区主机查询时通常发送全0
uint8_t data[8];
// 构造函数初始化数据为0
can_BMS_query_0x101()
{
memset(data, 0, sizeof(data));
}
can_BMS_query_0x101() { memset(data, 0, sizeof(data)); }
// 生成CAN帧
CANFrame toFrame() const
@ -85,10 +81,10 @@ union can_MCU_cmd_union
// Byte 3: 开关信号状态
struct
{
uint8_t cmd_status : 2; // BIT0-1: 命令状态(0空挡,1后退,2前进,3保留)
uint8_t brake : 1; // BIT2: 刹车开关(1=开)
uint8_t reserved_bit3 : 1; // BIT3: 保留
uint8_t reserved_bits47 : 4; // BIT4-7: 保留
uint8_t cmd_status : 2; // BIT0-1: 命令状态(0空挡,1后退,2前进,3保留)
uint8_t brake : 1; // BIT2: 刹车开关(1=开)
uint8_t reserved_bit3 : 1; // BIT3: 保留
uint8_t reserved_bits47 : 4; // BIT4-7: 保留
} switch_status;
// Byte 4-7: 保留
@ -105,14 +101,14 @@ union can_EPS_cmd_union
{
struct
{
uint8_t control_mode; // 控制方式
uint8_t reserve1; // 保留
uint8_t reserve2; // 保留
uint8_t angle_h; // 角度高位
uint8_t angle_l; // 角度低位
uint8_t center_cmd; // 角度对中指令
uint8_t angular_speed; // 角速度控制
uint8_t checksum; // 异或校验
uint8_t control_mode; // 控制方式
uint8_t reserve1; // 保留
uint8_t reserve2; // 保留
uint8_t angle_h; // 角度高位
uint8_t angle_l; // 角度低位
uint8_t center_cmd; // 角度对中指令
uint8_t angular_speed; // 角速度控制
uint8_t checksum; // 异或校验
} fields;
uint8_t bytes[8];
@ -134,36 +130,30 @@ struct can_MCU_cmd
{
memset(&data, 0, sizeof(data));
// 初始化默认值
data.fields.can_enabled = 0; // 默认不使能
data.fields.switch_status.cmd_status = 0; // 默认空挡
data.fields.switch_status.brake = 1; // 默认刹车
data.fields.can_enabled = 0; // 默认不使能
data.fields.switch_status.cmd_status = 0; // 默认空挡
data.fields.switch_status.brake = 1; // 默认刹车
}
// 设置使能状态
void setEnabled(bool en)
{
data.fields.can_enabled = en ? 1 : 0;
}
void setEnabled(bool en) { data.fields.can_enabled = en ? 1 : 0; }
// 设置档位 (0空挡,1后退,2前进,3保留)
void setGear(uint8_t gear)
{
data.fields.switch_status.cmd_status = gear & 0x03; // 只保留低2位
data.fields.switch_status.cmd_status = gear & 0x03; // 只保留低2位
}
// 设置刹车状态
void setBrake(bool brake_on)
{
data.fields.switch_status.brake = brake_on ? 1 : 0;
}
void setBrake(bool brake_on) { data.fields.switch_status.brake = brake_on ? 1 : 0; }
// 设置转速 (0-6000rpm)
void setRPM(uint16_t rpm)
{
// 限制转速范围0-6000
uint16_t clamped_rpm = std::clamp(rpm, static_cast<uint16_t>(0), static_cast<uint16_t>(6000));
data.fields.speed_low = clamped_rpm & 0xFF; // 低字节
data.fields.speed_high = (clamped_rpm >> 8) & 0xFF; // 高字节
data.fields.speed_low = clamped_rpm & 0xFF; // 低字节
data.fields.speed_high = (clamped_rpm >> 8) & 0xFF; // 高字节
}
CANFrame toFrame() const
@ -175,12 +165,12 @@ struct can_MCU_cmd
frame.ext = EXT_FLAG;
frame.rtr = RTR_FLAG;
// std::cout << "MCU frame : ";
// LOG_INFO("MCU frame : ");
// for (int i = 0; i < 8; ++i)
// {
// printf("0X%x ", frame.data[i]);
// LOG_INFO("0X%x ", frame.data[i]);
// }
// printf("\n");
// LOG_INFO("");
return frame;
}
@ -208,10 +198,7 @@ struct can_EPS_cmd
data.fields.angle_l = raw & 0xFF;
}
void setCenterCmd(uint8_t cmd)
{
data.fields.center_cmd = cmd;
}
void setCenterCmd(uint8_t cmd) { data.fields.center_cmd = cmd; }
void setAngularSpeed(uint16_t angle_speed)
{
@ -285,52 +272,28 @@ struct can_VCU_motor1_cmd
int8_t data[8]{};
// 设置Byte0
void setByte0(int8_t direction)
{
data[0] = std::clamp(direction, static_cast<int8_t>(0), static_cast<int8_t>(2));
}
void setByte0(int8_t direction) { data[0] = std::clamp(direction, static_cast<int8_t>(0), static_cast<int8_t>(2)); }
// 设置Byte1
void setByte1(int8_t value)
{
data[1] = std::clamp(value, static_cast<int8_t>(0), static_cast<int8_t>(100));
}
void setByte1(int8_t value) { data[1] = std::clamp(value, static_cast<int8_t>(-100), static_cast<int8_t>(100)); }
// 设置Byte2
void setByte2(int8_t value)
{
data[2] = std::clamp(value, static_cast<int8_t>(0), static_cast<int8_t>(100));
}
void setByte2(int8_t value) { data[2] = std::clamp(value, static_cast<int8_t>(-100), static_cast<int8_t>(100)); }
// 设置Byte3
void setByte3(int8_t value)
{
data[3] = std::clamp(value, static_cast<int8_t>(0), static_cast<int8_t>(100));
}
void setByte3(int8_t value) { data[3] = std::clamp(value, static_cast<int8_t>(-100), static_cast<int8_t>(100)); }
// 设置Byte4
void setByte4(int8_t value)
{
data[4] = std::clamp(value, static_cast<int8_t>(0), static_cast<int8_t>(100));
}
void setByte4(int8_t value) { data[4] = std::clamp(value, static_cast<int8_t>(-100), static_cast<int8_t>(100)); }
// 设置Byte5
void setByte5(int8_t value)
{
data[5] = std::clamp(value, static_cast<int8_t>(0), static_cast<int8_t>(100));
}
void setByte5(int8_t value) { data[5] = std::clamp(value, static_cast<int8_t>(-100), static_cast<int8_t>(100)); }
// 设置Byte6
void setByte6(int8_t value)
{
data[6] = std::clamp(value, static_cast<int8_t>(0), static_cast<int8_t>(100));
}
void setByte6(int8_t value) { data[6] = std::clamp(value, static_cast<int8_t>(-100), static_cast<int8_t>(100)); }
// 设置Byte7
void setByte7(int8_t value)
{
data[7] = std::clamp(value, static_cast<int8_t>(0), static_cast<int8_t>(100));
}
void setByte7(int8_t value) { data[7] = std::clamp(value, static_cast<int8_t>(-100), static_cast<int8_t>(100)); }
CANFrame toFrame() const
{
@ -354,52 +317,28 @@ struct can_VCU_motor2_cmd
int8_t data[8]{};
// 设置Byte0
void setByte0(int8_t value)
{
data[0] = std::clamp(value, static_cast<int8_t>(0), static_cast<int8_t>(100));
}
void setByte0(int8_t value) { data[0] = std::clamp(value, static_cast<int8_t>(-100), static_cast<int8_t>(100)); }
// 设置Byte1
void setByte1(int8_t value)
{
data[1] = std::clamp(value, static_cast<int8_t>(0), static_cast<int8_t>(100));
}
void setByte1(int8_t value) { data[1] = std::clamp(value, static_cast<int8_t>(-100), static_cast<int8_t>(100)); }
// 设置Byte2
void setByte2(int8_t value)
{
data[2] = std::clamp(value, static_cast<int8_t>(0), static_cast<int8_t>(100));
}
void setByte2(int8_t value) { data[2] = std::clamp(value, static_cast<int8_t>(-100), static_cast<int8_t>(100)); }
// 设置Byte3
void setByte3(int8_t value)
{
data[3] = std::clamp(value, static_cast<int8_t>(0), static_cast<int8_t>(100));
}
void setByte3(int8_t value) { data[3] = std::clamp(value, static_cast<int8_t>(-100), static_cast<int8_t>(100)); }
// 设置Byte4
void setByte4(int8_t value)
{
data[4] = std::clamp(value, static_cast<int8_t>(0), static_cast<int8_t>(100));
}
void setByte4(int8_t value) { data[4] = std::clamp(value, static_cast<int8_t>(-100), static_cast<int8_t>(100)); }
// 设置Byte5
void setByte5(int8_t value)
{
data[5] = std::clamp(value, static_cast<int8_t>(0), static_cast<int8_t>(100));
}
void setByte5(int8_t value) { data[5] = std::clamp(value, static_cast<int8_t>(-100), static_cast<int8_t>(100)); }
// 设置Byte6
void setByte6(int8_t value)
{
data[6] = std::clamp(value, static_cast<int8_t>(0), static_cast<int8_t>(100));
}
void setByte6(int8_t value) { data[6] = std::clamp(value, static_cast<int8_t>(-100), static_cast<int8_t>(100)); }
// 设置Byte7
void setByte7(int8_t value)
{
data[7] = std::clamp(value, static_cast<int8_t>(0), static_cast<int8_t>(100));
}
void setByte7(int8_t value) { data[7] = std::clamp(value, static_cast<int8_t>(-100), static_cast<int8_t>(100)); }
CANFrame toFrame() const
{

View File

@ -1,6 +1,10 @@
#pragma once
#include "rclcpp/rclcpp.hpp"
#include "mc/can_driver.h"
#include <functional>
// 注册所有定时器任务
void setupTimers(rclcpp::Node::SharedPtr node, CANDriver &canctl);
// 注册 VID 发送定时器任务
void setupVidTimer(rclcpp::Node::SharedPtr node, std::function<void()> callback);

View File

@ -0,0 +1,114 @@
#pragma once
#include <cstdint>
#include <cstring>
#include <string>
#include "logger/logger.h"
#include "mc/can_driver.h"
namespace vid_transmit
{
constexpr uint32_t VID_CAN_ID = 0x180;
constexpr uint8_t VID_DLC = 8;
constexpr size_t VID_LENGTH = 7;
/**
* @brief XOR
* @param data 7
* @return
*/
inline uint8_t calculate_xor_check(const uint8_t* data)
{
uint8_t check = 0;
for (size_t i = 0; i < VID_LENGTH; ++i)
{
check ^= data[i];
}
return check;
}
/**
* @brief VID
* @param vid VID
* @return
*/
inline bool validate_vid(const std::string& vid)
{
if (vid.length() != VID_LENGTH)
{
LOG_WARN("VID length invalid: expected %zu, got %zu", VID_LENGTH, vid.length());
return false;
}
for (char c : vid)
{
// 检查是否为 7 位 ASCII 可打印字符
if (static_cast<uint8_t>(c) > 0x7F || c < 0x20)
{
LOG_WARN("VID contains invalid character: 0x%02X", static_cast<uint8_t>(c));
return false;
}
}
return true;
}
/**
* @brief VID CAN
* @param vid VID 7ASCII字符
* @param frame CAN
* @return
*/
inline bool build_vid_frame(const std::string& vid, CANFrame& frame)
{
if (!validate_vid(vid))
{
return false;
}
frame.id = VID_CAN_ID;
frame.dlc = VID_DLC;
frame.ext = false;
frame.rtr = false;
// 复制 VID ASCII 字符
std::memcpy(frame.data, vid.data(), VID_LENGTH);
// 计算并填充校验值
frame.data[7] = calculate_xor_check(frame.data);
return true;
}
/**
* @brief VID CAN 线
* @param can_driver CAN
* @param vid VID
* @return
*/
inline bool send_vid_to_can(CANDriver& can_driver, const std::string& vid)
{
CANFrame frame;
if (!build_vid_frame(vid, frame))
{
LOG_ERROR("Failed to build VID frame for VID: %s", vid.c_str());
return false;
}
if (!can_driver.sendFrame(frame))
{
LOG_ERROR_THROTTLE(5000, "Failed to send VID frame to CAN bus");
return false;
}
LOG_INFO_THROTTLE(5000, "VID sent to CAN bus: %s (CAN ID: 0x%03X, Data: %02X %02X %02X %02X %02X %02X %02X %02X)",
vid.c_str(), frame.id, frame.data[0], frame.data[1], frame.data[2], frame.data[3], frame.data[4],
frame.data[5], frame.data[6], frame.data[7]);
return true;
}
} // namespace vid_transmit

Some files were not shown because too many files have changed in this diff Show More