Skip to content

Commit d38a8ff

Browse files
committed
Adjust interface between CM and RM for managing controllers' reference interfaces.
1 parent 19ecefc commit d38a8ff

File tree

3 files changed

+128
-27
lines changed

3 files changed

+128
-27
lines changed

hardware_interface/include/hardware_interface/resource_manager.hpp

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -119,20 +119,50 @@ class HARDWARE_INTERFACE_PUBLIC ResourceManager
119119
* controllers.
120120
* Therefore, they should be managed in the same way as command interface of hardware.
121121
*
122+
* \param[in] controller_name name of the controller which reference interfaces are imported.
122123
* \param[in] interfaces list of controller's reference interfaces as CommandInterfaces.
123-
* \return list of added reference interfaces
124124
*/
125-
std::vector<std::string> import_controller_reference_interfaces(
126-
std::vector<CommandInterface> & interfaces);
125+
void import_controller_reference_interfaces(
126+
const std::string & controller_name, std::vector<CommandInterface> & interfaces);
127+
128+
/// Get list of reference interface of a controller.
129+
/**
130+
* Returns lists of stored reference interfaces names for a controller.
131+
*
132+
* \param[in] controller_name for which list of reference interface names is returned.
133+
* \returns list of reference interface names.
134+
*/
135+
std::vector<std::string> get_controller_reference_interface_names(
136+
const std::string & controller_name);
137+
138+
/// Add controller's reference interface to available list.
139+
/**
140+
* Adds interfaces of a controller with given name to the available list. This method should be
141+
* called when a controller gets activated with chained mode turned on. That means, the
142+
* controller's reference interfaces can be used by another controller in chained architectures.
143+
*
144+
* \param[in] controller_name name of the controller which interfaces should become available.
145+
*/
146+
void make_controller_reference_interfaces_available(const std::string & controller_name);
147+
148+
/// Remove controller's reference interface to available list.
149+
/**
150+
* Removes interfaces of a controller with given name from the available list. This method should
151+
* be called when a controller gets deactivated and its reference interfaces cannot be used by
152+
* another controller anymore.
153+
*
154+
* \param[in] controller_name name of the controller which interfaces should become unavailable.
155+
*/
156+
void make_controller_reference_interfaces_unavailable(const std::string & controller_name);
127157

128158
/// Remove controllers reference interfaces from resource manager.
129159
/**
130160
* Remove reference interfaces from resource manager, i.e., resource storage.
131161
* The interfaces will be deleted from all internal maps and lists.
132162
*
133-
* \param[in] interface_names list of interface names that will be deleted from resource manager.
163+
* \param[in] controller_name list of interface names that will be deleted from resource manager.
134164
*/
135-
void remove_controller_reference_interfaces(const std::vector<std::string> & interface_names);
165+
void remove_controller_reference_interfaces(const std::string & controller_name);
136166

137167
/// Checks whether a command interface is already claimed.
138168
/**

hardware_interface/src/resource_manager.cpp

Lines changed: 51 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -449,16 +449,6 @@ class ResourceStorage
449449
{
450450
command_interface_map_.erase(interface);
451451
claimed_command_interface_map_.erase(interface);
452-
453-
auto found_it = std::find(
454-
available_command_interfaces_.begin(), available_command_interfaces_.end(), interface);
455-
if (found_it != available_command_interfaces_.end())
456-
{
457-
available_command_interfaces_.erase(found_it);
458-
RCUTILS_LOG_DEBUG_NAMED(
459-
"resource_manager", "'%s' command interface removed from available list",
460-
interface.c_str());
461-
}
462452
}
463453
}
464454

@@ -523,6 +513,8 @@ class ResourceStorage
523513

524514
std::unordered_map<std::string, HardwareComponentInfo> hardware_info_map_;
525515

516+
std::unordered_map<std::string, std::vector<std::string>> controllers_reference_interfaces_map_;
517+
526518
/// Storage of all available state interfaces
527519
std::map<std::string, StateInterface> state_interface_map_;
528520
/// Storage of all available command interfaces
@@ -616,6 +608,7 @@ std::vector<std::string> ResourceManager::state_interface_keys() const
616608

617609
std::vector<std::string> ResourceManager::available_state_interfaces() const
618610
{
611+
std::lock_guard<std::recursive_mutex> guard(resource_interfaces_lock_);
619612
return resource_storage_->available_state_interfaces_;
620613
}
621614

@@ -635,19 +628,62 @@ bool ResourceManager::state_interface_is_available(const std::string & name) con
635628
name) != resource_storage_->available_state_interfaces_.end();
636629
}
637630

638-
std::vector<std::string> ResourceManager::import_controller_reference_interfaces(
639-
std::vector<CommandInterface> & interfaces)
631+
void ResourceManager::import_controller_reference_interfaces(
632+
const std::string & controller_name, std::vector<CommandInterface> & interfaces)
640633
{
634+
std::lock_guard<std::recursive_mutex> guard(resource_interfaces_lock_);
635+
std::lock_guard<std::recursive_mutex> guard_claimed(claimed_command_interfaces_lock_);
641636
auto interface_names = resource_storage_->add_command_interfaces(interfaces);
637+
resource_storage_->controllers_reference_interfaces_map_[controller_name] = interface_names;
638+
}
639+
640+
std::vector<std::string> ResourceManager::get_controller_reference_interface_names(
641+
const std::string & controller_name)
642+
{
643+
return resource_storage_->controllers_reference_interfaces_map_.at(controller_name);
644+
}
645+
646+
void ResourceManager::make_controller_reference_interfaces_available(
647+
const std::string & controller_name)
648+
{
649+
auto interface_names =
650+
resource_storage_->controllers_reference_interfaces_map_.at(controller_name);
651+
std::lock_guard<std::recursive_mutex> guard(resource_interfaces_lock_);
642652
resource_storage_->available_command_interfaces_.insert(
643653
resource_storage_->available_command_interfaces_.end(), interface_names.begin(),
644654
interface_names.end());
645-
return interface_names;
646655
}
647656

648-
void ResourceManager::remove_controller_reference_interfaces(
649-
const std::vector<std::string> & interface_names)
657+
void ResourceManager::make_controller_reference_interfaces_unavailable(
658+
const std::string & controller_name)
650659
{
660+
auto interface_names =
661+
resource_storage_->controllers_reference_interfaces_map_.at(controller_name);
662+
663+
std::lock_guard<std::recursive_mutex> guard(resource_interfaces_lock_);
664+
for (const auto & interface : interface_names)
665+
{
666+
auto found_it = std::find(
667+
resource_storage_->available_command_interfaces_.begin(),
668+
resource_storage_->available_command_interfaces_.end(), interface);
669+
if (found_it != resource_storage_->available_command_interfaces_.end())
670+
{
671+
resource_storage_->available_command_interfaces_.erase(found_it);
672+
RCUTILS_LOG_DEBUG_NAMED(
673+
"resource_manager", "'%s' command interface removed from available list",
674+
interface.c_str());
675+
}
676+
}
677+
}
678+
679+
void ResourceManager::remove_controller_reference_interfaces(const std::string & controller_name)
680+
{
681+
auto interface_names =
682+
resource_storage_->controllers_reference_interfaces_map_.at(controller_name);
683+
resource_storage_->controllers_reference_interfaces_map_.erase(controller_name);
684+
685+
std::lock_guard<std::recursive_mutex> guard(resource_interfaces_lock_);
686+
std::lock_guard<std::recursive_mutex> guard_claimed(claimed_command_interfaces_lock_);
651687
resource_storage_->remove_command_interfaces(interface_names);
652688
}
653689

hardware_interface/test/test_resource_manager.cpp

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1202,31 +1202,49 @@ TEST_F(TestResourceManager, managing_controllers_reference_interfaces)
12021202
{
12031203
hardware_interface::ResourceManager rm(ros2_control_test_assets::minimal_robot_urdf);
12041204

1205+
std::string CONTROLLER_NAME = "test_controller";
1206+
std::vector<std::string> REFERENCE_INTERFACE_NAMES = {"input1", "input2", "input3"};
12051207
std::vector<std::string> FULL_REFERENCE_INTERFACE_NAMES = {
1206-
"test_controller/input1", "test_controller/input2", "test_controller/input3"};
1208+
CONTROLLER_NAME + "/" + REFERENCE_INTERFACE_NAMES[0],
1209+
CONTROLLER_NAME + "/" + REFERENCE_INTERFACE_NAMES[1],
1210+
CONTROLLER_NAME + "/" + REFERENCE_INTERFACE_NAMES[2]};
12071211

12081212
std::vector<hardware_interface::CommandInterface> reference_interfaces;
12091213
std::vector<double> reference_interface_values = {1.0, 2.0, 3.0};
1210-
std::vector<std::string> reference_interface_names = {"input1", "input2", "input3"};
12111214

1212-
for (size_t i = 0; i < reference_interface_names.size(); ++i)
1215+
for (size_t i = 0; i < REFERENCE_INTERFACE_NAMES.size(); ++i)
12131216
{
12141217
reference_interfaces.push_back(hardware_interface::CommandInterface(
1215-
"test_controller", reference_interface_names[i], &(reference_interface_values[i])));
1218+
CONTROLLER_NAME, REFERENCE_INTERFACE_NAMES[i], &(reference_interface_values[i])));
12161219
}
12171220

1218-
auto ref_itf_names = rm.import_controller_reference_interfaces(reference_interfaces);
1221+
rm.import_controller_reference_interfaces(CONTROLLER_NAME, reference_interfaces);
12191222

1220-
ASSERT_THAT(ref_itf_names, testing::ElementsAreArray(FULL_REFERENCE_INTERFACE_NAMES));
1223+
ASSERT_THAT(
1224+
rm.get_controller_reference_interface_names(CONTROLLER_NAME),
1225+
testing::ElementsAreArray(FULL_REFERENCE_INTERFACE_NAMES));
12211226

12221227
// check that all interfaces are imported properly
12231228
for (const auto & interface : FULL_REFERENCE_INTERFACE_NAMES)
1229+
{
1230+
EXPECT_TRUE(rm.command_interface_exists(interface));
1231+
EXPECT_FALSE(rm.command_interface_is_available(interface));
1232+
EXPECT_FALSE(rm.command_interface_is_claimed(interface));
1233+
}
1234+
1235+
// make interface available
1236+
rm.make_controller_reference_interfaces_available(CONTROLLER_NAME);
1237+
for (const auto & interface : FULL_REFERENCE_INTERFACE_NAMES)
12241238
{
12251239
EXPECT_TRUE(rm.command_interface_exists(interface));
12261240
EXPECT_TRUE(rm.command_interface_is_available(interface));
12271241
EXPECT_FALSE(rm.command_interface_is_claimed(interface));
12281242
}
12291243

1244+
// try to make interfaces available from unknown controller
1245+
EXPECT_THROW(
1246+
rm.make_controller_reference_interfaces_available("unknown_controller"), std::out_of_range);
1247+
12301248
// claim interfaces in a scope that deletes them after
12311249
{
12321250
auto claimed_itf1 = rm.claim_command_interface(FULL_REFERENCE_INTERFACE_NAMES[0]);
@@ -1263,18 +1281,35 @@ TEST_F(TestResourceManager, managing_controllers_reference_interfaces)
12631281
EXPECT_FALSE(rm.command_interface_is_claimed(interface));
12641282
}
12651283

1284+
// make interfaces unavailable
1285+
rm.make_controller_reference_interfaces_unavailable(CONTROLLER_NAME);
1286+
for (const auto & interface : FULL_REFERENCE_INTERFACE_NAMES)
1287+
{
1288+
EXPECT_TRUE(rm.command_interface_exists(interface));
1289+
EXPECT_FALSE(rm.command_interface_is_available(interface));
1290+
EXPECT_FALSE(rm.command_interface_is_claimed(interface));
1291+
}
1292+
1293+
// try to make interfaces unavailable from unknown controller
1294+
EXPECT_THROW(
1295+
rm.make_controller_reference_interfaces_unavailable("unknown_controller"), std::out_of_range);
1296+
12661297
// Last written values should stay
12671298
EXPECT_EQ(reference_interface_values[0], 11.1);
12681299
EXPECT_EQ(reference_interface_values[1], 2.0);
12691300
EXPECT_EQ(reference_interface_values[2], 33.3);
12701301

12711302
// remove reference interfaces from resource manager
1272-
rm.remove_controller_reference_interfaces(ref_itf_names);
1303+
rm.remove_controller_reference_interfaces(CONTROLLER_NAME);
12731304

12741305
// they should not exist in resource manager
12751306
for (const auto & interface : FULL_REFERENCE_INTERFACE_NAMES)
12761307
{
12771308
EXPECT_FALSE(rm.command_interface_exists(interface));
12781309
EXPECT_FALSE(rm.command_interface_is_available(interface));
12791310
}
1311+
1312+
// try to remove interfaces from unknown controller
1313+
EXPECT_THROW(
1314+
rm.make_controller_reference_interfaces_unavailable("unknown_controller"), std::out_of_range);
12801315
}

0 commit comments

Comments
 (0)