ubuntu 通过ros-noetic获取RTK模块的nmea格式数据

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
  1. 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"
相关推荐
寻星探路1 小时前
【深度长文】万字攻克网络原理:从 HTTP 报文解构到 HTTPS 终极加密逻辑
java·开发语言·网络·python·http·ai·https
崔庆才丨静觅3 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
曹牧4 小时前
Spring Boot:如何测试Java Controller中的POST请求?
java·开发语言
passerby60614 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了4 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅4 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅4 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
爬山算法4 小时前
Hibernate(90)如何在故障注入测试中使用Hibernate?
java·后端·hibernate
kfyty7255 小时前
集成 spring-ai 2.x 实践中遇到的一些问题及解决方案
java·人工智能·spring-ai
猫头虎5 小时前
如何排查并解决项目启动时报错Error encountered while processing: java.io.IOException: closed 的问题
java·开发语言·jvm·spring boot·python·开源·maven