当前位置: 首页 > article >正文

亚博microros小车-原生ubuntu支持系列:20 ROS Robot APP建图

依赖工程

新建工程laserscan_to_point_publisher

src/laserscan_to_point_publisher/laserscan_to_point_publisher/目录下新建文件laserscan_to_point_publish.py

#!/usr/bin/env python3import rclpy
from rclpy.node import Node
from geometry_msgs.msg import PoseStamped, TransformStamped
from nav_msgs.msg import Path
from sensor_msgs.msg import LaserScan
import tf2_ros
import mathclass laserscanToPointPublish(Node):def __init__(self):super().__init__('robot_pose_publisher')self.subscription = self.create_subscription(LaserScan,'/scan',self.laserscan_callback,10)self.sacn_point_publisher = self.create_publisher(Path,'/scan_points',10)def laserscan_callback(self, msg):
#            print(msg)angle_min  = msg.angle_minangle_increment = msg.angle_incrementlaserscan = msg.ranges# 获取激光雷达数据
#            print(laserscan)laser_points = self.laserscan_to_points(laserscan, angle_increment, angle_increment) self.sacn_point_publisher.publish(laser_points)def laserscan_to_points(self, laserscan, angle_min, angle_increment):points = []angle = angle_minlaser_points = Path()for distance in laserscan:x = distance * math.cos(angle + 135)#获取当前激光雷达数据点的的坐标值y = distance * math.sin(angle + 135)pose = PoseStamped()pose.pose.position.x = xpose.pose.position.y = ypoints.append(pose)angle += angle_incrementlaser_points.poses = pointsreturn laser_pointsdef main(args=None):rclpy.init(args=args)robot_laser_scan_publisher = laserscanToPointPublish()rclpy.spin(robot_laser_scan_publisher)robot_pose_publisher.destroy_node()rclpy.shutdown()if __name__ == '__main__':main()

robot_pose_publisher_ros2

src/robot_pose_publisher_ros2/src/目录下新建robot_pose_publisher.cpp

/*!* \file robot_pose_publisher.cpp* \brief Publishes the robot's position in a geometry_msgs/Pose message.** Publishes the robot's position in a geometry_msgs/Pose message based on the TF* difference between /map and /base_link.** \author Milan - milan.madathiparambil@gmail.com* \date April 20 1020*/#include <chrono>
#include <memory>#include "rclcpp/rclcpp.hpp"
#include "geometry_msgs/msg/pose_stamped.hpp"
#include "geometry_msgs/msg/pose.hpp"
#include "geometry_msgs/msg/transform_stamped.hpp"
#include "tf2_ros/transform_listener.h"
#include "tf2_ros/buffer.h"using namespace std::chrono_literals;/* This example creates a subclass of Node and uses std::bind() to register a* member function as a callback from the timer. */class RobotPosePublisher : public rclcpp::Node
{
public:RobotPosePublisher() : Node("robot_pose_publisher"){tf_buffer_ = std::make_shared<tf2_ros::Buffer>(this->get_clock());tf_listener_ = std::make_shared<tf2_ros::TransformListener>(*tf_buffer_);this->declare_parameter<std::string>("map_frame","map");this->declare_parameter<std::string>("base_frame","base_link");this->declare_parameter<bool>("is_stamped",false);this->get_parameter("map_frame", map_frame);this->get_parameter("base_frame", base_frame);this->get_parameter("is_stamped", is_stamped);if (is_stamped)publisher_stamp = this->create_publisher<geometry_msgs::msg::PoseStamped>("robot_pose", 1);elsepublisher_ = this->create_publisher<geometry_msgs::msg::Pose>("robot_pose", 1);timer_ = this->create_wall_timer(50ms, std::bind(&RobotPosePublisher::timer_callback, this));}private:void timer_callback(){geometry_msgs::msg::TransformStamped transformStamped;try{transformStamped = tf_buffer_->lookupTransform(map_frame, base_frame,this->now());}catch (tf2::TransformException &ex){return;}geometry_msgs::msg::PoseStamped pose_stamped;pose_stamped.header.frame_id = map_frame;pose_stamped.header.stamp = this->now();pose_stamped.pose.orientation.x = transformStamped.transform.rotation.x;pose_stamped.pose.orientation.y = transformStamped.transform.rotation.y;pose_stamped.pose.orientation.z = transformStamped.transform.rotation.z;pose_stamped.pose.orientation.w = transformStamped.transform.rotation.w;pose_stamped.pose.position.x = transformStamped.transform.translation.x;pose_stamped.pose.position.y = transformStamped.transform.translation.y;pose_stamped.pose.position.z = transformStamped.transform.translation.z;if (is_stamped)publisher_stamp->publish(pose_stamped);elsepublisher_->publish(pose_stamped.pose);}rclcpp::TimerBase::SharedPtr timer_;rclcpp::Publisher<geometry_msgs::msg::PoseStamped>::SharedPtr publisher_stamp;rclcpp::Publisher<geometry_msgs::msg::Pose>::SharedPtr publisher_;size_t count_;bool is_stamped = false;std::string base_frame = "base_link";std::string map_frame = "map";std::shared_ptr<tf2_ros::TransformListener> tf_listener_;std::shared_ptr<tf2_ros::Buffer> tf_buffer_;
};int main(int argc, char *argv[])
{rclcpp::init(argc, argv);rclcpp::spin(std::make_shared<RobotPosePublisher>());rclcpp::shutdown();return 0;
}

其中获取结果 buffer_.lookup_transform  获取map到base_link的坐标变化, 再发布robot_pose。

rosbridge_server

这个没有安装也需要安装下。

启动脚本

src/yahboomcar_nav/launch/map_cartographer_app_launch.xml

<launch><include file="$(find-pkg-share rosbridge_server)/launch/rosbridge_websocket_launch.xml"/><node name="laserscan_to_point_publisher" pkg="laserscan_to_point_publisher" exec="laserscan_to_point_publisher"/><include file="$(find-pkg-share yahboomcar_nav)/launch/map_cartographer_launch.py"/><include file="$(find-pkg-share robot_pose_publisher_ros2)/launch/robot_pose_publisher_launch.py"/><include file="$(find-pkg-share yahboom_app_save_map)/yahboom_app_save_map.launch.py"/>
</launch>

 这里运行了以下几个launch文件和节点Node:

  • rosbridge_websocket_launch.xml:开启rosbridge服务相关节点,启动后,可以通过网络连接到ROS

  • laserscan_to_point_publisher:把雷达的点云转换发布到APP上进行可视化

  • map_cartographer_launch.py:cartographer建图程序

  • robot_pose_publisher_launch.py:小车位姿发布程序,小车位姿在APP进行可视化

  • yahboom_app_save_map.launch.py:保存地图的程序

程序功能说明

小车连接上代理,运行程序,打开手机上下载的【ROS Robot】app,输入小车的IP地址,选择ROS2,点击连接,即可连接上小车。通过滑动界面的轮盘可以控制小车,缓慢控制小车走完建图的区域,最后点击保存地图,小车会保存当前建好的地图。

启动

#小车代理
sudo docker run -it --rm -v /dev:/dev -v /dev/shm:/dev/shm --privileged --net=host microros/micro-ros-agent:humble udp4 --port 8090 -v4
#摄像头代理(先启动代理再打开小车开关)
docker run -it --rm -v /dev:/dev -v /dev/shm:/dev/shm --privileged --net=host microros/micro-ros-agent:humble udp4 --port 9999 -v4

首先启动小车处理底层数据程序,终端输入,

ros2 launch yahboomcar_bringup yahboomcar_bringup_launch.py

启动APP建图命令,终端输入,

ros2 launch yahboomcar_nav map_cartographer_app_launch.xml
#启动ESP32 摄像头
ros2 run yahboom_esp32_camera sub_img

手机APP显示如下图,输入小车的IP地址,【zh】表示中文,【en】表示英文;选择ROS2,下边的Video Tpoic选择/usb_cam/image_raw/compressed,最后点击【连接】

image-20231219143224710

这个ip就是小车的配置ip。成功连接上后,跑一点地图显示如下,

 

有个问题就是app上不显示摄像头画面。我看亚博官网的文章上也没有显示,不知道为啥,猜测是控制小车的ip跟摄像头代理的不是1个。

另外的感受这个比较难操控小车,速度太快了,不如键盘好掌握。

以上。

相关文章:

亚博microros小车-原生ubuntu支持系列:20 ROS Robot APP建图

依赖工程 新建工程laserscan_to_point_publisher src/laserscan_to_point_publisher/laserscan_to_point_publisher/目录下新建文件laserscan_to_point_publish.py #!/usr/bin/env python3import rclpy from rclpy.node import Node from geometry_msgs.msg import PoseStam…...

计算机毕业设计Python+Vue.js游戏推荐系统 Steam游戏推荐系统 Django Flask 游 戏可视化 游戏数据分析 游戏大数据 爬虫

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…...

Qt最新热点

Qt的最新热点主要集中在以下几个方面: 跨平台开发:Qt继续强调其在跨平台开发方面的优势,支持在Windows、macOS、Linux以及移动操作系统(如Android和iOS)上的应用开发。 Qt for Python:Qt for Python(PySide2和PySide6)的发展,为Python开发者提供了更强大的工具来创建桌…...

k8sollama部署deepseek-R1模型,内网无坑

这是目录 linux下载ollama模型文件下载到本地,打包迁移到k8s等无网络环境使用下载打包ollama镜像非k8s环境使用k8s部署访问方式非ollama运行deepseek模型linux下载ollama 下载后可存放其他服务器 curl -L https://ollama.com/download/ollama-linux-amd64.tgz -o ollama-linu…...

音频录制一般在什么情况下会选择保存为PCM?什么情况会选择保存为WAV?

在音频开发中,选择保存为 PCM 或 WAV 格式取决于具体的应用场景和需求。以下是两种格式的特点以及适用场景的分析: PCM 格式 特点: 原始音频数据: PCM 是未压缩的原始音频数据,没有任何文件头或元数据。数据直接以二进制形式存储,通常是采样点的值。文件体积较大: 由于…...

【Elasticsearch】nested聚合

在 Elasticsearch 中&#xff0c;嵌套聚合&#xff08;nestedaggregation&#xff09;的语法形式用于对嵌套字段&#xff08;nestedfields&#xff09;进行聚合操作。嵌套字段是 Elasticsearch 中的一种特殊字段类型&#xff0c;用于存储数组中的对象&#xff0c;这些对象需要独…...

从零创建 Vue 3 项目

Vue 3 作为当前最流行的前端框架之一&#xff0c;提供了多种创建项目的方式。本文将详细介绍七种常见的创建 Vue 3 项目的方法&#xff0c;涵盖从本地开发到在线编辑器的多种场景&#xff0c;帮助您选择最适合的方式 快速创建 Vue 3项目 进行开发。 方法一&#xff1a;使用 Vue…...

Day48_20250130【回校继续打卡】_单调栈part1_739.每日温度|496.下一个更大元素I|503.下一个更大元素II

Day48_20250130_单调栈part1_739.每日温度|496.下一个更大元素I|503.下一个更大元素II 20250130补完 739.每日温度 题目 给定一个整数数组 temperatures &#xff0c;表示每天的温度&#xff0c;返回一个数组 answer &#xff0c;其中 answer[i] 是指对于第 i 天&#xff0…...

spy-debugger + Charles 调试移动端/内嵌小程序H5

简介说明&#xff1a; PC端可以用F12进行console等进行调试&#xff0c;但移动端App中使用webview就无法进行实时调试&#xff0c;针对这种情况 1. 安装 全局安装 spy-debugger sudo npm install spy-debugger -g // window不用加sudo2. spy-debugger 证书 其实spy-debugg…...

【NLP 20、Encoding编码 和 Embedding嵌入】

目录 一、核心定义与区别 二、常见Encoding编码 (1) 独热编码&#xff08;One-Hot Encoding&#xff09; (2) 位置编码&#xff08;Positional Encoding&#xff09; (3) 标签编码&#xff08;Label Encoding&#xff09; (4) 注意事项 三、常见Embedding词嵌入 (1) 基础词嵌入…...

【LeetCode 刷题】二叉树(3)-二叉树的属性

此博客为《代码随想录》二叉树章节的学习笔记&#xff0c;主要内容为二叉树的属性相关的题目解析。 文章目录 101. 对称二叉树104.二叉树的最大深度111.二叉树的最小深度222.完全二叉树的节点个数110.平衡二叉树257. 二叉树的所有路径404.左叶子之和513.找树左下角的值112. 路…...

深度学习模型可视化小工具wandb

1 概述 Wandb&#xff08;Weights & Biases&#xff0c;网址是https://wandb.ai&#xff09;是一个用于机器学习项目实验跟踪、可视化和管理的工具&#xff0c;旨在用户更有效地监控模型训练过程、优化性能&#xff0c;并分享和复现实验结果‌‌。对于使用者而言&#xff…...

数据库系统概论的第六版与第五版的区别,附pdf

我用夸克网盘分享了「数据库系统概论第五六版资源」&#xff0c;点击链接即可保存。 链接&#xff1a;https://pan.quark.cn/s/21a278378dee 第6版教材修订的主要内容 为了保持科学性、先进性和实用性&#xff0c;在第5版教材基础上对全书内容进行了修改、更新和充实。 在科…...

【Kubernetes Pod间通信-第2篇】使用BGP实现Pod到Pod的通信

Kubernetes中Pod间的通信 本系列文章共3篇: 【Kubernetes Pod间通信-第1篇】在单个子网中使用underlay网络实现Pod到Pod的通信【Kubernetes Pod间通信-第2篇】使用BGP实现Pod到Pod的通信(本文介绍)【Kubernetes Pod间通信-第3篇】Kubernetes中Pod与ClusterIP服务之间的通信…...

python:csv文件批量导入mysql

1.导入sql文件到数据库中 mysql -u username -p要先创建一个空的数据库 CREATE DATABASE your_database_name;USE your_database_name;导入sql文件 source /path/to/your/file.sql;查看某个表格的结构&#xff0c;为后续数据插入做准备 DESCRIBE table_name;2.插入假数据到对应…...

软件设计模式

目录 一.创建型模式 抽象工厂 Abstract Factory 构建器 Builder 工厂方法 Factory Method 原型 Prototype 单例模式 Singleton 二.结构型模式 适配器模式 Adapter 桥接模式 Bridge 组合模式 Composite 装饰者模式 Decorator 外观模式 Facade 享元模式 Flyw…...

C++证件识别接口-身份证识别-护照识别-驾驶证识别-户口页识别

数字化信息时代&#xff0c;快速准确地处理各类证件信息已经成为许多行业提升效率的关键。无论是金融、物流、旅游还是公共服务领域&#xff0c;证件识别接口的应用极大的简化了证件信息提取的流程&#xff0c;提高了录入效率。 证件识别接口提升业务处理效率 传统的人工审核…...

3步打造C# API安全密盾

引言&#xff1a;API 安全的重要性 在数字化浪潮中&#xff0c;应用程序编程接口&#xff08;API&#xff09;已成为不同软件系统之间通信和数据交互的关键桥梁。无论是企业内部的微服务架构&#xff0c;还是面向外部用户的在线服务&#xff0c;API 都承担着数据传输和业务逻辑…...

vscode 如何通过Continue引入AI 助手deepseek

第一步&#xff1a; 在deepseek 官网上注册账号&#xff0c;得到APIKeys(deepseek官网地址) 创建属于自己的APIKey,然后复制这个key,(注意保存自己的key)! 第二步&#xff1a; 打开vscode,在插件市场安装Continue插件, 点击设置&#xff0c;添加deepseek模型&#xff0c;默认…...

通过docker安装部署deepseek以及python实现

前提条件 Docker 安装:确保你的系统已经安装并正确配置了 Docker。可以通过运行 docker --version 来验证 Docker 是否安装成功。 网络环境:保证设备有稳定的网络连接,以便拉取 Docker 镜像和模型文件。 步骤一:拉取 Ollama Docker 镜像 Ollama 可以帮助我们更方便地管理…...

iOS 音频录制、播放与格式转换

iOS 音频录制、播放与格式转换:基于 AVFoundation 和 FFmpegKit 的实现 在 iOS 开发中,音频处理是一个非常常见的需求,比如录音、播放音频、音频格式转换等。本文将详细解读一段基于 AVFoundation 和 FFmpegKit 的代码,展示如何实现音频录制、播放以及 PCM 和 AAC 格式之间…...

RK3576——USB3.2 OTG无法识别到USB设备

问题&#xff1a;使用硬盘接入到OTG接口无热插拔信息&#xff0c;接入DP显示屏无法正常识别到显示设备&#xff0c;但是能通过RKDdevTool工具烧录系统。 问题分析&#xff1a;由于热插拔功能实现是靠HUSB311芯片完成的&#xff0c;因此需要先确保HUSB311芯片驱动正常工作。 1. …...

【MySQL】语言连接

语言连接 一、下载二、mysql_get_client_info1、函数2、介绍3、示例 三、其他函数1、mysql_init2、mysql_real_connect3、mysql_query4、mysql_store_result5、mysql_free_result6、mysql_num_fields7、mysql_num_rows8、mysql_fetch_fields9、mysql_fetch_row10、mysql_close …...

20240206 adb 连不上手机解决办法

Step 1: lsusb 确认电脑 usb 端口能识别设备 lsusb不知道设备有没有连上&#xff0c;就插拔一下&#xff0c;对比观察多了/少了哪个设备。 Step 2: 重启 adb server sudo adb kill-serversudo adb start-serveradb devices基本上就可以了&#xff5e; Reference https://b…...

何为运行时(Runtime)

Runtime&#xff08;运行时&#xff09; 是计算机程序中实际执行的阶段&#xff0c;指从程序启动到终止的整个运行过程。它涵盖了程序运行所需的环境、资源管理和底层支持机制。 1. 核心概念 运行时环境&#xff08;Runtime Environment&#xff09; 程序运行依赖的基础设施&am…...

基于ansible部署elk集群

ansible部署 ELK部署 ELK常见架构 &#xff08;1&#xff09;ElasticsearchLogstashKibana&#xff1a;这种架构是最常见的一种&#xff0c;也是最简单的一种架构&#xff0c;这种架构通过Logstash收集日志&#xff0c;运用Elasticsearch分析日志&#xff0c;最后通过Kibana中…...

【C语言设计模式学习笔记1】面向接口编程/简单工厂模式/多态

面向接口编程可以提供更高级的抽象&#xff0c;实现的时候&#xff0c;外部不需要知道内部的具体实现&#xff0c;最简单的是使用简单工厂模式来进行实现&#xff0c;比如一个Sensor具有多种表示形式&#xff0c;这时候可以在给Sensor结构体添加一个enum类型的type&#xff0c;…...

Mac上搭建k8s环境——Minikube

1、在mac上安装Minikube可执行程序 brew cask install minikub 安装后使用minikube version命令查看版本 2、安装docker环境 brew install --cask --appdir/Applications docker #安装docker open -a Docker #启动docker 3、安装kubectl curl -LO https://storage.g…...

Github - 记录一次对“不小心包含了密码的PR”的修复

Github - 记录一次对“不小心包含了密码的PR”的修复 前言 和好朋友一起开发一个字节跳动青训营抖音电商后端(now private)的项目&#xff0c;某大佬不小心把本地一密码commit上去并提了PR。 PR一旦发出则无法被删除&#xff0c;且其包含的commit也能被所有能看到这个仓库的…...

【创建模式-单例模式(Singleton Pattern)】

赐萧瑀 实现方案饿汉模式懒汉式&#xff08;非线程安全&#xff09;懒汉模式&#xff08;线程安全&#xff09;双重检查锁定静态内部类 攻击方式序列化攻击反射攻击 枚举(最佳实践)枚举是一种类 唐 李世民 疾风知劲草&#xff0c;板荡识诚臣。 勇夫安识义&#xff0c;智者必怀仁…...