紧急通知:禁止一切关于政治&VPN翻墙等话题,发现相关帖子会立马删除封号
小鱼 ROS 2 新书上线!点击链接查看, 新书配套视频点击链接查看。
提问前必看的发帖注意事项—— 提问前必看!不符合要求的问题拒绝回答!!
社区使用指南—如何添加标签修改密码
小鱼 ROS 2 新书上线!点击链接查看, 新书配套视频点击链接查看。
提问前必看的发帖注意事项—— 提问前必看!不符合要求的问题拒绝回答!!
社区使用指南—如何添加标签修改密码
ros2 launch文件出现Unknown substitution: find
-
系统ubuntu22.04 ROS2 humble
各位大佬,我在编译运行ROS2的一个launch文件时终端输出以下问题:[INFO] [launch]: All log files can be found below /home/user2/.ros/log/2023-02-10-15-26-02-475140-user2-339817 [INFO] [launch]: Default logging verbosity is set to INFO [ERROR] [launch]: Caught exception in launch (see debug for traceback): Caught exception when trying to load file of format [launch]: Error trying to process rule "substitution":
我的launch文件如下:
<?xml version="1.0"?> <launch> <arg name="config" default="$(find ros_ads_node)/config/configuration.yaml" /> <node pkg="ros_ads_node" exec="ros_ads_node" name="ros_ads_node" output="screen"> <param name="name" type="str" value="test_device"/> <param name="config_file" type="str" value="$(arg config)"/> </node> </launch>
用到launch文件的两个参数的cpp文件为:
#include "Ads_node.h" #include <iostream> #include <unistd.h> #include "rclcpp/rclcpp.hpp" #include "ros_ads_msgs/msg/ads.hpp" #include "ros_ads_msgs/msg/state.hpp" using namespace ads_node; using namespace std::chrono_literals; using std::placeholders::_1; using std::placeholders::_2; using std::placeholders::_3; /** * @brief ADSNode::initialize initialize the parameters of the node and it's variables * @return 1 if the initialization failed * @return 0 otherwise */ ADSNode::ADSNode(rclcpp::NodeOptions options) : Node("ads_node", options) { /* bool ADSNode::initialize() { */ /* ros::NodeHandle n; ros::NodeHandle nprive("~"); */ /* std::shared_ptr<rclcpp::Node> nprive; */ if(rclcpp::Node::has_parameter("name")) /* if(nprive->has_parameter("name")) */ { rclcpp::Node::get_parameter("name", m_name); } else { RCLCPP_ERROR(rclcpp::get_logger("rclcpp"), "Param name unknown"); /* return 0; */ } if(rclcpp::Node::has_parameter("config_file")) { try { //get parameters from YAML file rclcpp::Node::get_parameter("config_file", m_config_file); YAML::Node config = YAML::LoadFile(m_config_file); if(config[m_name]) { m_ADS.setLocalNetID(config[m_name]["localNetID"].as<string>()); m_ADS.setRemoteNetID(config[m_name]["remoteNetID"].as<string>()); m_ADS.setRemoteIPV4(config[m_name]["remoteIP"].as<string>()); m_rate_update = config[m_name]["refresh_rate"].as<int>(); m_rate_publish = config[m_name]["publish_rate"].as<int>(); m_rate_state = config[m_name]["state_rate"].as<int>(); if(config[m_name]["publish_on_timer"].size() != 0) { auto onTimer = config[m_name]["publish_on_timer"].as<vector<string>>(); for(auto & var: onTimer) { m_publish_on_timer_guard.lock(); m_publish_on_timer[var] = pair<string, double>(); m_publish_on_timer_guard.unlock(); m_variables_guard.lock(); m_variables[var] = pair<string, double>(); m_variables_guard.unlock(); } } if(config[m_name]["publish_on_event"].size() != 0) { auto onEvent = config[m_name]["publish_on_event"].as<vector<string>>(); for(auto & var: onEvent) { m_publish_on_event_guard.lock(); m_publish_on_event[var] = pair<string, double>(); m_publish_on_event_guard.unlock(); m_variables_guard.lock(); m_variables[var] = pair<string, double>(); m_variables_guard.unlock(); } } } } catch (...) { RCLCPP_ERROR(rclcpp::get_logger("rclcpp"),"Invalid configuration file"); } } else { RCLCPP_ERROR(rclcpp::get_logger("rclcpp"),"Error with configuration file"); /* return 0; */ } try { RCLCPP_INFO_STREAM(rclcpp::get_logger("rclcpp"),"GO FOR Init Route"); m_ADS.initRoute(); RCLCPP_INFO(rclcpp::get_logger("rclcpp"),"Init Route done"); } catch(...) { RCLCPP_ERROR(rclcpp::get_logger("rclcpp"),"ERROR while connecting with ADS"); /* return 0; */ } try { RCLCPP_INFO(rclcpp::get_logger("rclcpp"),"Acquiring ADS variables"); m_ADS.acquireVariables(); RCLCPP_INFO(rclcpp::get_logger("rclcpp"),"ADS variables acquired"); RCLCPP_INFO(rclcpp::get_logger("rclcpp"),"Aliasing ADS variables"); m_ADS.setName(m_name); m_ADS.setFile(m_config_file); m_ADS.bindPLcVar(); RCLCPP_INFO(rclcpp::get_logger("rclcpp"),"Ready to communicate with the remote PLC via ADS."); } catch(AdsException& e) { RCLCPP_ERROR_STREAM(rclcpp::get_logger("rclcpp"),e.what()); RCLCPP_ERROR(rclcpp::get_logger("rclcpp"),"ERROR in mapping alias with ADS"); /* return 0; */ } try { m_sub_option.callback_group = mp_callback_group_publisher; //m_subscriber = this->create_subscription<ros_ads_msgs::msg::ADS>("command", 10, boost::bind(&ADSNode::Subscriber, this, _1),m_sub_option); m_subscriber = this->create_subscription<ros_ads_msgs::msg::ADS>("command", 10, [this](ros_ads_msgs::msg::ADS::ConstPtr msg){Subscriber(msg);},m_sub_option); m_on_event_publisher = this->create_publisher<ros_ads_msgs::msg::ADS>("report_event", 10); m_on_timer_publisher = this->create_publisher<ros_ads_msgs::msg::ADS>("report_timer", 10); m_state_publisher = this->create_publisher<ros_ads_msgs::msg::State>("state", 10); /* m_subscriber = n.subscribe<ros_ads_msgs::msg::ADS>("command", 10, boost::bind(&ADSNode::Subscriber, this, _1)); m_on_event_publisher = n.advertise<ros_ads_msgs::msg::ADS>("report_event", 10); m_on_timer_publisher = n.advertise<ros_ads_msgs::msg::ADS>("report_timer", 10); m_state_publisher = n.advertise<ros_ads_msgs::msg::ADS>("state", 10); */ } catch (...) { RCLCPP_ERROR(rclcpp::get_logger("rclcpp"),"ERROR in creating subscriber"); /* return 0; */ } /* m_timer_thread = std::make_shared<boost::thread>(&ADSNode::publishOnTimer,this, m_rate_publish); m_update_thread = std::make_shared<boost::thread>(&ADSNode::update,this, m_rate_update); m_checker_thread = std::make_shared<boost::thread>(&ADSNode::publishOnEvent,this, m_rate_update); m_state_thread = std::make_shared<boost::thread>(&ADSNode::publishState,this, m_rate_state); */ m_timer_thread = this->create_wall_timer(std::chrono::milliseconds(int(m_rate_publish)),std::bind(&ADSNode::publishOnTimer, this),mp_callback_group_subscriber); m_update_thread = this->create_wall_timer(std::chrono::milliseconds(int(m_rate_update)),std::bind(&ADSNode::update, this),mp_callback_group_update); m_checker_thread = this->create_wall_timer(std::chrono::milliseconds(int(m_rate_update)),std::bind(&ADSNode::publishOnEvent, this),mp_callback_group_checker); m_state_thread = this->create_wall_timer(std::chrono::milliseconds(int(m_rate_state)),std::bind(&ADSNode::publishState, this),mp_callback_group_state); /* return 1; } */ /** * @brief ADSNode::update update internal variable values memory * * Starts by verifying and updating connection state * * @param timer_rate rate to update at */ } void ADSNode::update() { /* auto loop_rate_update = rclcpp::Rate(timer_rate); while(rclcpp::ok()) { */ m_variables_guard.lock(); try { m_ADS.connectionCheck(); if(m_ADS.getState()) { m_ADS.updateMemory(); auto variables_map = m_ADS.getVariablesMap(); for(auto &[name, pair]: variables_map) { //cast as double for the message m_variables[name].first = pair.first; switch (pair.second.index()) { case ros_ads_msgs::BOOL: { m_variables[name].second = static_cast<double>(get<bool>(pair.second)); break; } case ros_ads_msgs::UINT8_T: { m_variables[name].second = static_cast<double>(get<uint8_t>(pair.second)); break; } case ros_ads_msgs::INT8_T: { m_variables[name].second = static_cast<double>(get<int8_t>(pair.second)); break; } case ros_ads_msgs::UINT16_T: { m_variables[name].second = static_cast<double>(get<uint16_t>(pair.second)); break; } case ros_ads_msgs::INT16_T: { m_variables[name].second = static_cast<double>(get<int16_t>(pair.second)); break; } case ros_ads_msgs::UINT32_T: { m_variables[name].second = static_cast<double>(get<uint32_t>(pair.second)); break; } case ros_ads_msgs::INT32_T: { m_variables[name].second = static_cast<double>(get<int32_t>(pair.second)); break; } case ros_ads_msgs::INT64_T: { m_variables[name].second = static_cast<double>(get<int64_t>(pair.second)); break; } case ros_ads_msgs::FLOAT: { m_variables[name].second = static_cast<double>(get<float>(pair.second)); break; } case ros_ads_msgs::DOUBLE: { m_variables[name].second = static_cast<double>(get<double>(pair.second)); break; } case ros_ads_msgs::DATE: { tm temp = get<tm>(pair.second); m_variables[name].second = static_cast<double>(mktime(&temp)); break; } default: { } } m_publish_on_timer_guard.lock(); if(m_publish_on_timer.find(name) != m_publish_on_timer.end() && m_ADS.getState()) { m_publish_on_timer[name] = m_variables[name]; } m_publish_on_timer_guard.unlock(); } } } catch (...) { RCLCPP_ERROR(rclcpp::get_logger("rclcpp"),"fail timer CB"); } m_variables_guard.unlock(); /* loop_rate_update.sleep(); } */ } /** * @brief ADSNode::publishState publish state periodically * @param timer_rate rate to publish at */ void ADSNode::publishState() { /* auto loop_rate_state = rclcpp::Rate(timer_rate); while(rclcpp::ok()) { */ m_state_msg.header.stamp =this->now(); m_state_msg.state = m_ADS.getState(); m_state_msg.error = m_ADS.getADSState(); m_state_publisher->publish(m_state_msg); /* loop_rate_state.sleep(); } */ } /** * @brief ADSNode::publishOnEvent publish variables if an event occured * @param timer_rate rate to verify if an event occured at */ void ADSNode::publishOnEvent() { /* auto loop_rate_check = rclcpp::Rate(timer_rate); while(rclcpp::ok()) { */ try { if(m_ADS.getState()) { m_publish_on_event_guard.lock(); auto publish_on_event = m_publish_on_event; m_publish_on_event_guard.unlock(); m_variables_guard.lock(); auto variables = m_variables; m_variables_guard.unlock(); m_publish = false; for(auto &[key, pair_] : publish_on_event) { m_checker_temp_value = variables[key]; if(pair_ != m_checker_temp_value) // A change has occured { m_publish_on_event_guard.lock(); m_publish_on_event[key] = m_checker_temp_value; // Update value m_publish_on_event_guard.unlock(); if(!m_publish) { m_publish = true; } } } if (m_publish) // Publish if a change occured { m_on_event_msg.header.stamp = this->now(); m_on_event_msg.varnames = vector<string>(); m_on_event_msg.vartypes = vector<string>(); m_on_event_msg.varvalues = vector<double>(); for (auto &[key, pair] : publish_on_event) { m_on_event_msg.varnames.push_back(key); auto type = pair.first; m_on_event_msg.vartypes.push_back(type); auto value = pair.second; m_on_event_msg.varvalues.push_back(value); } if(m_on_event_msg.varnames.size() !=0) { m_on_event_publisher->publish(m_on_event_msg); } } } } catch(...) { RCLCPP_ERROR(rclcpp::get_logger("rclcpp"),"fail checker CB"); } /* loop_rate_check.sleep(); } */ } /** * @brief ADSNode::publishOnTimer publish variables periodically * @param timer_rate rate to publish at */ void ADSNode::publishOnTimer() { /* auto loop_rate_pub = rclcpp::Rate(timer_rate); while(rclcpp::ok()) { */ try { m_on_timer_msg.header.stamp = this->now(); m_on_timer_msg.varnames = vector<string>(); m_on_timer_msg.vartypes = vector<string>(); m_on_timer_msg.varvalues = vector<double>(); m_publish_on_timer_guard.lock(); auto publish_on_timer = m_publish_on_timer; m_publish_on_timer_guard.unlock(); for(auto &[name, pair]: publish_on_timer) { m_on_timer_msg.varnames.push_back(name); m_on_timer_msg.vartypes.push_back(pair.first); m_on_timer_msg.varvalues.push_back(pair.second); } if(m_on_timer_msg.varnames.size() != 0) { m_on_timer_publisher->publish(m_on_timer_msg); } /* loop_rate_pub.sleep(); */ } catch(...) { RCLCPP_ERROR(rclcpp::get_logger("rclcpp"),"fail pub CB"); } /* } */ } /** * @brief ADSNode::Subscriber send the ADS device the received commands * @param msg the command message * @return true if the command was successfully sent */ void ADSNode::Subscriber(const ros_ads_msgs::msg::ADS::ConstPtr &msg) { m_state_publisher->publish(m_state_msg); /* bool result = true; */ auto command = ros_ads_msgs::decode(msg); /* try { */ if(m_ADS.getState()) { for (auto &[name, value]: command) { m_ADS.adsWriteValue(name, value); } } /* } */ /* catch (...) { result = false; } */ /* return result; */ } int main(int argc, char **argv) { /* rclcpp::init(argc, argv, "ros_ads_node"); */ rclcpp::init(argc, argv); /* auto node=std::make_shared<ADSNode>(); node->initialize(); while(rclcpp::ok()) { rclcpp::spin_some(node); } */ auto node{std::make_shared<ads_node::ADSNode>()}; rclcpp::executors::MultiThreadedExecutor executor; executor.add_node(node); executor.spin(); rclcpp::shutdown(); return 0; }
cmakelist文件如下,我是将src中的多个cpp文件放入了一个节点:
cmake_minimum_required(VERSION 3.8) project(ros_ads_node) ## Compile as C++17, supported in ROS Kinetic and newer set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17") set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") add_compile_options(-Wall -Wextra -Wpedantic) endif() find_package(Threads REQUIRED) set(CMAKE_BUILD_TYPE debug) ##add_definitions(-D _GLIBCXX_USE_CXX11_ABI=0) add_subdirectory(lib/ADS/AdsLib) ## Find catkin macros and libraries ## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz) ## is used, also find other catkin packages find_package(ament_cmake REQUIRED) find_package(rclcpp REQUIRED) find_package(std_msgs REQUIRED) find_package(ros_ads_msgs REQUIRED) find_package(yaml-cpp REQUIRED) #find_package(TinyXML REQUIRED) #include_directories( # include # ${TinyXML_INCLUDE_DIRS} #) add_executable(ros_ads_node src/ADSDecode.cpp src/Ads_node.cpp src/Ads_Interface.cpp) add_dependencies(ros_ads_node ads) target_include_directories(ros_ads_node PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> $<INSTALL_INTERFACE:include>) target_link_libraries(ros_ads_node ${ament_LIBRARIES} ads -lpthread yaml-cpp)# ${TinyXML_LIBRARIES} target_compile_features(ros_ads_node PUBLIC c_std_99 cxx_std_17) # Require C99 and C++17 ament_target_dependencies( ros_ads_node "rclcpp" "std_msgs" "ros_ads_msgs" ) install(TARGETS ros_ads_node ARCHIVE DESTINATION lib LIBRARY DESTINATION lib RUNTIME DESTINATION lib/${PROJECT_NAME}) install(DIRECTORY launch config DESTINATION share/${PROJECT_NAME}/) if(BUILD_TESTING) find_package(ament_lint_auto REQUIRED) # the following line skips the linter which checks for copyrights # comment the line when a copyright and license is added to all source files set(ament_cmake_copyright_FOUND TRUE) # the following line skips cpplint (only works in a git repo) # comment the line when this package is in a git repo and when # a copyright and license is added to all source files set(ament_cmake_cpplint_FOUND TRUE) ament_lint_auto_find_test_dependencies() endif() ament_package()
请各位大佬帮忙看一下,是哪里的问题,是launch标签错了吗?万分感激
-