From 1b5552b69067bb78eb548065c5ca9535f1035c01 Mon Sep 17 00:00:00 2001 From: SofiaFaraci Date: Thu, 19 Sep 2024 17:43:35 +0200 Subject: [PATCH 01/16] add topic code generation Signed-off-by: SofiaFaraci --- code/include/Data.h | 5 ++ code/src/Replacer.cpp | 61 +++++++++++++++++++ .../template_skill/include/TemplateSkill.h | 6 +- templates/skills/template_skill/package.xml | 2 +- .../template_skill/src/TemplateSkill.cpp | 23 ++++++- 5 files changed, 94 insertions(+), 3 deletions(-) diff --git a/code/include/Data.h b/code/include/Data.h index e39f267..446f5e6 100644 --- a/code/include/Data.h +++ b/code/include/Data.h @@ -82,6 +82,7 @@ struct fileDataStr{ std::string outputFileNameCPP; bool debug_mode; bool datamodel_mode; + bool translate_mode; }; struct templateFileDataStr{ @@ -103,6 +104,10 @@ struct savedCodeStr{ std::string interfaceCMake; std::string packageCMake; std::string interfaceXML; + std::string topicSubscriptionC; + std::string topicCallbackC; + std::string topicSubscriptionH; + std::string topicCallbackH; }; struct cppCodeStr diff --git a/code/src/Replacer.cpp b/code/src/Replacer.cpp index 0f34ce7..fd93317 100644 --- a/code/src/Replacer.cpp +++ b/code/src/Replacer.cpp @@ -243,6 +243,51 @@ void handleGenericEvent(const eventDataStr eventData, const savedCodeStr savedCo } } + else if(eventData.eventType == "transition") + { + if(eventData.interfaceType == "topic") + { + std::string topicCallbackC = savedCode.topicCallbackC; + std::string topicCallbackH = savedCode.topicCallbackH; + std::string topicSubscriptionC = savedCode.topicSubscriptionC; + std::string topicSubscriptionH = savedCode.topicSubscriptionH; + std::string interfaceCodeH = savedCode.interfaceH; + std::string interfaceCodeCMake = savedCode.interfaceCMake; + std::string packageCodeCMake = savedCode.packageCMake; + std::string interfaceCodeXML = savedCode.interfaceXML; + //CPP + replaceAll(topicCallbackC, "$eventData.interfaceName$", eventData.interfaceName); + replaceAll(topicSubscriptionC, "$eventData.interfaceName$", eventData.interfaceName); + replaceAll(topicCallbackC, "$eventData.functionName$", eventData.functionName); + replaceAll(topicSubscriptionC, "$eventData.functionName$", eventData.functionName); + replaceAll(topicCallbackC, "$eventData.componentName$", eventData.componentName); + writeAfterCommand(str, "/*TOPIC_SUBSCRIPTIONS_LIST*/", topicSubscriptionC); + writeAfterCommand(str, "/*TOPIC_CALLBACK_LIST*/", topicCallbackC); + //H + replaceAll(topicCallbackH, "$eventData.interfaceName$", eventData.interfaceName); + replaceAll(topicSubscriptionH, "$eventData.interfaceName$", eventData.interfaceName); + replaceAll(topicCallbackH, "$eventData.functionName$", eventData.functionName); + replaceAll(topicSubscriptionH, "$eventData.functionName$", eventData.functionName); + writeAfterCommand(str, "/*TOPIC_SUBSCRIPTIONS_LIST_H*/", topicSubscriptionH); + writeAfterCommand(str, "/*TOPIC_CALLBACK_LIST_H*/", topicCallbackH); + + //CMakeLists.txt + replaceAll(interfaceCodeCMake, "$interfaceName$", eventData.interfaceName); + if(!checkIfStrPresent(str, interfaceCodeCMake)){ + writeAfterCommand(str, "#INTERFACE_LIST#", interfaceCodeCMake); + } + replaceAll(packageCodeCMake, "$interfaceName$", eventData.interfaceName); + if(!checkIfStrPresent(str, packageCodeCMake)){ + writeAfterCommand(str, "#PACKAGE_LIST#", packageCodeCMake); + } + + //package.xml + replaceAll(interfaceCodeXML, "$interfaceName$", eventData.interfaceName); + if(!checkIfStrPresent(str, interfaceCodeXML)){ + writeAfterCommand(str, "", interfaceCodeXML); + } + } + } } @@ -261,9 +306,17 @@ void saveCode(savedCodeStr& savedCode, std::string& code) deleteSection(code, "/*RETURN_PARAM*/", "/*END_RETURN_PARAM*/"); saveSection(code, "/*SEND_EVENT_SRV*/", "/*END_SEND_EVENT_SRV*/", savedCode.eventC); deleteSection(code, "/*SEND_EVENT_SRV*/", "/*END_SEND_EVENT_SRV*/"); + saveSection(code, "/*TOPIC_CALLBACK*/", "/*END_TOPIC_CALLBACK*/", savedCode.topicCallbackC); + deleteSection(code, "/*TOPIC_CALLBACK*/", "/*END_TOPIC_CALLBACK*/"); + saveSection(code, "/*TOPIC_SUBSCRIPTION*/", "/*END_TOPIC_SUBSCRIPTION*/", savedCode.topicSubscriptionC); + deleteSection(code, "/*TOPIC_SUBSCRIPTION*/", "/*END_TOPIC_SUBSCRIPTION*/"); //H saveSection(code, "/*INTERFACE*/", "/*END_INTERFACE*/", savedCode.interfaceH); deleteSection(code, "/*INTERFACE*/", "/*END_INTERFACE*/"); + saveSection(code, "/*TOPIC_CALLBACK_H*/", "/*END_TOPIC_CALLBACK_H*/", savedCode.topicCallbackH); + deleteSection(code, "/*TOPIC_CALLBACK_H*/", "/*END_TOPIC_CALLBACK_H*/"); + saveSection(code, "/*TOPIC_SUBSCRIPTION_H*/", "/*END_TOPIC_SUBSCRIPTION_H*/", savedCode.topicSubscriptionH); + deleteSection(code, "/*TOPIC_SUBSCRIPTION_H*/", "/*END_TOPIC_SUBSCRIPTION_H*/"); //CMakeLists.txt saveSection(code, "#INTERFACE#", "#END_INTERFACE#", savedCode.interfaceCMake); deleteSection(code, "#INTERFACE#", "#END_INTERFACE#"); @@ -291,6 +344,10 @@ void replaceEventCode(std::map & codeMap){ { if(itEv->first != cmdTick && itEv->first != cmdHalt && itEv->first != rspTick && itEv->first != rspHalt){ eventDataStr eventData = itEv->second; + if(eventData.interfaceName == "blackboard_interfaces") + { + eventData.functionNameSnakeCase += "_blackboard"; + } handleGenericEvent(eventData, savedCode, it->second); } } @@ -298,8 +355,12 @@ void replaceEventCode(std::map & codeMap){ deleteCommand(it->second, "/*SEND_EVENT_LIST*/"); deleteCommand(it->second, "/*PARAM_LIST*/"); deleteCommand(it->second, "/*RETURN_PARAM_LIST*/"); + deleteCommand(it->second, "/*TOPIC_SUBSCRIPTIONS_LIST*/"); + deleteCommand(it->second, "/*TOPIC_CALLBACK_LIST*/"); //H deleteCommand(it->second, "/*INTERFACES_LIST*/"); + deleteCommand(it->second, "/*TOPIC_SUBSCRIPTIONS_LIST_H*/"); + deleteCommand(it->second, "/*TOPIC_CALLBACK_LIST_H*/"); //CMakeLists.txt deleteCommand(it->second, "#INTERFACE_LIST#"); deleteCommand(it->second, "#PACKAGE_LIST#"); diff --git a/templates/skills/template_skill/include/TemplateSkill.h b/templates/skills/template_skill/include/TemplateSkill.h index d6e4ad8..1b756d3 100644 --- a/templates/skills/template_skill/include/TemplateSkill.h +++ b/templates/skills/template_skill/include/TemplateSkill.h @@ -34,6 +34,8 @@ class $className$ /*HALT_CMD*/ void halt( [[maybe_unused]] const std::shared_ptr request, [[maybe_unused]] std::shared_ptr response);/*END_HALT_CMD*/ + /*TOPIC_CALLBACK_LIST_H*/ + /*TOPIC_CALLBACK_H*/void topic_callback_$eventData.functionName$(const $eventData.interfaceName$::SharedPtr msg);/*END_TOPIC_CALLBACK_H*/ private: std::shared_ptr m_threadSpin; @@ -42,9 +44,11 @@ class $className$ std::string m_name; $SMName$ m_stateMachine; /*TICK_RESPONSE*/std::atomic m_tickResult{Status::undefined};/*END_TICK_RESPONSE*/ - /*TICK_CMD*/rclcpp::Service::SharedPtr m_tickService;/*END_TICK_CMD*/ + /*TICK_CMD*/rclcpp::Service::SharedPtr m_tickService;/*END_TICK_CMD*/ /*HALT_RESPONSE*/std::atomic m_haltResult{false};/*END_HALT_RESPONSE*/ /*HALT_CMD*/rclcpp::Service::SharedPtr m_haltService;/*END_HALT_CMD*/ /*DATAMODEL*/$skillName$SkillDataModel m_dataModel; /*END_DATAMODEL*/ + /*TOPIC_SUBSCRIPTIONS_LIST_H*/ + /*TOPIC_SUBSCRIPTION_H*/rclcpp::Subscription<$eventData.interfaceName$>::SharedPtr m_subscription_$eventData.functionName$;/*END_TOPIC_SUBSCRIPTION_H*/ }; diff --git a/templates/skills/template_skill/package.xml b/templates/skills/template_skill/package.xml index 1e52113..fc0ccfe 100644 --- a/templates/skills/template_skill/package.xml +++ b/templates/skills/template_skill/package.xml @@ -4,7 +4,7 @@ $projectName$ 0.0.0 Package description - + License declaration ament_cmake diff --git a/templates/skills/template_skill/src/TemplateSkill.cpp b/templates/skills/template_skill/src/TemplateSkill.cpp index a9149a2..6d3e958 100644 --- a/templates/skills/template_skill/src/TemplateSkill.cpp +++ b/templates/skills/template_skill/src/TemplateSkill.cpp @@ -69,6 +69,12 @@ bool $className$::start(int argc, char*argv[]) this, std::placeholders::_1, std::placeholders::_2));/*END_HALT*/ + + /*TOPIC_SUBSCRIPTIONS_LIST*//*TOPIC_SUBSCRIPTION*/ + m_subscription_$eventData.functionName$ = m_node->create_subscription<$eventData.interfaceName$>( + "$eventData.functionName$", 10, std::bind(&$className$::topic_callback_$eventData.functionName$, this, std::placeholders::_1)); + /*END_TOPIC_SUBSCRIPTION*/ + /*SEND_EVENT_LIST*//*SEND_EVENT_SRV*/ m_stateMachine.connectToEvent("$eventData.event$", [this]([[maybe_unused]]const QScxmlEvent & event){ std::shared_ptr $eventData.nodeName$ = rclcpp::Node::make_shared(m_name + "SkillNode$eventData.functionName$"); @@ -187,4 +193,19 @@ void $className$::halt( [[maybe_unused]] const std::shared_ptrget_logger(), "$className$::haltDone"); response->is_ok = true; } -/*END_HALT_CMD*/ \ No newline at end of file +/*END_HALT_CMD*/ + + +/*TOPIC_CALLBACK_LIST*//*TOPIC_CALLBACK*/ +void $className$::topic_callback_$eventData.functionName$(const $eventData.interfaceName$::SharedPtr msg) { + std::cout << "callback" << std::endl; + QVariantMap data; + m_statusMutex.lock(); + m_status = msg->data; + data.insert("status", m_status); + + m_stateMachine.submitEvent("$eventData.componentName$.$eventData.functionName$.Sub", data); + m_statusMutex.unlock(); + RCLCPP_INFO(m_node->get_logger(), "$eventData.componentName$.$eventData.functionName$.Sub"); +} +/*END_TOPIC_CALLBACK*/ \ No newline at end of file From 75738f1cf9f405ad53facc81b5850509db27b818 Mon Sep 17 00:00:00 2001 From: SofiaFaraci Date: Thu, 19 Sep 2024 17:44:28 +0200 Subject: [PATCH 02/16] add translator from HL-XML to compilable-XML Signed-off-by: SofiaFaraci --- code/CMakeLists.txt | 1 + code/include/Translator.h | 44 +++ code/src/Translator.cpp | 621 ++++++++++++++++++++++++++++++++++++++ code/src/main.cpp | 25 +- 4 files changed, 688 insertions(+), 3 deletions(-) create mode 100644 code/include/Translator.h create mode 100644 code/src/Translator.cpp diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index ee13360..0503605 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -27,6 +27,7 @@ target_sources( ${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src/Data.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/strManipulation.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Replacer.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/Translator.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/ExtractFromXML.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/ExtractFromElement.cpp ) diff --git a/code/include/Translator.h b/code/include/Translator.h new file mode 100644 index 0000000..de8d048 --- /dev/null +++ b/code/include/Translator.h @@ -0,0 +1,44 @@ +// SPDX-FileCopyrightText: 2024 Humanoid Sensing and Perception, Istituto Italiano di Tecnologia +// SPDX-License-Identifier: APACHE-2.0 + +/** + * @file Translator.h + * @brief This file contains the functions to translate the High-Level CONVINCE XML to the compilable SCXML used for code generation. + * @version 0.1 + * @date 2024-09-18 + * + */ +#include "Replacer.h" +#include + +/** + * @brief Deletes a specific attribute of a given XML element + * + * @param element element from which to delete the attribute + * @param attribute attribute name to be deleted + * @return bool + */ +bool deleteElementAttribute(tinyxml2::XMLElement* element, const std::string& attribute); + +/** + * @brief Deletes a specific attribute from all elements in a vector + * + * @param elements vector of elements from which to delete the attribute + * @param attribute attribute name to be deleted + * @return bool Returns true if at least one attribute was successfully deleted, false otherwise + */ +bool deleteElementAttributeFromVector(std::vector& elements, const std::string& attribute); + +/** + * @brief + * + * @param + */ +bool readHLXMLFile(tinyxml2::XMLDocument& doc, const std::string fileName); + +/** + * @brief + * + * @param + */ +bool Translator(fileDataStr& fileData); \ No newline at end of file diff --git a/code/src/Translator.cpp b/code/src/Translator.cpp new file mode 100644 index 0000000..fd3d0ea --- /dev/null +++ b/code/src/Translator.cpp @@ -0,0 +1,621 @@ +// SPDX-FileCopyrightText: 2024 Humanoid Sensing and Perception, Istituto Italiano di Tecnologia +// SPDX-License-Identifier: APACHE-2.0 + +/** + * @file Translator.cpp + * @brief This file contains the functions to translate the High-Level CONVINCE XML to the compilable SCXML used for code generation. + * @version 0.1 + * @date 2024-09-18 + * + */ +#include "Translator.h" + +/** + * @brief Deletes a specific attribute of a given XML element + * + * @param element element from which to delete the attribute + * @param attribute attribute name to be deleted + * @return bool + */ +bool deleteElementAttribute(tinyxml2::XMLElement* element, const std::string& attribute) +{ + if (element->Attribute(attribute.c_str())) { + + element->DeleteAttribute(attribute.c_str()); + return true; + } else { + std::cerr << "Attribute '" << attribute << "' of element '" << element->Value() << "' not found." << std::endl; + return false; + } +} + +/** + * @brief Deletes a specific attribute from all elements in a vector + * + * @param elements vector of elements from which to delete the attribute + * @param attribute attribute name to be deleted + * @return bool Returns true if at least one attribute was successfully deleted, false otherwise + */ +bool deleteElementAttributeFromVector(std::vector& elements, const std::string& attribute) +{ + bool deleted = false; + + for (auto& element : elements) { + deleted = deleteElementAttribute(element, attribute); + } + + return deleted; +} + +/** + * @brief Deletes the given XML element from its parent + * + * @param element the XML element to be deleted + * @return bool Returns true if the element was successfully deleted, false otherwise + */ +bool deleteElement(tinyxml2::XMLElement* element) +{ + if (!element) { + std::cerr << "Invalid element." << std::endl; + return false; + } + + tinyxml2::XMLNode* parent = element->Parent(); + if (!parent) { + std::cerr << "Element has no parent." << std::endl; + return false; + } + + // Remove the element from its parent + parent->DeleteChild(element); + + return true; +} + +/** + * @brief Deletes all elements in a vector + * + * @param elements vector of elements to delete + * @return bool Returns true if at least one element was successfully deleted, false otherwise + */ +bool deleteElementFromVector(std::vector& elements) +{ + // Check if the vector itself is empty + if (elements.empty()) { + std::cerr << "The vector is empty." << std::endl; + return false; + } + + bool deletedAny = false; + + for (auto& element : elements) { + if (element) { // Check if the element pointer is valid + if (deleteElement(element)) { + deletedAny = true; + } + } else { + std::cerr << "Encountered a null element pointer in the vector." << std::endl; + } + } + + return deletedAny; +} + + + +/** + * @brief Replaces the tag name of a given XML element + * + * @param doc XMLDocument to which the element belongs + * @param element the element whose tag name needs to be changed + * @param newTagName the new tag name + * @return bool Returns true if the tag name was successfully changed + */ +bool replaceTagName(tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& newTagName) +{ + if (!element || !doc) { + std::cerr << "Invalid document or element." << std::endl; + return false; + } + + // Create a new element with the new tag name + tinyxml2::XMLElement* newElement = doc->NewElement(newTagName.c_str()); + + // Copy attributes from the old element to the new element + for (const tinyxml2::XMLAttribute* attr = element->FirstAttribute(); attr; attr = attr->Next()) { + newElement->SetAttribute(attr->Name(), attr->Value()); + } + + // Copy the text content of the old element to the new element + if (element->GetText()) { + newElement->SetText(element->GetText()); + } + + // Move child elements from the old element to the new element + for (tinyxml2::XMLElement* child = element->FirstChildElement(); child; ) { + tinyxml2::XMLElement* next = child->NextSiblingElement(); + newElement->InsertEndChild(child); + child = next; + } + + // Replace the old element with the new element in the document + element->Parent()->InsertAfterChild(element, newElement); + element->Parent()->DeleteChild(element); + + return true; +} + + +/** + * @brief Replaces an attribute name of a given XML element + * + * @param element the element whose attribute name needs to be changed + * @param oldAttributeName the current attribute name to be replaced + * @param newAttributeName the new attribute name + * @return bool Returns true if the attribute name was successfully changed + */ +bool replaceAttributeName(tinyxml2::XMLElement* element, const std::string& oldAttributeName, const std::string& newAttributeName) +{ + if (!element) { + std::cerr << "Invalid element." << std::endl; + return false; + } + + // Get the value of the old attribute + const char* attributeValue = element->Attribute(oldAttributeName.c_str()); + if (!attributeValue) { + std::cerr << "Attribute '" << oldAttributeName << "' not found in element '" << element->Value() << "'" << std::endl; + return false; + } + + // Remove the old attribute + element->DeleteAttribute(oldAttributeName.c_str()); + + // Set the new attribute with the same value + element->SetAttribute(newAttributeName.c_str(), attributeValue); + + return true; +} + + +/** + * @brief Replaces the value of a given attribute in an XML element + * + * @param element the element whose attribute value needs to be changed + * @param attributeName the name of the attribute to be updated + * @param newValue the new value to set for the attribute + * @return bool Returns true if the attribute value was successfully changed, false if the attribute doesn't exist + */ +bool replaceAttributeValue(tinyxml2::XMLElement* element, const std::string& attributeName, const std::string& newValue) +{ + if (!element) { + std::cerr << "Invalid element." << std::endl; + return false; + } + + // Check if the attribute exists + const char* attributeValue = element->Attribute(attributeName.c_str()); + if (!attributeValue) { + std::cerr << "Attribute '" << attributeName << "' not found in element '" << element->Value() << "'" << std::endl; + return false; + } + + // Set the new value for the attribute + element->SetAttribute(attributeName.c_str(), newValue.c_str()); + + return true; +} + + +/** + * @brief Replaces the tag name of all elements in a vector + * + * @param doc XMLDocument to which the elements belong + * @param elements vector of elements whose tag names need to be replaced + * @param newTagName the new tag name to set + * @return bool Returns true if at least one tag name was successfully changed, false otherwise + */ +bool replaceTagNameFromVector(tinyxml2::XMLDocument* doc, std::vector& elements, const std::string& newTagName) +{ + bool replacedAny = false; + + for (auto& element : elements) { + if (element) { + if (replaceTagName(doc, element, newTagName)) { + replacedAny = true; + } + } else { + std::cerr << "Encountered a null element pointer in the vector." << std::endl; + } + } + + return replacedAny; +} + +/** + * @brief Replaces an attribute name in all elements in a vector + * + * @param elements vector of elements in which to replace the attribute name + * @param oldAttributeName the current attribute name to be replaced + * @param newAttributeName the new attribute name + * @return bool Returns true if at least one attribute name was successfully replaced, false otherwise + */ +bool replaceAttributeNameFromVector(std::vector& elements, const std::string& oldAttributeName, const std::string& newAttributeName) +{ + bool replacedAny = false; + + for (auto& element : elements) { + if (element) { + if (replaceAttributeName(element, oldAttributeName, newAttributeName)) { + replacedAny = true; + } + } else { + std::cerr << "Encountered a null element pointer in the vector." << std::endl; + } + } + + return replacedAny; +} + +/** + * @brief Replaces the value of a given attribute in all elements in a vector + * + * @param elements vector of elements in which to replace the attribute value + * @param attributeName the name of the attribute to be updated + * @param newValue the new value to set for the attribute + * @return bool Returns true if at least one attribute value was successfully replaced, false otherwise + */ +bool replaceAttributeValueFromVector(std::vector& elements, const std::string& attributeName, const std::string& newValue) +{ + bool replacedAny = false; + + for (auto& element : elements) { + if (element) { + if (replaceAttributeValue(element, attributeName, newValue)) { + replacedAny = true; + } + } else { + std::cerr << "Encountered a null element pointer in the vector." << std::endl; + } + } + + return replacedAny; +} + + +/** + * @brief Replaces the value of a given attribute in all elements in a vector if the current value contains a specific substring + * + * @param elements vector of elements in which to replace the attribute value + * @param attributeName the name of the attribute to be updated + * @param oldSubstring the substring to look for within the attribute value + * @param newValue the new value to set for the attribute if the substring is found + * @return bool Returns true if at least one attribute value was successfully replaced, false otherwise + */ +bool replaceAttributeValueContaingFromVector(std::vector& elements, const std::string& attributeName, const std::string& oldSubstring, const std::string& newValue) +{ + bool replacedAny = false; + for (auto& element : elements) { + if (element) { + const char* attributeValue = element->Attribute(attributeName.c_str()); + if (attributeValue) { + std::string attributeStr(attributeValue); + if (attributeStr.find(oldSubstring) != std::string::npos) { + if (replaceAttributeValue(element, attributeName, newValue)) { + replacedAny = true; + } + } + } else { + std::cerr << "Attribute '" << attributeName << "' not found in element." << std::endl; + } + } else { + std::cerr << "Encountered a null element pointer in the vector." << std::endl; + } + } + + return replacedAny; +} + +/** + * @brief Replaces a substring within the value of a given attribute in all elements in a vector if the current value contains a specific substring + * + * @param elements vector of elements in which to replace the attribute value + * @param attributeName the name of the attribute to be updated + * @param oldSubstring the substring to look for within the attribute value + * @param newSubstring the new substring to replace the old substring with + * @return bool Returns true if at least one attribute value was successfully updated, false otherwise + */ +bool replaceAttributeValueSubstringFromVector(std::vector& elements, const std::string& attributeName, const std::string& oldSubstring, const std::string& newSubstring) +{ + bool replacedAny = false; + + for (auto& element : elements) { + if (element) { + const char* attributeValue = element->Attribute(attributeName.c_str()); + if (attributeValue) { + std::string attributeStr(attributeValue); + // Check if the attribute value contains the substring + size_t pos = attributeStr.find(oldSubstring); + if (pos != std::string::npos) { + // Replace the old substring with the new substring + attributeStr.replace(pos, oldSubstring.length(), newSubstring); + // Set the updated value for the attribute + element->SetAttribute(attributeName.c_str(), attributeStr.c_str()); + replacedAny = true; + } + } else { + std::cerr << "Attribute '" << attributeName << "' not found in element." << std::endl; + } + } else { + std::cerr << "Encountered a null element pointer in the vector." << std::endl; + } + } + + return replacedAny; +} + + + +/** + * @brief Appends a substring to the end of the value of a given attribute in all elements in a vector + * + * @param elements vector of elements in which to append the attribute value + * @param attributeName the name of the attribute to be updated + * @param valueToAppend the substring to append to the attribute value + * @return bool Returns true if at least one attribute value was successfully updated, false otherwise + */ +bool appendAttributeValueFromVector(std::vector& elements, const std::string& attributeName, const std::string& valueToAppend) +{ + bool updatedAny = false; + + for (auto& element : elements) { + if (element) { + // Get the current attribute value + const char* attributeValue = element->Attribute(attributeName.c_str()); + if (attributeValue) { + std::string attributeStr(attributeValue); + // Append the new value to the end of the current value + attributeStr.append(valueToAppend); + // Set the updated value for the attribute + element->SetAttribute(attributeName.c_str(), attributeStr.c_str()); + updatedAny = true; + } else { + std::cerr << "Attribute '" << attributeName << "' not found in element." << std::endl; + } + } else { + std::cerr << "Encountered a null element pointer in the vector." << std::endl; + } + } + + return updatedAny; +} + +/** + * @brief Find a XML element by tag and attribute name where the attribute's value contains a specific substring + * + * @param root root element from which to start the search + * @param tag tag name to look for + * @param attributeName attribute name to look for inside the tag + * @param substring substring to check for in the attribute value + * @param element element found returned by reference + * @return true if an element with the tag and attribute containing the substring is found + * @return false otherwise + */ +bool findElementByTagAndAttValueContaining(tinyxml2::XMLElement* root, const std::string& tag, const std::string& attributeName, const std::string& substring, tinyxml2::XMLElement*& element) +{ + for (tinyxml2::XMLElement* child = root->FirstChildElement(); child; child = child->NextSiblingElement()) { + if (strcmp(child->Value(), tag.c_str()) == 0) { + const char* attributeValue = child->Attribute(attributeName.c_str()); + if (attributeValue && std::string(attributeValue).find(substring) != std::string::npos) { + element = child; + return true; + } + } + if (findElementByTagAndAttValueContaining(child, tag, attributeName, substring, element)) { + return true; + } + } + return false; +} + +/** + * @brief replaces the value of the event attribute in all elements in a vector + * + * @param elements vector of elements in which to replace the event value + */ +void replaceEventValueFromVector(std::vector& elements) +{ + std::string eventName; + for (auto& element : elements) + { + getElementAttValue(element, "event", eventName); + std::string temp = eventName; + size_t pos = 0; + if (temp == ""){ + std::cerr << "Input DataType has no value" << std::endl; + } + else{ + if((pos = temp.find("/", pos)) != std::string::npos) + { + temp.replace(pos, 1, ""); + pos += 1; + } + if((pos = temp.find("/", pos)) != std::string::npos) + { + temp.replace(pos, 1, "."); + pos += 1; + } + } + replaceAttributeValue(element, "event", temp); + } +} + + +/** + * @brief Get the data From SCXML Root Name object (Format: NameSkillType) + * + * @param attributeName root attribute name from which the skill data is extracted + * @param skillData skill data structure passed by reference where the skill data is stored + * @return bool + */ +bool getDataFromRootNameHighLevel(const std::string attributeName, skillDataStr& skillData) +{ + // e.g. attributeName = "FirstTemplateSkill" + if (attributeName != ""){ + std::cout << "Root attribute name: " << attributeName << std::endl; + size_t dotPos = attributeName.find("Skill"); + if (dotPos != std::string::npos){ + skillData.SMName = attributeName; // e.g. SMName = "FirstTemplateSkill" +"Action" added later + skillData.skillName = attributeName.substr(0, dotPos); // e.g. skillName = "FirstTemplate" + skillData.className = attributeName.substr(0, dotPos + 5); // e.g. className = "FirstTemplateSkill" + turnToSnakeCase(skillData.className, skillData.classNameSnakeCase); + } + else{ + std::cerr << "Skill name not found" << std::endl; + return false; + } + } + else{ + std::cerr << "Attribute 'name' not found or has no value" << std::endl; + return false; + } + return true; +} + +/** + * @brief + * + * @param + */ +bool readHLXMLFile(tinyxml2::XMLDocument& doc, std::string& fileContent, const std::string fileName){ + std::cout << "readFile" << std::endl; + if (doc.LoadFile(fileName.c_str()) != tinyxml2::XML_SUCCESS) { + std::cerr << "Failed to load '" << fileName << "' file" << std::endl; + return false; + } + if(!readTemplateFile(fileName, fileContent)){ + std::cerr << "Failed to read '" << fileName << "' file" << std::endl; + return false; + } + return true; +} + +/** + * @brief + * + * @param fileData + */ +bool Translator(fileDataStr& fileData){ + std::cout << "-----------" << std::endl; + std::cout << "Translator" << std::endl; + skillDataStr skillData; + tinyxml2::XMLDocument doc; + std::string fileContent; + if( !readHLXMLFile(doc, fileContent, fileData.inputFileName)){ + return false; + } + + // Get Root and SkillData + tinyxml2::XMLElement* root = doc.RootElement(); + if (!root) { + std::cerr << "No root element found" << std::endl; + return false; + } + getDataFromRootNameHighLevel(root->Attribute("name"), skillData); + // Delete server and topic declarations + std::vector serverVector; + + findElementVectorByTag(root, std::string("ros_service_server"), serverVector); + findElementVectorByTag(root, std::string("ros_topic_subscriber"), serverVector); + findElementVectorByTag(root, std::string("ros_service_client"), serverVector); + findElementVectorByTag(root, std::string("ros_topic_publisher"), serverVector); + findElementVectorByTag(root, std::string("ros_action_client"), serverVector); + deleteElementFromVector(serverVector); + + // Get Skill Type + tinyxml2::XMLElement* haltServerElement; + if(findElementByTagAndAttValueContaining(root, std::string("ros_service_server"), std::string("service"), std::string("halt"), haltServerElement)) + { + std::cout << "Halt found => Action Skill" << std::endl; + skillData.skillType = "Action"; + } else { + std::cout << "Halt not found => Condition Skill" << std::endl; + skillData.skillType = "Condition"; + } + skillData.SMName = skillData.SMName + skillData.skillType; + skillData.skillTypeLC = skillData.skillType; + for (char &c : skillData.skillTypeLC) + { + c = std::tolower(c); // e.g. skillType = "action" + } + if(!replaceAttributeValue(root, "name", skillData.SMName)) + { + std::cout << "Could not replace name attribute for root element" << std::endl; + return false; + } + + // add xmln + replaceAttributeValue(root, "xmlns", "http://www.w3.org/2005/07/scxml"); + + // Delete attribute type from data elements + std::vector dataVector; + findElementVectorByTag(root, std::string("data"), dataVector); + deleteElementAttributeFromVector(dataVector, "type"); + + // Translate elements with tag ros_service_handle_request + std::vector srvHndlReqVector; + findElementVectorByTag(root, std::string("ros_service_handle_request"), srvHndlReqVector); + replaceAttributeNameFromVector(srvHndlReqVector, "id", "event"); + replaceAttributeNameFromVector(srvHndlReqVector, "service", "event"); + replaceAttributeValueContaingFromVector(srvHndlReqVector, "event", "tick", "CMD_TICK"); + replaceAttributeValueContaingFromVector(srvHndlReqVector, "event", "halt", "CMD_HALT"); + replaceTagNameFromVector(&doc, srvHndlReqVector, "transition"); + + // Translate elements with tag ros_service_send_request + std::vector srvSendReqVector; + findElementVectorByTag(root, std::string("ros_service_send_request"), srvSendReqVector); + replaceAttributeNameFromVector(srvSendReqVector, "id", "event"); + replaceEventValueFromVector(srvSendReqVector); + appendAttributeValueFromVector(srvSendReqVector, "event", ".Call"); + replaceTagNameFromVector(&doc, srvSendReqVector, "send"); + + // Translate elements with tag ros_service_handle_response + std::vector srvHndlRspVector; + findElementVectorByTag(root, std::string("ros_service_handle_response"), srvHndlRspVector); + replaceAttributeNameFromVector(srvHndlRspVector, "service", "event"); + // replaceAttributeValueFromVector(srvHndlRspVector, "event", ""); get value e modificare le / con . + replaceAttributeValueSubstringFromVector(srvHndlRspVector, "cond", "_service.response.", "_event.data."); + replaceEventValueFromVector(srvHndlRspVector); + appendAttributeValueFromVector(srvHndlRspVector, "event", ".Return"); + replaceTagNameFromVector(&doc, srvHndlRspVector, "transition"); + + // Translate elements with tag ros_service_send_response + std::vector srvSendRspVector; + findElementVectorByTag(root, std::string("ros_service_send_response"), srvSendRspVector); + replaceAttributeNameFromVector(srvSendRspVector, "id", "event"); + replaceAttributeNameFromVector(srvSendRspVector, "service", "event"); + replaceAttributeValueContaingFromVector(srvSendRspVector, "event", "tick", "TICK_RESPONSE"); + replaceAttributeValueContaingFromVector(srvSendRspVector, "event", "tick", "HALT_RESPONSE"); + replaceTagNameFromVector(&doc, srvSendRspVector, "send"); + + // Translate elements with tag ros_topic_callback + std::vector topicCallbackVector; + findElementVectorByTag(root, std::string("ros_topic_callback"), topicCallbackVector); + replaceAttributeNameFromVector(topicCallbackVector, "topic", "event"); + replaceEventValueFromVector(topicCallbackVector); + appendAttributeValueFromVector(topicCallbackVector, "event", ".Sub"); + replaceTagNameFromVector(&doc, topicCallbackVector, "transition"); + + std::vector assignVector; + findElementVectorByTag(root, std::string("assign"), assignVector); + replaceAttributeValueSubstringFromVector(assignVector, "expr", "_msg.", "_event."); + + // doc.Print(); + std::string ouputFilePath = fileData.outputPathSrc + skillData.className + "SM.scxml"; + tinyxml2::XMLPrinter printer; + doc.Print(&printer); // Print the XML document into the printer + std::string outputContent = std::string(printer.CStr()); + writeFile(ouputFilePath, outputContent); + + return true; +} \ No newline at end of file diff --git a/code/src/main.cpp b/code/src/main.cpp index 4ed2b8f..136fc58 100644 --- a/code/src/main.cpp +++ b/code/src/main.cpp @@ -9,7 +9,8 @@ * */ -#include "Replacer.h" +// #include "Replacer.h" +#include "Translator.h" /** * @brief Print the help message @@ -43,6 +44,7 @@ bool handleInputs(int argc, char* argv[], fileDataStr& fileData, templateFileDat fileData.modelFileName = modelFilePath; fileData.interfaceFileName = interfaceFilePath; fileData.datamodel_mode = false; + fileData.translate_mode = false; templateFileData.templatePath = templateFilePath; if (argc == 1) @@ -81,6 +83,9 @@ bool handleInputs(int argc, char* argv[], fileDataStr& fileData, templateFileDat else if (arg == "--datamodel_mode") { fileData.datamodel_mode = true; } + else if (arg == "--translate_mode") { + fileData.translate_mode = true; + } } if(fileData.inputFileName == "") @@ -131,10 +136,24 @@ int main(int argc, char* argv[]) return RETURN_CODE_ERROR; } - if(!Replacer(fileData, templateFileData)) + if(fileData.translate_mode) + { + std::cout << "Translation request" << std::endl; + if(!Translator(fileData)) + { + std::cout << "Error in translation" << std::endl; + } + + } + else { - std::cout << "Error in code generation" << std::endl; + std::cout << "No translation request" << std::endl; + if(!Replacer(fileData, templateFileData)) + { + std::cout << "Error in code generation" << std::endl; + } } + return RETURN_CODE_OK; }; \ No newline at end of file From 33778942e874fb3546a9aff3b7933246dad52134 Mon Sep 17 00:00:00 2001 From: SofiaFaraci Date: Fri, 20 Sep 2024 11:56:46 +0200 Subject: [PATCH 03/16] topic interface fix Signed-off-by: SofiaFaraci --- code/include/Data.h | 3 +- code/src/Replacer.cpp | 18 +++++--- code/src/Translator.cpp | 45 +++++++++++++++++++ .../template_skill/include/TemplateSkill.h | 8 +++- .../template_skill/src/TemplateSkill.cpp | 11 ++--- 5 files changed, 70 insertions(+), 15 deletions(-) diff --git a/code/include/Data.h b/code/include/Data.h index 446f5e6..0553479 100644 --- a/code/include/Data.h +++ b/code/include/Data.h @@ -107,7 +107,8 @@ struct savedCodeStr{ std::string topicSubscriptionC; std::string topicCallbackC; std::string topicSubscriptionH; - std::string topicCallbackH; + std::string topicCallbackH; + std::string topicInterfaceH; }; struct cppCodeStr diff --git a/code/src/Replacer.cpp b/code/src/Replacer.cpp index fd93317..7599e7f 100644 --- a/code/src/Replacer.cpp +++ b/code/src/Replacer.cpp @@ -251,23 +251,29 @@ void handleGenericEvent(const eventDataStr eventData, const savedCodeStr savedCo std::string topicCallbackH = savedCode.topicCallbackH; std::string topicSubscriptionC = savedCode.topicSubscriptionC; std::string topicSubscriptionH = savedCode.topicSubscriptionH; + std::string topicInterfaceH = savedCode.topicInterfaceH; std::string interfaceCodeH = savedCode.interfaceH; std::string interfaceCodeCMake = savedCode.interfaceCMake; std::string packageCodeCMake = savedCode.packageCMake; std::string interfaceCodeXML = savedCode.interfaceXML; //CPP - replaceAll(topicCallbackC, "$eventData.interfaceName$", eventData.interfaceName); - replaceAll(topicSubscriptionC, "$eventData.interfaceName$", eventData.interfaceName); + replaceAll(topicCallbackC, "$eventData.interfaceData[interfaceDataType]$", eventData.interfaceData.begin()->second); + replaceAll(topicCallbackC, "$eventData.interfaceData[interfaceDataField]$", eventData.interfaceData.begin()->first); + replaceAll(topicSubscriptionC, "$eventData.interfaceData[interfaceDataType]$", eventData.interfaceData.begin()->second); replaceAll(topicCallbackC, "$eventData.functionName$", eventData.functionName); replaceAll(topicSubscriptionC, "$eventData.functionName$", eventData.functionName); replaceAll(topicCallbackC, "$eventData.componentName$", eventData.componentName); writeAfterCommand(str, "/*TOPIC_SUBSCRIPTIONS_LIST*/", topicSubscriptionC); writeAfterCommand(str, "/*TOPIC_CALLBACK_LIST*/", topicCallbackC); //H - replaceAll(topicCallbackH, "$eventData.interfaceName$", eventData.interfaceName); - replaceAll(topicSubscriptionH, "$eventData.interfaceName$", eventData.interfaceName); + std::string interface; + getDataTypePath(eventData.interfaceData.begin()->second, interface); + replaceAll(topicInterfaceH, "$eventData.interfaceData[interfaceDataType]$", interface); + replaceAll(topicCallbackH, "$eventData.interfaceData[interfaceDataType]$", eventData.interfaceData.begin()->second); + replaceAll(topicSubscriptionH, "$eventData.interfaceData[interfaceDataType]$", eventData.interfaceData.begin()->second); replaceAll(topicCallbackH, "$eventData.functionName$", eventData.functionName); replaceAll(topicSubscriptionH, "$eventData.functionName$", eventData.functionName); + writeAfterCommand(str, "/*INTERFACES_LIST*/", topicInterfaceH); writeAfterCommand(str, "/*TOPIC_SUBSCRIPTIONS_LIST_H*/", topicSubscriptionH); writeAfterCommand(str, "/*TOPIC_CALLBACK_LIST_H*/", topicCallbackH); @@ -311,8 +317,10 @@ void saveCode(savedCodeStr& savedCode, std::string& code) saveSection(code, "/*TOPIC_SUBSCRIPTION*/", "/*END_TOPIC_SUBSCRIPTION*/", savedCode.topicSubscriptionC); deleteSection(code, "/*TOPIC_SUBSCRIPTION*/", "/*END_TOPIC_SUBSCRIPTION*/"); //H - saveSection(code, "/*INTERFACE*/", "/*END_INTERFACE*/", savedCode.interfaceH); + saveSection(code, "/*INTERFACE*/", "/*END_INTERFACE*/", savedCode.topicInterfaceH); deleteSection(code, "/*INTERFACE*/", "/*END_INTERFACE*/"); + saveSection(code, "/*TOPIC_INTERFACE*/", "/*END_TOPIC_INTERFACE*/", savedCode.topicInterfaceH); + deleteSection(code, "/*TOPIC_INTERFACE*/", "/*END_TOPIC_INTERFACE*/"); saveSection(code, "/*TOPIC_CALLBACK_H*/", "/*END_TOPIC_CALLBACK_H*/", savedCode.topicCallbackH); deleteSection(code, "/*TOPIC_CALLBACK_H*/", "/*END_TOPIC_CALLBACK_H*/"); saveSection(code, "/*TOPIC_SUBSCRIPTION_H*/", "/*END_TOPIC_SUBSCRIPTION_H*/", savedCode.topicSubscriptionH); diff --git a/code/src/Translator.cpp b/code/src/Translator.cpp index fd3d0ea..db27684 100644 --- a/code/src/Translator.cpp +++ b/code/src/Translator.cpp @@ -390,6 +390,49 @@ bool appendAttributeValueFromVector(std::vector& elements return updatedAny; } +/** + * @brief Appends a substring saved in the location attribute to the end of the value of a given attribute in all elements in a vector + * + * @param elements vector of elements in which to append the attribute value + * @param attributeName the name of the attribute to be updated + * @param valueToAppend the substring to append to the attribute value + * @return bool Returns true if at least one attribute value was successfully updated, false otherwise + */ +bool appendAttributeValueLocationFromVector(std::vector& elements, const std::string& attributeName) +{ + bool updatedAny = false; + + for (auto& element : elements) { + if (element) { + // Get the current attribute value + const char* attributeValue = element->Attribute(attributeName.c_str()); + // Get the location attribute value + const char* locationValue = element->Attribute("location"); + + if (attributeValue && locationValue) { + std::string attributeStr(attributeValue); + // Append the location value to the end of the current attribute value + attributeStr.append(locationValue); + // Set the updated value for the attribute + element->SetAttribute(attributeName.c_str(), attributeStr.c_str()); + updatedAny = true; + } else { + if (!attributeValue) { + std::cerr << "Attribute '" << attributeName << "' not found in element." << std::endl; + } + if (!locationValue) { + std::cerr << "Location attribute not found in element." << std::endl; + } + } + } else { + std::cerr << "Encountered a null element pointer in the vector." << std::endl; + } + } + + return updatedAny; +} + + /** * @brief Find a XML element by tag and attribute name where the attribute's value contains a specific substring * @@ -609,6 +652,8 @@ bool Translator(fileDataStr& fileData){ std::vector assignVector; findElementVectorByTag(root, std::string("assign"), assignVector); replaceAttributeValueSubstringFromVector(assignVector, "expr", "_msg.", "_event."); + appendAttributeValueFromVector(assignVector, "expr", "."); + appendAttributeValueLocationFromVector(assignVector, "expr"); // doc.Print(); std::string ouputFilePath = fileData.outputPathSrc + skillData.className + "SM.scxml"; diff --git a/templates/skills/template_skill/include/TemplateSkill.h b/templates/skills/template_skill/include/TemplateSkill.h index 1b756d3..e593387 100644 --- a/templates/skills/template_skill/include/TemplateSkill.h +++ b/templates/skills/template_skill/include/TemplateSkill.h @@ -7,6 +7,9 @@ #include /*INTERFACES_LIST*/ /*INTERFACE*/ #include <$eventData.interfaceName$/srv/$eventData.functionNameSnakeCase$.hpp> /*END_INTERFACE*/ +/*TOPIC_INTERFACE*/ +#include <$eventData.interfaceData[interfaceDataType]$.hpp> +/*END_TOPIC_INTERFACE*/ /*TICK*/ #include /*END_TICK*/ /*HALT*/#include /*END_HALT*/ @@ -35,7 +38,7 @@ class $className$ void halt( [[maybe_unused]] const std::shared_ptr request, [[maybe_unused]] std::shared_ptr response);/*END_HALT_CMD*/ /*TOPIC_CALLBACK_LIST_H*/ - /*TOPIC_CALLBACK_H*/void topic_callback_$eventData.functionName$(const $eventData.interfaceName$::SharedPtr msg);/*END_TOPIC_CALLBACK_H*/ + /*TOPIC_CALLBACK_H*/void topic_callback_$eventData.functionName$(const $eventData.interfaceData[interfaceDataType]$::SharedPtr msg);/*END_TOPIC_CALLBACK_H*/ private: std::shared_ptr m_threadSpin; @@ -49,6 +52,7 @@ class $className$ /*HALT_CMD*/rclcpp::Service::SharedPtr m_haltService;/*END_HALT_CMD*/ /*DATAMODEL*/$skillName$SkillDataModel m_dataModel; /*END_DATAMODEL*/ /*TOPIC_SUBSCRIPTIONS_LIST_H*/ - /*TOPIC_SUBSCRIPTION_H*/rclcpp::Subscription<$eventData.interfaceName$>::SharedPtr m_subscription_$eventData.functionName$;/*END_TOPIC_SUBSCRIPTION_H*/ + /*TOPIC_SUBSCRIPTION_H*/ + rclcpp::Subscription<$eventData.interfaceData[interfaceDataType]$>::SharedPtr m_subscription_$eventData.functionName$;/*END_TOPIC_SUBSCRIPTION_H*/ }; diff --git a/templates/skills/template_skill/src/TemplateSkill.cpp b/templates/skills/template_skill/src/TemplateSkill.cpp index 6d3e958..8e200dc 100644 --- a/templates/skills/template_skill/src/TemplateSkill.cpp +++ b/templates/skills/template_skill/src/TemplateSkill.cpp @@ -71,8 +71,8 @@ bool $className$::start(int argc, char*argv[]) std::placeholders::_2));/*END_HALT*/ /*TOPIC_SUBSCRIPTIONS_LIST*//*TOPIC_SUBSCRIPTION*/ - m_subscription_$eventData.functionName$ = m_node->create_subscription<$eventData.interfaceName$>( - "$eventData.functionName$", 10, std::bind(&$className$::topic_callback_$eventData.functionName$, this, std::placeholders::_1)); + m_subscription_$eventData.functionName$ = m_node->create_subscription<$eventData.interfaceData[interfaceDataType]$>( + "/$eventData.functionName$", 10, std::bind(&$className$::topic_callback_$eventData.functionName$, this, std::placeholders::_1)); /*END_TOPIC_SUBSCRIPTION*/ /*SEND_EVENT_LIST*//*SEND_EVENT_SRV*/ @@ -197,15 +197,12 @@ void $className$::halt( [[maybe_unused]] const std::shared_ptrdata; - data.insert("status", m_status); + data.insert("$eventData.interfaceData[interfaceDataField]$", msg->data); m_stateMachine.submitEvent("$eventData.componentName$.$eventData.functionName$.Sub", data); - m_statusMutex.unlock(); RCLCPP_INFO(m_node->get_logger(), "$eventData.componentName$.$eventData.functionName$.Sub"); } /*END_TOPIC_CALLBACK*/ \ No newline at end of file From 2a4bf0a97250510528016188632b39c73c41340f Mon Sep 17 00:00:00 2001 From: SofiaFaraci Date: Fri, 20 Sep 2024 16:52:35 +0200 Subject: [PATCH 04/16] fix interface Signed-off-by: SofiaFaraci --- code/include/Replacer.h | 3 +++ code/src/Replacer.cpp | 26 +++++++++++++++++++++++++- code/src/Translator.cpp | 24 +++++++++++++----------- code/src/main.cpp | 1 - 4 files changed, 41 insertions(+), 13 deletions(-) diff --git a/code/include/Replacer.h b/code/include/Replacer.h index e2649ca..cc692b8 100644 --- a/code/include/Replacer.h +++ b/code/include/Replacer.h @@ -95,6 +95,9 @@ void replaceEventCode(std::map & codeMap); */ bool readTemplates(templateFileDataStr& templateFileData, std::map & codeMap); + +bool createDirectory(const std::string& path); + /** * @brief main function to get the code from template files and replace the placeholders with the data from the input file * diff --git a/code/src/Replacer.cpp b/code/src/Replacer.cpp index 7599e7f..8929dd2 100644 --- a/code/src/Replacer.cpp +++ b/code/src/Replacer.cpp @@ -9,6 +9,8 @@ * */ #include "Replacer.h" +#include + /** * @brief Get the Event Data from the model and interface files @@ -201,6 +203,7 @@ void handleGenericEvent(const eventDataStr eventData, const savedCodeStr savedCo replaceAll(eventCodeC, "$eventData.serverName$", eventData.serverName); replaceAll(eventCodeC, "$eventData.clientName$", eventData.clientName); replaceAll(eventCodeC, "$eventData.interfaceName$", eventData.interfaceName); + for (auto itParam = eventData.paramMap.begin(); itParam != eventData.paramMap.end(); ++itParam) { std::string paramCode = savedCode.sendParam; @@ -317,7 +320,7 @@ void saveCode(savedCodeStr& savedCode, std::string& code) saveSection(code, "/*TOPIC_SUBSCRIPTION*/", "/*END_TOPIC_SUBSCRIPTION*/", savedCode.topicSubscriptionC); deleteSection(code, "/*TOPIC_SUBSCRIPTION*/", "/*END_TOPIC_SUBSCRIPTION*/"); //H - saveSection(code, "/*INTERFACE*/", "/*END_INTERFACE*/", savedCode.topicInterfaceH); + saveSection(code, "/*INTERFACE*/", "/*END_INTERFACE*/", savedCode.interfaceH); deleteSection(code, "/*INTERFACE*/", "/*END_INTERFACE*/"); saveSection(code, "/*TOPIC_INTERFACE*/", "/*END_TOPIC_INTERFACE*/", savedCode.topicInterfaceH); deleteSection(code, "/*TOPIC_INTERFACE*/", "/*END_TOPIC_INTERFACE*/"); @@ -406,6 +409,24 @@ bool readTemplates(templateFileDataStr& templateFileData, std::map Attribute("name"), skillData); - // Delete server and topic declarations - std::vector serverVector; - - findElementVectorByTag(root, std::string("ros_service_server"), serverVector); - findElementVectorByTag(root, std::string("ros_topic_subscriber"), serverVector); - findElementVectorByTag(root, std::string("ros_service_client"), serverVector); - findElementVectorByTag(root, std::string("ros_topic_publisher"), serverVector); - findElementVectorByTag(root, std::string("ros_action_client"), serverVector); - deleteElementFromVector(serverVector); - // Get Skill Type tinyxml2::XMLElement* haltServerElement; if(findElementByTagAndAttValueContaining(root, std::string("ros_service_server"), std::string("service"), std::string("halt"), haltServerElement)) @@ -597,6 +587,16 @@ bool Translator(fileDataStr& fileData){ return false; } + // Delete server and topic declarations + std::vector serverVector; + + findElementVectorByTag(root, std::string("ros_service_server"), serverVector); + findElementVectorByTag(root, std::string("ros_topic_subscriber"), serverVector); + findElementVectorByTag(root, std::string("ros_service_client"), serverVector); + findElementVectorByTag(root, std::string("ros_topic_publisher"), serverVector); + findElementVectorByTag(root, std::string("ros_action_client"), serverVector); + deleteElementFromVector(serverVector); + // add xmln replaceAttributeValue(root, "xmlns", "http://www.w3.org/2005/07/scxml"); @@ -638,7 +638,7 @@ bool Translator(fileDataStr& fileData){ replaceAttributeNameFromVector(srvSendRspVector, "id", "event"); replaceAttributeNameFromVector(srvSendRspVector, "service", "event"); replaceAttributeValueContaingFromVector(srvSendRspVector, "event", "tick", "TICK_RESPONSE"); - replaceAttributeValueContaingFromVector(srvSendRspVector, "event", "tick", "HALT_RESPONSE"); + replaceAttributeValueContaingFromVector(srvSendRspVector, "event", "halt", "HALT_RESPONSE"); replaceTagNameFromVector(&doc, srvSendRspVector, "send"); // Translate elements with tag ros_topic_callback @@ -660,6 +660,8 @@ bool Translator(fileDataStr& fileData){ tinyxml2::XMLPrinter printer; doc.Print(&printer); // Print the XML document into the printer std::string outputContent = std::string(printer.CStr()); + createDirectory(fileData.outputPath); + createDirectory(fileData.outputPathSrc); writeFile(ouputFilePath, outputContent); return true; diff --git a/code/src/main.cpp b/code/src/main.cpp index 136fc58..335aeff 100644 --- a/code/src/main.cpp +++ b/code/src/main.cpp @@ -153,7 +153,6 @@ int main(int argc, char* argv[]) std::cout << "Error in code generation" << std::endl; } } - return RETURN_CODE_OK; }; \ No newline at end of file From c3f96720e5bd6591423d700e1c32baa766ed902b Mon Sep 17 00:00:00 2001 From: SofiaFaraci Date: Tue, 24 Sep 2024 08:24:17 +0200 Subject: [PATCH 05/16] add std_msgs, fix _service to _event Signed-off-by: SofiaFaraci --- code/src/Translator.cpp | 1 + templates/skills/template_skill/CMakeLists.txt | 2 ++ templates/skills/template_skill/package.xml | 1 + 3 files changed, 4 insertions(+) diff --git a/code/src/Translator.cpp b/code/src/Translator.cpp index f541d36..ed3ac9e 100644 --- a/code/src/Translator.cpp +++ b/code/src/Translator.cpp @@ -652,6 +652,7 @@ bool Translator(fileDataStr& fileData){ std::vector assignVector; findElementVectorByTag(root, std::string("assign"), assignVector); replaceAttributeValueSubstringFromVector(assignVector, "expr", "_msg.", "_event."); + replaceAttributeValueSubstringFromVector(assignVector, "expr", "_service.response.", "_event.data."); appendAttributeValueFromVector(assignVector, "expr", "."); appendAttributeValueLocationFromVector(assignVector, "expr"); diff --git a/templates/skills/template_skill/CMakeLists.txt b/templates/skills/template_skill/CMakeLists.txt index 5c90e80..e011006 100644 --- a/templates/skills/template_skill/CMakeLists.txt +++ b/templates/skills/template_skill/CMakeLists.txt @@ -9,6 +9,7 @@ endif() find_package(ament_cmake REQUIRED) find_package(rclcpp REQUIRED) +find_package(std_msgs REQUIRED) #TICK#find_package(bt_interfaces REQUIRED)#END_TICK# #PACKAGE_LIST##PACKAGE# find_package($interfaceName$ REQUIRED)#END_PACKAGE# @@ -26,6 +27,7 @@ endif() # find_package( REQUIRED) ament_target_dependencies(${PROJECT_NAME} + std_msgs #TICK#bt_interfaces #END_TICK# rclcpp #INTERFACE_LIST# #INTERFACE# diff --git a/templates/skills/template_skill/package.xml b/templates/skills/template_skill/package.xml index fc0ccfe..8858729 100644 --- a/templates/skills/template_skill/package.xml +++ b/templates/skills/template_skill/package.xml @@ -11,6 +11,7 @@ bt_interfaces $interfaceName$ + std_msgs ament_lint_auto ament_lint_common From 302178545d48442070a9f68d8a6df0d535228584 Mon Sep 17 00:00:00 2001 From: SofiaFaraci Date: Fri, 4 Oct 2024 16:55:10 +0200 Subject: [PATCH 06/16] edit models attribute and tags for SCXML translator Signed-off-by: SofiaFaraci --- code/src/Replacer.cpp | 2 ++ code/src/Translator.cpp | 35 +++++++++++++++++++++++------------ 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/code/src/Replacer.cpp b/code/src/Replacer.cpp index 8929dd2..c66fd7b 100644 --- a/code/src/Replacer.cpp +++ b/code/src/Replacer.cpp @@ -489,9 +489,11 @@ bool Replacer(fileDataStr& fileData, templateFileDataStr& templateFileData) writeFile(fileData.outputPathInclude + fileData.outputDatamodelFileNameH, codeMap["hDataModelCode"]); writeFile(fileData.outputPathSrc + fileData.outputDatamodelFileNameCPP, codeMap["cppDataModelCode"]); } + std::cout << "-----------" << std::endl; createDirectory(fileData.outputPath); createDirectory(fileData.outputPathInclude); createDirectory(fileData.outputPathSrc); + std::cout << "-----------" << std::endl; writeFile(fileData.outputPathInclude + fileData.outputFileNameH, codeMap["hCode"]); writeFile(fileData.outputPathSrc + fileData.outputFileNameCPP, codeMap["cppCode"]); writeFile(fileData.outputPath + fileData.outputCMakeListsFileName, codeMap["cmakeCode"]); diff --git a/code/src/Translator.cpp b/code/src/Translator.cpp index ed3ac9e..bccdd8a 100644 --- a/code/src/Translator.cpp +++ b/code/src/Translator.cpp @@ -567,7 +567,7 @@ bool Translator(fileDataStr& fileData){ getDataFromRootNameHighLevel(root->Attribute("name"), skillData); // Get Skill Type tinyxml2::XMLElement* haltServerElement; - if(findElementByTagAndAttValueContaining(root, std::string("ros_service_server"), std::string("service"), std::string("halt"), haltServerElement)) + if(findElementByTagAndAttValueContaining(root, std::string("ros_service_server"), std::string("service_name"), std::string("halt"), haltServerElement)) { std::cout << "Halt found => Action Skill" << std::endl; skillData.skillType = "Action"; @@ -608,8 +608,7 @@ bool Translator(fileDataStr& fileData){ // Translate elements with tag ros_service_handle_request std::vector srvHndlReqVector; findElementVectorByTag(root, std::string("ros_service_handle_request"), srvHndlReqVector); - replaceAttributeNameFromVector(srvHndlReqVector, "id", "event"); - replaceAttributeNameFromVector(srvHndlReqVector, "service", "event"); + replaceAttributeNameFromVector(srvHndlReqVector, "name", "event"); replaceAttributeValueContaingFromVector(srvHndlReqVector, "event", "tick", "CMD_TICK"); replaceAttributeValueContaingFromVector(srvHndlReqVector, "event", "halt", "CMD_HALT"); replaceTagNameFromVector(&doc, srvHndlReqVector, "transition"); @@ -617,17 +616,22 @@ bool Translator(fileDataStr& fileData){ // Translate elements with tag ros_service_send_request std::vector srvSendReqVector; findElementVectorByTag(root, std::string("ros_service_send_request"), srvSendReqVector); - replaceAttributeNameFromVector(srvSendReqVector, "id", "event"); + replaceAttributeNameFromVector(srvSendReqVector, "name", "event"); replaceEventValueFromVector(srvSendReqVector); appendAttributeValueFromVector(srvSendReqVector, "event", ".Call"); + for (auto& element : srvSendReqVector) { + std::vector srvSendReqFieldVector; + findElementVectorByTag(element, std::string("field"), srvSendReqFieldVector); + replaceTagNameFromVector(&doc, srvSendReqFieldVector, "param"); + } replaceTagNameFromVector(&doc, srvSendReqVector, "send"); // Translate elements with tag ros_service_handle_response std::vector srvHndlRspVector; findElementVectorByTag(root, std::string("ros_service_handle_response"), srvHndlRspVector); - replaceAttributeNameFromVector(srvHndlRspVector, "service", "event"); + replaceAttributeNameFromVector(srvHndlRspVector, "name", "event"); // replaceAttributeValueFromVector(srvHndlRspVector, "event", ""); get value e modificare le / con . - replaceAttributeValueSubstringFromVector(srvHndlRspVector, "cond", "_service.response.", "_event.data."); + replaceAttributeValueSubstringFromVector(srvHndlRspVector, "cond", "_res.", "_event.data."); replaceEventValueFromVector(srvHndlRspVector); appendAttributeValueFromVector(srvHndlRspVector, "event", ".Return"); replaceTagNameFromVector(&doc, srvHndlRspVector, "transition"); @@ -635,16 +639,21 @@ bool Translator(fileDataStr& fileData){ // Translate elements with tag ros_service_send_response std::vector srvSendRspVector; findElementVectorByTag(root, std::string("ros_service_send_response"), srvSendRspVector); - replaceAttributeNameFromVector(srvSendRspVector, "id", "event"); - replaceAttributeNameFromVector(srvSendRspVector, "service", "event"); + replaceAttributeNameFromVector(srvSendRspVector, "name", "event"); replaceAttributeValueContaingFromVector(srvSendRspVector, "event", "tick", "TICK_RESPONSE"); replaceAttributeValueContaingFromVector(srvSendRspVector, "event", "halt", "HALT_RESPONSE"); + for (auto& element : srvSendRspVector) { + std::vector srvSendRspFieldVector; + findElementVectorByTag(element, std::string("field"), srvSendRspFieldVector); + replaceTagNameFromVector(&doc, srvSendRspFieldVector, "param"); + } replaceTagNameFromVector(&doc, srvSendRspVector, "send"); + // Translate elements with tag ros_topic_callback std::vector topicCallbackVector; findElementVectorByTag(root, std::string("ros_topic_callback"), topicCallbackVector); - replaceAttributeNameFromVector(topicCallbackVector, "topic", "event"); + replaceAttributeNameFromVector(topicCallbackVector, "name", "event"); replaceEventValueFromVector(topicCallbackVector); appendAttributeValueFromVector(topicCallbackVector, "event", ".Sub"); replaceTagNameFromVector(&doc, topicCallbackVector, "transition"); @@ -652,17 +661,19 @@ bool Translator(fileDataStr& fileData){ std::vector assignVector; findElementVectorByTag(root, std::string("assign"), assignVector); replaceAttributeValueSubstringFromVector(assignVector, "expr", "_msg.", "_event."); - replaceAttributeValueSubstringFromVector(assignVector, "expr", "_service.response.", "_event.data."); - appendAttributeValueFromVector(assignVector, "expr", "."); - appendAttributeValueLocationFromVector(assignVector, "expr"); + replaceAttributeValueSubstringFromVector(assignVector, "expr", "_res.", "_event.data."); + // appendAttributeValueFromVector(assignVector, "expr", "."); + // appendAttributeValueLocationFromVector(assignVector, "expr"); // doc.Print(); std::string ouputFilePath = fileData.outputPathSrc + skillData.className + "SM.scxml"; tinyxml2::XMLPrinter printer; doc.Print(&printer); // Print the XML document into the printer std::string outputContent = std::string(printer.CStr()); + std::cout << "-----------" << std::endl; createDirectory(fileData.outputPath); createDirectory(fileData.outputPathSrc); + std::cout << "-----------" << std::endl; writeFile(ouputFilePath, outputContent); return true; From c89314dad5718e6b08851273e6e32ffc5085aa48 Mon Sep 17 00:00:00 2001 From: SofiaFaraci Date: Tue, 22 Oct 2024 16:57:15 +0200 Subject: [PATCH 07/16] small fixes in generated code Signed-off-by: SofiaFaraci --- code/src/Replacer.cpp | 24 +++++------ code/src/Translator.cpp | 42 +++++++++++++++++++ .../skills/template_skill/CMakeLists.txt | 4 +- .../template_skill/include/TemplateSkill.h | 21 ++++++---- templates/skills/template_skill/package.xml | 2 +- .../template_skill/src/TemplateSkill.cpp | 35 ++++++++-------- 6 files changed, 86 insertions(+), 42 deletions(-) diff --git a/code/src/Replacer.cpp b/code/src/Replacer.cpp index c66fd7b..a3f602c 100644 --- a/code/src/Replacer.cpp +++ b/code/src/Replacer.cpp @@ -281,20 +281,20 @@ void handleGenericEvent(const eventDataStr eventData, const savedCodeStr savedCo writeAfterCommand(str, "/*TOPIC_CALLBACK_LIST_H*/", topicCallbackH); //CMakeLists.txt - replaceAll(interfaceCodeCMake, "$interfaceName$", eventData.interfaceName); - if(!checkIfStrPresent(str, interfaceCodeCMake)){ - writeAfterCommand(str, "#INTERFACE_LIST#", interfaceCodeCMake); - } - replaceAll(packageCodeCMake, "$interfaceName$", eventData.interfaceName); - if(!checkIfStrPresent(str, packageCodeCMake)){ - writeAfterCommand(str, "#PACKAGE_LIST#", packageCodeCMake); - } + // replaceAll(interfaceCodeCMake, "$interfaceName$", eventData.interfaceName); + // if(!checkIfStrPresent(str, interfaceCodeCMake)){ + // writeAfterCommand(str, "#INTERFACE_LIST#", interfaceCodeCMake); + // } + // replaceAll(packageCodeCMake, "$interfaceName$", eventData.interfaceName); + // if(!checkIfStrPresent(str, packageCodeCMake)){ + // writeAfterCommand(str, "#PACKAGE_LIST#", packageCodeCMake); + // } //package.xml - replaceAll(interfaceCodeXML, "$interfaceName$", eventData.interfaceName); - if(!checkIfStrPresent(str, interfaceCodeXML)){ - writeAfterCommand(str, "", interfaceCodeXML); - } + // replaceAll(interfaceCodeXML, "$interfaceName$", eventData.interfaceName); + // if(!checkIfStrPresent(str, interfaceCodeXML)){ + // writeAfterCommand(str, "", interfaceCodeXML); + // } } } diff --git a/code/src/Translator.cpp b/code/src/Translator.cpp index bccdd8a..84305e4 100644 --- a/code/src/Translator.cpp +++ b/code/src/Translator.cpp @@ -432,6 +432,47 @@ bool appendAttributeValueLocationFromVector(std::vector& return updatedAny; } +/** + * @brief Appends a substring to the end of the value of a given attribute in all elements in a vector + * only if the attribute value contains a specific substring. + * + * @param elements vector of elements in which to append the attribute value + * @param attributeName the name of the attribute to be updated + * @param oldSubstring the substring that must be present in the attribute value + * @param valueToAppend the substring to append to the attribute value + * @return bool Returns true if at least one attribute value was successfully updated, false otherwise + */ +bool appendIfContainsSubstringVector(std::vector& elements, const std::string& attributeName, const std::string& oldSubstring, const std::string& valueToAppend) +{ + bool updatedAny = false; + + for (auto& element : elements) { + if (element) { + // Get the current attribute value + const char* attributeValue = element->Attribute(attributeName.c_str()); + const char* locationValue = element->Attribute("location"); + if (attributeValue && locationValue) { + std::string attributeStr(attributeValue); + // Check if the attribute value contains the old substring + if (attributeStr.find(oldSubstring) != std::string::npos) { + // Append the new value to the end of the current value + attributeStr.append(valueToAppend); + attributeStr.append(locationValue); + // Set the updated value for the attribute + element->SetAttribute(attributeName.c_str(), attributeStr.c_str()); + updatedAny = true; + } + } else { + std::cerr << "Attribute or location value'" << attributeName << "' not found in element." << std::endl; + } + } else { + std::cerr << "Encountered a null element pointer in the vector." << std::endl; + } + } + + return updatedAny; +} + /** * @brief Find a XML element by tag and attribute name where the attribute's value contains a specific substring @@ -660,6 +701,7 @@ bool Translator(fileDataStr& fileData){ std::vector assignVector; findElementVectorByTag(root, std::string("assign"), assignVector); + appendIfContainsSubstringVector(assignVector, "expr", "_msg.", "."); replaceAttributeValueSubstringFromVector(assignVector, "expr", "_msg.", "_event."); replaceAttributeValueSubstringFromVector(assignVector, "expr", "_res.", "_event.data."); // appendAttributeValueFromVector(assignVector, "expr", "."); diff --git a/templates/skills/template_skill/CMakeLists.txt b/templates/skills/template_skill/CMakeLists.txt index e011006..d9b3841 100644 --- a/templates/skills/template_skill/CMakeLists.txt +++ b/templates/skills/template_skill/CMakeLists.txt @@ -10,7 +10,7 @@ endif() find_package(ament_cmake REQUIRED) find_package(rclcpp REQUIRED) find_package(std_msgs REQUIRED) -#TICK#find_package(bt_interfaces REQUIRED)#END_TICK# +#TICK#find_package(bt_interfaces_dummy REQUIRED)#END_TICK# #PACKAGE_LIST##PACKAGE# find_package($interfaceName$ REQUIRED)#END_PACKAGE# find_package(Qt6 COMPONENTS Core Scxml StateMachine REQUIRED) @@ -28,7 +28,7 @@ endif() ament_target_dependencies(${PROJECT_NAME} std_msgs - #TICK#bt_interfaces #END_TICK# + #TICK#bt_interfaces_dummy #END_TICK# rclcpp #INTERFACE_LIST# #INTERFACE# $interfaceName$ #END_INTERFACE# diff --git a/templates/skills/template_skill/include/TemplateSkill.h b/templates/skills/template_skill/include/TemplateSkill.h index e593387..07db254 100644 --- a/templates/skills/template_skill/include/TemplateSkill.h +++ b/templates/skills/template_skill/include/TemplateSkill.h @@ -4,19 +4,22 @@ #include #include #include "$className$SM.h" -#include /*INTERFACES_LIST*/ +#include /*INTERFACES_LIST*/ /*INTERFACE*/ #include <$eventData.interfaceName$/srv/$eventData.functionNameSnakeCase$.hpp> /*END_INTERFACE*/ /*TOPIC_INTERFACE*/ #include <$eventData.interfaceData[interfaceDataType]$.hpp> /*END_TOPIC_INTERFACE*/ /*TICK*/ -#include /*END_TICK*/ -/*HALT*/#include /*END_HALT*/ +#include /*END_TICK*/ +/*HALT*/#include /*END_HALT*/ /*DATAMODEL*/ #include "$skillName$SkillDataModel.h" /*END_DATAMODEL*/ #define SERVICE_TIMEOUT 8 +#define SKILL_SUCCESS 0 +#define SKILL_FAILURE 1 +#define SKILL_RUNNING 2 enum class Status{ undefined,/*ACTION*/ @@ -32,11 +35,11 @@ class $className$ bool start(int argc, char * argv[]); static void spin(std::shared_ptr node); /*TICK_CMD*/ - void tick( [[maybe_unused]] const std::shared_ptr request, - std::shared_ptr response);/*END_TICK_CMD*/ + void tick( [[maybe_unused]] const std::shared_ptr request, + std::shared_ptr response);/*END_TICK_CMD*/ /*HALT_CMD*/ - void halt( [[maybe_unused]] const std::shared_ptr request, - [[maybe_unused]] std::shared_ptr response);/*END_HALT_CMD*/ + void halt( [[maybe_unused]] const std::shared_ptr request, + [[maybe_unused]] std::shared_ptr response);/*END_HALT_CMD*/ /*TOPIC_CALLBACK_LIST_H*/ /*TOPIC_CALLBACK_H*/void topic_callback_$eventData.functionName$(const $eventData.interfaceData[interfaceDataType]$::SharedPtr msg);/*END_TOPIC_CALLBACK_H*/ @@ -47,9 +50,9 @@ class $className$ std::string m_name; $SMName$ m_stateMachine; /*TICK_RESPONSE*/std::atomic m_tickResult{Status::undefined};/*END_TICK_RESPONSE*/ - /*TICK_CMD*/rclcpp::Service::SharedPtr m_tickService;/*END_TICK_CMD*/ + /*TICK_CMD*/rclcpp::Service::SharedPtr m_tickService;/*END_TICK_CMD*/ /*HALT_RESPONSE*/std::atomic m_haltResult{false};/*END_HALT_RESPONSE*/ - /*HALT_CMD*/rclcpp::Service::SharedPtr m_haltService;/*END_HALT_CMD*/ + /*HALT_CMD*/rclcpp::Service::SharedPtr m_haltService;/*END_HALT_CMD*/ /*DATAMODEL*/$skillName$SkillDataModel m_dataModel; /*END_DATAMODEL*/ /*TOPIC_SUBSCRIPTIONS_LIST_H*/ /*TOPIC_SUBSCRIPTION_H*/ diff --git a/templates/skills/template_skill/package.xml b/templates/skills/template_skill/package.xml index 8858729..c836e17 100644 --- a/templates/skills/template_skill/package.xml +++ b/templates/skills/template_skill/package.xml @@ -8,7 +8,7 @@ License declaration ament_cmake - bt_interfaces + bt_interfaces_dummy $interfaceName$ std_msgs diff --git a/templates/skills/template_skill/src/TemplateSkill.cpp b/templates/skills/template_skill/src/TemplateSkill.cpp index 8e200dc..d98ef1b 100644 --- a/templates/skills/template_skill/src/TemplateSkill.cpp +++ b/templates/skills/template_skill/src/TemplateSkill.cpp @@ -58,13 +58,13 @@ bool $className$::start(int argc, char*argv[]) std::cout << "$className$::start"; /*TICK*/ - m_tickService = m_node->create_service(m_name + "Skill/tick", + m_tickService = m_node->create_service(m_name + "Skill/tick", std::bind(&$className$::tick, this, std::placeholders::_1, std::placeholders::_2));/*END_TICK*/ /*HALT*/ - m_haltService = m_node->create_service(m_name + "Skill/halt", + m_haltService = m_node->create_service(m_name + "Skill/halt", std::bind(&$className$::halt, this, std::placeholders::_1, @@ -105,9 +105,9 @@ bool $className$::start(int argc, char*argv[]) if (futureResult == rclcpp::FutureReturnCode::SUCCESS) { auto response = result.get(); - if( response->is_ok ==true) { + if( response->is_ok == true) { QVariantMap data; - data.insert("result", "SUCCESS");/*RETURN_PARAM_LIST*//*RETURN_PARAM*/ + data.insert("is_ok", true);/*RETURN_PARAM_LIST*//*RETURN_PARAM*/ data.insert("$eventData.interfaceDataField$", response->$eventData.interfaceDataField$/*STATUS*/.status/*END_STATUS*/);/*END_RETURN_PARAM*/ m_stateMachine.submitEvent("$eventData.componentName$.$eventData.functionName$.Return", data); RCLCPP_INFO(rclcpp::get_logger("rclcpp"), "$eventData.componentName$.$eventData.functionName$.Return"); @@ -119,23 +119,23 @@ bool $className$::start(int argc, char*argv[]) } } QVariantMap data; - data.insert("result", "FAILURE"); + data.insert("is_ok", false); m_stateMachine.submitEvent("$eventData.componentName$.$eventData.functionName$.Return", data); RCLCPP_INFO(rclcpp::get_logger("rclcpp"), "$eventData.componentName$.$eventData.functionName$.Return"); });/*END_SEND_EVENT_SRV*/ /*TICK_RESPONSE*/ m_stateMachine.connectToEvent("TICK_RESPONSE", [this]([[maybe_unused]]const QScxmlEvent & event){ - RCLCPP_INFO(m_node->get_logger(), "$className$::tickReturn %s", event.data().toMap()["result"].toString().toStdString().c_str()); - std::string result = event.data().toMap()["result"].toString().toStdString(); - if (result == "SUCCESS" ) + RCLCPP_INFO(m_node->get_logger(), "$className$::tickReturn %s", event.data().toMap()["status"].toString().toStdString().c_str()); + std::string result = event.data().toMap()["status"].toString().toStdString(); + if (result == std::to_string(SKILL_SUCCESS) ) { m_tickResult.store(Status::success); }/*ACTION*/ - else if (result == "RUNNING" ) + else if (result == std::to_string(SKILL_RUNNING) ) { m_tickResult.store(Status::running); }/*END_ACTION*/ - else if (result == "FAILURE" ) + else if (result == std::to_string(SKILL_FAILURE) ) { m_tickResult.store(Status::failure); } @@ -152,12 +152,11 @@ bool $className$::start(int argc, char*argv[]) return true; } /*TICK_CMD*/ -void $className$::tick( [[maybe_unused]] const std::shared_ptr request, - std::shared_ptr response) +void $className$::tick( [[maybe_unused]] const std::shared_ptr request, + std::shared_ptr response) { std::lock_guard lock(m_requestMutex); RCLCPP_INFO(m_node->get_logger(), "$className$::tick"); - auto message = bt_interfaces::msg::$skillType$Response(); m_tickResult.store(Status::undefined); m_stateMachine.submitEvent("CMD_TICK"); @@ -167,21 +166,21 @@ void $className$::tick( [[maybe_unused]] const std::shared_ptrstatus.status = message.SKILL_RUNNING; + response->status = SKILL_RUNNING; break;/*END_ACTION*/ case Status::failure: - response->status.status = message.SKILL_FAILURE; + response->status = SKILL_FAILURE; break; case Status::success: - response->status.status = message.SKILL_SUCCESS; + response->status = SKILL_SUCCESS; break; } RCLCPP_INFO(m_node->get_logger(), "$className$::tickDone"); response->is_ok = true; }/*END_TICK_CMD*/ /*HALT_CMD*/ -void $className$::halt( [[maybe_unused]] const std::shared_ptr request, - [[maybe_unused]] std::shared_ptr response) +void $className$::halt( [[maybe_unused]] const std::shared_ptr request, + [[maybe_unused]] std::shared_ptr response) { std::lock_guard lock(m_requestMutex); RCLCPP_INFO(m_node->get_logger(), "$className$::halt"); From 90a68a8a415fe2137b43d8a065fb309e72b36d07 Mon Sep 17 00:00:00 2001 From: SofiaFaraci Date: Tue, 22 Oct 2024 17:34:38 +0200 Subject: [PATCH 08/16] unify translation and generation Signed-off-by: SofiaFaraci --- code/include/Data.h | 2 ++ code/src/Translator.cpp | 1 + code/src/main.cpp | 24 ++++++++++++++++++++++-- 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/code/include/Data.h b/code/include/Data.h index 0553479..a0d8211 100644 --- a/code/include/Data.h +++ b/code/include/Data.h @@ -80,9 +80,11 @@ struct fileDataStr{ std::string outputDatamodelFileNameCPP; std::string outputFileNameH; std::string outputFileNameCPP; + std::string outputFileTranslatedSM; bool debug_mode; bool datamodel_mode; bool translate_mode; + bool generate_mode; }; struct templateFileDataStr{ diff --git a/code/src/Translator.cpp b/code/src/Translator.cpp index 84305e4..8b4197f 100644 --- a/code/src/Translator.cpp +++ b/code/src/Translator.cpp @@ -717,6 +717,7 @@ bool Translator(fileDataStr& fileData){ createDirectory(fileData.outputPathSrc); std::cout << "-----------" << std::endl; writeFile(ouputFilePath, outputContent); + fileData.outputFileTranslatedSM = ouputFilePath; return true; } \ No newline at end of file diff --git a/code/src/main.cpp b/code/src/main.cpp index 335aeff..a2dd7a4 100644 --- a/code/src/main.cpp +++ b/code/src/main.cpp @@ -25,7 +25,9 @@ void print_help() std::cout << "--interface_filename \"interfaceFileName.scxml\"\n"; std::cout << "--output_path \"path/to/output/directory\"\n"; std::cout << "--template_path \"path/to/template_skill/directory\"\n"; - std::cout << "--datamodel_mode \n"; + // std::cout << "--datamodel_mode \n"; + std::cout << "--translate_mode \n"; + std::cout << "--generate_mode \n"; } /** @@ -45,6 +47,7 @@ bool handleInputs(int argc, char* argv[], fileDataStr& fileData, templateFileDat fileData.interfaceFileName = interfaceFilePath; fileData.datamodel_mode = false; fileData.translate_mode = false; + fileData.generate_mode = false; templateFileData.templatePath = templateFilePath; if (argc == 1) @@ -86,6 +89,9 @@ bool handleInputs(int argc, char* argv[], fileDataStr& fileData, templateFileDat else if (arg == "--translate_mode") { fileData.translate_mode = true; } + else if (arg == "--generate_mode") { + fileData.generate_mode = true; + } } if(fileData.inputFileName == "") @@ -145,7 +151,7 @@ int main(int argc, char* argv[]) } } - else + else if(fileData.generate_mode) { std::cout << "No translation request" << std::endl; if(!Replacer(fileData, templateFileData)) @@ -153,6 +159,20 @@ int main(int argc, char* argv[]) std::cout << "Error in code generation" << std::endl; } } + else + { + std::cout << "Translation request" << std::endl; + if(!Translator(fileData)) + { + std::cout << "Error in translation" << std::endl; + } + fileData.inputFileName = fileData.outputFileTranslatedSM; + std::cout << "Code generation request" << std::endl; + if(!Replacer(fileData, templateFileData)) + { + std::cout << "Error in code generation" << std::endl; + } + } return RETURN_CODE_OK; }; \ No newline at end of file From 4c8bd5b194d6c4e83325492f73cfd9539ccb2fd8 Mon Sep 17 00:00:00 2001 From: SofiaFaraci Date: Tue, 22 Oct 2024 18:09:55 +0200 Subject: [PATCH 09/16] code semplification for main function Signed-off-by: SofiaFaraci --- code/include/Data.h | 1 + code/include/Replacer.h | 4 ++-- code/src/Replacer.cpp | 34 ++++++++++++++++++++++++++-------- code/src/main.cpp | 35 +++++++++++++++++++---------------- 4 files changed, 48 insertions(+), 26 deletions(-) diff --git a/code/include/Data.h b/code/include/Data.h index a0d8211..9b38a8f 100644 --- a/code/include/Data.h +++ b/code/include/Data.h @@ -68,6 +68,7 @@ struct eventDataStr{ struct fileDataStr{ std::string inputFileName; + std::string inputFileNameGeneration; std::string interfaceFileName; std::string modelFileName; std::string outputPath; diff --git a/code/include/Replacer.h b/code/include/Replacer.h index cc692b8..1de2f62 100644 --- a/code/include/Replacer.h +++ b/code/include/Replacer.h @@ -18,7 +18,7 @@ * @param fileData file data structure passed by reference from which the event data is extracted * @param eventData event data structure passed by reference where the event data is stored */ -void getEventData(fileDataStr fileData, eventDataStr& eventData); +bool getEventData(fileDataStr fileData, eventDataStr& eventData); /** * @brief Get the Event Data from the vector of event elements @@ -27,7 +27,7 @@ void getEventData(fileDataStr fileData, eventDataStr& eventData); * @param elementsTransition vector of transition event elements * @param elementsSend vector of send event elements */ -void getEventsVecData(fileDataStr fileData, const std::vector elementsTransition, const std::vector elementsSend); +bool getEventsVecData(fileDataStr fileData, const std::vector elementsTransition, const std::vector elementsSend); /** * @brief function to keep or delete the sections of the code related to the Command Tick event diff --git a/code/src/Replacer.cpp b/code/src/Replacer.cpp index a3f602c..e42af20 100644 --- a/code/src/Replacer.cpp +++ b/code/src/Replacer.cpp @@ -18,11 +18,11 @@ * @param fileData file data structure passed by reference from which the event data is extracted * @param eventData event data structure passed by reference where the event data is stored */ -void getEventData(fileDataStr fileData, eventDataStr& eventData) +bool getEventData(fileDataStr fileData, eventDataStr& eventData) { if(eventsMap.find(eventData.event) != eventsMap.end()){ std::cout << "Event already processed: " << eventData.event << std::endl; - return; + return true; } eventsMap[eventData.event]; @@ -37,11 +37,19 @@ void getEventData(fileDataStr fileData, eventDataStr& eventData) if(extractInterfaceName(fileData.modelFileName, eventData)) { - extractInterfaceType(fileData.interfaceFileName, eventData); + if(!extractInterfaceType(fileData.interfaceFileName, eventData)) + { + return false; + } printEventData(eventData); + } + else + { + return false; } } eventsMap[eventData.event] = eventData; + return true; } /** @@ -51,7 +59,7 @@ void getEventData(fileDataStr fileData, eventDataStr& eventData) * @param elementsTransition vector of transition event elements * @param elementsSend vector of send event elements */ -void getEventsVecData(fileDataStr fileData, const std::vector elementsTransition, const std::vector elementsSend) +bool getEventsVecData(fileDataStr fileData, const std::vector elementsTransition, const std::vector elementsSend) { for (const auto& element : elementsTransition) { const char* event = element->Attribute("event"); @@ -64,7 +72,10 @@ void getEventsVecData(fileDataStr fileData, const std::vector tag" << std::endl; } } + return true; } @@ -443,7 +458,7 @@ bool Replacer(fileDataStr& fileData, templateFileDataStr& templateFileData) std::vector elementsTransition, elementsSend; tinyxml2::XMLDocument doc; std::cout << "-----------" << std::endl; - if(!extractFromSCXML(doc, fileData.inputFileName, rootName, elementsTransition, elementsSend)){ + if(!extractFromSCXML(doc, fileData.inputFileNameGeneration, rootName, elementsTransition, elementsSend)){ return 0; } @@ -481,7 +496,10 @@ bool Replacer(fileDataStr& fileData, templateFileDataStr& templateFileData) deleteSection(it->second, "#DATAMODEL#", "#END_DATAMODEL#"); } } - getEventsVecData(fileData, elementsTransition, elementsSend); + if (!getEventsVecData(fileData, elementsTransition, elementsSend)) + { + return false; + } replaceEventCode(codeMap); std::cout << "-----------" << std::endl; if(fileData.datamodel_mode) diff --git a/code/src/main.cpp b/code/src/main.cpp index a2dd7a4..7791728 100644 --- a/code/src/main.cpp +++ b/code/src/main.cpp @@ -142,35 +142,38 @@ int main(int argc, char* argv[]) return RETURN_CODE_ERROR; } + + if(!fileData.translate_mode & fileData.generate_mode) + { + // Generation request without translation + fileData.inputFileNameGeneration = fileData.inputFileName; + } + else if(!fileData.translate_mode & !fileData.generate_mode) + { + fileData.translate_mode= true; + fileData.generate_mode = true; + } + if(fileData.translate_mode) { std::cout << "Translation request" << std::endl; if(!Translator(fileData)) { + std::cout << "-----------" << std::endl; std::cout << "Error in translation" << std::endl; + return RETURN_CODE_ERROR; } + fileData.inputFileNameGeneration = fileData.outputFileTranslatedSM; } - else if(fileData.generate_mode) - { - std::cout << "No translation request" << std::endl; - if(!Replacer(fileData, templateFileData)) - { - std::cout << "Error in code generation" << std::endl; - } - } - else + if(fileData.generate_mode) { - std::cout << "Translation request" << std::endl; - if(!Translator(fileData)) - { - std::cout << "Error in translation" << std::endl; - } - fileData.inputFileName = fileData.outputFileTranslatedSM; - std::cout << "Code generation request" << std::endl; + if(!Replacer(fileData, templateFileData)) { + std::cout << "-----------" << std::endl; std::cout << "Error in code generation" << std::endl; + return RETURN_CODE_ERROR; } } From 54ae954ee0f8c44217e9ee71e34aba06a5ac252d Mon Sep 17 00:00:00 2001 From: SofiaFaraci Date: Tue, 5 Nov 2024 10:37:00 +0100 Subject: [PATCH 10/16] update doc Signed-off-by: SofiaFaraci --- README.md | 27 +++++++++++++++------------ docs/source/index.rst | 42 +++++++++++++++++++----------------------- 2 files changed, 34 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index 10cb6f0..15f3bab 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ > Please access the documentation via [convince-project.github.io/model2code](https://convince-project.github.io/model2code/) -MODEL2CODE is a tool that generates CPP code from a SCXML model. +MODEL2CODE is a tool that generates a ROS package with C++ code from a ROS-flavoured SCXML model. ## Installation @@ -12,15 +12,15 @@ MODEL2CODE has been tested on Ubuntu 22.04 with Python 3.10.12. MODEL2CODE requires the following dependencies: -* [TinyXML2](https://github.com/leethomason/tinyxml2/) (Tested with v10.0.0) +* [TinyXML2](https://github.com/leethomason/tinyxml2/) (Tested with v10.0.0) for XML file handling. To install see [TinyXML2 Installation](https://github.com/leethomason/tinyxml2/tree/master?tab=readme-ov-file#building-tinyxml-2---using-vcpkg) ## Compiling -To compile the code run the following commands +To compile the code run the following commands: ``` git clone https://github.com/convince-project/model2code.git -cd model2code/code +cd model2code mkdir build cd build cmake ../code @@ -28,18 +28,21 @@ make install ``` ## Execution -To run the `model2code` tool you need three different files: -- An SCXML file with your state machine -- An XML file with the definition of your model -- An XML file with the definition of your interfaces -- A directory containing the templates of the files to generate +To run the `model2code` tool, you will need the following: +- An SCXML file with the state machine of the model; +- An XML file defining the model of your project; +- An XML file defining the interfaces of your project; +- A directory containing templates for the files to be generated. To run the `model2code` tool use the following command ``` -model2code --input_filename "input_filename.scxml" --model_filename "model_filename.scxml" --interface_filename "interface_filename.scxml" --output_path "path/to/output/directory" --template_path "path/to/template_skill/directory" +model2code --input_filename "input_model.scxml" --model_filename "project_model_definition.xml" --interface_filename "interface_definition.xml" --output_path "path/to/output/directory" --template_path "path/to/template_skill/directory" ``` -replace `input_filename.scxml`, `model_filename.scxml`, `interface_filename.scxml`, `path/to/output/directory` and `path/to/template_skill/directory` with your needs. -By default the `path/to/output/directory` is set to the location of `input_filename.scxml` and `path/to/template_skill/directory` is set to the 'templates/skills/template_skill' directory of this repository. +replace `input_model.scxml`, `project_model_definition.scxml`, `interface_definition.scxml`, `path/to/output/directory` and `path/to/template_skill/directory` with your needs. + +By default the `path/to/output/directory` is set to the location of `input_model.scxml`, and `path/to/template_skill/directory` is set to the 'templates/skills/template_skill' directory of this repository. + +Example XML files with the required structure for defining the project's model and interfaces are available in the `template/specifications` folder. ## Run examples To run an example of MODEL2CODE go to the main directory and run the following commands: diff --git a/docs/source/index.rst b/docs/source/index.rst index 4f511c2..a9c6ae7 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -1,38 +1,34 @@ CONVINCE model2code Documentation ================================== -The tool is developed as part of the CONVINCE project and is mainly used to generate skill-level code starting from an SCXML model. +The model2code tool is developed as part of the CONVINCE project and is used to generate skill-level code from the high-level SCXML model of a skill. -The inputs of the program are: +Program inputs: -- an SCXML model that describes the behavior of the skill, -- an XML file that describes the full model of the program, which includes the behavior tree, the skills and the components used in the system, -- an XML file that describes the interfaces used between behavior tree and skills, and between skills and components, -- a directory containing the templates of the files to generate. +- An SCXML model that describes the behavior of the skill, +- An XML file that outlines the full model of the program, including the behavior tree, skills, and components used in the system. +- An XML file that specifies the interfaces between the behavior tree and skills, as well as between skills and components. +- A directory containing templates for the files to be generated. -The output of the program is composed of: +Program outputs: -- a C++ file that contains the code of the skill, -- a header file that contains the declaration of the skill, -- a main C++ file that contains the main function of the skill, -- a package.xml file that contains the information of the ROS package, -- a CMakeLists.txt file that includes the generated files. +- A C++ file containing skill code. +- A header file declaring the skill. +- A main C++ file that includes the main function of the skill. +- A package.xml file with information about the ROS package. +- A CMakeLists.txt file that incorporates the generated files. -The output above is only if the data model is ECMAscript, otherwise, you will need to add the parameter ``--datamodel_mode`` to generate the C++ data model files. -In this case, you will get 2 additional files: -- a C++ file that contains the code of the data model, -- a header file that contains the declaration of the data model. +Required parameters: +- ``--input_filename``: The path to the SCXML file that describes the behavior of the skill. +- ``--model_filename``: The path to the XML file that describes the full model of the program. +- ``--interface_filename``: The path to the XML file that describes the interfaces used. -The parameters required to run the program are: +By default, the program generates the code in the same directory as the SCXML file specified by the ``--input_filename`` parameter. However, you can select a different output directory by using the ``--output_path`` parameter. -- ``--input_filename`` : the path to the SCXML file that describes the behavior of the skill, -- ``--model_filename`` : the path to the XML file that describes the full model of the program, -- ``--interface_filename`` : the path to the XML file that describes the interfaces used. +Additionally, the program uses files from the ``templates`` directory by default to generate the code, but you can specify a different directory with the ``--templates_path`` parameter. -By default the program will generate the code in the directory where the SCXML file passed by the parameter ``--input_filename`` is located, but you can specify a different directory by using the parameter ``--output_path``. - -The skills generated are based on a behavior tree structure and will have a ROS2 tick service in case they are a condition a ROS2 tick and halt services in case they are an action. +The generated skills are based on a behavior tree structure. Skills defined as conditions will have a ROS2 tick service, while skills defined as actions will have both tick and halt services. Contents ---------- From 73829e036d8c221e1a74481bf9437d36ae99f9d9 Mon Sep 17 00:00:00 2001 From: SofiaFaraci Date: Tue, 5 Nov 2024 11:29:06 +0100 Subject: [PATCH 11/16] edit and moved tutorials Signed-off-by: SofiaFaraci --- .../src/FirstTemplateSkillSM.scxml | 71 ------------------- .../src/SecondTemplateSkillSM.scxml | 58 --------------- templates/specifications/interfaces.xml | 4 -- .../src/FirstTutorialSkill.scxml | 52 ++++++++++++++ .../src/SecondTutorialSkill.scxml | 49 +++++++++++++ 5 files changed, 101 insertions(+), 133 deletions(-) delete mode 100644 templates/skills/first_template_skill/src/FirstTemplateSkillSM.scxml delete mode 100644 templates/skills/second_template_skill/src/SecondTemplateSkillSM.scxml create mode 100644 tutorials/skills/first_tutorial_skill/src/FirstTutorialSkill.scxml create mode 100644 tutorials/skills/second_tutorial_skill/src/SecondTutorialSkill.scxml diff --git a/templates/skills/first_template_skill/src/FirstTemplateSkillSM.scxml b/templates/skills/first_template_skill/src/FirstTemplateSkillSM.scxml deleted file mode 100644 index 842a9a8..0000000 --- a/templates/skills/first_template_skill/src/FirstTemplateSkillSM.scxml +++ /dev/null @@ -1,71 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/templates/skills/second_template_skill/src/SecondTemplateSkillSM.scxml b/templates/skills/second_template_skill/src/SecondTemplateSkillSM.scxml deleted file mode 100644 index a60f65e..0000000 --- a/templates/skills/second_template_skill/src/SecondTemplateSkillSM.scxml +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/templates/specifications/interfaces.xml b/templates/specifications/interfaces.xml index b281b5a..437d566 100644 --- a/templates/specifications/interfaces.xml +++ b/templates/specifications/interfaces.xml @@ -41,10 +41,6 @@ bool is_active - - bool - is_active2 - \ No newline at end of file diff --git a/tutorials/skills/first_tutorial_skill/src/FirstTutorialSkill.scxml b/tutorials/skills/first_tutorial_skill/src/FirstTutorialSkill.scxml new file mode 100644 index 0000000..22e33f8 --- /dev/null +++ b/tutorials/skills/first_tutorial_skill/src/FirstTutorialSkill.scxml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tutorials/skills/second_tutorial_skill/src/SecondTutorialSkill.scxml b/tutorials/skills/second_tutorial_skill/src/SecondTutorialSkill.scxml new file mode 100644 index 0000000..c1dbf95 --- /dev/null +++ b/tutorials/skills/second_tutorial_skill/src/SecondTutorialSkill.scxml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From eee8aa99469e6174b40cefed235891c7d7723d2a Mon Sep 17 00:00:00 2001 From: SofiaFaraci Date: Tue, 5 Nov 2024 11:42:10 +0100 Subject: [PATCH 12/16] edit second tutorial Signed-off-by: SofiaFaraci --- templates/specifications/interfaces.xml | 4 +- .../src/SecondTutorialSkill.scxml | 48 +++++++++---------- 2 files changed, 24 insertions(+), 28 deletions(-) diff --git a/templates/specifications/interfaces.xml b/templates/specifications/interfaces.xml index 437d566..fce3894 100644 --- a/templates/specifications/interfaces.xml +++ b/templates/specifications/interfaces.xml @@ -34,11 +34,11 @@ - + - bool + std_msgs::msg::Bool is_active diff --git a/tutorials/skills/second_tutorial_skill/src/SecondTutorialSkill.scxml b/tutorials/skills/second_tutorial_skill/src/SecondTutorialSkill.scxml index c1dbf95..a44a025 100644 --- a/tutorials/skills/second_tutorial_skill/src/SecondTutorialSkill.scxml +++ b/tutorials/skills/second_tutorial_skill/src/SecondTutorialSkill.scxml @@ -6,7 +6,7 @@ xmlns="http://www.w3.org/2005/07/scxml"> - + @@ -14,36 +14,32 @@ - - + + - - - + + + + - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + \ No newline at end of file From 87a7e41c03c1f25b1f57b2492eb45a511c760249 Mon Sep 17 00:00:00 2001 From: SofiaFaraci Date: Tue, 5 Nov 2024 11:53:35 +0100 Subject: [PATCH 13/16] edit tutorials Signed-off-by: SofiaFaraci --- README.md | 2 +- .../src/FirstTutorialSkill.scxml | 24 +++++++++---------- .../src/SecondTutorialSkill.scxml | 10 ++++---- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 15f3bab..5f1b8a5 100644 --- a/README.md +++ b/README.md @@ -47,5 +47,5 @@ Example XML files with the required structure for defining the project's model a ## Run examples To run an example of MODEL2CODE go to the main directory and run the following commands: ``` -model2code --input_filename "templates/skills/first_template_skill/src/FirstTemplateSkillSM.scxml" --model_filename "templates/specifications/full-model.xml" --interface_filename "templates/specifications/interfaces.xml" +model2code --input_filename "tutorials/skills/first_tutorial_skill/src/FirstTutorialSkill.scxml" --model_filename "templates/specifications/full-model.xml" --interface_filename "templates/specifications/interfaces.xml" --output_path "tutorials/skills/first_tutorial_skill" ``` diff --git a/tutorials/skills/first_tutorial_skill/src/FirstTutorialSkill.scxml b/tutorials/skills/first_tutorial_skill/src/FirstTutorialSkill.scxml index 22e33f8..4952252 100644 --- a/tutorials/skills/first_tutorial_skill/src/FirstTutorialSkill.scxml +++ b/tutorials/skills/first_tutorial_skill/src/FirstTutorialSkill.scxml @@ -12,40 +12,40 @@ - - - - - + + + + + - + - - + + - + - + - - + + diff --git a/tutorials/skills/second_tutorial_skill/src/SecondTutorialSkill.scxml b/tutorials/skills/second_tutorial_skill/src/SecondTutorialSkill.scxml index a44a025..3bbe81b 100644 --- a/tutorials/skills/second_tutorial_skill/src/SecondTutorialSkill.scxml +++ b/tutorials/skills/second_tutorial_skill/src/SecondTutorialSkill.scxml @@ -12,14 +12,14 @@ - - + + - + @@ -28,12 +28,12 @@ - + - + From 2b1b498f4f80f2fe42886d9ab0a35bbfff4c7c8b Mon Sep 17 00:00:00 2001 From: SofiaFaraci Date: Tue, 5 Nov 2024 12:06:48 +0100 Subject: [PATCH 14/16] add second example Signed-off-by: SofiaFaraci --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 5f1b8a5..7df831e 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,11 @@ Example XML files with the required structure for defining the project's model a ## Run examples To run an example of MODEL2CODE go to the main directory and run the following commands: +Example 1: ``` model2code --input_filename "tutorials/skills/first_tutorial_skill/src/FirstTutorialSkill.scxml" --model_filename "templates/specifications/full-model.xml" --interface_filename "templates/specifications/interfaces.xml" --output_path "tutorials/skills/first_tutorial_skill" ``` +Example 2: +``` +model2code --input_filename "tutorials/skills/second_tutorial_skill/src/SecondTutorialSkill.scxml" --model_filename "templates/specifications/full-model.xml" --interface_filename "templates/specifications/interfaces.xml" +``` \ No newline at end of file From bec1f4e3b7e108e96cc113e84356c0c023039da3 Mon Sep 17 00:00:00 2001 From: SofiaFaraci Date: Tue, 5 Nov 2024 12:07:47 +0100 Subject: [PATCH 15/16] edit --help print Signed-off-by: SofiaFaraci --- code/src/main.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/code/src/main.cpp b/code/src/main.cpp index 7791728..c4b20bf 100644 --- a/code/src/main.cpp +++ b/code/src/main.cpp @@ -19,15 +19,15 @@ void print_help() { std::cout << "Welcome to model2code tool.\n"; - std::cout << "Syntax:\n"; - std::cout << "model2code --input_filename \"inputFileName.scxml\" \n"; - std::cout << "--model_filename \"modelFileName.scxml\"\n"; - std::cout << "--interface_filename \"interfaceFileName.scxml\"\n"; + std::cout << "Usage:\n"; + std::cout << "model2code --input_filename \"inputFile.scxml\" "; + std::cout << "--model_filename \"projectModel.xml\" "; + std::cout << "--interface_filename \"interfaceFile.xml\" "; + std::cout << "--template_path \"path/to/template_skill/directory\" "; std::cout << "--output_path \"path/to/output/directory\"\n"; - std::cout << "--template_path \"path/to/template_skill/directory\"\n"; // std::cout << "--datamodel_mode \n"; - std::cout << "--translate_mode \n"; - std::cout << "--generate_mode \n"; + // std::cout << "--translate_mode \n"; + // std::cout << "--generate_mode \n"; } /** From 9834a2ff9829fa2f26e811102e3d3c828e009177 Mon Sep 17 00:00:00 2001 From: SofiaFaraci Date: Wed, 6 Nov 2024 15:27:27 +0100 Subject: [PATCH 16/16] mv CMake file and del code folder Signed-off-by: SofiaFaraci --- code/CMakeLists.txt => CMakeLists.txt | 0 {code/include => include}/Data.h | 0 {code/include => include}/ExtractFromElement.h | 0 {code/include => include}/ExtractFromXML.h | 0 {code/include => include}/Replacer.h | 0 {code/include => include}/Translator.h | 0 {code/include => include}/strManipulation.h | 0 {code/src => src}/Data.cpp | 0 {code/src => src}/ExtractFromElement.cpp | 0 {code/src => src}/ExtractFromXML.cpp | 0 {code/src => src}/Replacer.cpp | 0 {code/src => src}/Translator.cpp | 0 {code/src => src}/main.cpp | 0 {code/src => src}/strManipulation.cpp | 0 14 files changed, 0 insertions(+), 0 deletions(-) rename code/CMakeLists.txt => CMakeLists.txt (100%) rename {code/include => include}/Data.h (100%) rename {code/include => include}/ExtractFromElement.h (100%) rename {code/include => include}/ExtractFromXML.h (100%) rename {code/include => include}/Replacer.h (100%) rename {code/include => include}/Translator.h (100%) rename {code/include => include}/strManipulation.h (100%) rename {code/src => src}/Data.cpp (100%) rename {code/src => src}/ExtractFromElement.cpp (100%) rename {code/src => src}/ExtractFromXML.cpp (100%) rename {code/src => src}/Replacer.cpp (100%) rename {code/src => src}/Translator.cpp (100%) rename {code/src => src}/main.cpp (100%) rename {code/src => src}/strManipulation.cpp (100%) diff --git a/code/CMakeLists.txt b/CMakeLists.txt similarity index 100% rename from code/CMakeLists.txt rename to CMakeLists.txt diff --git a/code/include/Data.h b/include/Data.h similarity index 100% rename from code/include/Data.h rename to include/Data.h diff --git a/code/include/ExtractFromElement.h b/include/ExtractFromElement.h similarity index 100% rename from code/include/ExtractFromElement.h rename to include/ExtractFromElement.h diff --git a/code/include/ExtractFromXML.h b/include/ExtractFromXML.h similarity index 100% rename from code/include/ExtractFromXML.h rename to include/ExtractFromXML.h diff --git a/code/include/Replacer.h b/include/Replacer.h similarity index 100% rename from code/include/Replacer.h rename to include/Replacer.h diff --git a/code/include/Translator.h b/include/Translator.h similarity index 100% rename from code/include/Translator.h rename to include/Translator.h diff --git a/code/include/strManipulation.h b/include/strManipulation.h similarity index 100% rename from code/include/strManipulation.h rename to include/strManipulation.h diff --git a/code/src/Data.cpp b/src/Data.cpp similarity index 100% rename from code/src/Data.cpp rename to src/Data.cpp diff --git a/code/src/ExtractFromElement.cpp b/src/ExtractFromElement.cpp similarity index 100% rename from code/src/ExtractFromElement.cpp rename to src/ExtractFromElement.cpp diff --git a/code/src/ExtractFromXML.cpp b/src/ExtractFromXML.cpp similarity index 100% rename from code/src/ExtractFromXML.cpp rename to src/ExtractFromXML.cpp diff --git a/code/src/Replacer.cpp b/src/Replacer.cpp similarity index 100% rename from code/src/Replacer.cpp rename to src/Replacer.cpp diff --git a/code/src/Translator.cpp b/src/Translator.cpp similarity index 100% rename from code/src/Translator.cpp rename to src/Translator.cpp diff --git a/code/src/main.cpp b/src/main.cpp similarity index 100% rename from code/src/main.cpp rename to src/main.cpp diff --git a/code/src/strManipulation.cpp b/src/strManipulation.cpp similarity index 100% rename from code/src/strManipulation.cpp rename to src/strManipulation.cpp