第三章:话题

1.编程环境VScode

  下载连接:Visual Studio Code - Code Editing. Redefined

    

  Ubuntu系统需要下载.deb文件 

  用终端打开文件所在目录

cd ~/下载

  安装VScode

sudo dpkg -i ./code_1.100.2-1747260578_amd64.deb
# code_1.100.2-1747260578_amd64.deb为文件名

  sudo:提升权限,允许对系统文件进行修改

  dpkg:调用 Debian 包管理工具。

 -i:表示“install”(安装),指定要执行的操作为安装软件包

2.话题

  2.1创建工作空间

  创建文件夹

mkdir text1

  进入文件夹目录

cd text1

  当前文件夹下启动VScode

code ./

 

  在当前目录下创建文件夹topic/src

  

  调出VScode在text1下的终端

ros2 pkg create topic_ws --build-type ament_python --license Apache-2.0 --dependencies rclpy example_interfaces

ros2 pkg create是固定的

topic_ws:功能包名字

--build-type ament_python :功能包类型为python

--license Apache-2.0 :功能包许可用Apache-2.0

--dependencies rclpy example_interfaces:添加依赖项rclpy和example_interfaces

生成目录表如下:

  回到topic/src目录下终端构建功能包(终端输入):

colcon build

 colcon 是一个用于构建和测试 ROS 工作空间的工具。

  buildcolcon 的一个子命令,用于构建工作空间中的包。

   

  2.2发布者

  在src/topic_ws文件夹下创建python文件topic_pub.py(python文件是以.py结尾)

代码:
# 导入ROS2 Python客户端库
import rclpy                             
# 从rclpy.node模块导入Node类,用于创建ROS2节点
from rclpy.node import Node              
# 导入requests库,用于发送HTTP请求获取网络资源
import requests                          
# 导入ROS2标准消息类型String
from example_interfaces.msg import String
# 导入Python标准库中的Queue,用于线程间通信
from queue import Queue

# 定义小说发布节点类,继承自Node类
class NovelPubNode(Node):                
    def __init__(self, node_name):       # 节点初始化方法
        super().__init__(node_name)      # 调用父类Node的初始化方法
        # 打印节点启动日志信息
        self.get_logger().info(f'{node_name},启动')  
        # 创建一个先进先出(FIFO)队列,用于存储小说文本行
        self.topic_queue = Queue()       
        # 创建一个发布者,发布到'novel'话题,消息类型为String,队列大小为10
        self.topic_pubulisher = self.create_publisher(String,'novel',10)   
        # 创建一个定时器,每5秒触发一次timer_callback回调函数
        self.create_timer(5, self.timer_callback)                           

    # 定时器回调函数
    def timer_callback(self):
        # 检查队列中是否有待发布的消息
        if self.topic_queue.qsize() > 0:
            # 从队列中获取一行文本
            line = self.topic_queue.get()
            # 创建一个String消息对象
            msg = String()
            # 将文本行存入消息的data字段
            msg.data = line
            # 发布消息到'novel'话题
            self.topic_pubulisher.publish(msg)
            # 打印发布日志
            self.get_logger().info(f'发布了:{msg}')

    # 下载小说文本方法
    def download(self, url):
        # 发送GET请求获取URL内容
        response = requests.get(url)
        # 设置响应内容的编码为UTF-8(确保正确处理中文字符)
        response.encoding = 'utf-8'
        # 获取响应文本内容
        text = response.text
        # 打印下载信息(URL和文本长度)
        self.get_logger().info(f'下载{url},{len(text)}')
        # 按行分割文本并存入队列
        for line in text.splitlines():
            self.topic_queue.put(line)

# 主函数
def main():
    # 初始化ROS2 Python客户端库
    rclpy.init()
    # 创建小说发布节点实例
    node = NovelPubNode('novel_pub')
    # 下载指定URL的小说文本
    node.download('http://0.0.0:8000/斗破苍穹.txt')
    # 保持节点运行,等待回调函数执行
    rclpy.spin(node)
    # 关闭ROS2 Python客户端库
    rclpy.shutdown()

  在setup.py中进行申明

'topic_pub = topic_ws.topic_pub:main'

  打开新的终端启动一个基于当前目录的静态文件 Web 服务器,默认监听 0.0.0.0:8000(所有  网络接口,端口 8000)

 python3 -m http.server

  网络上随意下载一节小说包,命名放在text1空间下

  

  构建功能包

colcon build

   为当前终端会话加载 ROS 工作空间的环境变量和功能包路径

source install/setup.bash 

   用ros2运行

ros2 run topic_ws topic_pub     # ros2运行topic_ws文件下的topic_pub可执行文件

  

  2.3订阅者  

  先在安装python3-pip

sudo apt install python3-pip

pip3 install espeakng

sudo apt install espeak-ng

  若在pip3 install espeakng部分报错error: externally-managed-environment,则需要虚拟环境能够创建独立的 Python 环境,可有效避免系统环境受到影响

# 安装python3.12-venv
sudo apt install python3.12-venv

# 创建虚拟环境
python3 -m venv myenv

# 激活虚拟环境
source myenv/bin/activate

# 在虚拟环境里安装包
pip install espeakng

# 使用完毕后停用虚拟环境
deactivate

  我用Ubuntu24.04.2不知道为什么会报错没有独立的python环境,之前有用ubuntu22则不会报错。

 在src/topic_ws文件夹下创建python文件topic_sub.py

import espeakng
# 导入ROS2 Python客户端库
import rclpy                             
# 从rclpy.node模块导入Node类,用于创建ROS2节点
from rclpy.node import Node              
# 导入requests库,用于发送HTTP请求获取网络资源
import requests                          
# 导入ROS2标准消息类型String
from example_interfaces.msg import String
# 导入Python标准库中的Queue,用于线程间通信
from queue import Queue
import threading
import time
 
# 定义小说订阅节点类,继承自ROS2的Node基类
# 该节点负责订阅小说文本消息并通过语音合成朗读出来
class NovelSubNode(Node):                
    def __init__(self, node_name):       # 节点初始化方法
        super().__init__(node_name)      # 调用父类Node的初始化方法
        
        # 打印节点启动日志信息
        self.get_logger().info(f'{node_name},启动')  
        
        # 创建一个先进先出(FIFO)队列,用于存储待朗读的小说文本行
        # 使用队列的目的是解耦消息接收和语音合成处理,避免阻塞主线程
        self.topic_queue = Queue()       
 
        # 创建一个订阅者,订阅名为'novel'的话题,消息类型为String
        # 当接收到新消息时,调用novel_callback方法处理
        self.topic_subscriber = self.create_subscription(
            String,
            'novel',
            self.novel_callback,
            10  # 消息队列大小,当消息处理不及时时最多缓存10条
        )
        
        # 创建并启动语音处理线程
        # 该线程独立于ROS2主循环,专门负责语音合成和朗读
        self.topic_thread = threading.Thread(target=self.speake_thread)  
        self.topic_thread.start()          
 
    # 话题回调函数,当接收到新的小说文本消息时被调用
    def novel_callback(self, msg):
        # 将接收到的文本消息放入队列
        self.topic_queue.put(msg.data)       
 
    # 语音处理线程的主函数
    def speake_thread(self):
        # 初始化espeak-ng语音合成器
        speaker = espeakng.Speaker()
        
        # 设置中文语音,这里正常可以使用'zh',但我查询发现没有zh这个包,且'zh'朗读的听不清是否是中文
        # 使用'cmn-latn-pinyin'语音,它支持中文拼音输入
        # 若系统没有该语音,可能需要额外安装中文语音包
        speaker.voice = 'cmn-latn-pinyin'
 
        # 线程主循环,只要ROS2系统正常运行就持续执行
        while rclpy.ok():
            # 检查队列中是否有待处理的文本
            if self.topic_queue.qsize() > 0:
                # 从队列中取出一行文本
                text = self.topic_queue.get()
                
                # 记录日志,显示当前正在朗读的文本
                self.get_logger().info(f'朗读:{text}')
                
                # 使用语音合成器朗读文本
                speaker.say(text)
                
                # 等待当前文本朗读完成
                speaker.wait()
            else:
                # 队列为空时休眠1秒,避免CPU空转
                time.sleep(1)
 
# 主函数,程序入口点
def main():
    # 初始化ROS2 Python客户端库
    rclpy.init()
    
    # 创建小说订阅节点实例
    node = NovelSubNode('novel_sub')
    
    # 进入节点的主循环,等待回调函数执行
    # 该函数会阻塞,直到节点被关闭
    rclpy.spin(node)
    
    # 节点关闭后,清理ROS2资源
    rclpy.shutdown()

  在setup.py中进行申明

'topic_sub = topic_ws.topic_sub:main'

   构建功能包

colcon build

   为当前终端会话加载 ROS 工作空间的环境变量和功能包路径

source install/setup.bash 

   用ros2运行

ros2 run topic_ws topic_sub     # ros2运行topic_ws文件下的topic_pub可执行文件

   完成以上操作则可以完成小说发布,用户订阅朗读小说的功能

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值