• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
MKT-porter
博客园    首页    新随笔    联系   管理    订阅  订阅
ros(1-2) 图像和GPS发布节点python版本

 

 node0_image_gps_publisher.py

 

#!/bin/bash

#外部给与执行权限
#sudo chmod +x run_ros_nodes.sh
# conda activate gaussian_splatting

WORKSPACE_DIR="/home/r9000k/v2_project/gaosi_slam/GNSS_openvslam/ros" # 修改1-1 自己创建的ros节点工程catkin_make根目录
python_DIR="/home/r9000k/v2_project/gaosi_slam/GNSS_openvslam/ros/src/gaosi_img_pose_flag/src" # 修改1-2 自己创建的python脚本位置

data_dir="/home/r9000k/v2_project/data/NWPU"

conda_envs="/home/r9000k/anaconda3" # 修改2-1 自己的conda 安装路径
#ROS_cv_briage_dir = "/home/r9000k/v1_software/opencv/catkin_ws_cv_bridge/devel/setup.bash" # 修改2-2 自己编译的cv_briage包节点,貌似不用也行 制定了依赖opencv3.4.9 而非自带4.2
#echo $ROS_cv_briage_dir
conda_envs_int=$conda_envs"/etc/profile.d/conda.sh" # 不用改 conda自带初始化文件
echo $conda_envs_int
conda_envs_bin=$conda_envs"/envs/gaussian_splatting/bin" # 不用改 conda自带python安装位置 脚本中需要指定是conda特定的环境python而不是系统默认的
echo $conda_envs_bin
ROS_SETUP="/opt/ros/noetic/setup.bash" #不用改  安装时候添加到系统路径了 不需要每次都source 这里留着
#指定目录

# 启动 ROS Master 不用改
echo "Starting ROS 总结点..."
gnome-terminal -- bash -c "\
cd $WORKSPACE_DIR; source devel/setup.bash; \  
roscore; \
exec bash"

# 等待 ROS Master 启动
sleep 3




# 运行 python 原始数据数据发布节点
echo "Running python 数据发布节点..."
echo "1 激活conda本身(脚本执行需要) 2 激活conda环境  3运行python 节点 并跟上输入参数['-g', '--gps_file' '-i', '--image_folder' ]"
gnome-terminal -- bash -c "\
source $conda_envs_int; \ 
cd $WORKSPACE_DIR; source devel/setup.bash; \
conda activate gaussian_splatting ; \
cd $python_DIR; \
python3 node0_image_gps_publisher.py \
-i $data_dir/images \
-g $data_dir/FHY_config/FHY_gps.txt \
;\
exec bash"

  

 

#!/usr/bin/env python

import rospy
import cv2
from cv_bridge import CvBridge
from sensor_msgs.msg import Image, NavSatFix
import os
import argparse

class ImageGPSReader:
    def __init__(self, gps_file, img_folder):
        # Initialize ROS node
        rospy.init_node('image_gps_publisher', anonymous=True)

        self.img_folder=img_folder
        self.gps_file=gps_file
         
        # Initialize publishers
        self.image_pub = rospy.Publisher('/camera/image_raw', Image, queue_size=10)
        self.gps_pub = rospy.Publisher('/gps/fix', NavSatFix, queue_size=10)
         
        # Initialize CvBridge
        self.bridge = CvBridge()
 
        # Load GPS and image data
        self.gps_data = self.load_gps_data(gps_file)
        self.image_files = self.load_image_filenames(img_folder)
 
    def load_gps_data(self, gps_file):
        gps_data = {}
        try:
            with open(gps_file, 'r') as f:
                for line in f:
                    parts = line.strip().split()
                    if len(parts) < 4:
                        continue
                    timestamp = parts[0]
                    lat, lon, alt = map(float, parts[1:])
                    gps_data[timestamp] = (lat, lon, alt)
        except Exception as e:
            rospy.logerr(f"Error loading GPS data: {e}")
        return gps_data
 
    def load_image_filenames(self, img_folder):
        try:
            image_files = [f for f in os.listdir(img_folder) if f.endswith('.jpg')]
            image_files.sort()
            return image_files
        except Exception as e:
            rospy.logerr(f"Error loading image files: {e}")
            return []

    def publish_data(self):
        rate = rospy.Rate(1)  # 10 Hz
         
        for img_file in self.image_files:
            timestamp = img_file.split('.')[0]+ "."+ img_file.split('.')[1]
            rospy.loginfo(f"Processing timestamp: {timestamp}")

            if timestamp in self.gps_data:
                img_path = os.path.join(self.img_folder, img_file)
                cv_image = cv2.imread(img_path)

                if cv_image is not None:
                    img_msg = self.bridge.cv2_to_imgmsg(cv_image, "bgr8")
                    img_msg.header.stamp = rospy.Time.from_sec(float(timestamp))
                    self.image_pub.publish(img_msg)

                    lat, lon, alt = self.gps_data[timestamp]
                    gps_msg = NavSatFix()
                    gps_msg.header.stamp = rospy.Time.from_sec(float(timestamp))
                    gps_msg.latitude = lat
                    gps_msg.longitude = lon
                    gps_msg.altitude = alt
                    self.gps_pub.publish(gps_msg)

                    rospy.loginfo(f"Published image: {img_file} and GPS data")
                else:
                    rospy.logwarn(f"Could not read image: {img_path}")
            else:
                rospy.logwarn(f"No GPS data for timestamp: {timestamp}")

            rate.sleep()  # Sleep to maintain the loop rate
 
#rosrun your_package image_gps_publisher.py -g /path/to/gps.txt -i /path/to/image_folder

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='Publish images and GPS data to ROS topics.')
    parser.add_argument('-g', '--gps_file', required=True, help='Path to the GPS data file')
    parser.add_argument('-i', '--image_folder', required=True, help='Path to the image folder')

    args = parser.parse_args()

    try:
        reader = ImageGPSReader(args.gps_file, args.image_folder)
        reader.publish_data()
    except rospy.ROSInterruptException:
        pass

  

 

 

image_gps_publisher.py

 

 

#!/usr/bin/env python

import rospy
import cv2
from cv_bridge import CvBridge
from sensor_msgs.msg import Image, NavSatFix
import os

class ImageGPSReader:
    def __init__(self):
        # Initialize ROS node
        rospy.init_node('image_gps_publisher', anonymous=True)
        
        # Initialize publishers
        self.image_pub = rospy.Publisher('/camera/image_raw', Image, queue_size=10)
        self.gps_pub = rospy.Publisher('/gps/fix', NavSatFix, queue_size=10)
        
        # Initialize CvBridge
        self.bridge = CvBridge()

        # Load GPS and image data
        self.gps_data = self.load_gps_data("/home/dongdong/2project/0data/NWPU/config/gps.txt")
        self.image_files = self.load_image_filenames("/home/dongdong/2project/0data/NWPU/img")

    def load_gps_data(self, gps_file):
        gps_data = {}
        with open(gps_file, 'r') as f:
            for line in f:
                parts = line.strip().split()
                timestamp = parts[0]
                lat, lon, alt = map(float, parts[1:])
                gps_data[timestamp] = (lat, lon, alt)
        return gps_data

    def load_image_filenames(self, img_folder):
        image_files = [f for f in os.listdir(img_folder) if f.endswith('.jpg')]
        image_files.sort()  # Ensure consistent ordering
        return image_files

    def publish_data(self):
        rate = rospy.Rate(10)  # 10 Hz
        
        for img_file in self.image_files:
            timestamp = img_file.split('.')[0]+ "."+ img_file.split('.')[1]  # Assuming timestamp is in the filename
            print("timestamp ",timestamp)

            if timestamp in self.gps_data:
                img_path = os.path.join("/home/dongdong/2project/0data/NWPU/img", img_file)
                cv_image = cv2.imread(img_path)

                if cv_image is not None:
                    # Publish image
                    img_msg = self.bridge.cv2_to_imgmsg(cv_image, "bgr8")
                    img_msg.header.stamp = rospy.Time.from_sec(float(timestamp))
                    self.image_pub.publish(img_msg)

                    # Publish GPS data
                    lat, lon, alt = self.gps_data[timestamp]
                    gps_msg = NavSatFix()
                    gps_msg.header.stamp = rospy.Time.from_sec(float(timestamp))
                    gps_msg.latitude = lat
                    gps_msg.longitude = lon
                    gps_msg.altitude = alt
                    self.gps_pub.publish(gps_msg)

                    rospy.loginfo(f"Published image: {img_file} and GPS data")

            rate.sleep()  # Sleep to maintain the loop rate


            

if __name__ == '__main__':
    try:
        reader = ImageGPSReader()
        reader.publish_data()
    except rospy.ROSInterruptException:
        pass

  

image_listener.py

 

#!/usr/bin/env python

import rospy
import cv2
from cv_bridge import CvBridge, CvBridgeError
from sensor_msgs.msg import Image, NavSatFix
from collections import deque
import threading
import queue
import time



# Initialize queues and locks
image_queue = queue.Queue()  # Thread-safe queue for images
gps_queue = deque()  # Queue for GPS messages
gps_queue_lock = threading.Lock()  # Lock for GPS queue

# Initialize CvBridge
bridge = CvBridge()

def gps_callback(gps_msg):
    """Callback function for GPS messages."""
    global gps_queue
    with gps_queue_lock:
        gps_queue.append(gps_msg)  # Add GPS message to the right end of the queue

def image_callback(image_msg):
    """Callback function for image messages."""
    global image_queue, gps_queue

    # Convert ROS image message to OpenCV image
    try:
        cv_image = bridge.imgmsg_to_cv2(image_msg, "bgr8")
    except CvBridgeError as e:
        rospy.logerr("CvBridge Error: %s", e)
        return

    # Get the timestamp of the image
    image_timestamp = image_msg.header.stamp.to_sec()

    # Store image and timestamp in the queue
    image_queue.put((cv_image, image_timestamp))

    with gps_queue_lock:
        while len(gps_queue) != 0:
            gps_msg = gps_queue.popleft()  # Remove GPS message from the left end
            gps_timestamp = gps_msg.header.stamp.to_sec()

            time_difference = image_timestamp - gps_timestamp
            rospy.loginfo(f"Image timestamp: {image_timestamp}, GPS timestamp: {gps_timestamp}, Time difference: {time_difference}")

            if abs(time_difference) <= 0.01:  # Match if time difference is within 10ms
                latitude = gps_msg.latitude
                longitude = gps_msg.longitude
                altitude = gps_msg.altitude

                rospy.loginfo(f"Match successful. Latitude: {latitude}, Longitude: {longitude}, Altitude: {altitude}")

                # Data is used, discard this GPS message
                break
            elif gps_timestamp < image_timestamp - 0.01:
                # Data too old, discard this GPS message
                rospy.loginfo("GPS data too old, discarding.")
                pass
            elif gps_timestamp > image_timestamp + 0.01:
                # Data too new, put it back for later use
                gps_queue.appendleft(gps_msg)  # Add to the left end for later processing
                rospy.loginfo("GPS data too new, putting back for later use.")
                break

def display_images():


    # Create a window to show matched images
    cv2.namedWindow("Matched Image", cv2.WINDOW_AUTOSIZE)

    """Thread function to display images."""
    while not rospy.is_shutdown():
        if not image_queue.empty():
            cv_image, image_timestamp = image_queue.get()
            if cv_image is None:
                #rospy.logwarn("Received empty image.")
                continue
            #rospy.loginfo("Displaying image...")
            cv2.imshow("Matched Image", cv_image)
            cv2.waitKey(1)  # Refresh the window
        else: 
            cv2.waitKey(1) # 不能空转 会出问题


def main():
    """Main function to initialize ROS node and subscribers."""
    rospy.init_node('image_gps_matcher', anonymous=True)

    # Subscribe to image and GPS topics
    rospy.Subscriber('/camera/image_raw', Image, image_callback)
    rospy.Subscriber('/gps/fix', NavSatFix, gps_callback)


    # Start the display thread
    display_thread = threading.Thread(target=display_images)
    display_thread.daemon = True  # Daemonize thread
    display_thread.start()

    try:
        rospy.spin()
    except rospy.ROSInterruptException:
        pass
    finally:
        cv2.destroyAllWindows()

if __name__ == '__main__':
    main()

  

 

posted on 2024-08-23 03:10  MKT-porter  阅读(107)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3