@@ -102,9 +102,10 @@ namespace rviz_mesh_tools_plugins
102102MeshDisplay::MeshDisplay ()
103103: rviz_common::Display()
104104, m_ignoreMsgs(false )
105- , m_meshQos(rclcpp::SystemDefaultsQoS())
106- , m_vertexColorsQos(rclcpp::SystemDefaultsQoS())
107- , m_vertexCostsQos(rclcpp::SystemDefaultsQoS())
105+ , m_meshQos(rclcpp::QoS(1 ).transient_local())
106+ , m_vertexColorsQos(rclcpp::QoS(5 ))
107+ , m_vertexCostsQos(rclcpp::QoS(5 ))
108+ , m_vertexCostUpdateQos(rclcpp::QoS(10 ))
108109{
109110 // mesh topic
110111 m_meshTopic = new rviz_common::properties::RosTopicProperty (
@@ -181,12 +182,21 @@ MeshDisplay::MeshDisplay()
181182
182183
183184 m_vertexCostsTopic = new rviz_common::properties::RosTopicProperty (
184- " Vertex Costs Topic" , " " ,
185+ " Costs Topic" , " " ,
185186 QString::fromStdString (rosidl_generator_traits::name<mesh_msgs::msg::MeshVertexCostsStamped>()),
186187 " Vertex cost topic to subscribe to." , m_displayType, SLOT (updateVertexCostsSubscription ()), this );
187188
188189 m_vertexCostsTopicQos = new rviz_common::properties::QosProfileProperty (m_vertexCostsTopic, m_vertexCostsQos);
189190
191+ m_vertexCostUpdateTopic = new rviz_common::properties::RosTopicProperty (
192+ " Update Topic" , " " ,
193+ QString::fromStdString (
194+ rosidl_generator_traits::name<mesh_msgs::msg::MeshVertexCostsSparseStamped>()
195+ ),
196+ " Vertex cost update topic to subscribe to." , m_displayType, SLOT (updateVertexCostsUpdateSubscription ()), this
197+ );
198+ m_vertexCostUpdateTopicQos = new rviz_common::properties::QosProfileProperty (m_vertexCostUpdateTopic, m_vertexCostUpdateQos);
199+
190200 m_selectVertexCostMap = new rviz_common::properties::EnumProperty (" Vertex Costs Type" , " -- None --" ,
191201 " Select the type of vertex cost map to be displayed. New types "
192202 " will appear here when a new message arrives." ,
@@ -775,14 +785,50 @@ void MeshDisplay::updateVertexCostsSubscription()
775785 auto node = context_->getRosNodeAbstraction ().lock ()->get_raw_node ();
776786 m_vertexCostsSubscriber.subscribe (node, m_vertexCostsTopic->getTopicStd (), m_vertexCostsQos.get_rmw_qos_profile ());
777787
778- m_costsMsgCache = std::make_shared<message_filters::Cache<mesh_msgs::msg::MeshVertexCostsStamped>>(m_vertexCostsSubscriber, 1 );
788+ // TODO: What is a good cache size? Could it be configurable by the user? Also it is not possible to clear the message cache after we processed the messages?
789+ m_costsMsgCache = std::make_shared<message_filters::Cache<mesh_msgs::msg::MeshVertexCostsStamped>>(m_vertexCostsSubscriber, 10 );
779790 m_costsMsgCache->registerCallback (std::bind (&MeshDisplay::vertexCostsCallback, this , _1));
791+
792+ // Update update topic
793+ const std::string update_topic = m_vertexCostsTopic->getTopicStd () + " /updates" ;
794+ m_vertexCostUpdateTopic->setStdString (update_topic);
780795 } else {
781796 setStatus (rviz_common::properties::StatusProperty::Warn, " Topic" , QString (" Error subscribing: Empty cost topic name" ));
782797 }
783798 }
784799}
785800
801+ void MeshDisplay::updateVertexCostsUpdateSubscription ()
802+ {
803+ if (m_vertexCostUpdateTopic->getHidden ())
804+ {
805+ return ;
806+ }
807+
808+ if (m_vertexCostUpdateTopic->getTopic ().isEmpty ())
809+ {
810+ return ;
811+ }
812+
813+ // Update the subscription
814+ auto node_abstraction = context_->getRosNodeAbstraction ().lock ();
815+ if (nullptr == node_abstraction)
816+ {
817+ RCLCPP_ERROR (
818+ rclcpp::get_logger (" rviz_mesh_tools_plugins" ),
819+ " [MeshDisplay::updateVertexCostsUpdateSubscription] Could not get the ROS Node abstraction instance from RViz context!"
820+ );
821+ return ;
822+ }
823+
824+ // Update the subscription
825+ rclcpp::Node::SharedPtr node = node_abstraction->get_raw_node ();
826+ m_vertexCostUpdateSubscriber.subscribe (node, m_vertexCostUpdateTopic->getTopicStd (), m_vertexCostUpdateQos.get_rmw_qos_profile ());
827+ // Update the cache
828+ m_costsUpdateMsgCache = std::make_shared<message_filters::Cache<mesh_msgs::msg::MeshVertexCostsSparseStamped>>(m_vertexCostUpdateSubscriber, 10 );
829+ m_costsUpdateMsgCache->registerCallback (std::bind (&MeshDisplay::vertexCostsUpdateCallback, this , _1));
830+ }
831+
786832void MeshDisplay::updateMaterialAndTextureServices ()
787833{
788834 if (m_ignoreMsgs)
@@ -984,6 +1030,7 @@ void MeshDisplay::meshGeometryCallback(
9841030 m_messagesReceived++;
9851031 setStatus (rviz_common::properties::StatusProperty::Ok, " Topic" , QString::number (m_messagesReceived) + " messages received" );
9861032 processMessage (*meshMsg);
1033+ const rclcpp::Time now = context_->getClock ()->now ();
9871034
9881035 // check for cached color and cost msgs that might have arrived earlier:
9891036 if (m_colorsMsgCache) {
@@ -999,8 +1046,8 @@ void MeshDisplay::meshGeometryCallback(
9991046 }
10001047 }
10011048 if (m_costsMsgCache) {
1002- const auto costMsgs = m_costsMsgCache->getInterval (meshMsg->header .stamp , meshMsg-> header . stamp ); // get msgs where header.stamp match exactly (this should usually be only one msg)
1003- RCLCPP_DEBUG_STREAM (rclcpp::get_logger (" rviz_mesh_tools_plugins" ), " Got " << costMsgs.size () << " cost msgs from cache with header.stamp= " << rclcpp::Time (meshMsg-> header . stamp ). seconds () );
1049+ const auto costMsgs = m_costsMsgCache->getInterval (meshMsg->header .stamp , now);
1050+ RCLCPP_DEBUG_STREAM (rclcpp::get_logger (" rviz_mesh_tools_plugins" ), " Got " << costMsgs.size () << " cost msgs from cache" );
10041051 for (const mesh_msgs::msg::MeshVertexCostsStamped::ConstSharedPtr& costMsg : costMsgs) {
10051052 if (costMsg->uuid == meshMsg->uuid ) {
10061053 RCLCPP_DEBUG_STREAM (rclcpp::get_logger (" rviz_mesh_tools_plugins" ), " Found cached cost msg with matching UUID, applying its information now" );
@@ -1044,6 +1091,92 @@ void MeshDisplay::vertexCostsCallback(
10441091 updateVertexCosts ();
10451092}
10461093
1094+ void MeshDisplay::vertexCostsUpdateCallback (
1095+ const mesh_msgs::msg::MeshVertexCostsSparseStamped::ConstSharedPtr& update
1096+ )
1097+ {
1098+ if (update->uuid .compare (m_lastUuid) != 0 )
1099+ {
1100+ RCLCPP_WARN (rclcpp::get_logger (" rviz_mesh_tools_plugins" ), " Received vertex costs update, but its UUID does not match the latest mesh geometry UUID. Not updating costs." );
1101+ return ;
1102+ }
1103+
1104+ if (update->mesh_vertex_costs .vertices .empty () || update->mesh_vertex_costs .costs .empty ())
1105+ {
1106+ RCLCPP_WARN (rclcpp::get_logger (" rviz_mesh_tools_plugins" ), " Received an empty vertex costs update." );
1107+ return ;
1108+ }
1109+
1110+ // Vertex cost have to be applied to the cached layer
1111+ auto result = m_costCache.find (update->type );
1112+ // Unknown layer
1113+ if (result == m_costCache.end ())
1114+ {
1115+ // TODO: We could create an empty layer
1116+ return ;
1117+ }
1118+
1119+ // Update data in the cache
1120+ const auto & data = update->mesh_vertex_costs ;
1121+ for (size_t i = 0 ; i < data.vertices .size (); i++)
1122+ {
1123+ result->second [data.vertices [i]] = data.costs [i];
1124+ }
1125+
1126+ // Update the mesh if we updated the current visual
1127+ if (update->type == m_selectVertexCostMap->getStdString ())
1128+ {
1129+ if (m_costUseCustomLimits->getBool ())
1130+ {
1131+ if (m_costCache.count (m_selectVertexCostMap->getStdString ()) != 0 )
1132+ {
1133+ std::shared_ptr<MeshVisual> visual = getLatestVisual ();
1134+ if (visual)
1135+ {
1136+ visual->updateVertexCosts (
1137+ data.vertices ,
1138+ data.costs ,
1139+ m_costColorType->getOptionInt (),
1140+ m_costLowerLimit->getFloat (),
1141+ m_costUpperLimit->getFloat ()
1142+ );
1143+ }
1144+ }
1145+ }
1146+ else
1147+ {
1148+ if (m_costCache.count (m_selectVertexCostMap->getStdString ()) != 0 )
1149+ {
1150+ // The correct way is the get the limits from the whole layer
1151+ // TODO: Cache this with the layer itself
1152+ float maxCost = std::numeric_limits<float >::min ();
1153+ float minCost = std::numeric_limits<float >::max ();
1154+ for (float cost : result->second )
1155+ {
1156+ if (std::isfinite (cost) && cost > maxCost)
1157+ maxCost = cost;
1158+ if (std::isfinite (cost) && cost < minCost)
1159+ minCost = cost;
1160+ }
1161+
1162+
1163+ std::shared_ptr<MeshVisual> visual = getLatestVisual ();
1164+ if (visual)
1165+ {
1166+ visual->updateVertexCosts (
1167+ data.vertices ,
1168+ data.costs ,
1169+ m_costColorType->getOptionInt (),
1170+ minCost,
1171+ maxCost
1172+ );
1173+ }
1174+ }
1175+ }
1176+ updateMeshMaterial ();
1177+ }
1178+ }
1179+
10471180void MeshDisplay::requestVertexColors (std::string uuid)
10481181{
10491182 if (m_ignoreMsgs)
0 commit comments