11// Copyright (c) 2026 Robotics and AI Institute LLC dba RAI Institute. All rights reserved.
22
33#include < fmt/core.h>
4+ #include < fmt/ranges.h>
45#include < optional>
6+ #include < ranges>
57#include < regex>
68#include < string>
79#include < string_view>
1315
1416namespace exploy ::control {
1517
18+ namespace {
19+
20+ // Builds a regex pattern for base tensor matching.
21+ // Returns std::nullopt when base_names is empty, causing matchers to reject the tensor.
22+ std::optional<std::regex> buildBasePattern (
23+ const std::unordered_map<std::string, std::string>& base_names, std::string_view field) {
24+ if (base_names.empty ()) return std::nullopt ;
25+ auto pairs = base_names | std::views::transform ([](const auto & p) {
26+ return fmt::format (R"( {}\.{})" , p.first , p.second );
27+ });
28+ return std::regex (fmt::format (R"( obj\.({})\.{})" , fmt::join (pairs, " |" ), field));
29+ }
30+
31+ } // namespace
32+
1633// --------------- Joint matchers --------------------------------
1734bool JointMatcher::matches (const Match& maybe_match) {
1835 std::smatch match;
@@ -53,8 +70,8 @@ std::vector<std::unique_ptr<Input>> JointMatcher::createInputs() const {
5370
5471// --------------- Base matchers --------------------------------
5572bool BasePositionMatcher::matches (const Match& maybe_match) {
56- std::regex pattern = std::regex ( fmt::format ( " obj \\ .({}) \\ .base \\ .pos_b_rt_w_in_w " , alphanumeric) );
57- if (std::regex_match (maybe_match.name , pattern )) {
73+ auto maybe_pattern = buildBasePattern (maybe_match. base_names , " pos_b_rt_w_in_w " );
74+ if (maybe_pattern. has_value () && std::regex_match (maybe_match.name , maybe_pattern. value () )) {
5875 found_matches_[maybe_match.name ] = maybe_match;
5976 return true ;
6077 }
@@ -70,8 +87,8 @@ std::vector<std::unique_ptr<Input>> BasePositionMatcher::createInputs() const {
7087}
7188
7289bool BaseOrientationMatcher::matches (const Match& maybe_match) {
73- std::regex pattern = std::regex ( fmt::format ( " obj \\ .({}) \\ .base \\ .w_Q_b " , alphanumeric) );
74- if (std::regex_match (maybe_match.name , pattern )) {
90+ auto maybe_pattern = buildBasePattern (maybe_match. base_names , " w_Q_b " );
91+ if (maybe_pattern. has_value () && std::regex_match (maybe_match.name , maybe_pattern. value () )) {
7592 found_matches_[maybe_match.name ] = maybe_match;
7693 return true ;
7794 }
@@ -87,9 +104,8 @@ std::vector<std::unique_ptr<Input>> BaseOrientationMatcher::createInputs() const
87104}
88105
89106bool BaseLinearVelocityMatcher::matches (const Match& maybe_match) {
90- std::regex pattern =
91- std::regex (fmt::format (" obj\\ .({})\\ .base\\ .lin_vel_b_rt_w_in_b" , alphanumeric));
92- if (std::regex_match (maybe_match.name , pattern)) {
107+ auto maybe_pattern = buildBasePattern (maybe_match.base_names , " lin_vel_b_rt_w_in_b" );
108+ if (maybe_pattern.has_value () && std::regex_match (maybe_match.name , maybe_pattern.value ())) {
93109 found_matches_[maybe_match.name ] = maybe_match;
94110 return true ;
95111 }
@@ -105,9 +121,8 @@ std::vector<std::unique_ptr<Input>> BaseLinearVelocityMatcher::createInputs() co
105121}
106122
107123bool BaseAngularVelocityMatcher::matches (const Match& maybe_match) {
108- std::regex pattern =
109- std::regex (fmt::format (" obj\\ .({})\\ .base\\ .ang_vel_b_rt_w_in_b" , alphanumeric));
110- if (std::regex_match (maybe_match.name , pattern)) {
124+ auto maybe_pattern = buildBasePattern (maybe_match.base_names , " ang_vel_b_rt_w_in_b" );
125+ if (maybe_pattern.has_value () && std::regex_match (maybe_match.name , maybe_pattern.value ())) {
111126 found_matches_[maybe_match.name ] = maybe_match;
112127 return true ;
113128 }
0 commit comments