From b44982664f325f3d428ef4d79539b9c410378127 Mon Sep 17 00:00:00 2001 From: Joseph Duchesne Date: Fri, 1 Jun 2018 12:54:24 +0000 Subject: [PATCH 01/11] Added lua preprocessor for flatland yaml files --- flatland_server/CMakeLists.txt | 13 ++ .../flatland_server/yaml_preprocessor.h | 108 +++++++++ flatland_server/package.xml | 1 + flatland_server/src/yaml_preprocessor.cpp | 211 ++++++++++++++++++ .../yaml/eval.strings.out.yaml | 30 +++ .../yaml_preprocessor/yaml/eval.strings.yaml | 31 +++ .../yaml_preprocessor_test.cpp | 71 ++++++ .../yaml_preprocessor_test.test | 13 ++ 8 files changed, 478 insertions(+) create mode 100644 flatland_server/include/flatland_server/yaml_preprocessor.h create mode 100644 flatland_server/src/yaml_preprocessor.cpp create mode 100644 flatland_server/test/yaml_preprocessor/yaml/eval.strings.out.yaml create mode 100644 flatland_server/test/yaml_preprocessor/yaml/eval.strings.yaml create mode 100644 flatland_server/test/yaml_preprocessor/yaml_preprocessor_test.cpp create mode 100644 flatland_server/test/yaml_preprocessor/yaml_preprocessor_test.test diff --git a/flatland_server/CMakeLists.txt b/flatland_server/CMakeLists.txt index df942d8d..59711c12 100644 --- a/flatland_server/CMakeLists.txt +++ b/flatland_server/CMakeLists.txt @@ -33,6 +33,9 @@ find_library(YAML_CPP_LIBRARY PATHS ${YAML_CPP_LIBRARY_DIRS}) link_directories(${YAML_CPP_LIBRARY_DIRS}) +# lua5.1 +find_package(Lua 5.1 QUIET) + # OpenCV find_package(OpenCV REQUIRED) @@ -71,6 +74,7 @@ include_directories( ${YAML_CPP_INCLUDE_DIRS} ${OpenCV_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS} + ${LUA_INCLUDE_DIR} thirdparty ) @@ -98,6 +102,7 @@ add_library(flatland_lib src/yaml_reader.cpp src/dummy_model_plugin.cpp src/dummy_world_plugin.cpp + src/yaml_preprocessor.cpp ) add_dependencies(flatland_lib ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) @@ -105,6 +110,7 @@ target_link_libraries(flatland_lib ${catkin_LIBRARIES} ${OpenCV_LIBRARIES} ${Boost_LIBRARIES} + ${LUA_LIBRARIES} flatland_Box2D yaml-cpp ) @@ -123,6 +129,7 @@ target_link_libraries(flatland_server ${catkin_LIBRARIES} ${OpenCV_LIBRARIES} ${Boost_LIBRARIES} + ${LUA_LIBRARIES} flatland_Box2D yaml-cpp flatland_lib @@ -226,5 +233,11 @@ if(CATKIN_ENABLE_TESTING) target_link_libraries(dummy_world_plugin_test flatland_lib yaml-cpp) + add_rostest_gtest(yaml_preprocessor_test + test/yaml_preprocessor/yaml_preprocessor_test.test + test/yaml_preprocessor/yaml_preprocessor_test.cpp) + target_link_libraries(yaml_preprocessor_test + flatland_lib yaml-cpp) + endif() diff --git a/flatland_server/include/flatland_server/yaml_preprocessor.h b/flatland_server/include/flatland_server/yaml_preprocessor.h new file mode 100644 index 00000000..46ff6b97 --- /dev/null +++ b/flatland_server/include/flatland_server/yaml_preprocessor.h @@ -0,0 +1,108 @@ +/* + * ______ __ __ __ + * /\ _ \ __ /\ \/\ \ /\ \__ + * \ \ \L\ \ __ __ /\_\ \_\ \ \ \____ ___\ \ ,_\ ____ + * \ \ __ \/\ \/\ \\/\ \ /'_` \ \ '__`\ / __`\ \ \/ /',__\ + * \ \ \/\ \ \ \_/ |\ \ \/\ \L\ \ \ \L\ \/\ \L\ \ \ \_/\__, `\ + * \ \_\ \_\ \___/ \ \_\ \___,_\ \_,__/\ \____/\ \__\/\____/ + * \/_/\/_/\/__/ \/_/\/__,_ /\/___/ \/___/ \/__/\/___/ + * @copyright Copyright 2018 Avidbots Corp. + * @name yaml_preprocessor.h + * @brief Yaml preprocessor using Lua + * @author Joseph Duchesne + * + * Software License Agreement (BSD License) + * + * Copyright (c) 2017, Avidbots Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Avidbots Corp. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef FLATLAND_SERVER_YAML_PREPROCESSOR_H +#define FLATLAND_SERVER_YAML_PREPROCESSOR_H + +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace flatland_server { + +/** + */ +class YamlPreprocessor { + public: + /** + * @brief Preprocess with a given node + * @param[in/out] node A Yaml node to parse + * @return The parsed YAML::Node + */ + static void Parse(YAML::Node &node); + + /** + * @brief Constructor with a given path to a yaml file, throws exception on + * failure + * @param[in] path Path to the yaml file + * @return The parsed YAML::Node + */ + static YAML::Node LoadParse(const std::string &path); + + /** + * @brief Find and run any eval nodes ($evalString etc.) + * @param[in/out] node A Yaml node to recursively parse + */ + static void ProcessNodes(YAML::Node &node); + + /** + * @brief Find and run any eval expressions ($evalString etc.) + * @param[in/out] node A Yaml string node to parse + */ + static void ProcessScalarNode(YAML::Node &node); + + /** + * @brief Get an environment variable with an optional default value + * @param[in/out] lua_State The lua state/stack to read/write to/from + */ + static int LuaGetEnv(lua_State *L); + + /** + * @brief Get a rosparam with an optional default value + * @param[in/out] lua_State The lua state/stack to read/write to/from + */ + static int LuaGetParam(lua_State *L); +}; + +} + +#endif // FLATLAND_SERVER_YAML_PREPROCESSOR_H \ No newline at end of file diff --git a/flatland_server/package.xml b/flatland_server/package.xml index 6dd24c36..c8087d8a 100644 --- a/flatland_server/package.xml +++ b/flatland_server/package.xml @@ -26,6 +26,7 @@ visualization_msgs interactive_markers flatland_msgs + lua-dev diff --git a/flatland_server/src/yaml_preprocessor.cpp b/flatland_server/src/yaml_preprocessor.cpp new file mode 100644 index 00000000..a8abd4a1 --- /dev/null +++ b/flatland_server/src/yaml_preprocessor.cpp @@ -0,0 +1,211 @@ +/* + * ______ __ __ __ + * /\ _ \ __ /\ \/\ \ /\ \__ + * \ \ \L\ \ __ __ /\_\ \_\ \ \ \____ ___\ \ ,_\ ____ + * \ \ __ \/\ \/\ \\/\ \ /'_` \ \ '__`\ / __`\ \ \/ /',__\ + * \ \ \/\ \ \ \_/ |\ \ \/\ \L\ \ \ \L\ \/\ \L\ \ \ \_/\__, `\ + * \ \_\ \_\ \___/ \ \_\ \___,_\ \_,__/\ \____/\ \__\/\____/ + * \/_/\/_/\/__/ \/_/\/__,_ /\/___/ \/___/ \/__/\/___/ + * @copyright Copyright 2018 Avidbots Corp. + * @name yaml_preprocessor + * @brief Yaml preprocessor using Lua + * @author Joseph Duchesne + * + * Software License Agreement (BSD License) + * + * Copyright (c) 2017, Avidbots Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Avidbots Corp. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "flatland_server/yaml_preprocessor.h" +#include +#include +#include + +#include +#include + +namespace flatland_server { + +void YamlPreprocessor::Parse(YAML::Node &node) { + ROS_WARN_NAMED("YamlPreprocessor","Parse called!"); + + YamlPreprocessor::ProcessNodes(node); +} + +void YamlPreprocessor::ProcessNodes(YAML::Node &node) { + switch (node.Type()) { + case YAML::NodeType::Sequence: + for (YAML::Node child : node){ + YamlPreprocessor::ProcessNodes(child); + } + break; + case YAML::NodeType::Map: + for(YAML::iterator it=node.begin();it!=node.end();++it) { + YamlPreprocessor::ProcessNodes(it->second); + } + break; + case YAML::NodeType::Scalar: + ROS_INFO_STREAM("Scalar: " << node.as()); + if (node.as().compare(0, 5, "$eval") == 0) { + ROS_WARN_STREAM("Found $eval"); + ProcessScalarNode(node); + } + break; + } +} + +void YamlPreprocessor::ProcessScalarNode(YAML::Node &node) { + std::string value = node.as().substr(5); //omit the $parse + boost::algorithm::trim(value); //trim whitespace + + + if (value.find("return ") == std::string::npos) { // Has no return statement + value = "return " + value; + } + + ROS_WARN_STREAM(value); + + // Create the Lua context + lua_State *L = luaL_newstate(); + luaL_openlibs(L); + lua_pushcfunction(L, YamlPreprocessor::LuaGetEnv); + lua_setglobal(L, "env"); + lua_pushcfunction(L, YamlPreprocessor::LuaGetParam); + lua_setglobal(L, "param"); + + int error = luaL_dostring(L, value.c_str()); + if (error) { + ROS_ERROR_STREAM(lua_tostring(L, -1)); + lua_pop(L, 1); /* pop error message from the stack */ + } else { + int t = lua_type(L, 1); + if ( t == LUA_TNIL ) { + ROS_ERROR_STREAM("NULL result"); + } else { + ROS_ERROR_STREAM("result: " << lua_tostring(L, 1)); + } + + } +} + +YAML::Node YamlPreprocessor::LoadParse(const std::string &path) { + YAML::Node node; + + try { + node = YAML::LoadFile(path); + } catch (const YAML::BadFile &e) { + throw YAMLException("File does not exist, path=" + path); + } catch (const YAML::ParserException &e) { + throw YAMLException("Malformatted file, path=" + path, e); + } catch (const YAML::Exception &e) { + throw YAMLException("Error loading file, path=" + path, e); + } + + YamlPreprocessor::Parse(node); + return node; +} + +int YamlPreprocessor::LuaGetEnv(lua_State *L) { + const char *name = lua_tostring(L, 1); + const char* env = std::getenv(name); + + if (lua_gettop(L) == 2) { // default passed in + if (lua_isnumber(L, 2)) { + if (env == NULL) { + lua_pushnumber(L, lua_tonumber(L, 2)); + } else { + lua_pushnumber(L, std::atof(env)); + } + } else if (lua_isstring(L, 2)) { + if (env == NULL) { + lua_pushstring(L, lua_tostring(L, 2)); + } else { + lua_pushstring(L, env); + } + } + } else { // no default + if (env == NULL) { // Push back a nil + ROS_ERROR_STREAM("No environment variable for: " << name); + lua_pushnil(L); + } else { + try { // Try to push a number + double x = boost::lexical_cast(env); + ROS_ERROR_STREAM("Assuming number for: " << name); + lua_pushnumber(L, x); + } catch(boost::bad_lexical_cast&) { // Otherwise it's a string + ROS_ERROR_STREAM("Assuming string for: " << name); + lua_pushstring(L,env); + } + } + } + + return 1; // 1 return value +} + +int YamlPreprocessor::LuaGetParam(lua_State *L) { + const char *name = lua_tostring(L, 1); + std::string param; + ros::param::param(name, param, "default_value"); + + if (lua_gettop(L) == 2) { // default value was passed in + if (lua_isnumber(L, 2)) { + if (!ros::param::has(name)) { // return default + lua_pushnumber(L, lua_tonumber(L, 2)); + } else { + lua_pushnumber(L, std::atof(param.c_str())); + } + } else if (lua_isstring(L, 2)) { + if (!ros::param::has(name)) { // return default + lua_pushstring(L, lua_tostring(L, 2)); + } else { + lua_pushstring(L, param.c_str()); + } + } + } else { // no default + if (!ros::param::has(name)) { // Push back a nil + ROS_ERROR_STREAM("No environment variable for: " << name); + lua_pushnil(L); + } else { + try { // Try to push a number + double x = boost::lexical_cast(param.c_str()); + ROS_ERROR_STREAM("Assuming number for: " << name); + lua_pushnumber(L, x); + } catch(boost::bad_lexical_cast&) { // Otherwise it's a string + ROS_ERROR_STREAM("Assuming string for: " << name); + lua_pushstring(L, param.c_str()); + } + } + } + + return 1; // 1 return value +} + +} \ No newline at end of file diff --git a/flatland_server/test/yaml_preprocessor/yaml/eval.strings.out.yaml b/flatland_server/test/yaml_preprocessor/yaml/eval.strings.out.yaml new file mode 100644 index 00000000..26f7af49 --- /dev/null +++ b/flatland_server/test/yaml_preprocessor/yaml/eval.strings.out.yaml @@ -0,0 +1,30 @@ +foo: Hello World +bar: Hello World +baz: Hello World +bash: 1234 +boop: + bal: 12.34 +foop: + - A + - B + - C +bom: | + Some + multiline + string +testEnv: + env1: Bar + env2: 123.4 + env3: Bar + env4: 123.4 + env5: null + env6: 444.4 + env7: ZZZ +testParam: + param1: Foo + param2: 10.0 + param3: Foo + param4: 10.0 + param5: null + param6: 223 + param7: BBBC \ No newline at end of file diff --git a/flatland_server/test/yaml_preprocessor/yaml/eval.strings.yaml b/flatland_server/test/yaml_preprocessor/yaml/eval.strings.yaml new file mode 100644 index 00000000..488bc373 --- /dev/null +++ b/flatland_server/test/yaml_preprocessor/yaml/eval.strings.yaml @@ -0,0 +1,31 @@ +foo: $eval return "Hello World" +bar: $eval return string.gsub("Hello banana", "banana", "World") +baz: $eval string.gsub("Hello banana", "banana", "World") +bash: $eval 1234 +boop: + bal: $eval 12.34 +foop: + - A + - $eval "B" + - C +bom: | + $eval + [[Some + multiline + string]] +testEnv: + env1: $eval env("VALIDSTRING") + env2: $eval env("VALIDNUMBER") + env3: $eval env("VALIDSTRING","YYY") + env4: $eval env("VALIDNUMBER","333.3") + env5: $eval env("INVALID") + env6: $eval env("INVALID","444.4") + env7: $eval env("INVALID","ZZZ") +testParam: + param1: $eval param("/string") + param2: $eval param("/number") + param3: $eval param("/string","AAA") + param4: $eval param("/number","111") + param5: $eval param("/invalid") + param6: $eval param("/invalid","222")+1 + param7: $eval param("/invalid","BBB").."C" \ No newline at end of file diff --git a/flatland_server/test/yaml_preprocessor/yaml_preprocessor_test.cpp b/flatland_server/test/yaml_preprocessor/yaml_preprocessor_test.cpp new file mode 100644 index 00000000..d7066399 --- /dev/null +++ b/flatland_server/test/yaml_preprocessor/yaml_preprocessor_test.cpp @@ -0,0 +1,71 @@ +/* + * ______ __ __ __ + * /\ _ \ __ /\ \/\ \ /\ \__ + * \ \ \L\ \ __ __ /\_\ \_\ \ \ \____ ___\ \ ,_\ ____ + * \ \ __ \/\ \/\ \\/\ \ /'_` \ \ '__`\ / __`\ \ \/ /',__\ + * \ \ \/\ \ \ \_/ |\ \ \/\ \L\ \ \ \L\ \/\ \L\ \ \ \_/\__, `\ + * \ \_\ \_\ \___/ \ \_\ \___,_\ \_,__/\ \____/\ \__\/\____/ + * \/_/\/_/\/__/ \/_/\/__,_ /\/___/ \/___/ \/__/\/___/ + * @copyright Copyright 2017 Avidbots Corp. + * @name null.cpp + * @brief Sanity check / example test file + * @author Joseph Duchesne + * + * Software License Agreement (BSD License) + * + * Copyright (c) 2017, Avidbots Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Avidbots Corp. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "flatland_server/yaml_preprocessor.h" +#include +#include +#include + +namespace fs = boost::filesystem; +using namespace flatland_server; + +// Test the bodyToMarkers method on a polygon shape +TEST(YamlPreprocTest, testEvalStrings) { + + boost::filesystem::path cwd = fs::path(__FILE__).parent_path(); + + YAML::Node in = YamlPreprocessor::LoadParse((cwd / fs::path("/yaml/eval.strings.yaml")).string()); + + // check that marker was created + ASSERT_EQ(1, 1); +} + +// Run all the tests that were declared with TEST() +int main(int argc, char** argv) { + ros::init(argc, argv, "yaml_preprocessor_test"); + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/flatland_server/test/yaml_preprocessor/yaml_preprocessor_test.test b/flatland_server/test/yaml_preprocessor/yaml_preprocessor_test.test new file mode 100644 index 00000000..b5ee1c32 --- /dev/null +++ b/flatland_server/test/yaml_preprocessor/yaml_preprocessor_test.test @@ -0,0 +1,13 @@ + + + + + + + + + \ No newline at end of file From f658fdd641579c1572dbf3fcbeaceb90eb5438f5 Mon Sep 17 00:00:00 2001 From: Joseph Duchesne Date: Fri, 1 Jun 2018 12:56:07 +0000 Subject: [PATCH 02/11] Fixed lint --- .../flatland_server/yaml_preprocessor.h | 23 ++++++------ flatland_server/src/yaml_preprocessor.cpp | 37 +++++++++---------- .../yaml_preprocessor_test.cpp | 6 +-- 3 files changed, 31 insertions(+), 35 deletions(-) diff --git a/flatland_server/include/flatland_server/yaml_preprocessor.h b/flatland_server/include/flatland_server/yaml_preprocessor.h index 46ff6b97..6dd3b441 100644 --- a/flatland_server/include/flatland_server/yaml_preprocessor.h +++ b/flatland_server/include/flatland_server/yaml_preprocessor.h @@ -50,12 +50,12 @@ #include #include +#include +#include +#include #include #include #include -#include -#include -#include namespace flatland_server { @@ -90,19 +90,18 @@ class YamlPreprocessor { */ static void ProcessScalarNode(YAML::Node &node); - /** - * @brief Get an environment variable with an optional default value - * @param[in/out] lua_State The lua state/stack to read/write to/from - */ + /** + * @brief Get an environment variable with an optional default value + * @param[in/out] lua_State The lua state/stack to read/write to/from + */ static int LuaGetEnv(lua_State *L); - /** - * @brief Get a rosparam with an optional default value - * @param[in/out] lua_State The lua state/stack to read/write to/from - */ + /** + * @brief Get a rosparam with an optional default value + * @param[in/out] lua_State The lua state/stack to read/write to/from + */ static int LuaGetParam(lua_State *L); }; - } #endif // FLATLAND_SERVER_YAML_PREPROCESSOR_H \ No newline at end of file diff --git a/flatland_server/src/yaml_preprocessor.cpp b/flatland_server/src/yaml_preprocessor.cpp index a8abd4a1..de0d9700 100644 --- a/flatland_server/src/yaml_preprocessor.cpp +++ b/flatland_server/src/yaml_preprocessor.cpp @@ -49,13 +49,13 @@ #include #include -#include #include - +#include + namespace flatland_server { void YamlPreprocessor::Parse(YAML::Node &node) { - ROS_WARN_NAMED("YamlPreprocessor","Parse called!"); + ROS_WARN_NAMED("YamlPreprocessor", "Parse called!"); YamlPreprocessor::ProcessNodes(node); } @@ -63,12 +63,12 @@ void YamlPreprocessor::Parse(YAML::Node &node) { void YamlPreprocessor::ProcessNodes(YAML::Node &node) { switch (node.Type()) { case YAML::NodeType::Sequence: - for (YAML::Node child : node){ + for (YAML::Node child : node) { YamlPreprocessor::ProcessNodes(child); } break; case YAML::NodeType::Map: - for(YAML::iterator it=node.begin();it!=node.end();++it) { + for (YAML::iterator it = node.begin(); it != node.end(); ++it) { YamlPreprocessor::ProcessNodes(it->second); } break; @@ -83,10 +83,9 @@ void YamlPreprocessor::ProcessNodes(YAML::Node &node) { } void YamlPreprocessor::ProcessScalarNode(YAML::Node &node) { - std::string value = node.as().substr(5); //omit the $parse - boost::algorithm::trim(value); //trim whitespace + std::string value = node.as().substr(5); // omit the $parse + boost::algorithm::trim(value); // trim whitespace - if (value.find("return ") == std::string::npos) { // Has no return statement value = "return " + value; } @@ -104,15 +103,14 @@ void YamlPreprocessor::ProcessScalarNode(YAML::Node &node) { int error = luaL_dostring(L, value.c_str()); if (error) { ROS_ERROR_STREAM(lua_tostring(L, -1)); - lua_pop(L, 1); /* pop error message from the stack */ + lua_pop(L, 1); /* pop error message from the stack */ } else { int t = lua_type(L, 1); - if ( t == LUA_TNIL ) { + if (t == LUA_TNIL) { ROS_ERROR_STREAM("NULL result"); } else { ROS_ERROR_STREAM("result: " << lua_tostring(L, 1)); } - } } @@ -135,7 +133,7 @@ YAML::Node YamlPreprocessor::LoadParse(const std::string &path) { int YamlPreprocessor::LuaGetEnv(lua_State *L) { const char *name = lua_tostring(L, 1); - const char* env = std::getenv(name); + const char *env = std::getenv(name); if (lua_gettop(L) == 2) { // default passed in if (lua_isnumber(L, 2)) { @@ -151,18 +149,18 @@ int YamlPreprocessor::LuaGetEnv(lua_State *L) { lua_pushstring(L, env); } } - } else { // no default + } else { // no default if (env == NULL) { // Push back a nil ROS_ERROR_STREAM("No environment variable for: " << name); - lua_pushnil(L); + lua_pushnil(L); } else { try { // Try to push a number double x = boost::lexical_cast(env); ROS_ERROR_STREAM("Assuming number for: " << name); lua_pushnumber(L, x); - } catch(boost::bad_lexical_cast&) { // Otherwise it's a string + } catch (boost::bad_lexical_cast &) { // Otherwise it's a string ROS_ERROR_STREAM("Assuming string for: " << name); - lua_pushstring(L,env); + lua_pushstring(L, env); } } } @@ -189,16 +187,16 @@ int YamlPreprocessor::LuaGetParam(lua_State *L) { lua_pushstring(L, param.c_str()); } } - } else { // no default + } else { // no default if (!ros::param::has(name)) { // Push back a nil ROS_ERROR_STREAM("No environment variable for: " << name); - lua_pushnil(L); + lua_pushnil(L); } else { try { // Try to push a number double x = boost::lexical_cast(param.c_str()); ROS_ERROR_STREAM("Assuming number for: " << name); lua_pushnumber(L, x); - } catch(boost::bad_lexical_cast&) { // Otherwise it's a string + } catch (boost::bad_lexical_cast &) { // Otherwise it's a string ROS_ERROR_STREAM("Assuming string for: " << name); lua_pushstring(L, param.c_str()); } @@ -207,5 +205,4 @@ int YamlPreprocessor::LuaGetParam(lua_State *L) { return 1; // 1 return value } - } \ No newline at end of file diff --git a/flatland_server/test/yaml_preprocessor/yaml_preprocessor_test.cpp b/flatland_server/test/yaml_preprocessor/yaml_preprocessor_test.cpp index d7066399..6cd2a902 100644 --- a/flatland_server/test/yaml_preprocessor/yaml_preprocessor_test.cpp +++ b/flatland_server/test/yaml_preprocessor/yaml_preprocessor_test.cpp @@ -54,10 +54,10 @@ using namespace flatland_server; // Test the bodyToMarkers method on a polygon shape TEST(YamlPreprocTest, testEvalStrings) { - boost::filesystem::path cwd = fs::path(__FILE__).parent_path(); - - YAML::Node in = YamlPreprocessor::LoadParse((cwd / fs::path("/yaml/eval.strings.yaml")).string()); + + YAML::Node in = YamlPreprocessor::LoadParse( + (cwd / fs::path("/yaml/eval.strings.yaml")).string()); // check that marker was created ASSERT_EQ(1, 1); From b51924f8060aa8b36788f42fce929324bed07bd7 Mon Sep 17 00:00:00 2001 From: Joseph Duchesne Date: Fri, 1 Jun 2018 15:37:07 +0000 Subject: [PATCH 03/11] Fixed all unit tests --- flatland_server/src/yaml_preprocessor.cpp | 46 ++++++------- .../yaml/eval.strings.out.yaml | 8 +-- .../yaml_preprocessor/yaml/eval.strings.yaml | 7 +- .../yaml_preprocessor_test.cpp | 67 ++++++++++++++++++- .../yaml_preprocessor_test.test | 6 +- 5 files changed, 99 insertions(+), 35 deletions(-) diff --git a/flatland_server/src/yaml_preprocessor.cpp b/flatland_server/src/yaml_preprocessor.cpp index de0d9700..d94aab5a 100644 --- a/flatland_server/src/yaml_preprocessor.cpp +++ b/flatland_server/src/yaml_preprocessor.cpp @@ -55,8 +55,6 @@ namespace flatland_server { void YamlPreprocessor::Parse(YAML::Node &node) { - ROS_WARN_NAMED("YamlPreprocessor", "Parse called!"); - YamlPreprocessor::ProcessNodes(node); } @@ -73,9 +71,7 @@ void YamlPreprocessor::ProcessNodes(YAML::Node &node) { } break; case YAML::NodeType::Scalar: - ROS_INFO_STREAM("Scalar: " << node.as()); if (node.as().compare(0, 5, "$eval") == 0) { - ROS_WARN_STREAM("Found $eval"); ProcessScalarNode(node); } break; @@ -90,8 +86,6 @@ void YamlPreprocessor::ProcessScalarNode(YAML::Node &node) { value = "return " + value; } - ROS_WARN_STREAM(value); - // Create the Lua context lua_State *L = luaL_newstate(); luaL_openlibs(L); @@ -107,9 +101,9 @@ void YamlPreprocessor::ProcessScalarNode(YAML::Node &node) { } else { int t = lua_type(L, 1); if (t == LUA_TNIL) { - ROS_ERROR_STREAM("NULL result"); + node = ""; } else { - ROS_ERROR_STREAM("result: " << lua_tostring(L, 1)); + node = lua_tostring(L, 1); } } } @@ -151,15 +145,13 @@ int YamlPreprocessor::LuaGetEnv(lua_State *L) { } } else { // no default if (env == NULL) { // Push back a nil - ROS_ERROR_STREAM("No environment variable for: " << name); + ROS_WARN_STREAM("No environment variable for: " << name); lua_pushnil(L); } else { try { // Try to push a number double x = boost::lexical_cast(env); - ROS_ERROR_STREAM("Assuming number for: " << name); lua_pushnumber(L, x); } catch (boost::bad_lexical_cast &) { // Otherwise it's a string - ROS_ERROR_STREAM("Assuming string for: " << name); lua_pushstring(L, env); } } @@ -170,35 +162,43 @@ int YamlPreprocessor::LuaGetEnv(lua_State *L) { int YamlPreprocessor::LuaGetParam(lua_State *L) { const char *name = lua_tostring(L, 1); - std::string param; - ros::param::param(name, param, "default_value"); + std::string param_s; + int param_i; + double param_d; if (lua_gettop(L) == 2) { // default value was passed in if (lua_isnumber(L, 2)) { if (!ros::param::has(name)) { // return default lua_pushnumber(L, lua_tonumber(L, 2)); } else { - lua_pushnumber(L, std::atof(param.c_str())); + if (ros::param::get(name, param_d)) { + lua_pushnumber(L, param_d); + } else { + ROS_WARN_STREAM("Couldn't load int/double value at param " << name); + lua_pushnil(L); + } } } else if (lua_isstring(L, 2)) { if (!ros::param::has(name)) { // return default lua_pushstring(L, lua_tostring(L, 2)); } else { - lua_pushstring(L, param.c_str()); + ros::param::get(name, param_s); + lua_pushstring(L, param_s.c_str()); } } } else { // no default if (!ros::param::has(name)) { // Push back a nil - ROS_ERROR_STREAM("No environment variable for: " << name); + ROS_WARN_STREAM("No rosparam found for: " << name); lua_pushnil(L); } else { - try { // Try to push a number - double x = boost::lexical_cast(param.c_str()); - ROS_ERROR_STREAM("Assuming number for: " << name); - lua_pushnumber(L, x); - } catch (boost::bad_lexical_cast &) { // Otherwise it's a string - ROS_ERROR_STREAM("Assuming string for: " << name); - lua_pushstring(L, param.c_str()); + if (ros::param::get(name, param_d)) { + lua_pushnumber(L, param_d); + } else if (ros::param::get(name, param_s)) { + lua_pushstring(L, param_s.c_str()); + } else { + ROS_WARN_STREAM("Couldn't load int/double/string value at param " + << name); + lua_pushnil(L); } } } diff --git a/flatland_server/test/yaml_preprocessor/yaml/eval.strings.out.yaml b/flatland_server/test/yaml_preprocessor/yaml/eval.strings.out.yaml index 26f7af49..f2a479e9 100644 --- a/flatland_server/test/yaml_preprocessor/yaml/eval.strings.out.yaml +++ b/flatland_server/test/yaml_preprocessor/yaml/eval.strings.out.yaml @@ -17,14 +17,14 @@ testEnv: env2: 123.4 env3: Bar env4: 123.4 - env5: null + env5: "" env6: 444.4 env7: ZZZ testParam: param1: Foo - param2: 10.0 + param2: 7 param3: Foo - param4: 10.0 - param5: null + param4: 10.5 + param5: "" param6: 223 param7: BBBC \ No newline at end of file diff --git a/flatland_server/test/yaml_preprocessor/yaml/eval.strings.yaml b/flatland_server/test/yaml_preprocessor/yaml/eval.strings.yaml index 488bc373..96240c3b 100644 --- a/flatland_server/test/yaml_preprocessor/yaml/eval.strings.yaml +++ b/flatland_server/test/yaml_preprocessor/yaml/eval.strings.yaml @@ -12,7 +12,8 @@ bom: | $eval [[Some multiline - string]] + string + ]] testEnv: env1: $eval env("VALIDSTRING") env2: $eval env("VALIDNUMBER") @@ -23,9 +24,9 @@ testEnv: env7: $eval env("INVALID","ZZZ") testParam: param1: $eval param("/string") - param2: $eval param("/number") + param2: $eval param("/int") param3: $eval param("/string","AAA") - param4: $eval param("/number","111") + param4: $eval param("/float","111") param5: $eval param("/invalid") param6: $eval param("/invalid","222")+1 param7: $eval param("/invalid","BBB").."C" \ No newline at end of file diff --git a/flatland_server/test/yaml_preprocessor/yaml_preprocessor_test.cpp b/flatland_server/test/yaml_preprocessor/yaml_preprocessor_test.cpp index 6cd2a902..66c17efc 100644 --- a/flatland_server/test/yaml_preprocessor/yaml_preprocessor_test.cpp +++ b/flatland_server/test/yaml_preprocessor/yaml_preprocessor_test.cpp @@ -52,6 +52,37 @@ namespace fs = boost::filesystem; using namespace flatland_server; +void compareNodes(const char *p1, YAML::Node &a, YAML::Node &b) { + try { + EXPECT_STREQ(b[p1].as().c_str(), + a[p1].as().c_str()) + << "at " << p1; + } catch (...) { + ADD_FAILURE() << "Failure to compare " << p1; + } +} + +void compareNodes(const char *p1, int p2, YAML::Node &a, YAML::Node &b) { + try { + EXPECT_STREQ(b[p1][p2].as().c_str(), + a[p1][p2].as().c_str()) + << "at " << p1 << ":" << p2; + } catch (...) { + ADD_FAILURE() << "Failure to compare " << p1 << ":" << p2; + } +} + +void compareNodes(const char *p1, const char *p2, YAML::Node &a, + YAML::Node &b) { + try { + EXPECT_STREQ(b[p1][p2].as().c_str(), + a[p1][p2].as().c_str()) + << "at " << p1 << ":" << p2; + } catch (...) { + ADD_FAILURE() << "Failure to compare " << p1 << ":" << p2; + } +} + // Test the bodyToMarkers method on a polygon shape TEST(YamlPreprocTest, testEvalStrings) { boost::filesystem::path cwd = fs::path(__FILE__).parent_path(); @@ -59,12 +90,42 @@ TEST(YamlPreprocTest, testEvalStrings) { YAML::Node in = YamlPreprocessor::LoadParse( (cwd / fs::path("/yaml/eval.strings.yaml")).string()); - // check that marker was created - ASSERT_EQ(1, 1); + YAML::Node out = YamlPreprocessor::LoadParse( + (cwd / fs::path("/yaml/eval.strings.out.yaml")).string()); + + // check that the two strings match + compareNodes("foo", in, out); + compareNodes("bar", in, out); + compareNodes("baz", in, out); + compareNodes("bash", in, out); + + compareNodes("boop", "bal", in, out); + + compareNodes("foop", 0, in, out); + compareNodes("foop", 1, in, out); + compareNodes("foop", 2, in, out); + + compareNodes("bom", in, out); + + compareNodes("testEnv", "env1", in, out); + compareNodes("testEnv", "env2", in, out); + compareNodes("testEnv", "env3", in, out); + compareNodes("testEnv", "env4", in, out); + compareNodes("testEnv", "env5", in, out); + compareNodes("testEnv", "env6", in, out); + compareNodes("testEnv", "env7", in, out); + + compareNodes("testParam", "param1", in, out); + compareNodes("testParam", "param2", in, out); + compareNodes("testParam", "param3", in, out); + compareNodes("testParam", "param4", in, out); + compareNodes("testParam", "param5", in, out); + compareNodes("testParam", "param6", in, out); + compareNodes("testParam", "param7", in, out); } // Run all the tests that were declared with TEST() -int main(int argc, char** argv) { +int main(int argc, char **argv) { ros::init(argc, argv, "yaml_preprocessor_test"); testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); diff --git a/flatland_server/test/yaml_preprocessor/yaml_preprocessor_test.test b/flatland_server/test/yaml_preprocessor/yaml_preprocessor_test.test index b5ee1c32..a7e04395 100644 --- a/flatland_server/test/yaml_preprocessor/yaml_preprocessor_test.test +++ b/flatland_server/test/yaml_preprocessor/yaml_preprocessor_test.test @@ -4,10 +4,12 @@ Test launchfile for yaml_preprocessor_test This file tests that the preprocessor handles all manner of conditionals and statements --> + + + + - - \ No newline at end of file From e3505705e79d8f79be5331bfb7fab41953c93e52 Mon Sep 17 00:00:00 2001 From: Joseph Duchesne Date: Fri, 1 Jun 2018 19:54:22 +0000 Subject: [PATCH 04/11] Added enable/disable support to plugins, models and joints. Fixed bug in 3d vis rendering. Fixed boolean params. --- flatland_server/src/layer.cpp | 6 +- flatland_server/src/model.cpp | 24 +++++ flatland_server/src/plugin_manager.cpp | 12 +++ flatland_server/src/yaml_preprocessor.cpp | 99 ++++++++++--------- flatland_server/src/yaml_reader.cpp | 3 + .../yaml/eval.strings.out.yaml | 5 +- .../yaml_preprocessor/yaml/eval.strings.yaml | 6 +- .../yaml_preprocessor_test.cpp | 3 + 8 files changed, 107 insertions(+), 51 deletions(-) diff --git a/flatland_server/src/layer.cpp b/flatland_server/src/layer.cpp index 9b922412..a7e8c148 100644 --- a/flatland_server/src/layer.cpp +++ b/flatland_server/src/layer.cpp @@ -301,7 +301,11 @@ void Layer::LoadFromBitmap(const cv::Mat &bitmap, double occupied_thresh, } void Layer::DebugVisualize() const { - ROS_WARN("======== 3d visualize? ==========="); + // Don't try to visualized uninitalized layers + if (viz_name_.length() == 0) { + return; + } + DebugVisualization::Get().Reset(viz_name_); DebugVisualization::Get().Reset(viz_name_ + "_3d"); diff --git a/flatland_server/src/model.cpp b/flatland_server/src/model.cpp index ed481696..8db10f42 100644 --- a/flatland_server/src/model.cpp +++ b/flatland_server/src/model.cpp @@ -106,6 +106,18 @@ void Model::LoadBodies(YamlReader &bodies_reader) { } else { for (int i = 0; i < bodies_reader.NodeSize(); i++) { YamlReader body_reader = bodies_reader.Subnode(i, YamlReader::MAP); + if (!body_reader.Get("enabled", "true")) { + ROS_WARN_STREAM("Body " + << Q(name_) << "." + << body_reader.Get("name", "unnamed") + << " disabled"); + continue; + } else { + ROS_WARN_STREAM("Body " + << Q(name_) << "." + << body_reader.Get("name", "unnamed") + << " enabled"); + } ModelBody *b = ModelBody::MakeBody(physics_world_, cfr_, this, body_reader); bodies_.push_back(b); @@ -125,6 +137,18 @@ void Model::LoadJoints(YamlReader &joints_reader) { if (!joints_reader.IsNodeNull()) { for (int i = 0; i < joints_reader.NodeSize(); i++) { YamlReader joint_reader = joints_reader.Subnode(i, YamlReader::MAP); + if (!joint_reader.Get("enabled", "true")) { + ROS_WARN_STREAM("Joint " + << Q(name_) << "." + << joint_reader.Get("name", "unnamed") + << " disabled"); + continue; + } else { + ROS_WARN_STREAM("Joint " + << Q(name_) << "." + << joint_reader.Get("name", "unnamed") + << " enabled"); + } Joint *j = Joint::MakeJoint(physics_world_, this, joint_reader); joints_.push_back(j); diff --git a/flatland_server/src/plugin_manager.cpp b/flatland_server/src/plugin_manager.cpp index 5957644b..995a1eb1 100644 --- a/flatland_server/src/plugin_manager.cpp +++ b/flatland_server/src/plugin_manager.cpp @@ -116,6 +116,18 @@ void PluginManager::LoadModelPlugin(Model *model, YamlReader &plugin_reader) { " already exists"); } + if (!plugin_reader.Get("enabled", "true")) { + ROS_WARN_STREAM("Plugin " + << Q(model->name_) << "." + << plugin_reader.Get("name", "unnamed") + << " disabled"); + return; + } else { + ROS_WARN_STREAM("Body " << Q(model->name_) << "." + << plugin_reader.Get("name", "unnamed") + << " enabled"); + } + // remove the name and type of the YAML Node, the plugin does not need to know // about these parameters, remove method is broken in yaml cpp 5.2, so we // create a new node and add everything diff --git a/flatland_server/src/yaml_preprocessor.cpp b/flatland_server/src/yaml_preprocessor.cpp index d94aab5a..12ae7964 100644 --- a/flatland_server/src/yaml_preprocessor.cpp +++ b/flatland_server/src/yaml_preprocessor.cpp @@ -82,29 +82,42 @@ void YamlPreprocessor::ProcessScalarNode(YAML::Node &node) { std::string value = node.as().substr(5); // omit the $parse boost::algorithm::trim(value); // trim whitespace - if (value.find("return ") == std::string::npos) { // Has no return statement - value = "return " + value; - } + try { + if (value.find("return ") == + std::string::npos) { // Has no return statement + value = "return " + value; + } - // Create the Lua context - lua_State *L = luaL_newstate(); - luaL_openlibs(L); - lua_pushcfunction(L, YamlPreprocessor::LuaGetEnv); - lua_setglobal(L, "env"); - lua_pushcfunction(L, YamlPreprocessor::LuaGetParam); - lua_setglobal(L, "param"); - - int error = luaL_dostring(L, value.c_str()); - if (error) { - ROS_ERROR_STREAM(lua_tostring(L, -1)); - lua_pop(L, 1); /* pop error message from the stack */ - } else { - int t = lua_type(L, 1); - if (t == LUA_TNIL) { - node = ""; + // Create the Lua context + lua_State *L = luaL_newstate(); + luaL_openlibs(L); + lua_pushcfunction(L, YamlPreprocessor::LuaGetEnv); + lua_setglobal(L, "env"); + lua_pushcfunction(L, YamlPreprocessor::LuaGetParam); + lua_setglobal(L, "param"); + + int error = luaL_dostring(L, value.c_str()); + if (error) { + ROS_ERROR_STREAM(lua_tostring(L, -1)); + lua_pop(L, 1); /* pop error message from the stack */ } else { - node = lua_tostring(L, 1); + int t = lua_type(L, 1); + if (t == LUA_TNIL) { + node = ""; + ROS_INFO_STREAM("Preprocessor parsed " << value << " as empty string"); + } else if (t == LUA_TBOOLEAN) { + ROS_INFO_STREAM("Preprocessor parsed " + << value << " as bool " + << (lua_toboolean(L, 1) ? "true" : "false")); + node = lua_toboolean(L, 1) ? "true" : "false"; + } else { + ROS_INFO_STREAM("Preprocessor parsed " << value << " as " + << lua_tostring(L, 1)); + node = lua_tostring(L, 1); + } } + } catch (...) { + ROS_ERROR_STREAM("Lua error in: " << value); } } @@ -129,25 +142,20 @@ int YamlPreprocessor::LuaGetEnv(lua_State *L) { const char *name = lua_tostring(L, 1); const char *env = std::getenv(name); - if (lua_gettop(L) == 2) { // default passed in + if (lua_gettop(L) == 2 && env == NULL) { // use default if (lua_isnumber(L, 2)) { - if (env == NULL) { - lua_pushnumber(L, lua_tonumber(L, 2)); - } else { - lua_pushnumber(L, std::atof(env)); - } + lua_pushnumber(L, lua_tonumber(L, 2)); } else if (lua_isstring(L, 2)) { - if (env == NULL) { - lua_pushstring(L, lua_tostring(L, 2)); - } else { - lua_pushstring(L, env); - } + lua_pushstring(L, lua_tostring(L, 2)); + } else if (lua_isboolean(L, 2)) { + lua_pushboolean(L, lua_toboolean(L, 2)); } } else { // no default if (env == NULL) { // Push back a nil ROS_WARN_STREAM("No environment variable for: " << name); lua_pushnil(L); } else { + ROS_WARN_STREAM("Found env for " << name); try { // Try to push a number double x = boost::lexical_cast(env); lua_pushnumber(L, x); @@ -165,26 +173,19 @@ int YamlPreprocessor::LuaGetParam(lua_State *L) { std::string param_s; int param_i; double param_d; + bool param_b; - if (lua_gettop(L) == 2) { // default value was passed in + if (lua_gettop(L) == 2 && !ros::param::has(name)) { // use default if (lua_isnumber(L, 2)) { - if (!ros::param::has(name)) { // return default - lua_pushnumber(L, lua_tonumber(L, 2)); - } else { - if (ros::param::get(name, param_d)) { - lua_pushnumber(L, param_d); - } else { - ROS_WARN_STREAM("Couldn't load int/double value at param " << name); - lua_pushnil(L); - } - } + lua_pushnumber(L, lua_tonumber(L, 2)); + } else if (lua_isboolean(L, 2)) { + lua_pushboolean(L, lua_toboolean(L, 2)); } else if (lua_isstring(L, 2)) { - if (!ros::param::has(name)) { // return default - lua_pushstring(L, lua_tostring(L, 2)); - } else { - ros::param::get(name, param_s); - lua_pushstring(L, param_s.c_str()); - } + lua_pushstring(L, lua_tostring(L, 2)); + } else { + ROS_WARN_STREAM("Couldn't load int/double/string value at param " + << name); + lua_pushnil(L); } } else { // no default if (!ros::param::has(name)) { // Push back a nil @@ -195,6 +196,8 @@ int YamlPreprocessor::LuaGetParam(lua_State *L) { lua_pushnumber(L, param_d); } else if (ros::param::get(name, param_s)) { lua_pushstring(L, param_s.c_str()); + } else if (ros::param::get(name, param_b)) { + lua_pushstring(L, param_b ? "true" : "false"); } else { ROS_WARN_STREAM("Couldn't load int/double/string value at param " << name); diff --git a/flatland_server/src/yaml_reader.cpp b/flatland_server/src/yaml_reader.cpp index b370ddc8..6c3df6f1 100644 --- a/flatland_server/src/yaml_reader.cpp +++ b/flatland_server/src/yaml_reader.cpp @@ -44,6 +44,7 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#include #include #include @@ -54,12 +55,14 @@ YamlReader::YamlReader() : node_(YAML::Node()) { } YamlReader::YamlReader(const YAML::Node &node) : node_(node) { + YamlPreprocessor::Parse(node_); SetErrorInfo("_NONE_", "_NONE_"); } YamlReader::YamlReader(const std::string &path) { try { node_ = YAML::LoadFile(path); + YamlPreprocessor::Parse(node_); } catch (const YAML::BadFile &e) { throw YAMLException("File does not exist, path=" + Q(path)); diff --git a/flatland_server/test/yaml_preprocessor/yaml/eval.strings.out.yaml b/flatland_server/test/yaml_preprocessor/yaml/eval.strings.out.yaml index f2a479e9..1281c69a 100644 --- a/flatland_server/test/yaml_preprocessor/yaml/eval.strings.out.yaml +++ b/flatland_server/test/yaml_preprocessor/yaml/eval.strings.out.yaml @@ -20,6 +20,7 @@ testEnv: env5: "" env6: 444.4 env7: ZZZ + env8: true testParam: param1: Foo param2: 7 @@ -27,4 +28,6 @@ testParam: param4: 10.5 param5: "" param6: 223 - param7: BBBC \ No newline at end of file + param7: BBBC + param8: true + param9: true \ No newline at end of file diff --git a/flatland_server/test/yaml_preprocessor/yaml/eval.strings.yaml b/flatland_server/test/yaml_preprocessor/yaml/eval.strings.yaml index 96240c3b..f6d29d56 100644 --- a/flatland_server/test/yaml_preprocessor/yaml/eval.strings.yaml +++ b/flatland_server/test/yaml_preprocessor/yaml/eval.strings.yaml @@ -22,6 +22,8 @@ testEnv: env5: $eval env("INVALID") env6: $eval env("INVALID","444.4") env7: $eval env("INVALID","ZZZ") + env8: $eval param("INVALID", true) + testParam: param1: $eval param("/string") param2: $eval param("/int") @@ -29,4 +31,6 @@ testParam: param4: $eval param("/float","111") param5: $eval param("/invalid") param6: $eval param("/invalid","222")+1 - param7: $eval param("/invalid","BBB").."C" \ No newline at end of file + param7: $eval param("/invalid","BBB").."C" + param8: $eval param("/invalid", true) + param9: $eval true \ No newline at end of file diff --git a/flatland_server/test/yaml_preprocessor/yaml_preprocessor_test.cpp b/flatland_server/test/yaml_preprocessor/yaml_preprocessor_test.cpp index 66c17efc..50bfd619 100644 --- a/flatland_server/test/yaml_preprocessor/yaml_preprocessor_test.cpp +++ b/flatland_server/test/yaml_preprocessor/yaml_preprocessor_test.cpp @@ -114,6 +114,7 @@ TEST(YamlPreprocTest, testEvalStrings) { compareNodes("testEnv", "env5", in, out); compareNodes("testEnv", "env6", in, out); compareNodes("testEnv", "env7", in, out); + compareNodes("testEnv", "env8", in, out); compareNodes("testParam", "param1", in, out); compareNodes("testParam", "param2", in, out); @@ -122,6 +123,8 @@ TEST(YamlPreprocTest, testEvalStrings) { compareNodes("testParam", "param5", in, out); compareNodes("testParam", "param6", in, out); compareNodes("testParam", "param7", in, out); + compareNodes("testParam", "param8", in, out); + compareNodes("testParam", "param9", in, out); } // Run all the tests that were declared with TEST() From 92a0586cb5719419e0af6c06b1bb2bc83f1f9962 Mon Sep 17 00:00:00 2001 From: Joseph Duchesne Date: Mon, 4 Jun 2018 12:42:14 +0000 Subject: [PATCH 05/11] Fixed handling of booleans --- flatland_server/src/plugin_manager.cpp | 24 ++++++++++++------- flatland_server/src/yaml_preprocessor.cpp | 5 +++- .../yaml_preprocessor/yaml/eval.strings.yaml | 2 +- 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/flatland_server/src/plugin_manager.cpp b/flatland_server/src/plugin_manager.cpp index 995a1eb1..3696b320 100644 --- a/flatland_server/src/plugin_manager.cpp +++ b/flatland_server/src/plugin_manager.cpp @@ -116,16 +116,24 @@ void PluginManager::LoadModelPlugin(Model *model, YamlReader &plugin_reader) { " already exists"); } - if (!plugin_reader.Get("enabled", "true")) { - ROS_WARN_STREAM("Plugin " - << Q(model->name_) << "." - << plugin_reader.Get("name", "unnamed") - << " disabled"); - return; - } else { + try { + if (!plugin_reader.Get("enabled", "true")) { + ROS_WARN_STREAM("Plugin " + << Q(model->name_) << "." + << plugin_reader.Get("name", "unnamed") + << " disabled"); + return; + } else { + ROS_WARN_STREAM("Body " + << Q(model->name_) << "." + << plugin_reader.Get("name", "unnamed") + << " enabled"); + } + } catch (...) { ROS_WARN_STREAM("Body " << Q(model->name_) << "." << plugin_reader.Get("name", "unnamed") - << " enabled"); + << " enabled because flag failed to parse: " + << plugin_reader.Get("enabled")); } // remove the name and type of the YAML Node, the plugin does not need to know diff --git a/flatland_server/src/yaml_preprocessor.cpp b/flatland_server/src/yaml_preprocessor.cpp index 12ae7964..df4aacad 100644 --- a/flatland_server/src/yaml_preprocessor.cpp +++ b/flatland_server/src/yaml_preprocessor.cpp @@ -81,6 +81,7 @@ void YamlPreprocessor::ProcessNodes(YAML::Node &node) { void YamlPreprocessor::ProcessScalarNode(YAML::Node &node) { std::string value = node.as().substr(5); // omit the $parse boost::algorithm::trim(value); // trim whitespace + ROS_INFO_STREAM("Attempting to parse lua " << value); try { if (value.find("return ") == @@ -110,10 +111,12 @@ void YamlPreprocessor::ProcessScalarNode(YAML::Node &node) { << value << " as bool " << (lua_toboolean(L, 1) ? "true" : "false")); node = lua_toboolean(L, 1) ? "true" : "false"; - } else { + } else if (t == LUA_TSTRING || t == LUA_TNUMBER) { ROS_INFO_STREAM("Preprocessor parsed " << value << " as " << lua_tostring(L, 1)); node = lua_tostring(L, 1); + } else { + ROS_ERROR_STREAM("No lua output for " << value); } } } catch (...) { diff --git a/flatland_server/test/yaml_preprocessor/yaml/eval.strings.yaml b/flatland_server/test/yaml_preprocessor/yaml/eval.strings.yaml index f6d29d56..19dd299d 100644 --- a/flatland_server/test/yaml_preprocessor/yaml/eval.strings.yaml +++ b/flatland_server/test/yaml_preprocessor/yaml/eval.strings.yaml @@ -22,7 +22,7 @@ testEnv: env5: $eval env("INVALID") env6: $eval env("INVALID","444.4") env7: $eval env("INVALID","ZZZ") - env8: $eval param("INVALID", true) + env8: $eval env("INVALID", true) testParam: param1: $eval param("/string") From fdfac772438e353a802fdabb9c46cbc40e4a1786 Mon Sep 17 00:00:00 2001 From: Joseph Duchesne Date: Mon, 4 Jun 2018 13:11:11 +0000 Subject: [PATCH 06/11] added yaml preprocessor documentation --- docs/core_functions/yaml_preprocessor.rst | 73 +++++++++++++++++++++++ docs/index.rst | 1 + 2 files changed, 74 insertions(+) create mode 100644 docs/core_functions/yaml_preprocessor.rst diff --git a/docs/core_functions/yaml_preprocessor.rst b/docs/core_functions/yaml_preprocessor.rst new file mode 100644 index 00000000..b173ec96 --- /dev/null +++ b/docs/core_functions/yaml_preprocessor.rst @@ -0,0 +1,73 @@ +.. image:: ../_static/flatland_logo2.png + :width: 250px + :align: right + :target: ../_static/flatland_logo2.png + +Yaml Preprocessor +============================== + +Flatland Server has a lua preprocessor for YAML with simple bindings for the environment variables and rosparam. +The intent is to be able to build parametric models that are defined by dimensions and flags found in either environment variables or rosparam, in a similar way to xacro+urdf. Because this is parsed at model load time, any roslaunch rosparam loading will have completed and those parameters will be available. + +body/joint/plugin enabled flag +------------------------------ +Model bodies, plugins and joints now have a new flag `enabled` which can be set to true or false either directly in the yaml, or based on more complex logic from a lua `$eval` string that returns "true" or "false". Disabled bodies, plugins and joints are skipped during yaml loading, and as a result are never instantiated. From Flatland's perspective `enabled: false` causes the affected body/plugin/joint to be deleted. + +bindings for env and param +------------------------------- + +Additional lua function bindings (beyond the normal standard libraries such as string, math, etc.): +.. code-block:: lua + env(EnvName) -- blank string + warning if not found + env(EnvName, Default) + param(ParamPath) -- blank string + warning if not found + param(ParamPath, Default) + +Sample expressions +------------------------------ + +.. code-block:: yaml + foo: $eval "Some arbitrary LUA expression" + bar: | # Multiline string + $eval -- $eval flag required to trigger LUA parsing + if env("FRONT_WHEEL",true) then + return 1.2 + else + return 2.4 + end + +Lua expressions can explicitly `return` their value, but if no `return` is given, one will be prepended to the statement. + +env + param examples +----------------------------- + +.. code-block:: yaml + # in: (SOME_ENV not set) + foo: $eval env("SOME_ENV") + # out: + foo: "" + +.. code-block:: yaml + # in: (SOME_ENV not set) + foo: $eval env("SOME_ENV", false) + # out: + foo: false + +.. code-block:: yaml + # in: (export SOME_ENV=true) + foo: $eval env("SOME_ENV") + # out: + foo: true + +.. code-block:: yaml + # in: (rosparam /test/param not set) + foo: $eval param("/test/param", 0)/2.0 + # out: + foo: 0 + +.. code-block:: yaml + # in: (rosparam /test/param set to 5.0) + foo: $eval param("/test/param", 0)/2.0 + 1 + # out: + foo: 2.5 + diff --git a/docs/index.rst b/docs/index.rst index 300bcc29..74169a8e 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -36,6 +36,7 @@ Class APIs are documented `here ` core_functions/world core_functions/layers core_functions/models + core_functions/yaml_preprocessor core_functions/ros_services core_functions/model_plugins core_functions/joystick From 660154eb33b356900bf169e584e94f2a86a47cdc Mon Sep 17 00:00:00 2001 From: Joseph Duchesne Date: Mon, 4 Jun 2018 13:24:39 +0000 Subject: [PATCH 07/11] tried to fix documentation --- docs/core_functions/yaml_preprocessor.rst | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/docs/core_functions/yaml_preprocessor.rst b/docs/core_functions/yaml_preprocessor.rst index b173ec96..c182945a 100644 --- a/docs/core_functions/yaml_preprocessor.rst +++ b/docs/core_functions/yaml_preprocessor.rst @@ -17,7 +17,8 @@ bindings for env and param ------------------------------- Additional lua function bindings (beyond the normal standard libraries such as string, math, etc.): -.. code-block:: lua + +.. highlight:: lua env(EnvName) -- blank string + warning if not found env(EnvName, Default) param(ParamPath) -- blank string + warning if not found @@ -26,7 +27,7 @@ Additional lua function bindings (beyond the normal standard libraries such as s Sample expressions ------------------------------ -.. code-block:: yaml +.. highlight:: yaml foo: $eval "Some arbitrary LUA expression" bar: | # Multiline string $eval -- $eval flag required to trigger LUA parsing @@ -41,31 +42,31 @@ Lua expressions can explicitly `return` their value, but if no `return` is given env + param examples ----------------------------- -.. code-block:: yaml +.. highlight:: yaml # in: (SOME_ENV not set) foo: $eval env("SOME_ENV") # out: foo: "" -.. code-block:: yaml +.. highlight:: yaml # in: (SOME_ENV not set) foo: $eval env("SOME_ENV", false) # out: foo: false -.. code-block:: yaml +.. highlight:: yaml # in: (export SOME_ENV=true) foo: $eval env("SOME_ENV") # out: foo: true -.. code-block:: yaml +.. highlight:: yaml # in: (rosparam /test/param not set) foo: $eval param("/test/param", 0)/2.0 # out: foo: 0 -.. code-block:: yaml +.. highlight:: yaml # in: (rosparam /test/param set to 5.0) foo: $eval param("/test/param", 0)/2.0 + 1 # out: From f69fc64437e2d8907ddf135f7232442aacc1032d Mon Sep 17 00:00:00 2001 From: Joseph Duchesne Date: Mon, 4 Jun 2018 13:37:20 +0000 Subject: [PATCH 08/11] tried to fix documentation --- docs/core_functions/yaml_preprocessor.rst | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/docs/core_functions/yaml_preprocessor.rst b/docs/core_functions/yaml_preprocessor.rst index c182945a..03ff0bbe 100644 --- a/docs/core_functions/yaml_preprocessor.rst +++ b/docs/core_functions/yaml_preprocessor.rst @@ -18,7 +18,8 @@ bindings for env and param Additional lua function bindings (beyond the normal standard libraries such as string, math, etc.): -.. highlight:: lua +.. code-block:: lua + env(EnvName) -- blank string + warning if not found env(EnvName, Default) param(ParamPath) -- blank string + warning if not found @@ -27,7 +28,8 @@ Additional lua function bindings (beyond the normal standard libraries such as s Sample expressions ------------------------------ -.. highlight:: yaml +.. code-block:: yaml + foo: $eval "Some arbitrary LUA expression" bar: | # Multiline string $eval -- $eval flag required to trigger LUA parsing @@ -42,31 +44,36 @@ Lua expressions can explicitly `return` their value, but if no `return` is given env + param examples ----------------------------- -.. highlight:: yaml +.. code-block:: yaml + # in: (SOME_ENV not set) foo: $eval env("SOME_ENV") # out: foo: "" -.. highlight:: yaml +.. code-block:: yaml + # in: (SOME_ENV not set) foo: $eval env("SOME_ENV", false) # out: foo: false -.. highlight:: yaml +.. code-block:: yaml + # in: (export SOME_ENV=true) foo: $eval env("SOME_ENV") # out: foo: true -.. highlight:: yaml +.. code-block:: yaml + # in: (rosparam /test/param not set) foo: $eval param("/test/param", 0)/2.0 # out: foo: 0 -.. highlight:: yaml +.. code-block:: yaml + # in: (rosparam /test/param set to 5.0) foo: $eval param("/test/param", 0)/2.0 + 1 # out: From aedb8b74e22eb7fcde6bd79c931eb06908135e14 Mon Sep 17 00:00:00 2001 From: Joseph Duchesne Date: Mon, 4 Jun 2018 09:56:43 -0400 Subject: [PATCH 09/11] Update yaml_preprocessor.h --- flatland_server/include/flatland_server/yaml_preprocessor.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flatland_server/include/flatland_server/yaml_preprocessor.h b/flatland_server/include/flatland_server/yaml_preprocessor.h index 6dd3b441..9753e27b 100644 --- a/flatland_server/include/flatland_server/yaml_preprocessor.h +++ b/flatland_server/include/flatland_server/yaml_preprocessor.h @@ -79,13 +79,13 @@ class YamlPreprocessor { static YAML::Node LoadParse(const std::string &path); /** - * @brief Find and run any eval nodes ($evalString etc.) + * @brief Find and run any $eval nodes * @param[in/out] node A Yaml node to recursively parse */ static void ProcessNodes(YAML::Node &node); /** - * @brief Find and run any eval expressions ($evalString etc.) + * @brief Find and run any $eval expressions * @param[in/out] node A Yaml string node to parse */ static void ProcessScalarNode(YAML::Node &node); @@ -104,4 +104,4 @@ class YamlPreprocessor { }; } -#endif // FLATLAND_SERVER_YAML_PREPROCESSOR_H \ No newline at end of file +#endif // FLATLAND_SERVER_YAML_PREPROCESSOR_H From df63e0f4443113ba0e66ddaf69c66a187ff2d4e6 Mon Sep 17 00:00:00 2001 From: Joseph Duchesne Date: Mon, 4 Jun 2018 15:00:23 +0000 Subject: [PATCH 10/11] Extended model documentation to document the enabled flag --- docs/core_functions/models.rst | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/docs/core_functions/models.rst b/docs/core_functions/models.rst index 1d1c618d..a603b3e6 100644 --- a/docs/core_functions/models.rst +++ b/docs/core_functions/models.rst @@ -17,6 +17,9 @@ shown here. Examples can be found in flatland_server/tests. # required, name of the body, must be unique within the model - name: base_link + # optional, default true. If false (see yaml preprocessor for details), this body is skipped + enabled: true + # optional, defaults to [0, 0, 0], in the form of [x, y, theta] w.r.t the # model pose specified in world yaml. Pose is simply the initial pose # of the body, it does not add additional constrains in any way @@ -115,6 +118,9 @@ shown here. Examples can be found in flatland_server/tests. # joint types name: rear_wheel_revolute + # optional, default true. If false (see yaml preprocessor for details), this joint is skipped + enabled: true + # optional, default to false, specifies whether two bodies connected a # this joint should collide with each other, applies to all joint types collide_connected: false @@ -186,6 +192,9 @@ shown here. Examples can be found in flatland_server/tests. # property to be discovered. See the Writing Model Plugins page - type: Laser + # optional, default true. If false (see yaml preprocessor for details), this plugin is skipped + enabled: true + # required, name of the plugin to load, must be unique in a model name: kinect From a0640a476542a80f425d7e81fea80cec8c7d26cb Mon Sep 17 00:00:00 2001 From: Joseph Duchesne Date: Mon, 4 Jun 2018 15:47:59 +0000 Subject: [PATCH 11/11] Addressed Luke's code review comments --- .../flatland_server/yaml_preprocessor.h | 69 +++++++++---------- flatland_server/src/model.cpp | 14 +--- flatland_server/src/plugin_manager.cpp | 5 -- flatland_server/src/yaml_preprocessor.cpp | 30 ++++---- 4 files changed, 53 insertions(+), 65 deletions(-) diff --git a/flatland_server/include/flatland_server/yaml_preprocessor.h b/flatland_server/include/flatland_server/yaml_preprocessor.h index 6dd3b441..486f2683 100644 --- a/flatland_server/include/flatland_server/yaml_preprocessor.h +++ b/flatland_server/include/flatland_server/yaml_preprocessor.h @@ -61,46 +61,45 @@ namespace flatland_server { /** */ -class YamlPreprocessor { - public: - /** - * @brief Preprocess with a given node - * @param[in/out] node A Yaml node to parse - * @return The parsed YAML::Node - */ - static void Parse(YAML::Node &node); +namespace YamlPreprocessor { +/** + * @brief Preprocess with a given node + * @param[in/out] node A Yaml node to parse + * @return The parsed YAML::Node + */ +void Parse(YAML::Node &node); - /** - * @brief Constructor with a given path to a yaml file, throws exception on - * failure - * @param[in] path Path to the yaml file - * @return The parsed YAML::Node - */ - static YAML::Node LoadParse(const std::string &path); +/** + * @brief Constructor with a given path to a yaml file, throws exception on + * failure + * @param[in] path Path to the yaml file + * @return The parsed YAML::Node + */ +YAML::Node LoadParse(const std::string &path); - /** - * @brief Find and run any eval nodes ($evalString etc.) - * @param[in/out] node A Yaml node to recursively parse - */ - static void ProcessNodes(YAML::Node &node); +/** + * @brief Find and run any eval nodes ($evalString etc.) + * @param[in/out] node A Yaml node to recursively parse + */ +void ProcessNodes(YAML::Node &node); - /** - * @brief Find and run any eval expressions ($evalString etc.) - * @param[in/out] node A Yaml string node to parse - */ - static void ProcessScalarNode(YAML::Node &node); +/** + * @brief Find and run any eval expressions ($evalString etc.) + * @param[in/out] node A Yaml string node to parse + */ +void ProcessScalarNode(YAML::Node &node); - /** - * @brief Get an environment variable with an optional default value - * @param[in/out] lua_State The lua state/stack to read/write to/from - */ - static int LuaGetEnv(lua_State *L); +/** + * @brief Get an environment variable with an optional default value + * @param[in/out] lua_State The lua state/stack to read/write to/from + */ +int LuaGetEnv(lua_State *L); - /** - * @brief Get a rosparam with an optional default value - * @param[in/out] lua_State The lua state/stack to read/write to/from - */ - static int LuaGetParam(lua_State *L); +/** + * @brief Get a rosparam with an optional default value + * @param[in/out] lua_State The lua state/stack to read/write to/from + */ +int LuaGetParam(lua_State *L); }; } diff --git a/flatland_server/src/model.cpp b/flatland_server/src/model.cpp index 8db10f42..21491025 100644 --- a/flatland_server/src/model.cpp +++ b/flatland_server/src/model.cpp @@ -107,16 +107,11 @@ void Model::LoadBodies(YamlReader &bodies_reader) { for (int i = 0; i < bodies_reader.NodeSize(); i++) { YamlReader body_reader = bodies_reader.Subnode(i, YamlReader::MAP); if (!body_reader.Get("enabled", "true")) { - ROS_WARN_STREAM("Body " + ROS_INFO_STREAM("Body " << Q(name_) << "." << body_reader.Get("name", "unnamed") << " disabled"); continue; - } else { - ROS_WARN_STREAM("Body " - << Q(name_) << "." - << body_reader.Get("name", "unnamed") - << " enabled"); } ModelBody *b = ModelBody::MakeBody(physics_world_, cfr_, this, body_reader); @@ -138,16 +133,11 @@ void Model::LoadJoints(YamlReader &joints_reader) { for (int i = 0; i < joints_reader.NodeSize(); i++) { YamlReader joint_reader = joints_reader.Subnode(i, YamlReader::MAP); if (!joint_reader.Get("enabled", "true")) { - ROS_WARN_STREAM("Joint " + ROS_INFO_STREAM("Joint " << Q(name_) << "." << joint_reader.Get("name", "unnamed") << " disabled"); continue; - } else { - ROS_WARN_STREAM("Joint " - << Q(name_) << "." - << joint_reader.Get("name", "unnamed") - << " enabled"); } Joint *j = Joint::MakeJoint(physics_world_, this, joint_reader); joints_.push_back(j); diff --git a/flatland_server/src/plugin_manager.cpp b/flatland_server/src/plugin_manager.cpp index 3696b320..60021a62 100644 --- a/flatland_server/src/plugin_manager.cpp +++ b/flatland_server/src/plugin_manager.cpp @@ -123,11 +123,6 @@ void PluginManager::LoadModelPlugin(Model *model, YamlReader &plugin_reader) { << plugin_reader.Get("name", "unnamed") << " disabled"); return; - } else { - ROS_WARN_STREAM("Body " - << Q(model->name_) << "." - << plugin_reader.Get("name", "unnamed") - << " enabled"); } } catch (...) { ROS_WARN_STREAM("Body " << Q(model->name_) << "." diff --git a/flatland_server/src/yaml_preprocessor.cpp b/flatland_server/src/yaml_preprocessor.cpp index df4aacad..6dfcdbab 100644 --- a/flatland_server/src/yaml_preprocessor.cpp +++ b/flatland_server/src/yaml_preprocessor.cpp @@ -75,6 +75,10 @@ void YamlPreprocessor::ProcessNodes(YAML::Node &node) { ProcessScalarNode(node); } break; + case default: + ROS_WARN_STREAM( + "Yaml Preprocessor found an unexpected type: " << node.Type()); + break; } } @@ -83,20 +87,19 @@ void YamlPreprocessor::ProcessScalarNode(YAML::Node &node) { boost::algorithm::trim(value); // trim whitespace ROS_INFO_STREAM("Attempting to parse lua " << value); - try { - if (value.find("return ") == - std::string::npos) { // Has no return statement - value = "return " + value; - } + if (value.find("return ") == std::string::npos) { // Has no return statement + value = "return " + value; + } - // Create the Lua context - lua_State *L = luaL_newstate(); - luaL_openlibs(L); - lua_pushcfunction(L, YamlPreprocessor::LuaGetEnv); - lua_setglobal(L, "env"); - lua_pushcfunction(L, YamlPreprocessor::LuaGetParam); - lua_setglobal(L, "param"); + // Create the Lua context + lua_State *L = luaL_newstate(); + luaL_openlibs(L); + lua_pushcfunction(L, YamlPreprocessor::LuaGetEnv); + lua_setglobal(L, "env"); + lua_pushcfunction(L, YamlPreprocessor::LuaGetParam); + lua_setglobal(L, "param"); + try { /* Attempt to run the Lua string and parse its results */ int error = luaL_dostring(L, value.c_str()); if (error) { ROS_ERROR_STREAM(lua_tostring(L, -1)); @@ -119,7 +122,8 @@ void YamlPreprocessor::ProcessScalarNode(YAML::Node &node) { ROS_ERROR_STREAM("No lua output for " << value); } } - } catch (...) { + } catch ( + ...) { /* Something went wrong parsing the lua, or gettings its results */ ROS_ERROR_STREAM("Lua error in: " << value); } }