ROS 主题重新映射不适用于 TransformBroadcaster

问题描述 投票:0回答:1

对于我想为一堆模拟机器人发布 odom tfs 的特定情况,我尝试将“/tf”主题重新映射到机器人特定主题,例如 /robot1_tf、/robot2_tf 等。更准确地说,在一个控制循环的某个地方,在一个通用过程中模拟我的所有机器人,我这样做是为了喂养 amcl:

tf::TransformBroadcaster* tfBroadcaster;

void ROSInterface::sendOdomData(const Vector<OdomData> &odomData)
{
    for (uint i = 0; i < odomData.size(); i++) // process odomData for every simulated robot
    {
        // Publish the odom message.
        nav_msgs::Odometry odom;
        odom.header.stamp = ros::Time::now();
        odom.header.frame_id = "odom";
        odom.child_frame_id = "base_link";
        odom.pose.pose.position.x = odomData[i].x;
        odom.pose.pose.position.y = odomData[i].y;
        odom.pose.pose.position.z = 0.0;
        odom.pose.pose.orientation = tf::createQuaternionMsgFromYaw(odomData[i].theta);
        odom.twist.twist.linear.x = odomData[i].vx;
        odom.twist.twist.linear.y = odomData[i].vy;
        odom.twist.twist.angular.z = odomData[i].omega;
        odomPub[i].publish(odom);

        // Publish the odom transform with the TransformBroadcaster.
        geometry_msgs::TransformStamped odom_tf;
        odom_tf.header = odom.header;
        odom_tf.child_frame_id = "base_link";
        odom_tf.transform.translation.x = odomData[i].x;
        odom_tf.transform.translation.y = odomData[i].y;
        odom_tf.transform.translation.z = 0.0;
        odom_tf.transform.rotation = odom.pose.pose.orientation;
        tfBroadcaster->sendTransform(odom_tf);
    }
}

看看我如何为每个机器人都有一个 odomPub 向量?我可以像这样轻松设置:

std::vector<ros::Publisher> odomPub;
for (uint i = 0; i < robots.size(); i++)
    odomPub.push_back(nh->advertise<nav_msgs::Odometry>(std::string(robots[i].name + "/odom"), 1));

但是对于 TransformBroadcaster 而言,这是毫无意义的,所有已发布的变换都在一个“/tf”主题中网格在一起,无法将它们彼此区分开。

经过大量谷歌搜索后,我想到了一个想法,我可以为每个模拟机器人使用单独的节点句柄,并使用特定的映射实例化每个节点句柄,如下所示:

ros::M_string remappings;
remappings.insert(std::make_pair("/tf", "/robot1_tf"));
remappings.insert(std::make_pair("tf", "/robot1_tf"));
nh1 = new ros::NodeHandle("devices", remappings);

但是没有。它不这样做。 TransformBroadcaster 仍然在“/tf”上发布,就好像映射不在那里一样。不过,该映射确实适用于我自己宣传的主题。我有什么做得不对的地方吗?有没有简单的方法来解决这个问题或以其他方式重新映射 /tf ?

到目前为止,我能够成功重新映射 /tf 的唯一方法是在启动文件中使用重新映射,

<remap from="/tf" to="/$(arg robot_id)_tf"/>

但这绝对是一场噩梦。模拟机器人的数量可以随时改变,理想情况下甚至在运行时也是如此。即使我重新启动整个模拟,我也必须动态创建一个启动文件,为每个机器人启动一个单独的节点,以便我可以单独重新映射它们的 /tf ,甚至不用说将 odom 数据从模拟过程获取到每个启动的节点都有单独的进程。

欢迎任何想法。

ros
1个回答
0
投票

但是对于 TransformBroadcaster 而言,这是毫无意义的,所有已发布的变换都在一个“/tf”主题中网格在一起,无法将它们彼此区分开。

TF的总体设计是它代表/管理整个系统中所有已建立的坐标系。因此,在这里您需要通过为伸手机器人提供自己的

frame_id
来区分 TF 网络中的机器人:

odom.child_frame_id = std::string(robots[i].name + "/base_link"; // match frame_id used in TF
...
odom_tf.child_frame_id = std::string(robots[i].name + "/base_link"; // separate frames in TF

这与 turtle_tf2_demo 生成多个海龟机器人的方式类似。

如果您尝试将每个模拟机器人的 TF 消息隔离到其自己的主题(就像使用 Odometry 正确完成的那样),您将遇到其他 ROS 工具(例如 rviz)都无法解决的问题设置为处理

/tf
/tf_static
以外主题的 TF 数据。当然,您可以重新映射主题名称,但是您永远不会同时拥有模拟机器人的所有的 TF 数据(我假设这就是您想要的)。

© www.soinside.com 2019 - 2024. All rights reserved.