write a tf listener

本文档介绍了在编写ROS TF监听器时遇到的常见问题,包括如何发布机器人的定位信息,解决"target_frame不存在"错误,以及启动launch文件时找不到节点的处理办法。提供了详细的解决步骤和代码示例。

写tf listener时遇到的问题:

参考网页:http://wiki.ros.org/tf/Tutorials/Writing%20a%20tf%20listener%20%28C%2B%2B%29

1.  How to publish the pose (position) of the robot after having the tf listener to "listener.lookupTransform("/map", "/base_link", ros::Time(0), transform);"?

解决方法:

use the standard ROS messages to represent pose info. You can use either geometry_msgs/Pose (http://docs.ros.org/jade/api/geometry_msgs/html/msg/Pose.html)or geometry_msgs/PoseWithCovariance (http://docs.ros.org/indigo/api/geometry_msgs/html/msg/PoseWithCovariance.html : if you need to publish pose together with its covariance )

so if you have populated transform variable with a call to lookupTransform, you can for example store the pose (without covariance) as follows,

geometry_msgs::Pose pose;
pose.position.x = transform.getOrigin().x();
pose.position.y = transform.getOrigin().y();
pose.position.z = transform.getOrigin().z();

// these two are valid only if the robot is operating in 2D
double yaw = tf::getYaw( transform.getRotation() );
pose.orientation = tf::createQuaternionMsgFromYaw( yaw );

now you can publish the 2D pose as a geometry_msgs/Pose message

2. 运行写好的程序时,遇到错误:"map" passed to lookupTransform argument target_frame does not exist.

解决方法:

- 加上listener.waitForTransform(...)

try {
    listener.waitForTransform(destination_frame, original_frame, ros::Time(0), ros::Duration(10.0) );
    listener.lookupTransform(destination_frame, original_frame, ros::Time(0), transform);
} catch (tf::TransformException ex) {
    ROS_ERROR("%s",ex.what());
}
- 加include的头文件:

#include <nav_msgs/Odometry.h>
#include <tf/transform_listener.h>

再重新编译,就可以通过:./<nodename> 得到publish:; destination_frame和orginal_frame的 tf的topic了。

3. 运行写好的launch file to run publish the tf. 错误:ERROR: cannot launch node of type [learning_tf/pioneer_tf_listener]: can't locate node [pioneer_tf_listener] in package [learning_tf]

解决方法:需要在当前路径下 source ~/catkin_ws/devel/setup.bash

from __future__ import print_function, with_statement import sys, time import os import string import re import subprocess import distutils.version from optparse import OptionParser import rospy from tf.srv import * import tf def listen(duration): rospy.init_node("view_frames", anonymous=True) tf_listener = tf.TransformListener() print("Listening to /tf for {} seconds".format(duration)) time.sleep(duration) print("Done Listening") return tf_listener.allFramesAsDot(rospy.Time.now()) def poll(node_name): print("Waiting for service {}/tf_frames".format(node_name)) rospy.wait_for_service('{}/tf_frames'.format(node_name)) try: print("Polling service") tf_frames_proxy = rospy.ServiceProxy('{}/tf_frames'.format(node_name), FrameGraph) output = tf_frames_proxy.call(FrameGraphRequest()) except rospy.ServiceException as e: print("Service call failed: {}".format(e)) return output.dot_graph def generate(dot_graph): with open('frames.gv', 'w') as outfile: outfile.write(dot_graph) try: # Check version, make postscript if too old to make pdf args = ["dot", "-V"] try: vstr = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()[1] except OSError as ex: print("Warning: Could not execute `dot -V`. Is graphviz installed?") sys.exit(-1) v = distutils.version.StrictVersion('2.16') r = re.compile(".*version (\d+\.?\d*)") print(vstr) vstr = str(vstr) m = r.search(vstr.decode('utf-8') if not m or not m.group(1): print('Warning: failed to determine your version of dot. Assuming v2.16') else: version = distutils.version.StrictVersion(m.group(1)) print('Detected dot version {}'.format(version)) if version > distutils.version.StrictVersion('2.8'): subprocess.check_call(["dot", "-Tpdf", "frames.gv", "-o", "frames.pdf"]) else: subprocess.check_call(["dot", "-Tps2", "frames.gv", "-o", "frames.ps"]) print("frames.ps generated") except subprocess.CalledProcessError: print("failed to generate frames.pdf", file=sys.stderr) if __name__ == '__main__': parser = OptionParser(usage="usage: %prog [options]", prog='viewFrames.py') parser.add_option("--node", metavar="node name", type="string", help="Node to get frames from", dest="node") options, args = parser.parse_args() dot_graph = '' if not options.node: dot_graph = listen(5.0) else: print("Generating graph for node: ", options.node) dot_graph = poll(options.node) generate(dot_graph) 什么问题
最新发布
07-01
#!/usr/bin/env python3 import rospy import tf2_ros import geometry_msgs.msg import serial import time def main(): # 初始化ROS节点 rospy.init_node('t265_serial_sender') # 设置串口(根据你的设备修改端口和波特率) serial_port = rospy.get_param('~port', '/dev/ttyS0') baud_rate = rospy.get_param('~baud', 115200) try: ser = serial.Serial(serial_port, baud_rate, timeout=1) rospy.loginfo(f"Serial port {serial_port} opened at {baud_rate} baud") except serial.SerialException as e: rospy.logerr(f"Failed to open serial port: {e}") return # 初始化TF2监听器 tf_buffer = tf2_ros.Buffer() tf_listener = tf2_ros.TransformListener(tf_buffer) rate = rospy.Rate(10) # 10Hz while not rospy.is_shutdown(): try: # 动态等待坐标系可用(最多等待5秒) tf_buffer.can_transform('camera_odom_frame', 'camera_pose_frame', rospy.Time(0), rospy.Duration(5.0)) # 获取T265的位姿(假设T265的frame_id是"camera_pose_frame") transform = tf_buffer.lookup_transform( 'camera_odom_frame', # 目标坐标系(通常是odom) 'camera_pose_frame', # 源坐标系(T265的坐标系) rospy.Time(0), # 获取最新数据 rospy.Duration(1.0) # 超时时间 ) # 提取位置和四元数姿态 trans = transform.transform.translation rot = transform.transform.rotation # 格式化数据为字符串(例如:x,y,z,qx,qy,qz,qw) data_str = f"{trans.x},{trans.y},{trans.z},{rot.x},{rot.y},{rot.z},{rot.w}\n" # 通过串口发送数据 ser.write(data_str.encode('utf-8')) rospy.loginfo(f"Sent: {data_str.strip()}") except (tf2_ros.LookupException, tf2_ros.ConnectivityException, tf2_ros.ExtrapolationException) as e: rospy.logwarn_throttle(5, f"等待TF数据中... 错误: {e}") except serial.SerialException as e: rospy.logerr(f"Serial write failed: {e}") break rate.sleep() continue # 跳过本次循环 ser.close() if __name__ == '__main__': main() 这是用ros和python将t265的位置信息通过树莓派串口发送的代码,我想把速度信息也发送出去,帮我改进一下
05-26
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值