gz中生成模型
生成模型
通过服务调用生成
还记得parameter_bridge 吗?
我们在生成桥接的时候调用了这个cpp文件。
-
一个
parameter_bridge实例用于消息传递(传感器数据)。之前的例子 -
另一个
parameter_bridge实例用于服务桥接(动态生成模型)。现在的例子
实现多开的方法
1. 启动消息桥接
用第一个 parameter_bridge 实例桥接消息话题,例如传递传感器数据:
ros2 run ros_gz_bridge parameter_bridge /scan@sensor_msgs/msg/LaserScan@gz.msgs.LaserScan
- 功能:桥接 Gazebo 和 ROS 2 的激光雷达数据。
2. 启动服务桥接
启动第二个 parameter_bridge 实例,用于桥接服务,例如生成模型:
ros2 run ros_gz_bridge parameter_bridge /world/empty/create@ros_gz_interfaces/srv/SpawnEntity
- 功能:桥接 Gazebo 和 ROS 2 的服务,允许通过 ROS 2 服务生成模型。
3. 发送请求生成模型
在服务桥接启动后,使用以下命令发送生成模型的请求:
ros2 service call /world/empty/create ros_gz_interfaces/srv/SpawnEntity \"{name: 'my_robot', sdf: '<完整的SDF内容>', pose: {position: {x: 0.0, y: 0.0, z: 0.0}, orientation: {x: 0.0, y: 0.0, z: 0.0, w: 1.0}}}"
总结两种调用的区别
| 功能 | 话题桥接 | 服务桥接 |
|---|---|---|
| 调用命令 | /scan@sensor_msgs/msg/LaserScan@gz.msgs.LaserScan | /world/empty/create@ros_gz_interfaces/srv/SpawnEntity |
| 桥接对象 | ROS 2 和 Gazebo 的话题 | ROS 2 和 Gazebo 的服务 |
| 桥接方向 | 支持单向或双向(GZ_TO_ROS、ROS_TO_GZ 或 BIDIRECTIONAL) | 服务请求从 ROS 2 转发到 Gazebo,返回响应 |
| 使用场景 | 数据流桥接,如传感器数据 | 动作桥接,如动态生成模型 |
同时运行的效果
- 两个
parameter_bridge实例可以独立运行,并不会互相干扰。 - 一个处理话题消息,另一个处理服务请求。
parameter_bridge 中服务桥接的实现
在这个调用服务的过程中,我十分好奇,到底是哪一个地方起了作用。
关键实现代码
-
解析服务参数:
if (config.ros_type_name.find("/srv/") != std::string::npos) {std::string gz_req_type_name;std::string gz_rep_type_name;if (config.direction == BridgeDirection::ROS_TO_GZ ||config.direction == BridgeDirection::GZ_TO_ROS) {usage();return -1;}if (config.direction == BridgeDirection::BIDIRECTIONAL) {delimPos = arg.find(delim);if (delimPos == std::string::npos || delimPos == 0) {usage();return -1;}gz_req_type_name = arg.substr(0, delimPos);arg.erase(0, delimPos + delim.size());gz_rep_type_name = std::move(arg);}try {bridge_node->add_service_bridge(config.ros_type_name,gz_req_type_name,gz_rep_type_name,config.ros_topic_name);} catch (std::runtime_error & e) {std::cerr << e.what() << std::endl;}continue; }- 解析传入参数,判断是否为服务桥接(
ros_type_name包含/srv/)。 - 处理服务的请求类型和响应类型(
gz_req_type_name和gz_rep_type_name)。
- 解析传入参数,判断是否为服务桥接(
-
调用服务桥接方法:
bridge_node->add_service_bridge(config.ros_type_name,gz_req_type_name,gz_rep_type_name,config.ros_topic_name);- 使用
RosGzBridge::add_service_bridge方法注册服务桥接。 - 桥接逻辑会将 ROS 2 的服务请求转发给 Gazebo 服务,并将响应返回给 ROS 2 客户端。
- 使用
-
服务桥接的核心逻辑:
- Gazebo 服务通过内部的 Gazebo Transport 提供功能。
- ROS 2 服务通过
rclcpp提供功能。 - 桥接会订阅 Gazebo 服务,并将其暴露为一个 ROS 2 服务。
- 响应流向:
- ROS 2 客户端 -> ROS 2 服务。
- ROS 2 服务 -> Gazebo 服务。
- Gazebo 服务 -> ROS 2 服务 -> ROS 2 客户端。
通过自带包生成
在ros_gz_sim里面有一个gz_spawn_model的东西,它可以帮助我们在一个已经建成的gz中添加模型。
ros2 launch ros_gz_sim gz_spawn_model.launch.py world:=empty file:=$(ros2 pkg prefix --share ros_gz_sim_demos)/models/vehicle/model.sdf entity_name:=my_vehicle x:=5.0 y:=5.0 z:=0.5
你可以打开这个文件,看看哪个没有默认值,没有默认值的需要你指定参数。一般是 world和file需要指定参数。
自定义配置
在功能包里面创建xml或者launch.py就行了
例如
<launch><arg name="world" default="" /><arg name="file" default="" /><arg name="model_string" default="" /><arg name="topic" default="" /><arg name="entity_name" default="" /><arg name="allow_renaming" default="False" /><arg name="x" default="" /><arg name="y" default="" /><arg name="z" default="" /><arg name="roll" default="" /><arg name="pitch" default="" /><arg name="yaw" default="" /><gz_spawn_model world="$(var world)"file="$(var file)"model_string="$(var model_string)"topic="$(var topic)"entity_name="$(var entity_name)"allow_renaming="$(var allow_renaming)"x="$(var x)"y="$(var y)"z="$(var z)"roll="$(var roll)"pitch="$(var pitch)"yaw="$(var yaw)"></gz_spawn_model>
</launch>
from launch import LaunchDescription
from launch.actions import DeclareLaunchArgument
from launch.substitutions import LaunchConfiguration
from launch_ros.actions import Nodedef generate_launch_description():# Declare argumentsreturn LaunchDescription([DeclareLaunchArgument('world', default_value='', description='Name of the Gazebo world'),DeclareLaunchArgument('file', default_value='', description='Path to the model file'),DeclareLaunchArgument('model_string', default_value='', description='Model description as a string'),DeclareLaunchArgument('topic', default_value='', description='Gazebo topic to use'),DeclareLaunchArgument('entity_name', default_value='', description='Name of the entity to spawn'),DeclareLaunchArgument('allow_renaming', default_value='False', description='Allow renaming of the entity'),DeclareLaunchArgument('x', default_value='0.0', description='X position of the model'),DeclareLaunchArgument('y', default_value='0.0', description='Y position of the model'),DeclareLaunchArgument('z', default_value='0.0', description='Z position of the model'),DeclareLaunchArgument('roll', default_value='0.0', description='Roll rotation of the model'),DeclareLaunchArgument('pitch', default_value='0.0', description='Pitch rotation of the model'),DeclareLaunchArgument('yaw', default_value='0.0', description='Yaw rotation of the model'),# Gazebo spawn model nodeNode(package='ros_gz_sim',executable='gz_spawn_model',output='screen',name='spawn_model',parameters=[{'world': LaunchConfiguration('world')},{'file': LaunchConfiguration('file')},{'model_string': LaunchConfiguration('model_string')},{'topic': LaunchConfiguration('topic')},{'entity_name': LaunchConfiguration('entity_name')},{'allow_renaming': LaunchConfiguration('allow_renaming')},{'x': LaunchConfiguration('x')},{'y': LaunchConfiguration('y')},{'z': LaunchConfiguration('z')},{'roll': LaunchConfiguration('roll')},{'pitch': LaunchConfiguration('pitch')},{'yaw': LaunchConfiguration('yaw')}]),])
当然我们也可以简化一些
我们调用了parameter_bridge
from launch import LaunchDescription
from launch_ros.actions import Node
from launch.actions import DeclareLaunchArgument
from launch.substitutions import LaunchConfigurationdef generate_launch_description():# 创建 LaunchDescriptionld = LaunchDescription()# 声明参数ld.add_action(DeclareLaunchArgument('entity_name', default_value='my_robot', description='Name of the entity to spawn'))ld.add_action(DeclareLaunchArgument('file', default_value='/path/to/your/model.sdf', description='Path to the model file'))ld.add_action(DeclareLaunchArgument('x', default_value='0.0', description='X position of the model'))ld.add_action(DeclareLaunchArgument('y', default_value='0.0', description='Y position of the model'))ld.add_action(DeclareLaunchArgument('z', default_value='0.0', description='Z position of the model'))# 配置 parameter_bridge,用于桥接 Gazebo 和 ROS 服务parameter_bridge_cmd = Node(package='ros_gz_bridge',executable='parameter_bridge',arguments=['/world/empty/create@ros_gz_interfaces/srv/SpawnEntity'],output='screen')# 添加到 LaunchDescriptionld.add_action(parameter_bridge_cmd)return ld
| XML 元素 | Python 替代 |
|---|---|
<arg name="..." /> | DeclareLaunchArgument |
<gz_spawn_model ... /> | Node,通过 parameters 字段传递参数 |
同时启动?
在官方教程中,我找到了这一个代码
ros2 launch ros_gz_sim ros_gz_spawn_model.launch.py world:=empty file:=$(ros2 pkg prefix --share ros_gz_sim_demos)/models/vehicle/model.sdf entity_name:=my_vehicle x:=5.0 y:=5.0 z:=0.5 bridge_name:=ros_gz_bridge config_file:=<path_to_your_YAML_file>
他说,可以同时桥接gz-ros和生成模型
- 关键参数的功能
world:=empty- 指定要加载的 Gazebo 世界为
empty(空白世界)。 - Gazebo 会在这个世界中加载模型。
- 指定要加载的 Gazebo 世界为
file:=$(ros2 pkg prefix --share ros_gz_sim_demos)/models/vehicle/model.sdf- 指定要加载的模型文件路径。
- 在这里,加载的是
vehicle模型的 SDF 文件。
entity_name:=my_vehicle- 模型的名称,生成后的模型会被命名为
my_vehicle。
- 模型的名称,生成后的模型会被命名为
x:=5.0 y:=5.0 z:=0.5- 指定模型的初始位置:
x:模型在 Gazebo 世界中的 X 坐标。y:模型在 Gazebo 世界中的 Y 坐标。z:模型在 Gazebo 世界中的 Z 坐标。
- 指定模型的初始位置:
bridge_name:=ros_gz_bridge- 定义桥接节点的名称为
ros_gz_bridge。 - 这是
ros_gz_bridge在 ROS 2 网络中的唯一标识。
- 定义桥接节点的名称为
config_file:=<path_to_your_YAML_file>- 指定一个 YAML 配置文件,用于定义要桥接的话题和服务。
通用的桥接 YAML 文件
以下是一个桥接 YAML 配置文件实例。
网络收集,可能会有错误。
bridge_config.yaml
# 桥接 Gazebo 服务到 ROS 2 服务
services:# 模型生成服务- ros_service_name: "/world/empty/create"gz_service_name: "/gazebo/spawn_entity"ros_service_type: "ros_gz_interfaces/srv/SpawnEntity"gz_request_type: "gz.msgs.EntityFactory"gz_response_type: "gz.msgs.Boolean"# 模型删除服务- ros_service_name: "/world/empty/delete"gz_service_name: "/gazebo/delete_entity"ros_service_type: "ros_gz_interfaces/srv/DeleteEntity"gz_request_type: "gz.msgs.Entity"gz_response_type: "gz.msgs.Boolean"# 世界控制服务- ros_service_name: "/world/empty/control"gz_service_name: "/gazebo/control_world"ros_service_type: "ros_gz_interfaces/srv/ControlWorld"gz_request_type: "gz.msgs.WorldControl"gz_response_type: "gz.msgs.Boolean"# 桥接 Gazebo 和 ROS 2 的话题
topics:# 激光雷达数据- ros_topic_name: "/scan"gz_topic_name: "/gazebo/laser_scan"ros_type_name: "sensor_msgs/msg/LaserScan"gz_type_name: "gz.msgs.LaserScan"direction: BIDIRECTIONAL# 摄像头图像数据- ros_topic_name: "/camera/image"gz_topic_name: "/gazebo/camera/image"ros_type_name: "sensor_msgs/msg/Image"gz_type_name: "gz.msgs.Image"direction: GZ_TO_ROS# 深度图像数据- ros_topic_name: "/camera/depth"gz_topic_name: "/gazebo/camera/depth_image"ros_type_name: "sensor_msgs/msg/Image"gz_type_name: "gz.msgs.Image"direction: GZ_TO_ROS# 点云数据- ros_topic_name: "/points"gz_topic_name: "/gazebo/point_cloud"ros_type_name: "sensor_msgs/msg/PointCloud2"gz_type_name: "gz.msgs.PointCloudPacked"direction: GZ_TO_ROS# 机器人位置数据- ros_topic_name: "/robot_pose"gz_topic_name: "/gazebo/pose/info"ros_type_name: "geometry_msgs/msg/Pose"gz_type_name: "gz.msgs.Pose"direction: GZ_TO_ROS# 速度命令- ros_topic_name: "/cmd_vel"gz_topic_name: "/gazebo/cmd_vel"ros_type_name: "geometry_msgs/msg/Twist"gz_type_name: "gz.msgs.Twist"direction: ROS_TO_GZ# 关节状态数据- ros_topic_name: "/joint_states"gz_topic_name: "/gazebo/joint_states"ros_type_name: "sensor_msgs/msg/JointState"gz_type_name: "gz.msgs.Model"direction: GZ_TO_ROS# TF 数据(用于坐标变换)- ros_topic_name: "/tf"gz_topic_name: "/gazebo/tf"ros_type_name: "tf2_msgs/msg/TFMessage"gz_type_name: "gz.msgs.Pose_V"direction: GZ_TO_ROS# 世界状态数据- ros_topic_name: "/world_state"gz_topic_name: "/gazebo/world_state"ros_type_name: "ros_gz_interfaces/msg/WorldState"gz_type_name: "gz.msgs.WorldStatistics"direction: GZ_TO_ROS
相关文章:
gz中生成模型
生成模型 通过服务调用生成 还记得parameter_bridge 吗? 我们在生成桥接的时候调用了这个cpp文件。 一个 parameter_bridge 实例用于消息传递(传感器数据)。之前的例子 另一个 parameter_bridge 实例用于服务桥接(动态生成模型…...
前端(Axios和Promis)
Promise 语法 <script>// 创建promise对象// 此函数需要再传入两个参数,都是函数类型let pnew Promise((resolve,reject)>{if(3>2){resolve({name:"李思蕾",age:23,地址:"河南省"});}else{reject("error");}});console.log(p);p.th…...
AI Agent:重塑业务流程自动化的未来力量(2/30)
《AI Agent:重塑业务流程自动化的未来力量》 摘要:整体思路是先介绍 AI Agent 的基本情况,再深入阐述其实现业务流程自动化的方法和在不同领域的应用,接着分析其价值和面临的挑战,最后得出结论,为读者全面…...
前端页面导出word
html-docx-js bug: vite使用html-docx.js会报错,点击下载上方文件替换即可 正文 npm install html-docx-js -S npm install file-saver -S<template><div id"managerReport">word内容......</div> </template><script>&l…...
【考前预习】1.计算机网络概述
往期推荐 子网掩码、网络地址、广播地址、子网划分及计算-CSDN博客 一文搞懂大数据流式计算引擎Flink【万字详解,史上最全】-CSDN博客 浅学React和JSX-CSDN博客 浅谈云原生--微服务、CICD、Serverless、服务网格_云原生 serverless-CSDN博客 浅谈维度建模、数据分析…...
ubuntu20.04复现 Leg-KILO
这里写目录标题 opencv版本问题下载3.2.0源代码进入解压后的目录创建构建目录运行 CMake 配置 配置时指定一个独立的安装目录,例如 /opt/opencv-3.2:出错: 使用多线程编译错误1: stdlib.h: 没有那个文件或目录错误2:er…...
Ensembl数据库下载参考基因组(常见模式植物)bioinfomatics 工具37
拟南芥参考基因组_拟南芥数据库-CSDN博客 1 Ensembl数据库网址 http://plants.ensembl.org/index.html #官网 如拟南芥等 那么问题来了,基因组fa文件和gff文件在哪里? 2 参考案例 拟南芥基因组fa在这里 注释gff文件在这里...
简单介绍web开发和HTML CSS_web网站开发流程
一、Web 开发:探索互联网世界的基石 1.1 什么是 Web 开发 Web 开发,简单来说,就是构建能够通过浏览器访问的网站的过程。Web 代表着全球广域网,也就是我们熟知的万维网(www),它连接着世界各地的…...
Docker 中使用 PHP 通过 Canal 同步 Mysql 数据到 ElasticSearch
一、Mysql 的安装和配置 1.使用 docker 安装 mysql,并且映射端口和 root 账号的密码 # 获取镜像 docker pull mysql:8.0.40-debian# 查看镜像是否下载成功 docker images# 运行msyql镜像 docker run -d -p 3388:3306 --name super-mysql -e MYSQL_ROOT_PASSWORD12…...
数据结构之五:排序
void*类型的实现:排序(void*类型)-CSDN博客 一、插入排序 1、直接插入排序 思想:把待排序的数据逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列 。 单趟&#x…...
科研绘图系列:R语言绘制热图和散点图以及箱线图(pheatmap, scatterplot boxplot)
禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍加载R包数据下载图1图2图3系统信息参考介绍 R语言绘制热图和散点图以及箱线图(pheatmap, scatterplot & boxplot) 加载R包 library(magrittr) library(dplyr) library(ve…...
基于 webRTC Vue 的局域网 文件传输工具
文件传输工具,匿名加密,只需访问网页,即可连接到其他设备,基于 webRTC 和 Vue.js coturn TURN 服务器 docker pull coturn/coturn docker run -d --networkhost \-v $(pwd)/my.conf:/etc/coturn/turnserver.conf \coturn/coturn…...
LeetCode 718. 最长重复子数组 java题解
https://leetcode.cn/problems/maximum-length-of-repeated-subarray/description/ 动态规划 class Solution {public int findLength(int[] nums1, int[] nums2) {int len1nums1.length,len2nums2.length;int[][] dpnew int[len11][len21];dp[0][0]0;//没有意义,…...
算法知识-15-深搜
一、概念 深度优先搜索(Deep First Search, DFS)是一种用于遍历或搜索树或图的算法。这种策略沿着树的深度遍历树的节点,尽可能深地搜索树的分支。 二、关键步骤 选择起点:根据题目要求,选择一个或多个节点作为搜索…...
区块链dapp 开发详解(VUE3.0)
1、安装metamask 插件。 2、使用封装的工具包: wagmi . 3、 wagmi 操作手册地址:connect | Wagmi 4、注意事项: 因为最初是react 版本,所以在VUE版的官方文档有很多地方在 import 用的是 wagmi,需要改为 wagmi/vue 。 连接成功后打印的内容如下&…...
Plugin [id: ‘flutter‘] was not found in any of the following sources解决方法
文章目录 错误描述解决方法修正方案:继续使用 apply from修正后的 build.gradle说明警告的处理进一步验证 错误描述 Plugin [id: ‘flutter’] was not found in any of the following sources: Gradle Core Plugins (not a core plugin, please see https://docs…...
专升本-高数 1
第 0 章,基础知识 一,重要公式 1、完全平方 (ab)a2abb (a-b)a-2abb 2、平方差公式 (a-b)(ab)a-b 3、立方差公式 a-b(a-b)(aabb) 4、 立方和公式 ab(ab)(a-abb) 二,基本初等函数 1,幂函数 一元二…...
【考前预习】3.计算机网络—数据链路层
往期推荐 【考前预习】2.计算机网络—物理层-CSDN博客 【考前预习】1.计算机网络概述-CSDN博客 浅谈云原生--微服务、CICD、Serverless、服务网格_云原生cicd-CSDN博客 子网掩码、网络地址、广播地址、子网划分及计算_子网广播地址-CSDN博客 浅学React和JSX-CSDN博客 目录 1.数…...
DockeUI 弱口令登录漏洞+未授权信息泄露
0x01 产品描述: DockerUI是一款开源的、强大的、轻量级的Docker管理工具。DockerUI覆盖了 docker cli 命令行 95% 以上的命令功能,通过可视化的界面,即使是不熟悉docker命令的用户也可以非常方便的进行Docker和Docker Swarm集群进行管理和维护。0x02 漏洞描述: DockerUI中存…...
【电子元器件】电感基础知识
本文章是笔者整理的备忘笔记。希望在帮助自己温习避免遗忘的同时,也能帮助其他需要参考的朋友。如有谬误,欢迎大家进行指正。 一、 电感的基本工作原理 1. 电感的基本工作原理如下: (1) 当线圈中有电流通过时&#…...
【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型
摘要 拍照搜题系统采用“三层管道(多模态 OCR → 语义检索 → 答案渲染)、两级检索(倒排 BM25 向量 HNSW)并以大语言模型兜底”的整体框架: 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后,分别用…...
大话软工笔记—需求分析概述
需求分析,就是要对需求调研收集到的资料信息逐个地进行拆分、研究,从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要,后续设计的依据主要来自于需求分析的成果,包括: 项目的目的…...
简易版抽奖活动的设计技术方案
1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...
在rocky linux 9.5上在线安装 docker
前面是指南,后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...
iPhone密码忘记了办?iPhoneUnlocker,iPhone解锁工具Aiseesoft iPhone Unlocker 高级注册版分享
平时用 iPhone 的时候,难免会碰到解锁的麻烦事。比如密码忘了、人脸识别 / 指纹识别突然不灵,或者买了二手 iPhone 却被原来的 iCloud 账号锁住,这时候就需要靠谱的解锁工具来帮忙了。Aiseesoft iPhone Unlocker 就是专门解决这些问题的软件&…...
【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表
1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...
srs linux
下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935,SRS管理页面端口是8080,可…...
【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分
一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计,提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合:各模块职责清晰,便于独立开发…...
【生成模型】视频生成论文调研
工作清单 上游应用方向:控制、速度、时长、高动态、多主体驱动 类型工作基础模型WAN / WAN-VACE / HunyuanVideo控制条件轨迹控制ATI~镜头控制ReCamMaster~多主体驱动Phantom~音频驱动Let Them Talk: Audio-Driven Multi-Person Conversational Video Generation速…...
CVE-2020-17519源码分析与漏洞复现(Flink 任意文件读取)
漏洞概览 漏洞名称:Apache Flink REST API 任意文件读取漏洞CVE编号:CVE-2020-17519CVSS评分:7.5影响版本:Apache Flink 1.11.0、1.11.1、1.11.2修复版本:≥ 1.11.3 或 ≥ 1.12.0漏洞类型:路径遍历&#x…...
