Skip to content

Commit

Permalink
Merge pull request #3 from convince-project/dev
Browse files Browse the repository at this point in the history
Enabling log_mode
  • Loading branch information
SofiaFaraci authored Nov 19, 2024
2 parents b9ab287 + 67874f3 commit d4d4f59
Show file tree
Hide file tree
Showing 13 changed files with 143 additions and 70 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ model2code --input_filename "input_model.scxml" --model_filename "project_model_
```
replace `input_model.scxml`, `project_model_definition.scxml`, `interface_definition.scxml`, `path/to/output/directory` and `path/to/template_skill/directory` with your needs.

Add `--verbose_mode` for enabling the logging.
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 '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 `tutorials/specifications` folder.
Expand All @@ -52,5 +53,5 @@ model2code --input_filename "tutorials/skills/first_tutorial_skill/src/FirstTuto
```
Example 2:
```
model2code --input_filename "tutorials/skills/second_tutorial_skill/src/SecondTutorialSkill.scxml" --model_filename "tutorials/specifications/full-model.xml" --interface_filename "tutorials/specifications/interfaces.xml"
model2code --input_filename "tutorials/skills/second_tutorial_skill/src/SecondTutorialSkill.scxml" --model_filename "tutorials/specifications/full-model.xml" --interface_filename "tutorials/specifications/interfaces.xml" --verbose_mode
```
1 change: 1 addition & 0 deletions docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ Required parameters:
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.

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.
The ``--log_mode`` parameter can be used to enable verbose logging.

The generated skills are based on a behavior tree structure. Skills corresponding to condition nodes will have a ROS2 tick service, while skills corresponding to action nodes will have both tick and halt services.

Expand Down
6 changes: 4 additions & 2 deletions docs/source/tutorials.rst
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ To run the model2code use the following parameters:
- `--interface_filename` (required): The path to the XML file that describes the interfaces used.
- `--template_path`: The path to the directory containing the templates for the files to be generated. By default, the program uses the `templates` directory.
- `--output_path`: The path to the directory where the generated files will be placed. By default, the program generates the code in the same directory as the SCXML file specified by the `--input_filename` parameter.
- `--log_mode`: To enable logging. By default, the program does not log.

First example
```````````````
Expand Down Expand Up @@ -62,6 +63,7 @@ To generate the code for this skill, move to the model2code folder and run the f

.. code-block:: bash
model2code --input_filename "tutorials/skills/second_tutorial_skill/src/SecondTutorialSkill.scxml" --model_filename "tutorials/specifications/full-model.xml" --interface_filename "tutorials/specifications/interfaces.xml" --output_path "tutorials/skills/second_tutorial_skill"
model2code --input_filename "tutorials/skills/second_tutorial_skill/src/SecondTutorialSkill.scxml" --model_filename "tutorials/specifications/full-model.xml" --interface_filename "tutorials/specifications/interfaces.xml" --output_path "tutorials/skills/second_tutorial_skill" --log_mode
The generated code will be placed in the `tutorials/skills/second_tutorial_skill` folder. The structure of generated files follows that of the first example, with the only difference being that 'SecondTutorialSkill.cpp' omits the halt service and includes a subscriber for 'Function2'.
The generated code will be placed in the `tutorials/skills/second_tutorial_skill` folder. The structure of generated files follows that of the first example, with the only difference being that 'SecondTutorialSkill.cpp' omits the halt service and includes a subscriber for 'Function2'.
In this example the `--log_mode` parameter is used to enable verbose logging.
15 changes: 15 additions & 0 deletions include/Data.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
#define rspTick "TICK_RESPONSE"
#define rspHalt "HALT_RESPONSE"



struct skillDataStr{
std::string SMName;
std::string className;
Expand Down Expand Up @@ -86,6 +88,7 @@ struct fileDataStr{
bool datamodel_mode;
bool translate_mode;
bool generate_mode;
bool verbose_mode;
};

struct templateFileDataStr{
Expand Down Expand Up @@ -197,3 +200,15 @@ void printSkillData(skillDataStr skillData);
*/
void setFileData(fileDataStr& fileData, const skillDataStr skillData);

/**
* @brief Add a message to the log
*
* @param fileName file name
* @param path path passed by reference where the path is stored
*/
void add_to_log(const std::string& message);
/**
* @brief print the log
*
*/
void print_log();
7 changes: 6 additions & 1 deletion include/Replacer.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,12 @@ void replaceEventCode(std::map <std::string, std::string>& codeMap);
*/
bool readTemplates(templateFileDataStr& templateFileData, std::map <std::string, std::string>& codeMap);


/**
* @brief function to create a directory
*
* @param path string of the directory path
* @return true if the directory is created successfully
*/
bool createDirectory(const std::string& path);

/**
Expand Down
11 changes: 7 additions & 4 deletions include/Translator.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,18 @@ bool deleteElementAttribute(tinyxml2::XMLElement* element, const std::string& at
bool deleteElementAttributeFromVector(std::vector<tinyxml2::XMLElement*>& elements, const std::string& attribute);

/**
* @brief
* @brief read the XML file
*
* @param
* @param doc XMLDocument to read the file
* @param fileName file name to read
* @return true if the file is read successfully
*/
bool readHLXMLFile(tinyxml2::XMLDocument& doc, const std::string fileName);

/**
* @brief
* @brief translate the XML file from High-Level SCXML to SCXML
*
* @param
* @param fileData file data structure passed by reference where the file data is stored
* @return true if the translation is successful
*/
bool Translator(fileDataStr& fileData);
2 changes: 1 addition & 1 deletion include/strManipulation.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ bool readTemplateFile(const std::string filePath, std::string& fileContent);
* @return true
* @return false
*/
bool writeFile(const std::string filePath, const std::string fileContent);
bool writeFile(const std::string filePath, const std::string fileName, const std::string fileContent);

/**
* @brief function that replaces all the occurences of a string with another string
Expand Down
32 changes: 25 additions & 7 deletions src/Data.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

#include "Data.h"

std::string log_str;
/**
* @brief Get component and function data from event string (Format: componentName.functionName.eventName)
*
Expand Down Expand Up @@ -55,7 +56,7 @@ bool getDataFromRootName(const std::string attributeName, skillDataStr& skillDat
{
// e.g. attributeName = "FirstTemplateSkillAction"
if (attributeName != ""){
std::cout << "Root attribute name: " << attributeName << std::endl;
add_to_log("Root attribute name: " + attributeName);
size_t dotPos = attributeName.find("Skill");
if (dotPos != std::string::npos){
skillData.SMName = attributeName; // e.g. SMName = "FirstTemplateSkillAction"
Expand Down Expand Up @@ -105,11 +106,11 @@ bool getDataFromRootName(const std::string attributeName, skillDataStr& skillDat
*/
void printEventData(eventDataStr eventData)
{
std::cout << "\tcomponent=" << eventData.componentName << ", service=" << eventData.functionName << ", eventName=" << eventData.eventName << std::endl;
std::cout<< "\tinterface=" << eventData.interfaceName << ", type=" << eventData.interfaceType;
add_to_log("\tcomponent=" + eventData.componentName + ", service=" + eventData.functionName + ", eventName=" + eventData.eventName);
add_to_log("\tinterface=" + eventData.interfaceName + ", type=" + eventData.interfaceType);
for(auto it = eventData.interfaceData.begin(); it != eventData.interfaceData.end(); ++it)
{
std::cout << "\n\t dataField=" << it->first << ", dataType=" << it->second;
add_to_log("\n\t dataField=" + it->first + ", dataType=" + it->second);
}
std::cout << std::endl;

Expand All @@ -122,9 +123,9 @@ void printEventData(eventDataStr eventData)
*/
void printSkillData(skillDataStr skillData)
{
std::cout << "-----------" << std::endl;
std::cout << "Class name: " << skillData.className << std::endl << "Skill name: " << skillData.skillName << std::endl << "Skill type: " << skillData.skillType << std::endl;
std::cout << "-----------" << std::endl;
add_to_log("-----------");
add_to_log("Class name: " + skillData.className + "\nSkill name: " + skillData.skillName + "\nSkill type: " + skillData.skillType);
add_to_log("-----------");
}
/** @} */ // end of printData subgroup

Expand All @@ -143,4 +144,21 @@ void setFileData(fileDataStr& fileData, const skillDataStr skillData)
fileData.outputMainFileName = "main.cpp";
fileData.outputCMakeListsFileName = "CMakeLists.txt";
fileData.outputPackageXMLFileName = "package.xml";
}

/**
* @brief Add a message to the log
*
* @param fileName file name
* @param path path passed by reference where the path is stored
*/
void add_to_log(const std::string& message) {
log_str += message + "\n";
}
/**
* @brief print the log
*
*/
void print_log() {
std::cout << log_str;
}
20 changes: 12 additions & 8 deletions src/ExtractFromXML.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,23 +103,27 @@ bool extractInterfaceType(const std::string fileName, eventDataStr& eventData)
eventData.interfaceType = interfaceType;
if(!findElementByTag(elementFunction, std::string("dataField"), elementDataField))
{
std::cerr << "No tag <dataField> for function '" << functionName << "'."<< std::endl;
// std::cerr << "No tag <dataField> for function '" << functionName << "'."<< std::endl;
add_to_log("No tag <dataField> for function '" + functionName + "'.");
return true;
}
if(!getElementText(elementDataField, interfaceDataField))
{
std::cerr << "No value in tag <dataField> for function '" << functionName << "'."<< std::endl;
// std::cerr << "No value in tag <dataField> for function '" << functionName << "'."<< std::endl;
add_to_log("No value in tag <dataField> for function '" + functionName + "'.");
return true;
}
if(!findElementByTag(elementFunction, std::string("dataType"), elementDataType))
{
std::cerr << "No tag <dataType> for function '" << functionName << "'."<< std::endl;
// std::cerr << "No tag <dataType> for function '" << functionName << "'."<< std::endl;
add_to_log("No tag <dataType> for function '" + functionName + "'.");
//Not every interface has a defined DataType TODO
return true;
}
if(!getElementText(elementDataType, interfaceDataType))
{
std::cerr << "No value in tag <dataType> for function '" << functionName << "'."<< std::endl;
// std::cerr << "No value in tag <dataType> for function '" << functionName << "'."<< std::endl;
add_to_log("No value in tag <dataType> for function '" + functionName + "'.");
return true;
}
std::vector<tinyxml2::XMLElement*> elementsReturnValue;
Expand Down Expand Up @@ -168,21 +172,21 @@ bool extractFromSCXML(tinyxml2::XMLDocument& doc, const std::string fileName, st
// Get transitions
findElementVectorByTagAndAttribute(root, std::string("transition"), "event", elementsTransition);
if (elementsTransition.empty()) {
std::cout << "No transition elements found." << std::endl;
add_to_log("No transition elements found.");
}
else
{
std::cout << "Transition elements found." << std::endl;
add_to_log("Transition elements found.");
}

// Get Send
findElementVectorByTagAndAttribute(root, std::string("send"), "event", elementsSend);
if (elementsSend.empty()) {
std::cout << "No Send elements found." << std::endl;
add_to_log("No Send elements found.");
}
else
{
std::cout << "Send elements found." << std::endl;
add_to_log("Send elements found.");
}
return true;
}
Expand Down
46 changes: 26 additions & 20 deletions src/Replacer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
bool getEventData(fileDataStr fileData, eventDataStr& eventData)
{
if(eventsMap.find(eventData.event) != eventsMap.end()){
std::cout << "Event already processed: " << eventData.event << std::endl;
add_to_log("Event already processed: " + eventData.event);
return true;
}
eventsMap[eventData.event];
Expand Down Expand Up @@ -67,7 +67,8 @@ bool getEventsVecData(fileDataStr fileData, const std::vector<tinyxml2::XMLEleme

if (event && target)
{
std::cout << "\nTransition: event=" << event << ", target=" << target << std::endl;

add_to_log("Transition: event=" + std::string(event) + ", target=" + std::string(target));
eventDataStr eventData;
eventData.target = target;
eventData.event = event;
Expand All @@ -87,7 +88,7 @@ bool getEventsVecData(fileDataStr fileData, const std::vector<tinyxml2::XMLEleme

if (event)
{
std::cout << "\nSend: event=" << event << std::endl;
add_to_log("Send: event=" + std::string(event));
eventDataStr eventData;
eventData.event = event;
eventData.eventType = "send";
Expand All @@ -98,7 +99,7 @@ bool getEventsVecData(fileDataStr fileData, const std::vector<tinyxml2::XMLEleme
getElementAttValue(element, "name", paramName);
getElementAttValue(element, "expr", paramExpr);
eventData.paramMap[paramName] = paramExpr;
std::cout << "\tparamName=" << paramName << ", paramExpr=" << eventData.paramMap[paramName] << std::endl;
add_to_log("\tparamName=" + paramName + ", paramExpr=" + eventData.paramMap[paramName]);
}
if(!getEventData(fileData, eventData))
{
Expand Down Expand Up @@ -424,15 +425,21 @@ bool readTemplates(templateFileDataStr& templateFileData, std::map <std::string,
return res;
}

/**
* @brief function to create a directory
*
* @param path path to the directory
* @return true if the directory is created successfully
*/
bool createDirectory(const std::string& path) {
namespace fs = std::filesystem;
try {
// Create the directory (and any intermediate directories, if necessary)
if (fs::create_directories(path)) {
std::cout << "Directory created successfully: " << path << std::endl;
add_to_log("Directory created successfully: " + path);
return true;
} else {
std::cerr << "Directory already exists or failed to create: " << path << std::endl;
add_to_log("Directory already exists or failed to create: " + path);
return false;
}
} catch (const fs::filesystem_error& err) {
Expand All @@ -447,8 +454,7 @@ bool createDirectory(const std::string& path) {
*
* @param fileData file data structure passed by reference where the file data is stored
* @param templateFileData template file data structure passed by reference where the template file data is stored
* @return true
* @return false
* @return true if the generation is successful
*/
bool Replacer(fileDataStr& fileData, templateFileDataStr& templateFileData)
{
Expand All @@ -457,7 +463,7 @@ bool Replacer(fileDataStr& fileData, templateFileDataStr& templateFileData)
std::map <std::string, std::string> codeMap;
std::vector<tinyxml2::XMLElement *> elementsTransition, elementsSend;
tinyxml2::XMLDocument doc;
std::cout << "-----------" << std::endl;
add_to_log("-----------");
if(!extractFromSCXML(doc, fileData.inputFileNameGeneration, rootName, elementsTransition, elementsSend)){
return 0;
}
Expand All @@ -473,7 +479,6 @@ bool Replacer(fileDataStr& fileData, templateFileDataStr& templateFileData)
}

for (auto it = codeMap.begin(); it != codeMap.end(); it++) {
// std::cout << it->first << ": " << it->second << std::endl;
replaceAll(it->second, "$className$", skillData.className);
replaceAll(it->second, "$projectName$", skillData.classNameSnakeCase);
replaceAll(it->second, "$SMName$", skillData.SMName);
Expand Down Expand Up @@ -501,22 +506,23 @@ bool Replacer(fileDataStr& fileData, templateFileDataStr& templateFileData)
return false;
}
replaceEventCode(codeMap);
std::cout << "-----------" << std::endl;

add_to_log("-----------");
if(fileData.datamodel_mode)
{
writeFile(fileData.outputPathInclude + fileData.outputDatamodelFileNameH, codeMap["hDataModelCode"]);
writeFile(fileData.outputPathSrc + fileData.outputDatamodelFileNameCPP, codeMap["cppDataModelCode"]);
writeFile(fileData.outputPathInclude, fileData.outputDatamodelFileNameH, codeMap["hDataModelCode"]);
writeFile(fileData.outputPathSrc, fileData.outputDatamodelFileNameCPP, codeMap["cppDataModelCode"]);
}
std::cout << "-----------" << std::endl;
add_to_log("-----------");
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"]);
writeFile(fileData.outputPath + fileData.outputPackageXMLFileName, codeMap["packageCode"]);
writeFile(fileData.outputPathSrc + fileData.outputMainFileName, codeMap["mainCode"]);
add_to_log("-----------");
writeFile(fileData.outputPathInclude, fileData.outputFileNameH, codeMap["hCode"]);
writeFile(fileData.outputPathSrc, fileData.outputFileNameCPP, codeMap["cppCode"]);
writeFile(fileData.outputPath, fileData.outputCMakeListsFileName, codeMap["cmakeCode"]);
writeFile(fileData.outputPath, fileData.outputPackageXMLFileName, codeMap["packageCode"]);
writeFile(fileData.outputPathSrc, fileData.outputMainFileName, codeMap["mainCode"]);

return true;
}
Loading

0 comments on commit d4d4f59

Please sign in to comment.