0、安装
sudo apt-get install ros-noetic-nmea-msgs ros-noetic-serial
cd ~/catkin_ws/src
git clone https://github.com/ros-drivers/nmea_navsat_driver
cd ~/catkin_ws
catkin_make -DCATKIN_WHITELIST_PACKAGES='nmea_navsat_driver'
编译如果报错,AI解决一下,我是少安装了包ros-noetic-nmea-navsat-driver
sudo apt-get install ros-noetic-nmea-navsat-driver
- roscore
2、第二个终端(开启rtk模块)
rosrun nmea_navsat_driver nmea_serial_driver _port:=/dev/ttyACM0 _baud:=115200 _frame_id:=gps _useGGA:=true _useRMC:=true _useGSA:=true _useGSV:=false
3、第三个终端
rostopic echo /fix
---
header:
seq: 178
stamp:
secs: 1769427995
nsecs: 840435028
frame_id: "gps"
status:
status: 0 //大于1才可能是开启RTK
service: 1
latitude: 30.323176666666665
longitude: 120.360728
altitude: nan
position_covariance: [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
position_covariance_type: 0
status.status = -1 表示 "无可用数据" 或 "服务不可用" 。在 sensor_msgs/NavSatFix 消息中,status.status 字段的值为:
-
-1: 无法定位(无可用数据) -
0: 未定位 -
1: GPS 定位(单点定位) -
2: DGPS 定位(差分 GPS) -
4: RTK 固定解(厘米级精度) -
5: RTK 浮点解(亚米级精度)
cd /home/zeh/catkin_ws/script
./rtk_diagnostic.sh
诊断rtk状态
#!/bin/bash
PORT="/dev/ttyACM0"
BAUD="115200"
LOG_FILE="rtk_diagnostic_$(date +%Y%m%d_%H%M%S).log"
echo "=== RTK 模块详细诊断 ===" | tee -a "$LOG_FILE"
echo "端口: $PORT" | tee -a "$LOG_FILE"
echo "波特率: $BAUD" | tee -a "$LOG_FILE"
echo "日志文件: $LOG_FILE" | tee -a "$LOG_FILE"
echo "时间: $(date)" | tee -a "$LOG_FILE"
echo "" | tee -a "$LOG_FILE"
# 1. 检查设备连接
echo "1. 检查设备连接..." | tee -a "$LOG_FILE"
if [ -c "$PORT" ]; then
echo " ✓ 设备 $PORT 存在" | tee -a "$LOG_FILE"
echo " 设备信息:" | tee -a "$LOG_FILE"
ls -l $PORT | tee -a "$LOG_FILE"
echo "" | tee -a "$LOG_FILE"
else
echo " ✗ 设备 $PORT 不存在!" | tee -a "$LOG_FILE"
echo " 请检查:" | tee -a "$LOG_FILE"
echo " 1. USB 连接是否牢固" | tee -a "$LOG_FILE"
echo " 2. 设备是否供电" | tee -a "$LOG_FILE"
echo " 3. 使用 dmesg | grep tty 查看设备识别" | tee -a "$LOG_FILE"
exit 1
fi
# 2. 设置串口参数
echo "2. 设置串口参数..." | tee -a "$LOG_FILE"
# 尝试设置串口参数,忽略错误(可能已经由其他程序设置)
stty -F $PORT raw 2>/dev/null
stty -F $PORT -echo -echoe -echok 2>/dev/null
# 3. 测试多个波特率
echo "3. 测试多个波特率..." | tee -a "$LOG_FILE"
echo " 每个波特率测试10秒..." | tee -a "$LOG_FILE"
echo "" | tee -a "$LOG_FILE"
BAUD_RATES=(9600 19200 38400 57600 115200 230400 460800)
FOUND_DATA=0
BEST_BAUD=""
for baud in "${BAUD_RATES[@]}"; do
echo " 测试波特率: $baud ..." | tee -a "$LOG_FILE"
# 设置波特率
stty -F $PORT $baud 2>/dev/null
# 清空缓冲区
timeout 0.1 cat $PORT > /dev/null 2>&1
# 收集数据(10秒)
echo " 正在接收数据 (10秒)..." | tee -a "$LOG_FILE"
DATA=$(timeout 10 cat $PORT 2>&1 | tr -d '\000')
if [ -n "$DATA" ]; then
# 统计行数
LINE_COUNT=$(echo "$DATA" | wc -l)
# 检查是否有有效的NMEA语句
NMEA_COUNT=$(echo "$DATA" | grep -c '^\$')
echo " ✓ 接收到 $LINE_COUNT 行数据,其中 $NMEA_COUNT 行是NMEA语句" | tee -a "$LOG_FILE"
if [ $NMEA_COUNT -gt 0 ]; then
FOUND_DATA=1
BEST_BAUD=$baud
echo " ⭐ 找到有效数据!波特率可能为: $baud" | tee -a "$LOG_FILE"
# 显示前几条NMEA语句
echo " 示例数据:" | tee -a "$LOG_FILE"
echo "$DATA" | grep '^\$' | head -5 | while read line; do
echo " $line" | tee -a "$LOG_FILE"
done
# 保存这个波特率的数据用于后续分析
echo "$DATA" > "rtk_data_${baud}.txt"
break
else
echo " ⚠ 有数据但不是NMEA格式" | tee -a "$LOG_FILE"
echo " 前100个字符: $(echo "$DATA" | head -c 100)" | tee -a "$LOG_FILE"
fi
else
echo " ✗ 没有数据" | tee -a "$LOG_FILE"
fi
echo "" | tee -a "$LOG_FILE"
done
echo "" | tee -a "$LOG_FILE"
if [ $FOUND_DATA -eq 0 ]; then
echo "4. 诊断结果: 未找到有效NMEA数据" | tee -a "$LOG_FILE"
echo " 可能原因:" | tee -a "$LOG_FILE"
echo " 1. 波特率不匹配(尝试了所有常见波特率)" | tee -a "$LOG_FILE"
echo " 2. 模块没有输出NMEA数据" | tee -a "$LOG_FILE"
echo " 3. 模块需要配置才能输出NMEA" | tee -a "$LOG_FILE"
echo " 4. 模块故障" | tee -a "$LOG_FILE"
echo "" | tee -a "$LOG_FILE"
echo "5. 建议操作:" | tee -a "$LOG_FILE"
echo " a) 使用Python脚本测试:" | tee -a "$LOG_FILE"
cat > test_serial.py << 'EOF'
#!/usr/bin/env python3
import serial
import time
port = '/dev/ttyACM0'
baud_rates = [9600, 19200, 38400, 57600, 115200, 230400, 460800]
for baud in baud_rates:
print(f"\n尝试波特率: {baud}")
try:
ser = serial.Serial(port, baud, timeout=2)
print("连接成功,等待数据...")
# 尝试读取20秒
start_time = time.time()
data_received = False
while time.time() - start_time < 20:
if ser.in_waiting > 0:
try:
line = ser.readline().decode('ascii', errors='ignore').strip()
if line:
print(f"收到: {line[:80]}")
data_received = True
break
except:
pass
time.sleep(0.1)
if not data_received:
print("20秒内没有收到数据")
ser.close()
except Exception as e:
print(f"连接失败: {e}")
EOF
echo " python3 test_serial.py" | tee -a "$LOG_FILE"
echo "" | tee -a "$LOG_FILE"
echo " b) 检查设备是否被其他程序占用:" | tee -a "$LOG_FILE"
echo " sudo lsof $PORT" | tee -a "$LOG_FILE"
echo "" | tee -a "$LOG_FILE"
echo " c) 检查设备原始数据(二进制):" | tee -a "$LOG_FILE"
echo " sudo od -x $PORT | head -20" | tee -a "$LOG_FILE"
exit 1
fi
# 4. 分析NMEA数据
echo "4. 分析NMEA数据 (波特率: $BEST_BAUD)..." | tee -a "$LOG_FILE"
DATA_FILE="rtk_data_${BEST_BAUD}.txt"
if [ -f "$DATA_FILE" ]; then
# 统计各种NMEA语句
echo " NMEA语句统计:" | tee -a "$LOG_FILE"
for msg_type in GGA RMC GSV GSA GST GLL; do
COUNT=$(grep -c "$msg_type" "$DATA_FILE" 2>/dev/null || echo 0)
echo " $msg_type: $COUNT" | tee -a "$LOG_FILE"
done
echo "" | tee -a "$LOG_FILE"
# 分析最新的GGA语句
LATEST_GGA=$(grep "GGA" "$DATA_FILE" | tail -1)
if [ -n "$LATEST_GGA" ]; then
echo " 最新GGA语句:" | tee -a "$LOG_FILE"
echo " $LATEST_GGA" | tee -a "$LOG_FILE"
echo "" | tee -a "$LOG_FILE"
# 解析GGA
IFS=',' read -ra PARTS <<< "$LATEST_GGA"
if [ ${#PARTS[@]} -gt 10 ]; then
TIME="${PARTS[1]:-N/A}"
LAT="${PARTS[2]:-N/A}${PARTS[3]:-}"
LON="${PARTS[4]:-N/A}${PARTS[5]:-}"
FIX_QUALITY="${PARTS[6]:-N/A}"
SAT_COUNT="${PARTS[7]:-N/A}"
HDOP="${PARTS[8]:-N/A}"
ALT="${PARTS[9]:-N/A}${PARTS[10]:-}"
echo " 解析结果:" | tee -a "$LOG_FILE"
echo " 时间(UTC): $TIME" | tee -a "$LOG_FILE"
echo " 纬度: $LAT" | tee -a "$LOG_FILE"
echo " 经度: $LON" | tee -a "$LOG_FILE"
echo " 定位质量: $FIX_QUALITY" | tee -a "$LOG_FILE"
echo " 使用卫星数: $SAT_COUNT" | tee -a "$LOG_FILE"
echo " HDOP: $HDOP" | tee -a "$LOG_FILE"
echo " 海拔: $ALT" | tee -a "$LOG_FILE"
# 定位质量说明
case $FIX_QUALITY in
"0") echo " 状态: 无效定位" | tee -a "$LOG_FILE" ;;
"1") echo " 状态: GPS单点定位" | tee -a "$LOG_FILE" ;;
"2") echo " 状态: 差分GPS" | tee -a "$LOG_FILE" ;;
"4") echo " ✅ 状态: RTK固定解 (厘米级精度)" | tee -a "$LOG_FILE" ;;
"5") echo " ⚠ 状态: RTK浮点解 (亚米级精度)" | tee -a "$LOG_FILE" ;;
"6") echo " 状态: 估算DR模式" | tee -a "$LOG_FILE" ;;
*) echo " 状态: 未知 ($FIX_QUALITY)" | tee -a "$LOG_FILE" ;;
esac
fi
else
echo " ⚠ 没有找到GGA语句" | tee -a "$LOG_FILE"
fi
echo "" | tee -a "$LOG_FILE"
# 分析卫星信息
LATEST_GSV=$(grep "GSV" "$DATA_FILE" | tail -4 | head -1)
if [ -n "$LATEST_GSV" ]; then
IFS=',' read -ra GSV_PARTS <<< "$LATEST_GSV"
TOTAL_SATS="${GSV_PARTS[3]:-0}"
echo " 卫星信息:" | tee -a "$LOG_FILE"
echo " 可见卫星总数: $TOTAL_SATS" | tee -a "$LOG_FILE"
if [ "$TOTAL_SATS" -lt 4 ]; then
echo " ⚠ 警告: 卫星少于4颗,无法定位" | tee -a "$LOG_FILE"
elif [ "$TOTAL_SATS" -lt 6 ]; then
echo " ⚠ 注意: 卫星数较少,定位精度可能受影响" | tee -a "$LOG_FILE"
else
echo " ✓ 卫星数量足够" | tee -a "$LOG_FILE"
fi
fi
echo "" | tee -a "$LOG_FILE"
# 检查是否有RTCM数据(RTK差分信号)
RTCM_COUNT=$(grep -c "RTCM" "$DATA_FILE" 2>/dev/null || echo 0)
if [ $RTCM_COUNT -gt 0 ]; then
echo " 📡 检测到RTCM差分数据 ($RTCM_COUNT 条)" | tee -a "$LOG_FILE"
else
echo " ⚠ 未检测到RTCM差分数据" | tee -a "$LOG_FILE"
echo " 如果你使用网络RTK或基站RTK,请检查差分源" | tee -a "$LOG_FILE"
fi
else
echo " ✗ 数据文件不存在" | tee -a "$LOG_FILE"
fi
echo "" | tee -a "$LOG_FILE"
# 5. 实时监控建议
echo "5. 实时监控 (运行以下命令):" | tee -a "$LOG_FILE"
echo " # 查看原始NMEA数据:" | tee -a "$LOG_FILE"
echo " stty -F $PORT $BEST_BAUD && cat $PORT" | tee -a "$LOG_FILE"
echo "" | tee -a "$LOG_FILE"
echo " # 使用Python实时监控:" | tee -a "$LOG_FILE"
cat > realtime_monitor.py << 'EOF'
#!/usr/bin/env python3
import serial
import time
from datetime import datetime
port = '/dev/ttyACM0'
baud = 115200 # 根据上面检测到的波特率修改
try:
ser = serial.Serial(port, baud, timeout=1)
print(f"连接到 {port} ({baud} baud)")
print("按 Ctrl+C 停止")
print("-" * 80)
while True:
try:
line = ser.readline().decode('ascii', errors='ignore').strip()
if line:
timestamp = datetime.now().strftime("%H:%M:%S")
if line.startswith('$GNGGA') or line.startswith('$GPGGA'):
parts = line.split(',')
if len(parts) > 7:
fix_quality = parts[6]
sats = parts[7]
fix_desc = {
'0': '无效', '1': 'GPS', '2': '差分',
'4': 'RTK固定', '5': 'RTK浮点'
}.get(fix_quality, fix_quality)
print(f"[{timestamp}] GGA: {fix_desc}解, {sats}颗卫星")
elif line.startswith('$GPGSV'):
parts = line.split(',')
if len(parts) > 3:
total_sats = parts[3]
print(f"[{timestamp}] GSV: 总共{total_sats}颗可见卫星")
elif line.startswith('$GPRMC'):
parts = line.split(',')
if len(parts) > 7:
speed_knots = float(parts[7]) if parts[7] else 0
speed_kmh = speed_knots * 1.852
print(f"[{timestamp}] RMC: 速度 {speed_kmh:.1f} km/h")
else:
# 显示其他语句类型
msg_type = line[3:6] if len(line) > 6 else "???"
print(f"[{timestamp}] {msg_type}: {line[:60]}...")
except UnicodeDecodeError:
continue
except KeyboardInterrupt:
print("\n停止监控")
break
except Exception as e:
print(f"错误: {e}")
EOF
echo " python3 realtime_monitor.py" | tee -a "$LOG_FILE"
echo "" | tee -a "$LOG_FILE"
echo "=== 诊断完成 ===" | tee -a "$LOG_FILE"
echo "详细日志已保存到: $LOG_FILE" | tee -a "$LOG_FILE"