diff --git a/src/brsoa_build.py b/src/brsoa_build.py
new file mode 100644
index 0000000..42a481c
--- /dev/null
+++ b/src/brsoa_build.py
@@ -0,0 +1,87 @@
+# Copyright (C) 2025 Bellande Robotics Sensors Research Innovation Center, Ronaldson Bellande
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+import os
+import subprocess
+from bellande_parser.bellande_parser import Bellande_Format
+
+def load_config():
+ bellande_parser = Bellande_Format()
+ raw_content = bellande_parser.parse_bellande("project_config.bellande")
+
+def build_cpp(package_dir, output_dir, config):
+ src_file = os.path.join(package_dir, f"{os.path.basename(package_dir)}.cpp")
+ output_file = os.path.join(output_dir, os.path.basename(package_dir))
+ compiler = config['build_settings']['cpp']['compiler']
+ flags = ' '.join(config['build_settings']['cpp']['flags'])
+
+ cmd = f"{compiler} {flags} -I build/common_msgs {src_file} -o {output_file}"
+ subprocess.run(cmd, shell=True, check=True)
+
+def build_python(package_dir, output_dir, config):
+ src_file = os.path.join(package_dir, f"{os.path.basename(package_dir)}.py")
+ output_file = os.path.join(output_dir, os.path.basename(src_file))
+ os.makedirs(output_dir, exist_ok=True)
+ os.symlink(src_file, output_file)
+
+def build_java(package_dir, output_dir, config):
+ src_file = os.path.join(package_dir, f"{os.path.basename(package_dir)}.java")
+ output_dir = os.path.join(output_dir, "classes")
+ os.makedirs(output_dir, exist_ok=True)
+
+ cmd = f"javac -d {output_dir} -cp build/common_msgs {src_file}"
+ subprocess.run(cmd, shell=True, check=True)
+
+def build_rust(package_dir, output_dir, config):
+ cmd = f"cargo build --release --manifest-path {os.path.join(package_dir, 'Cargo.toml')}"
+ subprocess.run(cmd, shell=True, check=True)
+
+ binary_name = os.path.basename(package_dir)
+ src = os.path.join(package_dir, "target", "release", binary_name)
+ dst = os.path.join(output_dir, binary_name)
+ os.makedirs(output_dir, exist_ok=True)
+ os.rename(src, dst)
+
+def build_go(package_dir, output_dir, config):
+ cmd = f"go build -o {output_dir} {os.path.join(package_dir, '*.go')}"
+ subprocess.run(cmd, shell=True, check=True)
+
+def main():
+ config = load_config()
+
+ # Generate common messages
+ subprocess.run(["python", "generate_msgs.py"], check=True)
+
+ build_functions = {
+ 'cpp': build_cpp,
+ 'python': build_python,
+ 'java': build_java,
+ 'rust': build_rust,
+ 'go': build_go,
+ }
+
+ for package in config['packages']:
+ package_dir = os.path.join('src', package['name'])
+ output_dir = os.path.join('build', package['name'])
+ os.makedirs(output_dir, exist_ok=True)
+
+ lang = package['language']
+ if lang in build_functions:
+ build_functions[lang](package_dir, output_dir, config)
+ else:
+ print(f"Warning: No build function for language '{lang}'")
+
+if __name__ == "__main__":
+ main()
diff --git a/src/brsoa_create_package.py b/src/brsoa_create_package.py
new file mode 100644
index 0000000..77f4202
--- /dev/null
+++ b/src/brsoa_create_package.py
@@ -0,0 +1,187 @@
+# Copyright (C) 2025 Bellande Robotics Sensors Research Innovation Center, Ronaldson Bellande
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+import os
+import argparse
+from bellande_parser.bellande_parser import Bellande_Format
+
+TEMPLATE_DIR = "templates"
+
+def create_package_bellande(package_name, language, dependencies):
+ content = {
+ "name": package_name,
+ "language": language,
+ "dependencies": dependencies
+ }
+ return yaml.dump(content, default_flow_style=False)
+
+def create_cpp_source(package_name):
+ return f"""#include "common_msgs.hpp"
+#include
+#include
+#include
+
+class {package_name.capitalize()} {{
+public:
+ void run() {{
+ while (true) {{
+ // TODO: Implement node logic
+ std::cout << "Running {package_name}" << std::endl;
+ std::this_thread::sleep_for(std::chrono::seconds(1));
+ }}
+ }}
+}};
+
+int main(int argc, char** argv) {{
+ {package_name.capitalize()} node;
+ node.run();
+ return 0;
+}}
+"""
+
+def create_python_source(package_name):
+ return f"""from common_msgs import *
+import time
+
+class {package_name.capitalize()}:
+ def run(self):
+ while True:
+ # TODO: Implement node logic
+ print(f"Running {package_name}")
+ time.sleep(1)
+
+if __name__ == "__main__":
+ node = {package_name.capitalize()}()
+ node.run()
+"""
+
+def create_java_source(package_name):
+ return f"""import common_msgs.Messages.*;
+
+public class {package_name.capitalize()} {{
+ public void run() {{
+ while (true) {{
+ // TODO: Implement node logic
+ System.out.println("Running {package_name}");
+ try {{
+ Thread.sleep(1000);
+ }} catch (InterruptedException e) {{
+ e.printStackTrace();
+ }}
+ }}
+ }}
+
+ public static void main(String[] args) {{
+ {package_name.capitalize()} node = new {package_name.capitalize()}();
+ node.run();
+ }}
+}}
+"""
+
+def create_rust_source(package_name):
+ return f"""use common_msgs::*;
+use std::{{thread, time}};
+
+struct {package_name.capitalize()};
+
+impl {package_name.capitalize()} {{
+ fn run(&self) {{
+ loop {{
+ // TODO: Implement node logic
+ println!("Running {package_name}");
+ thread::sleep(time::Duration::from_secs(1));
+ }}
+ }}
+}}
+
+fn main() {{
+ let node = {package_name.capitalize()}{{}};
+ node.run();
+}}
+"""
+
+def create_go_source(package_name):
+ return f"""package main
+
+import (
+ "fmt"
+ "time"
+ "common_msgs"
+)
+
+type {package_name.capitalize()} struct{{}}
+
+func (n *{package_name.capitalize()}) Run() {{
+ for {{
+ // TODO: Implement node logic
+ fmt.Println("Running {package_name}")
+ time.Sleep(1 * time.Second)
+ }}
+}}
+
+func main() {{
+ node := &{package_name.capitalize()}{{}}
+ node.Run()
+}}
+"""
+
+def create_package(package_name, language):
+ package_dir = os.path.join("src", package_name)
+ os.makedirs(package_dir, exist_ok=True)
+
+ # Create package.bellande
+ with open(os.path.join(package_dir, "package.bellande"), "w") as f:
+ f.write(create_package_bellande(package_name, language, ["common_msgs"]))
+
+ # Create source file
+ source_creators = {
+ "cpp": create_cpp_source,
+ "python": create_python_source,
+ "java": create_java_source,
+ "rust": create_rust_source,
+ "go": create_go_source
+ }
+
+ if language in source_creators:
+ source_content = source_creators[language](package_name)
+ source_filename = f"{package_name}.{language}"
+ if language == "cpp":
+ source_filename = f"{package_name}.cpp"
+ elif language == "python":
+ source_filename = f"{package_name}.py"
+ elif language == "java":
+ source_filename = f"{package_name.capitalize()}.java"
+ elif language == "rust":
+ source_filename = "main.rs"
+ os.makedirs(os.path.join(package_dir, "src"), exist_ok=True)
+ with open(os.path.join(package_dir, "Cargo.toml"), "w") as f:
+ f.write(f"[package]\nname = \"{package_name}\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n[dependencies]\ncommon_msgs = {{ path = \"../../build/common_msgs\" }}\n")
+ elif language == "go":
+ source_filename = f"{package_name}.go"
+
+ with open(os.path.join(package_dir, source_filename), "w") as f:
+ f.write(source_content)
+ else:
+ print(f"Unsupported language: {language}")
+
+if __name__ == "__main__":
+ parser = argparse.ArgumentParser(description="Create a new package for the robot architecture.")
+ parser.add_argument("package_name", help="Name of the package to create")
+ parser.add_argument("language", choices=["cpp", "python", "java", "rust", "go"], help="Programming language for the package")
+
+ args = parser.parse_args()
+
+ create_package(args.package_name, args.language)
+ print(f"Created package {args.package_name} using {args.language}")
diff --git a/src/brsoa_create_system_config.py b/src/brsoa_create_system_config.py
new file mode 100644
index 0000000..61f411a
--- /dev/null
+++ b/src/brsoa_create_system_config.py
@@ -0,0 +1,131 @@
+# Copyright (C) 2025 Bellande Robotics Sensors Research Innovation Center, Ronaldson Bellande
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+#!/usr/bin/env python3
+
+# Will later be programming bellronos
+def create_example_lua_config_file(filename="brsoa_system_config.lua"):
+ """
+ Creates an example Lua configuration file for a robot system with generic settings.
+
+ Args:
+ filename (str): The name of the file to create
+
+ Returns:
+ bool: True if file creation was successful
+ """
+ # Configuration content with generic example values
+ config_content = """-- brsoa_system_config.lua
+-- Global configuration
+global_config = {
+ max_nodes = 50,
+ discovery_method = "broadcast",
+ system_name = "example_system",
+ log_level = "debug"
+}
+
+-- Define nodes to be launched
+nodes = {
+ {
+ name = "example_node_cpp",
+ package = "example_package_cpp",
+ executable = "example_driver_cpp",
+ language = "cpp",
+ args = {"--fps=30"},
+ env = {SENSOR_TYPE = "lidar"}
+ },
+ {
+ name = "example_node_py",
+ package = "example_package_py",
+ executable = "example_package_py.py",
+ language = "python",
+ args = {"--algorithm=detection"},
+ env = {PYTHONPATH = "${WORKSPACE}/lib:${WORKSPACE}/include"}
+ },
+ {
+ name = "example_node_java",
+ package = "example_ui_package_java",
+ executable = "ExampleDisplayAppJava",
+ language = "java",
+ args = {"--resolution=720p"},
+ env = {JAVA_OPTS = "-Xmx1g"}
+ },
+ {
+ name = "example_node_rust",
+ package = "example_package_rust",
+ executable = "example_package_rust",
+ language = "rust",
+ args = {"--mode=manual"},
+ env = {RUST_BACKTRACE = "1"}
+ },
+ {
+ name = "example_node_bridge_go",
+ package = "example_package_go",
+ executable = "example_package_go",
+ language = "go",
+ args = {"--port=9090"},
+ env = {GOMAXPROCS = "2"}
+ }
+}
+
+-- Define communication setup
+topics = {
+ {
+ name = "/example/example",
+ type = "Example",
+ queue_size = 5,
+ publishers = {"example_node"},
+ subscribers = {"example1", "example2"}
+ }
+}
+
+-- Define services
+services = {
+ {
+ name = "/example/example",
+ type = "Example",
+ server = "example_server",
+ clients = {"example_client"}
+ }
+}
+
+-- Define parameters
+parameters = {
+ {
+ name = "/example/example",
+ type = "string",
+ value = global_config.system_name
+ }
+}"""
+
+ try:
+ # Write the configuration to the file
+ with open(filename, 'w') as file:
+ file.write(config_content)
+ print(f"Successfully created example file {filename}")
+ return True
+ except Exception as e:
+ print(f"Error creating file: {e}")
+ return False
+
+
+if __name__ == "__main__":
+ # Create the example Lua configuration file
+ success = create_example_lua_config_file()
+
+ if success:
+ print("Example configuration file creation completed.")
+ else:
+ print("Failed to create example configuration file.")
diff --git a/src/brsoa_generate_msgs.py b/src/brsoa_generate_msgs.py
new file mode 100644
index 0000000..9a249d3
--- /dev/null
+++ b/src/brsoa_generate_msgs.py
@@ -0,0 +1,192 @@
+# Copyright (C) 2025 Bellande Robotics Sensors Research Innovation Center, Ronaldson Bellande
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+import os
+from bellande_parser.bellande_parser import Bellande_Format
+
+def parse_def_file(filename):
+ bellande_parser = Bellande_Format()
+ content = bellande_parser.parse_bellande(filename)
+
+ structures = {}
+ enums = {}
+ current_struct = None
+ current_enum = None
+
+ for line in content.split('\n'):
+ line = line.strip()
+ if not line or line.startswith('#'):
+ continue
+
+ if line.startswith('struct'):
+ current_struct = line.split()[1]
+ structures[current_struct] = []
+ current_enum = None
+ elif line.startswith('enum'):
+ current_enum = line.split()[1]
+ enums[current_enum] = []
+ current_struct = None
+ elif current_struct:
+ field_type, field_name = line.split()
+ structures[current_struct].append((field_type, field_name))
+ elif current_enum:
+ enums[current_enum].append(line)
+
+ return structures, enums
+
+def generate_cpp(structures, enums):
+ code = "#pragma once\n\n#include \n#include \n#include \n\nnamespace common_msgs {\n\n"
+
+ for enum_name, enum_values in enums.items():
+ code += f"enum class {enum_name} {{\n"
+ code += ',\n'.join(f" {value}" for value in enum_values)
+ code += "\n};\n\n"
+
+ for struct_name, fields in structures.items():
+ code += f"struct {struct_name} {{\n"
+ for field_type, field_name in fields:
+ if field_type == 'timestamp':
+ code += f" std::chrono::system_clock::time_point {field_name};\n"
+ elif field_type.startswith('list<'):
+ inner_type = field_type[5:-1]
+ code += f" std::vector<{inner_type}> {field_name};\n"
+ else:
+ code += f" {field_type} {field_name};\n"
+ code += "};\n\n"
+
+ code += "} // namespace common_msgs\n"
+ return code
+
+def generate_python(structures, enums):
+ code = "from dataclasses import dataclass\nfrom typing import List\nimport datetime\n\n"
+
+ for enum_name, enum_values in enums.items():
+ code += f"class {enum_name}:\n"
+ for i, value in enumerate(enum_values):
+ code += f" {value} = {i}\n"
+ code += "\n"
+
+ for struct_name, fields in structures.items():
+ code += f"@dataclass\nclass {struct_name}:\n"
+ for field_type, field_name in fields:
+ if field_type == 'timestamp':
+ code += f" {field_name}: datetime.datetime\n"
+ elif field_type.startswith('list<'):
+ inner_type = field_type[5:-1]
+ code += f" {field_name}: List[{inner_type}]\n"
+ else:
+ code += f" {field_name}: {field_type}\n"
+ code += "\n"
+
+ return code
+
+def generate_java(structures, enums):
+ code = "package common_msgs;\n\nimport java.time.Instant;\nimport java.util.List;\n\npublic class Messages {\n\n"
+
+ for enum_name, enum_values in enums.items():
+ code += f" public enum {enum_name} {{\n"
+ code += ',\n'.join(f" {value}" for value in enum_values)
+ code += "\n }\n\n"
+
+ for struct_name, fields in structures.items():
+ code += f" public static class {struct_name} {{\n"
+ for field_type, field_name in fields:
+ if field_type == 'timestamp':
+ code += f" public Instant {field_name};\n"
+ elif field_type.startswith('list<'):
+ inner_type = field_type[5:-1]
+ code += f" public List<{inner_type}> {field_name};\n"
+ else:
+ code += f" public {field_type} {field_name};\n"
+ code += " }\n\n"
+
+ code += "}\n"
+ return code
+
+def generate_rust(structures, enums):
+ code = "use chrono::DateTime;\nuse chrono::Utc;\n\n"
+
+ for enum_name, enum_values in enums.items():
+ code += f"pub enum {enum_name} {{\n"
+ code += ',\n'.join(f" {value}" for value in enum_values)
+ code += "\n}\n\n"
+
+ for struct_name, fields in structures.items():
+ code += f"pub struct {struct_name} {{\n"
+ for field_type, field_name in fields:
+ if field_type == 'timestamp':
+ code += f" pub {field_name}: DateTime,\n"
+ elif field_type.startswith('list<'):
+ inner_type = field_type[5:-1]
+ code += f" pub {field_name}: Vec<{inner_type}>,\n"
+ elif field_type == 'string':
+ code += f" pub {field_name}: String,\n"
+ else:
+ code += f" pub {field_name}: {field_type},\n"
+ code += "}\n\n"
+
+ return code
+
+def generate_go(structures, enums):
+ code = "package common_msgs\n\nimport (\n\t\"time\"\n)\n\n"
+
+ for enum_name, enum_values in enums.items():
+ code += f"type {enum_name} int\n\nconst (\n"
+ for i, value in enumerate(enum_values):
+ code += f" {value} {enum_name} = iota\n"
+ code += ")\n\n"
+
+ for struct_name, fields in structures.items():
+ code += f"type {struct_name} struct {{\n"
+ for field_type, field_name in fields:
+ if field_type == 'timestamp':
+ code += f" {field_name.capitalize()} time.Time\n"
+ elif field_type.startswith('list<'):
+ inner_type = field_type[5:-1]
+ code += f" {field_name.capitalize()} []{inner_type}\n"
+ elif field_type == 'string':
+ code += f" {field_name.capitalize()} string\n"
+ else:
+ code += f" {field_name.capitalize()} {field_type}\n"
+ code += "}\n\n"
+
+ return code
+
+def main():
+ bellande_parser = Bellande_Format()
+
+ config = bellande_parser.parse_bellande("project_config.bellande")
+ structures, enums = parse_def_file('common_msgs.bellande')
+
+ os.makedirs('build/common_msgs', exist_ok=True)
+
+ generators = {
+ 'cpp': ('common_msgs.hpp', generate_cpp),
+ 'python': ('common_msgs.py', generate_python),
+ 'java': ('common_msgs.java', generate_java),
+ 'rust': ('common_msgs.rs', generate_rust),
+ 'go': ('common_msgs.go', generate_go),
+ }
+
+ for lang in config['languages']:
+ if lang in generators:
+ filename, generator = generators[lang]
+ with open(f'build/common_msgs/{filename}', 'w') as f:
+ f.write(generator(structures, enums))
+ else:
+ print(f"Warning: No generator for language '{lang}'")
+
+if __name__ == "__main__":
+ main()