153 lines
6.0 KiB
Python
153 lines
6.0 KiB
Python
import os
|
|
import subprocess
|
|
from conan import ConanFile
|
|
from conan.tools.cmake import CMakeToolchain, CMakeDeps, cmake_layout
|
|
from conan.tools.files import copy, rmdir
|
|
from conan.errors import ConanException
|
|
|
|
|
|
class VideoToRosbag(ConanFile):
|
|
name = "video-to-rosbag"
|
|
description = (
|
|
"ROS2 (Jazzy) package to convert MP4 videos to image rosbags (MCAP format)"
|
|
)
|
|
license = "MIT"
|
|
url = "https://github.com/yourusername/video_to_rosbag"
|
|
author = "your.email@example.com"
|
|
topics = ("ros2", "jazzy", "video", "rosbag", "mp4", "mcap", "conversion")
|
|
|
|
settings = "os", "compiler", "build_type", "arch"
|
|
|
|
def export_sources(self):
|
|
copy(self, "CMakeLists.txt", self.recipe_folder, self.export_sources_folder)
|
|
copy(self, "package.xml", self.recipe_folder, self.export_sources_folder)
|
|
copy(self, "src/*", self.recipe_folder, self.export_sources_folder)
|
|
copy(self, "launch/*", self.recipe_folder, self.export_sources_folder)
|
|
copy(self, "LICENSE", self.recipe_folder, self.export_sources_folder)
|
|
copy(self, "README.md", self.recipe_folder, self.export_sources_folder)
|
|
|
|
def layout(self):
|
|
cmake_layout(self)
|
|
|
|
def build_requirements(self):
|
|
self.tool_requires("make/4.4.1")
|
|
self.tool_requires("cmake/3.31.9")
|
|
self.tool_requires(
|
|
"ros2-jazzy-toolchain/latest", options={"variant": "ros_base"}
|
|
)
|
|
|
|
def requirements(self):
|
|
# Only ros_base - no cv_bridge, no perception
|
|
self.requires("ros2-jazzy-python/latest")
|
|
self.requires("ros2-jazzy-toolchain/latest", options={"variant": "ros_base"})
|
|
self.requires("openssl/1.1.1w")
|
|
self.requires("console_bridge/1.0.2")
|
|
self.requires("tinyxml2/7.1.0")
|
|
self.requires("yaml-cpp/0.8.0", options={"shared": True})
|
|
|
|
# OpenCV for video reading - with FFmpeg for MP4 support
|
|
self.requires(
|
|
"opencv/4.12.0",
|
|
options={
|
|
"with_ffmpeg": True,
|
|
# "shared": True,
|
|
},
|
|
)
|
|
|
|
def generate(self):
|
|
deps = CMakeDeps(self)
|
|
deps.generate()
|
|
|
|
tc = CMakeToolchain(self)
|
|
|
|
# Get Python from Conan
|
|
python_dep = self.dependencies["ros2-jazzy-python"]
|
|
python_exe = python_dep.conf_info.get(
|
|
"user.ros2:python_interpreter", check_type=str
|
|
)
|
|
|
|
if python_exe:
|
|
tc.variables["Python3_EXECUTABLE"] = python_exe
|
|
tc.variables["Python_EXECUTABLE"] = python_exe
|
|
|
|
# OpenCV configuration
|
|
opencv_dep = self.dependencies.get("opencv")
|
|
if opencv_dep:
|
|
tc.variables["OpenCV_ROOT"] = opencv_dep.package_folder.replace("\\", "/")
|
|
|
|
tc.generate()
|
|
|
|
def build(self):
|
|
build_dep = self.dependencies.get("ros2-jazzy-toolchain")
|
|
setup_script = None
|
|
|
|
if build_dep:
|
|
env_vars = build_dep.buildenv_info.vars(self)
|
|
raw_cmd = env_vars.get("CONAN_ROS2_SOURCE_CMD", "")
|
|
if "source " in raw_cmd:
|
|
setup_script = raw_cmd.split("source ")[1].strip().split(" ")[0]
|
|
elif raw_cmd.strip().endswith((".sh", ".bash")):
|
|
setup_script = raw_cmd.strip()
|
|
|
|
tc_file = os.path.join(self.generators_folder, "conan_toolchain.cmake")
|
|
abs_build_base = os.path.join(self.build_folder, "colcon_build")
|
|
abs_install_base = os.path.join(self.build_folder, "install")
|
|
|
|
colcon_cmd = (
|
|
f"colcon build --merge-install "
|
|
f"--packages-select video_to_rosbag "
|
|
f"--build-base '{abs_build_base}' "
|
|
f"--install-base '{abs_install_base}' "
|
|
f"--event-handlers console_direct+ "
|
|
f"--cmake-args -DCMAKE_TOOLCHAIN_FILE='{tc_file}' "
|
|
f"-DCMAKE_BUILD_TYPE={self.settings.build_type}"
|
|
)
|
|
|
|
if setup_script:
|
|
full_cmd = f'/bin/bash -c "source {setup_script} && {colcon_cmd}"'
|
|
else:
|
|
full_cmd = colcon_cmd
|
|
|
|
self.output.info(f"Building with: {full_cmd}")
|
|
self.run(full_cmd, shell=True, cwd=self.source_folder)
|
|
|
|
def package(self):
|
|
install_dir = os.path.join(self.build_folder, "install")
|
|
if not os.path.exists(install_dir):
|
|
raise ConanException(
|
|
f"Build failed to produce install directory: {install_dir}"
|
|
)
|
|
|
|
ros_package_dir = os.path.join(self.package_folder, "video_to_rosbag")
|
|
copy(self, "*", src=install_dir, dst=ros_package_dir)
|
|
copy(self, "LICENSE", src=self.source_folder, dst=self.package_folder)
|
|
copy(self, "README.md", src=self.source_folder, dst=self.package_folder)
|
|
|
|
rmdir(self, os.path.join(ros_package_dir, "share", "doc"))
|
|
rmdir(self, os.path.join(ros_package_dir, "colcon_build"))
|
|
|
|
def package_info(self):
|
|
ros_root = os.path.join(self.package_folder, "video_to_rosbag")
|
|
|
|
self.cpp_info.libs = []
|
|
self.cpp_info.libdirs = [os.path.join("video_to_rosbag", "lib")]
|
|
self.cpp_info.includedirs = [os.path.join("video_to_rosbag", "include")]
|
|
self.cpp_info.bindirs = [os.path.join("video_to_rosbag", "bin")]
|
|
|
|
self.runenv_info.prepend_path("AMENT_PREFIX_PATH", ros_root)
|
|
self.buildenv_info.prepend_path("AMENT_PREFIX_PATH", ros_root)
|
|
self.runenv_info.prepend_path("CMAKE_PREFIX_PATH", ros_root)
|
|
self.buildenv_info.prepend_path("CMAKE_PREFIX_PATH", ros_root)
|
|
self.runenv_info.prepend_path("PATH", os.path.join(ros_root, "bin"))
|
|
self.runenv_info.prepend_path("LD_LIBRARY_PATH", os.path.join(ros_root, "lib"))
|
|
|
|
lib_dir = os.path.join(ros_root, "lib")
|
|
if os.path.exists(lib_dir):
|
|
for item in os.listdir(lib_dir):
|
|
if item.startswith("python"):
|
|
site_packages = os.path.join(lib_dir, item, "site-packages")
|
|
if os.path.exists(site_packages):
|
|
self.runenv_info.prepend_path("PYTHONPATH", site_packages)
|
|
self.buildenv_info.prepend_path("PYTHONPATH", site_packages)
|
|
break
|