Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve bridge command parser #396

Open
wants to merge 24 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
041a53b
Refactor command parser to use vector of char*
LucasHaug Feb 3, 2023
82bdd30
Add argc argv splitter to dynamic bridge
LucasHaug Feb 3, 2023
5359817
Add argc argv splitter to paramter bridge
LucasHaug Feb 3, 2023
fd96bcf
Update github action
LucasHaug Feb 3, 2023
40dd1b2
Fix parameter bridge argv split
LucasHaug Feb 3, 2023
883d777
Remove static argv reading
LucasHaug Feb 3, 2023
ce8b178
Add command parser to parameter bridge
LucasHaug Feb 3, 2023
2911f8f
Fix compilation errors
LucasHaug Feb 3, 2023
8650d49
Fix compilation errors
LucasHaug Feb 6, 2023
f5f39a1
Fix parameter bidge command parser
LucasHaug Feb 6, 2023
b99c2a3
Refactor to add command parser utils file
LucasHaug Feb 6, 2023
2e47d5e
Add github action issue workaround
LucasHaug Feb 6, 2023
7bcbb2d
Ty to run github action inside container
LucasHaug Feb 6, 2023
7d32936
Fix ROS2 args when no ROS1 args
LucasHaug Feb 8, 2023
9a341f2
⏪ Revert changes on GitHub Action config
LucasHaug Mar 10, 2023
3b00615
Change parameter bridge ROS init order
LucasHaug Mar 10, 2023
38460e6
Rename parser functions
LucasHaug Mar 10, 2023
1097b4f
Add get_option_values function
LucasHaug Mar 10, 2023
02e1d27
Fix wrong help for the parameter bridge
LucasHaug Mar 10, 2023
5804cdc
Fix get_option_values parser function
LucasHaug Mar 10, 2023
d76cb81
Refactor bridges to use the get_option_values
LucasHaug Mar 10, 2023
daf83db
Add running scetion to README
LucasHaug Mar 10, 2023
e4c511c
Add print pairs to parameter bridge
LucasHaug Mar 21, 2023
d64d2d9
Revert mistakenly commented code
LucasHaug Jun 21, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Refactor to add command parser utils file
Signed-off-by: LucasHaug <lucas.haug@hotmail.com>
  • Loading branch information
LucasHaug committed Feb 6, 2023
commit b99c2a354969c86e20e4fb619d32ca47d293ba75
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ add_library(${PROJECT_NAME} SHARED
"src/builtin_interfaces_factories.cpp"
"src/convert_builtin_interfaces.cpp"
"src/bridge.cpp"
"src/command_parser_utils.cpp"
${generated_files})
ament_target_dependencies(${PROJECT_NAME}
${prefixed_ros1_message_packages}
Expand Down
46 changes: 46 additions & 0 deletions include/ros1_bridge/command_parser_utils.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Copyright 2015 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef ROS1_BRIDGE__COMMAND_PARSER_UTILS_HPP_
#define ROS1_BRIDGE__COMMAND_PARSER_UTILS_HPP_

#include <string>
#include <vector>

namespace ros1_bridge
{

bool find_command_option(
const std::vector<const char *> & args,
const std::string & option);

bool get_flag_option(
std::vector<const char *> & args,
const std::string & option,
const char * & value,
bool remove = false);

bool get_flag_option(
std::vector<const char *> & args,
const std::string & option,
bool remove = false);

void split_ros1_ros2_args(
const std::vector<const char *> & args,
std::vector<const char *> & ros1_args,
std::vector<const char *> & ros2_args);

} // namespace ros1_bridge

#endif // ROS1_BRIDGE__COMMAND_PARSER_UTILS_HPP_
91 changes: 91 additions & 0 deletions src/command_parser_utils.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
// Copyright 2015 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "ros1_bridge/command_parser_utils.hpp"

#include <algorithm>
#include <cstring>

namespace ros1_bridge
{

bool find_command_option(const std::vector<const char *> & args, const std::string & option)
{
auto it = std::find_if(args.begin(), args.end(), [&option] (const char * const & element) {
return strcmp(element, option.c_str()) == 0;
});

return it != args.end();
}

bool get_flag_option(std::vector<const char *> & args, const std::string & option, const char * & value, bool remove)
{
auto it = std::find_if(args.begin(), args.end(), [&option] (const char * const & element) {
return strcmp(element, option.c_str()) == 0;
});

if (it != args.end()) {
auto value_it = std::next(it);

if (value_it != args.end()) {
value = *value_it;

if (remove) {
args.erase(it); // Remove option
args.erase(it); // Remove value
}

return true;
}
}

return false;
}

bool get_flag_option(std::vector<const char *> & args, const std::string & option, bool remove)
{
auto it = std::find_if(args.begin(), args.end(), [&option] (const char * const & element) {
return strcmp(element, option.c_str()) == 0;
});

if (it != args.end()) {
if (remove) {
args.erase(it);
}
return true;
}

return false;
}

void split_ros1_ros2_args(
const std::vector<const char *> & args, std::vector<const char *> & ros1_args,
std::vector<const char *> & ros2_args)
{
// Start iterating from the second argument, since the first argument is the executable name
auto it = std::find_if(args.begin() + 1, args.end(), [] (const char * const & element) {
return strcmp(element, "--ros-args") == 0;
});

if (it != args.end()) {
ros1_args = std::vector<const char *>(args.begin(), it);
ros2_args = std::vector<const char *>(it, args.end());
ros2_args.insert(ros2_args.begin(), args.at(0));
} else {
ros1_args = args;
ros2_args = args;
}
}

} // namespace ros1_bridge
59 changes: 8 additions & 51 deletions src/dynamic_bridge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include "rcpputils/scope_exit.hpp"

#include "ros1_bridge/bridge.hpp"
#include "ros1_bridge/command_parser_utils.hpp"


std::mutex g_bridge_mutex;
Expand All @@ -57,58 +58,14 @@ struct Bridge2to1HandlesAndMessageTypes
std::string ros2_type_name;
};

bool find_command_option(const std::vector<const char *> & args, const std::string & option)
{
auto it = std::find_if(args.begin(), args.end(), [&option] (const char * const & element) {
return strcmp(element, option.c_str()) == 0;
});

return it != args.end();
}

bool get_flag_option(std::vector<const char *> & args, const std::string & option, bool remove = false)
{
auto it = std::find_if(args.begin(), args.end(), [&option] (const char * const & element) {
return strcmp(element, option.c_str()) == 0;
});

if (it != args.end()) {
if (remove) {
args.erase(it);
}
return true;
}

return false;
}

void split_ros1_ros2_args(
const std::vector<const char *> & args, std::vector<const char *> & ros1_args,
std::vector<const char *> & ros2_args)
{
// Start iterating from the second argument, since the first argument is the executable name
auto it = std::find_if(args.begin() + 1, args.end(), [] (const char * const & element) {
return strcmp(element, "--ros-args") == 0;
});

if (it != args.end()) {
ros1_args = std::vector<const char *>(args.begin(), it);
ros2_args = std::vector<const char *>(it, args.end());
ros2_args.insert(ros2_args.begin(), args.at(0));
} else {
ros1_args = args;
ros2_args = args;
}
}

bool parse_command_options(
int argc, char ** argv, std::vector<const char *> & ros1_args,
std::vector<const char *> & ros2_args, bool & output_topic_introspection,
bool & bridge_all_1to2_topics, bool & bridge_all_2to1_topics)
{
std::vector<const char *> args(argv, argv + argc);

if (find_command_option(args, "-h") || find_command_option(args, "--help")) {
if (ros1_bridge::find_command_option(args, "-h") || ros1_bridge::find_command_option(args, "--help")) {
std::stringstream ss;
ss << "Usage:" << std::endl;
ss << " -h, --help: This message." << std::endl;
Expand All @@ -126,7 +83,7 @@ bool parse_command_options(
return false;
}

if (get_flag_option(args, "--print-pairs")) {
if (ros1_bridge::get_flag_option(args, "--print-pairs")) {
auto mappings_2to1 = ros1_bridge::get_all_message_mappings_2to1();
if (mappings_2to1.size() > 0) {
printf("Supported ROS 2 <=> ROS 1 message type conversion pairs:\n");
Expand All @@ -148,13 +105,13 @@ bool parse_command_options(
return false;
}

output_topic_introspection = get_flag_option(args, "--show-introspection", true);
output_topic_introspection = ros1_bridge::get_flag_option(args, "--show-introspection", true);

bool bridge_all_topics = get_flag_option(args, "--bridge-all-topics", true);
bridge_all_1to2_topics = bridge_all_topics || get_flag_option(args, "--bridge-all-1to2-topics", true);
bridge_all_2to1_topics = bridge_all_topics || get_flag_option(args, "--bridge-all-2to1-topics", true);
bool bridge_all_topics = ros1_bridge::get_flag_option(args, "--bridge-all-topics", true);
bridge_all_1to2_topics = bridge_all_topics || ros1_bridge::get_flag_option(args, "--bridge-all-1to2-topics", true);
bridge_all_2to1_topics = bridge_all_topics || ros1_bridge::get_flag_option(args, "--bridge-all-2to1-topics", true);

split_ros1_ros2_args(args, ros1_args, ros2_args);
ros1_bridge::split_ros1_ros2_args(args, ros1_args, ros2_args);

return true;
}
Expand Down
63 changes: 6 additions & 57 deletions src/parameter_bridge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "rclcpp/rclcpp.hpp"

#include "ros1_bridge/bridge.hpp"
#include "ros1_bridge/command_parser_utils.hpp"

rclcpp::QoS qos_from_params(XmlRpc::XmlRpcValue qos_params)
{
Expand Down Expand Up @@ -229,58 +230,6 @@ rclcpp::QoS qos_from_params(XmlRpc::XmlRpcValue qos_params)
return ros2_publisher_qos;
}

bool find_command_option(const std::vector<const char *> & args, const std::string & option)
{
auto it = std::find_if(args.begin(), args.end(), [&option] (const char * const & element) {
return strcmp(element, option.c_str()) == 0;
});

return it != args.end();
}

bool get_flag_option(std::vector<const char *> & args, const std::string & option, const char * & value, bool remove = false)
{
auto it = std::find_if(args.begin(), args.end(), [&option] (const char * const & element) {
return strcmp(element, option.c_str()) == 0;
});

if (it != args.end()) {
auto value_it = std::next(it);

if (value_it != args.end()) {
value = *value_it;

if (remove) {
args.erase(it); // Remove option
args.erase(it); // Remove value
}

return true;
}
}

return false;
}

void split_ros1_ros2_args(
const std::vector<const char *> & args, std::vector<const char *> & ros1_args,
std::vector<const char *> & ros2_args)
{
// Start iterating from the second argument, since the first argument is the executable name
auto it = std::find_if(args.begin() + 1, args.end(), [] (const char * const & element) {
return strcmp(element, "--ros-args") == 0;
});

if (it != args.end()) {
ros1_args = std::vector<const char *>(args.begin(), it);
ros2_args = std::vector<const char *>(it, args.end());
ros2_args.insert(ros2_args.begin(), args.at(0));
} else {
ros1_args = args;
ros2_args = args;
}
}

bool parse_command_options(
int argc, char ** argv, std::vector<const char *> & ros1_args,
std::vector<const char *> & ros2_args, const char * & topics_parameter_name,
Expand All @@ -292,7 +241,7 @@ bool parse_command_options(

std::vector<const char *> args(argv, argv + argc);

if (find_command_option(args, "-h") || find_command_option(args, "--help")) {
if (ros1_bridge::find_command_option(args, "-h") || ros1_bridge::find_command_option(args, "--help")) {
std::stringstream ss;
ss << "Usage:" << std::endl;
ss << " -h, --help: This message." << std::endl;
Expand All @@ -306,19 +255,19 @@ bool parse_command_options(
return false;
}

if (!get_flag_option(args, "--topics", topics_parameter_name, true)) {
if (!ros1_bridge::get_flag_option(args, "--topics", topics_parameter_name, true)) {
printf("Using default topics parameter name: %s\n", topics_parameter_name);
}

if (!get_flag_option(args, "--services-1-to-2", services_1_to_2_parameter_name, true)) {
if (!ros1_bridge::get_flag_option(args, "--services-1-to-2", services_1_to_2_parameter_name, true)) {
printf("Using default services 1 to 2 parameter name: %s\n", services_1_to_2_parameter_name);
}

if (!get_flag_option(args, "--services-2-to-1", services_2_to_1_parameter_name, true)) {
if (!ros1_bridge::get_flag_option(args, "--services-2-to-1", services_2_to_1_parameter_name, true)) {
printf("Using default services 2 to 1 parameter name: %s\n", services_2_to_1_parameter_name);
}

split_ros1_ros2_args(args, ros1_args, ros2_args);
ros1_bridge::split_ros1_ros2_args(args, ros1_args, ros2_args);

return true;
}
Expand Down