ROS 2邊學邊練(48)-- 將URDF與robot_state_publisher一起使用

前言

??????? 本篇將完成一個行走的機器人,并以tf2消息的方式實時發布機器人狀態,以便我們在Rviz中同步查看。

????????首先,我們創建描述機器人裝配的URDF模型。接下來,我們編寫一個節點,用于模擬運動并發布JointState和位姿變換。然后,我們使用robot_state_publisher將整個robot狀態發布到/tf2。

動動手

創建新包

??????? 執行如下命令創建新的工作空間second_ros2_ws,并在其下創建src文件夾:

$mkdir -p second_ros2_ws/src

??????? 再在src下創建urdf_tutorial_r2d2包:

$cd second_ros2_ws/src
$ros2 pkg create --build-type ament_python --license Apache-2.0 urdf_tutorial_r2d2 --dependencies rclpy
$cd urdf_tutorial_r2d2

創建URDF文件

??????? 在urdf_tutorial_r2d2包根路徑下,創建urdf文件夾,以放置保存一些組件:

$mkdir -p urdf

??????? 分別下載URDF文件(r2d2.urdf.xml)和Rviz配置文件(r2d2.rviz)到second_ros2_ws/src/urdf_tutorial_r2d2/urdf/路徑下。

發布狀態

????????現在我們需要一種方法來指定機器人的狀態。要做到這一點,我們必須指定所有三個關節和整體里程計。

??????? 創建second_ros2_ws/src/urdf_tutorial_r2d2/urdf_tutorial_r2d2/state_publisher.py文件,將下述內容復制其中:

from math import sin, cos, pi
import rclpy
from rclpy.node import Node
from rclpy.qos import QoSProfile
from geometry_msgs.msg import Quaternion
from sensor_msgs.msg import JointState
from tf2_ros import TransformBroadcaster, TransformStampedclass StatePublisher(Node):def __init__(self):rclpy.init()super().__init__('state_publisher')qos_profile = QoSProfile(depth=10)self.joint_pub = self.create_publisher(JointState, 'joint_states', qos_profile)self.broadcaster = TransformBroadcaster(self, qos=qos_profile)self.nodeName = self.get_name()self.get_logger().info("{0} started".format(self.nodeName))degree = pi / 180.0loop_rate = self.create_rate(30)# robot statetilt = 0.tinc = degreeswivel = 0.angle = 0.height = 0.hinc = 0.005# message declarationsodom_trans = TransformStamped()odom_trans.header.frame_id = 'odom'odom_trans.child_frame_id = 'axis'joint_state = JointState()try:while rclpy.ok():rclpy.spin_once(self)# update joint_statenow = self.get_clock().now()joint_state.header.stamp = now.to_msg()joint_state.name = ['swivel', 'tilt', 'periscope']joint_state.position = [swivel, tilt, height]# update transform# (moving in a circle with radius=2)odom_trans.header.stamp = now.to_msg()odom_trans.transform.translation.x = cos(angle)*2odom_trans.transform.translation.y = sin(angle)*2odom_trans.transform.translation.z = 0.7odom_trans.transform.rotation = \euler_to_quaternion(0, 0, angle + pi/2) # roll,pitch,yaw# send the joint state and transformself.joint_pub.publish(joint_state)self.broadcaster.sendTransform(odom_trans)# Create new robot statetilt += tincif tilt < -0.5 or tilt > 0.0:tinc *= -1height += hincif height > 0.2 or height < 0.0:hinc *= -1swivel += degreeangle += degree/4# This will adjust as needed per iterationloop_rate.sleep()except KeyboardInterrupt:passdef euler_to_quaternion(roll, pitch, yaw):qx = sin(roll/2) * cos(pitch/2) * cos(yaw/2) - cos(roll/2) * sin(pitch/2) * sin(yaw/2)qy = cos(roll/2) * sin(pitch/2) * cos(yaw/2) + sin(roll/2) * cos(pitch/2) * sin(yaw/2)qz = cos(roll/2) * cos(pitch/2) * sin(yaw/2) - sin(roll/2) * sin(pitch/2) * cos(yaw/2)qw = cos(roll/2) * cos(pitch/2) * cos(yaw/2) + sin(roll/2) * sin(pitch/2) * sin(yaw/2)return Quaternion(x=qx, y=qy, z=qz, w=qw)def main():node = StatePublisher()if __name__ == '__main__':main()

創建啟動文件

??????? 創建second_ros2_ws/src/urdf_tutorial_r2d2/launch文件夾,在其中新建demo_launch.py文件,將下面內容復制其中:

import os
from ament_index_python.packages import get_package_share_directory
from launch import LaunchDescription
from launch.actions import DeclareLaunchArgument
from launch.substitutions import LaunchConfiguration
from launch_ros.actions import Nodedef generate_launch_description():use_sim_time = LaunchConfiguration('use_sim_time', default='false')urdf_file_name = 'r2d2.urdf.xml'urdf = os.path.join(get_package_share_directory('urdf_tutorial_r2d2'),urdf_file_name)with open(urdf, 'r') as infp:robot_desc = infp.read()return LaunchDescription([DeclareLaunchArgument('use_sim_time',default_value='false',description='Use simulation (Gazebo) clock if true'),Node(package='robot_state_publisher',executable='robot_state_publisher',name='robot_state_publisher',output='screen',parameters=[{'use_sim_time': use_sim_time, 'robot_description': robot_desc}],arguments=[urdf]),Node(package='urdf_tutorial_r2d2',executable='state_publisher',name='state_publisher',output='screen'),])

編輯setup.py文件

??????? 我們必須告訴colcon build工具如何安裝指定的python包。這可以通過修改python包根路徑下的setup.py文件實現。

????????包含如下內容

import os
from glob import glob
from setuptools import setup
from setuptools import find_packages
data_files=[...(os.path.join('share', package_name, 'launch'), glob(os.path.join('launch', '*launch.[pxy][yma]*'))),(os.path.join('share', package_name), glob('urdf/*')),
],

????????修改入口點(entry_points),使得可以通過控制臺啟動'state_publisher'.

'console_scripts': ['state_publisher = urdf_tutorial_r2d2.state_publisher:main'
],

安裝python包

$cd second_ros2_ws
$colcon build --symlink-install --packages-select urdf_tutorial_r2d2

????????最后配置下環境變量:

$source install/setup.bash

查看結果

$ros2 launch urdf_tutorial_r2d2 demo_launch.py

????????打開另外一個終端,運行rviz2進行查看(rviz使用參考)。

$source /opt/ros/iron/setup.bash
$rviz2 -d second_ros2_ws/install/urdf_tutorial_r2d2/share/urdf_tutorial_r2d2/r2d2.rviz

????????不出大意外的話,大家運行后的結果應該像下面這樣(需要手動點擊左下角的Add按鈕添加TF及機器人模型),機器人“隱身”了。?

?

? ? ? ? 如果我們換個命令,則一切正常了(其實前面的命令最后調用的還是下面這個路徑的rviz文件)

$rviz2 -d src/urdf_tutorial_r2d2/urdf/r2d2.rviz

或加上絕對路徑,

$rviz2 -d ~/Desktop/second_ros2_ws/install/urdf_tutorial_r2d2/share/urdf_tutorial_r2d2/r2d2.rviz

?

????????此例原始代碼工程在這(只不過編譯運行后會報錯誤,需要增加dummpy link來解決)。

本篇完。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/12947.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/12947.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/12947.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

C-函數的由淺入深

1.函數的定義 數據類型 函數名 &#xff08;【數據類型 形參名&#xff0c;數據類型 形參名&#xff0c; …】&#xff09; 2.函數的傳參 值傳遞 地址傳遞 全局變量 3.函數的調用 嵌套調用 遞歸 4.函數與數組 5.函數與指針 指針函數 函數指針 函數指針數組 函數的定義 #inclu…

醉了,面個功能測試,還問我Python裝飾器

Python 裝飾器是個強大的工具&#xff0c;可幫你生成整潔、可重用和可維護的代碼。某種意義上說&#xff0c;會不會用裝飾器是區分新手和老鳥的重要標志。如果你不熟悉裝飾器&#xff0c;你可以將它們視為將函數作為輸入并在不改變其主要用途的情況下擴展其功能的函數。裝飾器可…

dhcp(接口和全局地址池模式)

接口地址池和全局地址池 dhcp應用 1.全部開啟dhcp功能 2.ar5 0口接口地址池 1口全局地址池 3.ar6和ar7配置&#xff0c;查看能否自動獲取ip 左右不同兩個網絡&#xff0c;接口和全局地址池的區別 部分截圖 ar6 ar7 ar5

(實測驗證)【移遠EC800M-CN 】TCP 透傳

引言 本文章使用自研“超小體積TTL轉4GGPS集成模塊”進行實測驗證&#xff1b; 1、配置移遠EC800M-CN TCP 透傳 串口助手發送&#xff1a; ATQIOPEN1,0,"TCP","36.137.226.30",39755,0,2 //配置服務器地址和端口號&#xff1b; 4G模組返回…

07-Fortran基礎--Fortran指針(Pointer)的使用

07-Fortran基礎--Fortran指針Pointer的使用 0 引言1 指針&#xff08;Poionter&#xff09;的有關內容1.1 一般類型指針1.2 數組指針1.3 派生類(type)指針1.4 函數指針 2 可運行code 0 引言 Fortran是一種廣泛使用的編程語言&#xff0c;特別適合科學計算和數值分析。Fortran 9…

java代碼混淆工具ProGuard混淆插件

java代碼混淆工具ProGuard混淆插件 介紹 ProGuard是一個純java編寫的混淆工具&#xff0c;有客戶端跟jar包兩種使用方式。可以將程序打包為jar&#xff0c;然后用工具進行混淆&#xff0c;也可以在maven中導入ProGuard的插件&#xff0c;對代碼進行混淆。 大家都知道 java代…

【華為OD機試-C卷D卷-200分】田忌賽馬(C++/Java/Python)

【華為OD機試】-(A卷+B卷+C卷+D卷)-2024真題合集目錄 【華為OD機試】-(C卷+D卷)-2024最新真題目錄 題目描述 給定兩個只包含數字的數組a,b,調整數組 a 里面的數字的順序,使得盡可能多的a[i] > b[i]。 數組a和b中的數字各不相同。 輸出所有可以達到最優結果的a數組的…

SadTalker 自定義容器化部署配置

Docker 環境檢查 執行docker info 查看環境種是否有安裝docker&#xff0c;否則首先安裝好docker 運行環境。在線環境安裝執行執行兩條指令即可 sudo apt install docker sudo apt-get install docker-ce sudo apt-get install docker-composesudo systemctl restart dockerG…

langchain源碼

itemgetter&#xff1a;返回一個函數&#xff0c;函數取輸入dict的某個指定key Runnable 的基本方法有 invoke、 batch、 await、 ainvoke、 abatch 同步轉異步 Runnable 還具有的方法&#xff1a;bind、 with_config。 input_schema 屬性、output_schema 屬性 with_retry方…

Uniapp H5開發常見問題解析

引言 在移動應用開發領域&#xff0c;Uniapp已經成為一個備受矚目的技術框架&#xff0c;其跨平臺能力和高效開發特性使得開發者能夠更加便捷地構建出功能豐富、性能優越的應用程序。特別是在H5開發中&#xff0c;Uniapp的應用場景日益廣泛&#xff0c;然而&#xff0c;隨之而…

Vue2之使用provide和inject實現兩個不相干組件之間的通信

Vue2之使用provide和inject實現兩個不相干組件之間的通信 文章目錄 Vue2之使用provide和inject實現兩個不相干組件之間的通信1. 祖先組件中使用provide提供數據2.后代組件A中使用inject注入并使用數據3.后代組件B中使用inject注入并使用數據 在Vue 2中以使用provide和inject來實…

[ciscn 2022 東北賽區]math

1.題目 import gmpy2 from Crypto.Util.number import * from flag import flag assert flag.startswith(b"flag{") assert flag.endswith(b"}") messagebytes_to_long(flag) def keygen(nbit, dbit):if 2*dbit < nbit:while True:a1 getRandomNBitIn…

編輯器目錄樹的設計,一點也不簡單

朋友們好&#xff0c;我是優秀的大鵬 今天花了很長時間思考一個網頁文檔編輯器&#xff0c;云端目錄樹要怎么設計 這個看似簡單的需求&#xff0c;技術上和產品上的思考卻非常復雜 下面以幾種編輯器為例&#xff0c;講一下各種編輯器在技術上和產品的思考 1、以Vscode為代表的本…

Delphi DataSet轉JSon (使用SuperObject)

Delphi中將TDataSet轉換為JSon字符串。 with ATM.LoadDataSet() dobeginif IsEmpty thenbeginLogObj.WriteLog(未查詢到該視圖名稱下該時間段內的上傳數據&#xff0c;視圖名稱&#xff1a; AViewname 開始時間&#xff1a; AStartdate 結束時間&#xff1a; AEnddate);exit…

【神經網絡與深度學習】Transformer原理

transformer ENCODER 輸入部分 對拆分后的語句x [batch_size, seq_len]進行以下操作 Embedding 將離散的輸入&#xff08;如單詞索引或其他類別特征&#xff09;轉換為稠密的實數向量&#xff0c;以便可以在神經網絡中使用。位置編碼 與RNN相比&#xff0c;RNN是一個字一個字…

Django Rest Framework 全局異常處理

在Django Rest Framework&#xff08;DRF&#xff09;中&#xff0c;全局異常處理是一種重要的機制&#xff0c;它可以幫助我們更好地管理API中的異常情況&#xff0c;并返回統一的錯誤響應。本文將詳細介紹兩種全局異常處理的方法&#xff1a;使用中間件&#xff08;Middlewar…

機器學習(3)

目錄 3-1線性回歸 3-2最小二乘解 3-3多元線性回歸 3-4廣義線性模型 3-5對率回歸 3-6對率回歸求解 3-7線性判別分析 3-8LDA的多類推廣 3-9多分類學習基本思路 3-10類別不平衡 3-1線性回歸 線性模型為什么重要&#xff1f; 人類在考慮問題時&#xff0c;通常…

用python寫一個自動生成android開機動畫的工具

要創建一個自動生成Android開機動畫的工具&#xff0c;你需要一些基本的知識&#xff0c;比如Python編程、圖像處理和Android開機動畫的格式。以下是一個簡單的Python腳本示例&#xff0c;它可以生成一個基本的Android開機動畫&#xff0c;具體效果可能需要更多的調整和優化。 …

記錄glide加載圖片,設置圓角

支持所有角的圓角&#xff0c;自動計算合適的半徑&#xff0c;不用擔心圖片比預定值小導致的圓角過大的問題 修改自&#xff1a;https://blog.csdn.net/qq_15059163/article/details/97613790 增加了指定圖片尺寸、解決了圖片某些情況下圓角過大的問題 public class GlideRou…

先有JVM還是先有垃圾回收器?很多人弄混淆了

是先有垃圾回收器再有JVM呢&#xff0c;還是先有JVM再有垃圾回收器呢&#xff1f;或者是先有垃圾回收再有JVM呢&#xff1f;歷史上還真是垃圾回收更早面世&#xff0c;垃圾回收最早起源于1960年誕生的LISP語言&#xff0c;Java只是支持垃圾回收的其中一種。下面我們就來刨析刨析…