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) 当线圈中有电流通过时&#…...
调用支付宝接口响应40004 SYSTEM_ERROR问题排查
在对接支付宝API的时候,遇到了一些问题,记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...
K8S认证|CKS题库+答案| 11. AppArmor
目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作: 1)、切换集群 2)、切换节点 3)、切换到 apparmor 的目录 4)、执行 apparmor 策略模块 5)、修改 pod 文件 6)、…...
day52 ResNet18 CBAM
在深度学习的旅程中,我们不断探索如何提升模型的性能。今天,我将分享我在 ResNet18 模型中插入 CBAM(Convolutional Block Attention Module)模块,并采用分阶段微调策略的实践过程。通过这个过程,我不仅提升…...
练习(含atoi的模拟实现,自定义类型等练习)
一、结构体大小的计算及位段 (结构体大小计算及位段 详解请看:自定义类型:结构体进阶-CSDN博客) 1.在32位系统环境,编译选项为4字节对齐,那么sizeof(A)和sizeof(B)是多少? #pragma pack(4)st…...
Python爬虫实战:研究feedparser库相关技术
1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...
dedecms 织梦自定义表单留言增加ajax验证码功能
增加ajax功能模块,用户不点击提交按钮,只要输入框失去焦点,就会提前提示验证码是否正确。 一,模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...
苍穹外卖--缓存菜品
1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得,如果用户端访问量比较大,数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据,减少数据库查询操作。 缓存逻辑分析: ①每个分类下的菜品保持一份缓存数据…...
IoT/HCIP实验-3/LiteOS操作系统内核实验(任务、内存、信号量、CMSIS..)
文章目录 概述HelloWorld 工程C/C配置编译器主配置Makefile脚本烧录器主配置运行结果程序调用栈 任务管理实验实验结果osal 系统适配层osal_task_create 其他实验实验源码内存管理实验互斥锁实验信号量实验 CMISIS接口实验还是得JlINKCMSIS 简介LiteOS->CMSIS任务间消息交互…...
VM虚拟机网络配置(ubuntu24桥接模式):配置静态IP
编辑-虚拟网络编辑器-更改设置 选择桥接模式,然后找到相应的网卡(可以查看自己本机的网络连接) windows连接的网络点击查看属性 编辑虚拟机设置更改网络配置,选择刚才配置的桥接模式 静态ip设置: 我用的ubuntu24桌…...
使用LangGraph和LangSmith构建多智能体人工智能系统
现在,通过组合几个较小的子智能体来创建一个强大的人工智能智能体正成为一种趋势。但这也带来了一些挑战,比如减少幻觉、管理对话流程、在测试期间留意智能体的工作方式、允许人工介入以及评估其性能。你需要进行大量的反复试验。 在这篇博客〔原作者&a…...
