summaryrefslogtreecommitdiff
path: root/easynav-mpc-controller.spec
blob: ad373145f22e9ce2860ae4f39232afaeff7c6c1f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# ROS 2 包:easynav_mpc_controller(ament_cmake 形态)
# 来源:EasyNavigation/easynav_plugins 仓库 humble 分支(多包仓库,本包位于
#       controllers/easynav_mpc_controller/ 子目录)
# 严格遵循 /app/.claude/skills/build-rpm/spec-rules-ros.md 生成

# ros_distro 取自 session.json,禁止硬编码;RosPkgName 为 package.xml <name>
# 经下划线→连字符归一化(easynav_mpc_controller → easynav-mpc-controller)
%define ros_distro humble
%define RosPkgName easynav-mpc-controller

Name:       ros-%{ros_distro}-%{RosPkgName}
Version:    0.5.0
Release:    1%{?dist}
Summary:    Easy Navigation: MPC Controller package.
License:    Apache-2.0
URL:        https://github.com/EasyNavigation/easynav_plugins

# 源码取自 humble 分支 HEAD(commit 快照,无 0.5.0 tag,记录 commit 以保可追溯)
# 归档解压根目录 = <完整SHA>(纯 commit,无 repo 前缀;spec-rules-ros §2 实测纪律)
%global commit 2580d29baefe77305c6e9336dca743aa5ce51c2c
Source0:    https://github.com/EasyNavigation/easynav_plugins/archive/%{commit}.tar.gz

# NLopt:CMakeLists 在系统无 NLopt 时从 GitHub 下载内置静态库(MIT-only 子集),
# COPR 无网环境必失败(spec-rules §9 已知失败模式)。此处将上游归档作为 Source1
# 本地化,并用 Patch0 把 ExternalProject 的 URL 重定向到本地文件,实现离线构建。
# SHA256 与 CMakeLists 的 URL_HASH 一致(53e552d8...04cf0de),完整性可校验。
Source1:    https://github.com/stevengj/nlopt/archive/refs/tags/v2.11.0.tar.gz#/nlopt-2.11.0.tar.gz
Patch0:     nlopt-local-source.patch
# Eigen < 3.4 不支持 Matrix2d 的 brace-enclosed initializer list 语法
# {{a,b},{c,d}},openEuler 24.03 自带 Eigen 3.3 编译报错。改用逗号初始化器
# (Matrix2d() << ...).finished() 替代,兼容 Eigen 3.3+
Patch1:     eigen-matrix-init-fix.patch

# debug 子包无意义(/opt 前缀,strip/debugedit 路径非常规),统一关闭
%global debug_package %{nil}
# /opt 下 python 字节码编译会写标准 sitelib 路径,摘掉 brp-python-bytecompile
%global __os_install_post %(echo '%{__os_install_post}' | sed -e 's!/usr/lib[^[:space:]]*/brp-python-bytecompile[[:space:]].*$!!g')
# ROS 包不做自动依赖扫描(.so 全在 /opt/ros 下,由 ament 间接依赖模型替代)
%global __provides_exclude_from ^/opt/ros/%{ros_distro}/.*$
%global __requires_exclude_from ^/opt/ros/%{ros_distro}/.*$

BuildRequires:  cmake
BuildRequires:  gcc-c++
BuildRequires:  make
# ament_cmake 形态构建工具依赖(spec-rules §6)
BuildRequires:  ros-%{ros_distro}-ament-cmake
BuildRequires:  ros-%{ros_distro}-ros-workspace
# package.xml <depend> → ros-humble-<dep>(均经 ros-projects.list 实证为 SIG 维护包)
BuildRequires:  ros-%{ros_distro}-easynav-common
BuildRequires:  ros-%{ros_distro}-easynav-core
BuildRequires:  ros-%{ros_distro}-easynav-sensors
BuildRequires:  ros-%{ros_distro}-easynav-system
BuildRequires:  ros-%{ros_distro}-geometry-msgs
BuildRequires:  ros-%{ros_distro}-nav-msgs
BuildRequires:  ros-%{ros_distro}-pcl-conversions
BuildRequires:  ros-%{ros_distro}-pluginlib
BuildRequires:  ros-%{ros_distro}-rclcpp
BuildRequires:  ros-%{ros_distro}-sensor-msgs
BuildRequires:  ros-%{ros_distro}-tf2
BuildRequires:  ros-%{ros_distro}-tf2-ros
# CMake 直接 find_package 的系统依赖(package.xml 仅声明 eigen,pcl 经 pcl_conversions 传递,
# 但 CMakeLists 显式 find_package(PCL REQUIRED) 需 -devel 在 buildroot):
#   eigen → eigen3-devel(data/ros/global_config/pkg.remap 映射)
#   PCL   → pcl-devel(dnf 实证:pcl-devel-1.12.1 提供 cmake(PCL))
BuildRequires:  eigen3-devel
BuildRequires:  pcl-devel

# 运行时 Requires(spec-rules §6 三件套 + <depend> 运行期依赖):
#   ros-workspace 提供 /opt/ros/<distro>/setup.sh 与环境 hooks(所有 ROS 包强制)
#   ament-cmake ament 运行期钩子(ament_cmake 形态强制)
#   /opt/ros 被 __requires_exclude_from 豁免、autodeps 扫不到,故运行期依赖手写
Requires:       ros-%{ros_distro}-ros-workspace
Requires:       ros-%{ros_distro}-ament-cmake
Requires:       ros-%{ros_distro}-easynav-common
Requires:       ros-%{ros_distro}-easynav-core
Requires:       ros-%{ros_distro}-easynav-sensors
Requires:       ros-%{ros_distro}-easynav-system
Requires:       ros-%{ros_distro}-geometry-msgs
Requires:       ros-%{ros_distro}-nav-msgs
Requires:       ros-%{ros_distro}-pcl-conversions
Requires:       ros-%{ros_distro}-pluginlib
Requires:       ros-%{ros_distro}-rclcpp
Requires:       ros-%{ros_distro}-sensor-msgs
Requires:       ros-%{ros_distro}-tf2
Requires:       ros-%{ros_distro}-tf2-ros
# 控制器 .so 动态链接 libpcl_common/libpcl_io(在 /usr/lib64),/opt/ros 下 .so 被豁免
# 不扫 requires,故显式声明运行期 pcl
Requires:       pcl

# 单包策略:严禁拆实体子包(spec-rules §7),用虚拟别名兼容依赖方
Provides:       %{name}-devel = %{version}-%{release}
Provides:       %{name}-doc = %{version}-%{release}
Provides:       %{name}-runtime = %{version}-%{release}

%description
Easy Navigation: MPC Controller package.

Model Predictive Control (MPC) controller plugin for the Easy Navigation
stack. Built as an ament_cmake shared library registered as a pluginlib
plugin via easynav_core, with a bundled static NLopt optimizer (MIT-only
subset) when no system NLopt is available.

%prep
# 解压根目录 = <完整SHA>(纯 commit,无 repo 前缀;spec-rules-ros §2,与 regulated-pp/serest 兄弟包一致)
%autosetup -n %{commit} -p1
# 把 NLopt 源码归档放到包目录,供 Patch0 重定向后的 ExternalProject 本地引用
cp %{SOURCE1} controllers/easynav_mpc_controller/

%build
# ROS 基座环境(spec-rules §4):setup.sh 用 [ -f ] 守卫,避免无 ROS 依赖 chroot 中止脚本
[ -f /opt/ros/%{ros_distro}/setup.sh ] && source /opt/ros/%{ros_distro}/setup.sh || true
export PYTHONPATH=/opt/ros/%{ros_distro}/lib/python%{python3_version}/site-packages${PYTHONPATH:+:$PYTHONPATH}
export PKG_CONFIG_PATH=/opt/ros/%{ros_distro}/lib/pkgconfig${PKG_CONFIG_PATH:+:$PKG_CONFIG_PATH}

# 多包仓库:仅构建目标包子目录 controllers/easynav_mpc_controller
# ament_cmake 形态显式 out-of-source(spec-rules §5),规避 openEuler cmake 宏位置参数坑
# 注意:注释中严禁出现百分号+字母组合(RPM 会做宏展开注入实际命令)
cd controllers/easynav_mpc_controller
mkdir -p .obj && cd .obj
cmake \
  -DCMAKE_INSTALL_PREFIX="/opt/ros/%{ros_distro}" \
  -DAMENT_PREFIX_PATH="/opt/ros/%{ros_distro}" \
  -DCMAKE_PREFIX_PATH="/opt/ros/%{ros_distro}" \
  -UINCLUDE_INSTALL_DIR -ULIB_INSTALL_DIR -USYSCONF_INSTALL_DIR -USHARE_INSTALL_PREFIX -ULIB_SUFFIX \
  -DSETUPTOOLS_DEB_LAYOUT=OFF \
  -DBUILD_TESTING=OFF -DTESTING=OFF -DCMAKE_SUPPRESS_REGENERATION=ON \
  ..
make %{?_smp_mflags}

%install
[ -f /opt/ros/%{ros_distro}/setup.sh ] && source /opt/ros/%{ros_distro}/setup.sh || true
export PYTHONPATH=/opt/ros/%{ros_distro}/lib/python%{python3_version}/site-packages${PYTHONPATH:+:$PYTHONPATH}
export PKG_CONFIG_PATH=/opt/ros/%{ros_distro}/lib/pkgconfig${PKG_CONFIG_PATH:+:$PKG_CONFIG_PATH}
cd controllers/easynav_mpc_controller/.obj
make install DESTDIR=%{buildroot}

%files
# files 整树拥有(spec-rules §7):对「装了没打包」类错误免疫
/opt/ros/%{ros_distro}

%changelog
* Tue Oct 20 2026 AI Importer <ai-importer@opencode> - 0.5.0-1
- Initial ROS spec for easynav-mpc-controller (humble)
- Source: easynav_plugins humble branch snapshot (commit 2580d29)
- NLopt 2.11.0 vendored as Source1 + Patch0 for offline COPR build
- Single-package policy with virtual devel/doc/runtime Provides
- Fix: 注释中 cmake 宏泄漏导致构建失败,改用直接 cmake 调用(对齐 mhamcl 兄弟包)
- Fix: Eigen Matrix2d brace-init 不兼容 Eigen 3.3,Patch1 改用逗号初始化器