Go to the documentation of this file.00001 #include <tf_remapper_cpp/tf_remapper_node.h>
00002 #include <set>
00003
00004 tf_remapper_cpp::TfRemapperNode::TfRemapperNode() : privateNodeHandle("~")
00005 {
00006 this->oldTfTopic = this->privateNodeHandle.param<std::string>("old_tf_topic_name", "/tf_old");
00007 this->remappedTfTopic = this->privateNodeHandle.param<std::string>("new_tf_topic_name", "/tf");
00008
00009 if (this->privateNodeHandle.hasParam("static_tf"))
00010 this->staticTf = this->privateNodeHandle.param<bool>("static_tf", false);
00011 else
00012
00013 this->staticTf = this->remappedTfTopic == "tf_static" || this->remappedTfTopic == "/tf_static";
00014
00015
00016 XmlRpc::XmlRpcValue mappingsParam;
00017 const bool hasMappingsParam = this->privateNodeHandle.getParam("mappings", mappingsParam);
00018 if (!hasMappingsParam) {
00019 mappingsParam.setSize(0);
00020 ROS_WARN("The 'mappings' parameter to tf_remap is missing");
00021 }
00022
00023 const bool bidirectional = this->privateNodeHandle.param<bool>("is_bidirectional", false);
00024
00025 this->tfRemapper = TfRemapper(mappingsParam);
00026 if (bidirectional)
00027 this->reverseTfRemapper = TfRemapper(mappingsParam, true);
00028
00029 if (!tfRemapper.getMappings().empty()) {
00030 ROS_INFO_STREAM("Applying the following mappings" << (bidirectional ? " bidirectionally" : "") <<
00031 " to incoming tf frame ids:");
00032 for (TfRemapper::MappingsType::const_iterator it = tfRemapper.getMappings().begin();
00033 it != tfRemapper.getMappings().end(); ++it) {
00034 ROS_INFO_STREAM("* " << it->first << " " << (bidirectional && !it->second.empty() ? "<" : "") << "-> " <<
00035 (it->second.empty() ? "DELETE" : it->second));
00036 }
00037 if (bidirectional) {
00038 for (TfRemapper::MappingsType::const_iterator it = reverseTfRemapper.getMappings().begin();
00039 it != reverseTfRemapper.getMappings().end(); ++it) {
00040 if (it->second.empty())
00041 ROS_INFO_STREAM("* DELETE <- " << it->first);
00042 }
00043 }
00044 } else {
00045 ROS_WARN("No mappings defined.");
00046 }
00047
00048 ROS_INFO_STREAM("Old TF topic: " << this->oldTfTopic);
00049 ROS_INFO_STREAM("Remapped TF topic: " << this->remappedTfTopic);
00050 if (this->staticTf)
00051 ROS_INFO("Running in static TF mode (caching all TFs, latched publisher)");
00052
00053 this->oldTfSubscriber = this->publicNodeHandle.subscribe(
00054 this->oldTfTopic, 100, &TfRemapperNode::oldTfCallback, this);
00055 this->remappedTfPublisher = this->publicNodeHandle.advertise<tf2_msgs::TFMessage>(
00056 this->remappedTfTopic, 100, this->staticTf);
00057
00058 if (bidirectional) {
00059 this->remappedTfSubscriber = this->publicNodeHandle.subscribe(
00060 this->remappedTfTopic, 100, &TfRemapperNode::remappedTfCallback, this);
00061 this->oldTfPublisher = this->publicNodeHandle.advertise<tf2_msgs::TFMessage>(
00062 this->oldTfTopic, 100, this->staticTf);
00063 }
00064 }
00065
00066 void tf_remapper_cpp::TfRemapperNode::oldTfCallback(const ros::MessageEvent<tf2_msgs::TFMessage const>& event) {
00067
00068 const std::string& callerid = event.getPublisherName();
00069 if (callerid == ros::this_node::getName())
00070 return;
00071
00072 tf2_msgs::TFMessage message = this->tfRemapper.doRemapping(*event.getConstMessage());
00073
00074
00075
00076 if (this->staticTf) {
00077 this->addToStaticTfCache(message, this->staticTfCache);
00078 this->remappedTfPublisher.publish(this->staticTfCache);
00079 } else {
00080 this->remappedTfPublisher.publish(message);
00081 }
00082 }
00083
00084 void tf_remapper_cpp::TfRemapperNode::remappedTfCallback(const ros::MessageEvent<tf2_msgs::TFMessage const>& event) {
00085
00086 const std::string& callerid = event.getPublisherName();
00087 if (callerid == ros::this_node::getName())
00088 return;
00089
00090 tf2_msgs::TFMessage message = this->reverseTfRemapper.doRemapping(*event.getConstMessage());
00091
00092
00093
00094 if (this->staticTf) {
00095 this->addToStaticTfCache(message, this->reverseStaticTfCache);
00096 this->oldTfPublisher.publish(this->reverseStaticTfCache);
00097 } else {
00098 this->oldTfPublisher.publish(message);
00099 }
00100 }
00101
00102 void tf_remapper_cpp::TfRemapperNode::addToStaticTfCache(
00103 const tf2_msgs::TFMessage& message, tf2_msgs::TFMessage& cache) const {
00104
00105 for (std::vector<geometry_msgs::TransformStamped>::const_iterator it = message.transforms.begin();
00106 it != message.transforms.end(); ++it) {
00107 bool found = false;
00108 for (std::vector<geometry_msgs::TransformStamped>::iterator cacheIt = cache.transforms.begin();
00109 cacheIt != cache.transforms.end(); ++cacheIt) {
00110 if (it->child_frame_id == cacheIt->child_frame_id) {
00111 found = true;
00112 *cacheIt = *it;
00113 break;
00114 }
00115 }
00116 if (!found)
00117 cache.transforms.push_back(*it);
00118 }
00119 }
00120
00121 int main(int argc, char * argv[])
00122 {
00123 ros::init(argc, argv, "tf_remapper");
00124 tf_remapper_cpp::TfRemapperNode remapper;
00125 ros::spin();
00126 return 0;
00127 }