如何发布镜像 tf?
How to publish mirrored tf?
我试图将 rf2o laser_to_odometry 用于导航堆栈。但是,当我移动机器人时,tf 方向错误。即当我将机器人向右移动时,tf 向左移动。
对于激光雷达的配置:我将激光雷达绕z方向旋转90度并上下颠倒,它只扫描了一半范围,从-180度到0度。
tf 设置正确,我在创建地图时用 hector slam 再次检查,args="0.2 0 0 1.57 3.14 0 /base_link /laser_frame 40
,而且当我没有将激光雷达倒置时也没有出现此问题(并且还更改了 tf静态发布者到后面 args="0.2 0 0 0 0 0 /base_link /laser_frame 40
)
以下是我在rf2o包的CLaserOdometry2DNode.cpp中找到的代码(also can be found here)..这里会不会有什么问题导致包中的tf没有被正确读取,或者有什么编辑这个的方法,镜像 tf(左和右,即沿 y 轴镜像)?
如果有人能提供帮助,我们将不胜感激!!
// Set laser pose on the robot (through tF)
// This allow estimation of the odometry with respect to the robot base reference system.
tf::StampedTransform transform;
transform.setIdentity();
try
{
tf_listener.lookupTransform(base_frame_id, last_scan.header.frame_id, ros::Time(0), transform);
retrieved = true;
}
catch (tf::TransformException &ex)
{
ROS_ERROR("%s",ex.what());
ros::Duration(1.0).sleep();
retrieved = false;
}
//TF:transform -> Eigen::Isometry3d
const tf::Matrix3x3 &basis = transform.getBasis();
Eigen::Matrix3d R;
for(int r = 0; r < 3; r++)
for(int c = 0; c < 3; c++)
R(r,c) = basis[r][c];
Pose3d laser_tf(R);
const tf::Vector3 &t = transform.getOrigin();
laser_tf.translation()(0) = t[0];
laser_tf.translation()(1) = t[1];
laser_tf.translation()(2) = t[2];
setLaserPose(laser_tf);
return retrieved;
}
编辑:
这是 tf 树
tf tree
我试图了解这个包,知道在它监听 tf 之后,也就是上面附加的代码,它会将值传递给 setLaserPose:
void CLaserOdometry2D::setLaserPose(const Pose3d& laser_pose)
{
//Set laser pose on the robot
laser_pose_on_robot_ = laser_pose;
laser_pose_on_robot_inv_ = laser_pose_on_robot_.inverse();
}
并转换最终结果 robot_pose_ 相对于 tf,见下文: 但是,我发现两个 ROS_INFO_COND 消息是相同的,没有区别..似乎 laser_pose_on_robot_inv_ 没有转换结果...我可以就如何处理这个问题提出一些建议吗?
ROS_INFO_COND(verbose, "[rf2o] LASERodom = [%f %f %f]",
laser_pose_.translation()(0),
laser_pose_.translation()(1),
rf2o::getYaw(laser_pose_.rotation()));
//Compose Transformations
robot_pose_ = laser_pose_ * laser_pose_on_robot_inv_;
ROS_INFO_COND(verbose, "BASEodom = [%f %f %f]",
robot_pose_.translation()(0),
robot_pose_.translation()(1),
rf2o::getYaw(robot_pose_.rotation()));
在 rviz 中也有 tf
enter image description here
rf2o 的启动文件(导航堆栈中 robot_configuration)
<launch>
<node name="ydlidar_node" pkg="ydlidar" type="ydlidar_node" output="screen">
<param name="port" type="string" value="/dev/ydlidar"/>
<param name="baudrate" type="int" value="115200"/>
<param name="frame_id" type="string" value="laser_frame"/>
<param name="angle_fixed" type="bool" value="true"/>
<param name="low_exposure" type="bool" value="false"/>
<param name="heartbeat" type="bool" value="false"/>
<param name="resolution_fixed" type="bool" value="true"/>
<param name="angle_min" type="double" value="-180" />
<param name="angle_max" type="double" value="0" />
<param name="range_min" type="double" value="0.08" />
<param name="range_max" type="double" value="16.0" />
<param name="ignore_array" type="string" value="" />
<param name="samp_rate" type="int" value="9"/>
<param name="frequency" type="double" value="7"/>
</node>
<node pkg="tf" type="static_transform_publisher" name="base_footprint_to_base_link"
args="0 0 0 0 0 0 /base_footprint /base_link 40" />
<node pkg="tf" type="static_transform_publisher" name="base_link_to_laser_frame"
args="0.3 0 0 1.57 3.14 0 /base_link /laser_frame 40" />
<node pkg="rf2o_laser_odometry" type="rf2o_laser_odometry_node" name="rf2o_laser_odometry" output="screen">
<param name="laser_scan_topic" value="/scan"/> # topic where the lidar scans are being published
<param name="publish_tf" value="true" /> # wheter or not to publish the tf::transform (base->odom)
<param name="base_frame_id" value="/base_footprint"/> # frame_id (tf) of the mobile robot base. A tf transform from the laser_frame to the base_frame is mandatory
<param name="odom_frame_id" value="/odom" /> # frame_id (tf) to publish the odometry estimations
<param name="init_pose_from_topic" value="" /> # (Odom topic) Leave empty to start at point (0,0)
<param name="freq" value="40.0"/> # Execution frequency.
</node>
<node pkg="rviz" type="rviz" name="rviz"
args="-d $(find mobilet_2dnav)/rviz_cfg/configuration.rviz"/>
</launch>
非常感谢 Vik 的领导。
所以看起来 tf 在听的时候还没有在缓冲区里。
等待转换后它现在可以工作了:
对于CLaserOdometry2DNode.cpp,
我加一行
tf_listener.waitForTransform("/base_footprint","/laser_frame", ros::Time(), ros::Duration(5.0));
在tf_listener.lookupTransform
之前
希望这对使用 rf2o 的人有所帮助 laser_to_odometry。
我试图将 rf2o laser_to_odometry 用于导航堆栈。但是,当我移动机器人时,tf 方向错误。即当我将机器人向右移动时,tf 向左移动。
对于激光雷达的配置:我将激光雷达绕z方向旋转90度并上下颠倒,它只扫描了一半范围,从-180度到0度。
tf 设置正确,我在创建地图时用 hector slam 再次检查,args="0.2 0 0 1.57 3.14 0 /base_link /laser_frame 40
,而且当我没有将激光雷达倒置时也没有出现此问题(并且还更改了 tf静态发布者到后面 args="0.2 0 0 0 0 0 /base_link /laser_frame 40
)
以下是我在rf2o包的CLaserOdometry2DNode.cpp中找到的代码(also can be found here)..这里会不会有什么问题导致包中的tf没有被正确读取,或者有什么编辑这个的方法,镜像 tf(左和右,即沿 y 轴镜像)?
如果有人能提供帮助,我们将不胜感激!!
// Set laser pose on the robot (through tF)
// This allow estimation of the odometry with respect to the robot base reference system.
tf::StampedTransform transform;
transform.setIdentity();
try
{
tf_listener.lookupTransform(base_frame_id, last_scan.header.frame_id, ros::Time(0), transform);
retrieved = true;
}
catch (tf::TransformException &ex)
{
ROS_ERROR("%s",ex.what());
ros::Duration(1.0).sleep();
retrieved = false;
}
//TF:transform -> Eigen::Isometry3d
const tf::Matrix3x3 &basis = transform.getBasis();
Eigen::Matrix3d R;
for(int r = 0; r < 3; r++)
for(int c = 0; c < 3; c++)
R(r,c) = basis[r][c];
Pose3d laser_tf(R);
const tf::Vector3 &t = transform.getOrigin();
laser_tf.translation()(0) = t[0];
laser_tf.translation()(1) = t[1];
laser_tf.translation()(2) = t[2];
setLaserPose(laser_tf);
return retrieved;
}
编辑: 这是 tf 树 tf tree
我试图了解这个包,知道在它监听 tf 之后,也就是上面附加的代码,它会将值传递给 setLaserPose:
void CLaserOdometry2D::setLaserPose(const Pose3d& laser_pose)
{
//Set laser pose on the robot
laser_pose_on_robot_ = laser_pose;
laser_pose_on_robot_inv_ = laser_pose_on_robot_.inverse();
}
并转换最终结果 robot_pose_ 相对于 tf,见下文: 但是,我发现两个 ROS_INFO_COND 消息是相同的,没有区别..似乎 laser_pose_on_robot_inv_ 没有转换结果...我可以就如何处理这个问题提出一些建议吗?
ROS_INFO_COND(verbose, "[rf2o] LASERodom = [%f %f %f]",
laser_pose_.translation()(0),
laser_pose_.translation()(1),
rf2o::getYaw(laser_pose_.rotation()));
//Compose Transformations
robot_pose_ = laser_pose_ * laser_pose_on_robot_inv_;
ROS_INFO_COND(verbose, "BASEodom = [%f %f %f]",
robot_pose_.translation()(0),
robot_pose_.translation()(1),
rf2o::getYaw(robot_pose_.rotation()));
在 rviz 中也有 tf enter image description here
rf2o 的启动文件(导航堆栈中 robot_configuration)
<launch>
<node name="ydlidar_node" pkg="ydlidar" type="ydlidar_node" output="screen">
<param name="port" type="string" value="/dev/ydlidar"/>
<param name="baudrate" type="int" value="115200"/>
<param name="frame_id" type="string" value="laser_frame"/>
<param name="angle_fixed" type="bool" value="true"/>
<param name="low_exposure" type="bool" value="false"/>
<param name="heartbeat" type="bool" value="false"/>
<param name="resolution_fixed" type="bool" value="true"/>
<param name="angle_min" type="double" value="-180" />
<param name="angle_max" type="double" value="0" />
<param name="range_min" type="double" value="0.08" />
<param name="range_max" type="double" value="16.0" />
<param name="ignore_array" type="string" value="" />
<param name="samp_rate" type="int" value="9"/>
<param name="frequency" type="double" value="7"/>
</node>
<node pkg="tf" type="static_transform_publisher" name="base_footprint_to_base_link"
args="0 0 0 0 0 0 /base_footprint /base_link 40" />
<node pkg="tf" type="static_transform_publisher" name="base_link_to_laser_frame"
args="0.3 0 0 1.57 3.14 0 /base_link /laser_frame 40" />
<node pkg="rf2o_laser_odometry" type="rf2o_laser_odometry_node" name="rf2o_laser_odometry" output="screen">
<param name="laser_scan_topic" value="/scan"/> # topic where the lidar scans are being published
<param name="publish_tf" value="true" /> # wheter or not to publish the tf::transform (base->odom)
<param name="base_frame_id" value="/base_footprint"/> # frame_id (tf) of the mobile robot base. A tf transform from the laser_frame to the base_frame is mandatory
<param name="odom_frame_id" value="/odom" /> # frame_id (tf) to publish the odometry estimations
<param name="init_pose_from_topic" value="" /> # (Odom topic) Leave empty to start at point (0,0)
<param name="freq" value="40.0"/> # Execution frequency.
</node>
<node pkg="rviz" type="rviz" name="rviz"
args="-d $(find mobilet_2dnav)/rviz_cfg/configuration.rviz"/>
</launch>
非常感谢 Vik 的领导。 所以看起来 tf 在听的时候还没有在缓冲区里。 等待转换后它现在可以工作了:
对于CLaserOdometry2DNode.cpp, 我加一行
tf_listener.waitForTransform("/base_footprint","/laser_frame", ros::Time(), ros::Duration(5.0));
在tf_listener.lookupTransform
希望这对使用 rf2o 的人有所帮助 laser_to_odometry。