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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
|
%define ros_distro humble
%define RosPkgName as2-behaviors-perception
%global release_num 1
Name: ros-%{ros_distro}-%{RosPkgName}
Version: 1.1.3
Release: %{release_num}%{?dist}
Summary: AS2 Behavior for object perception using a modular plugin-based pipeline
License: BSD-3-Clause
URL: https://github.com/aerostack2/aerostack2
Source0: as2-behaviors-perception-%{version}-%{release_num}.tar.gz
# debug 子包无意义(/opt 前缀,strip/debugedit 路径非常规),SIG 模板统一关闭
%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
# ROS 构建工具
BuildRequires: ros-%{ros_distro}-ament-cmake
BuildRequires: ros-%{ros_distro}-ament-cmake-ros
# ROS 依赖(SIG 源已有)
BuildRequires: ros-%{ros_distro}-pluginlib
BuildRequires: ros-%{ros_distro}-rclcpp
BuildRequires: ros-%{ros_distro}-rclcpp-action
BuildRequires: ros-%{ros_distro}-action-msgs
BuildRequires: ros-%{ros_distro}-sensor-msgs
BuildRequires: ros-%{ros_distro}-geometry-msgs
BuildRequires: ros-%{ros_distro}-cv-bridge
BuildRequires: ros-%{ros_distro}-visualization-msgs
BuildRequires: ros-%{ros_distro}-tf2
BuildRequires: ros-%{ros_distro}-std-msgs
# ROS 依赖(同 COPR project / additional_repos,aerostack2 monorepo 同源包)
BuildRequires: ros-%{ros_distro}-as2-core
BuildRequires: ros-%{ros_distro}-as2-behavior
BuildRequires: ros-%{ros_distro}-as2-msgs
BuildRequires: ros-%{ros_distro}-as2-usb-camera-interface
# 系统依赖
BuildRequires: opencv
# 运行时 Requires(/opt/ros 被 __requires_exclude_from 豁免,autodeps 扫不到,必须手写)
Requires: ros-%{ros_distro}-ros-workspace
Requires: ros-%{ros_distro}-ament-cmake
Requires: ros-%{ros_distro}-pluginlib
Requires: ros-%{ros_distro}-rclcpp
Requires: ros-%{ros_distro}-rclcpp-action
Requires: ros-%{ros_distro}-action-msgs
Requires: ros-%{ros_distro}-as2-core
Requires: ros-%{ros_distro}-as2-behavior
Requires: ros-%{ros_distro}-as2-msgs
Requires: ros-%{ros_distro}-as2-usb-camera-interface
Requires: ros-%{ros_distro}-sensor-msgs
Requires: ros-%{ros_distro}-geometry-msgs
Requires: ros-%{ros_distro}-cv-bridge
Requires: ros-%{ros_distro}-visualization-msgs
Requires: ros-%{ros_distro}-tf2
Requires: ros-%{ros_distro}-std-msgs
# 单包策略:虚拟别名兼容依赖方
Provides: %{name}-devel = %{version}-%{release}
Provides: %{name}-doc = %{version}-%{release}
Provides: %{name}-runtime = %{version}-%{release}
%description
AS2 Behavior for object perception using a modular plugin-based pipeline.
This package is part of the Aerostack2 framework, a ROS 2 framework for
autonomous multi-aerial-robot systems.
%prep
%autosetup -n as2-behaviors-perception-%{version}-%{release_num}
# 兼容性修复:本地源码(main 分支)使用 as2::Node::getParameter<T>(...) 模板方法,
# 但已安装的 as2-core(旧版 tag)node.hpp 不含此方法。创建等价自由函数
# as2_compat::getParameter 并替换所有调用点(3 文件 / 25 处)。
python3 - << 'PYEOF'
import os, re
base = "as2_behaviors/as2_behaviors_object_perception"
# 1. 创建兼容头文件
compat_path = os.path.join(base, "include/as2_behaviors_object_perception/as2_compat.hpp")
if not os.path.exists(compat_path):
with open(compat_path, 'w') as f:
f.write(
'#ifndef AS2_BEHAVIORS_OBJECT_PERCEPTION__AS2_COMPAT_HPP_\n'
'#define AS2_BEHAVIORS_OBJECT_PERCEPTION__AS2_COMPAT_HPP_\n'
'\n'
'#include <string>\n'
'#include <rclcpp/rclcpp.hpp>\n'
'\n'
'namespace as2_compat {\n'
'\n'
'template<typename T>\n'
'T getParameter(rclcpp::Node * node, const std::string & name, const T & default_value)\n'
'{\n'
' if (!node->has_parameter(name)) {\n'
' node->declare_parameter<T>(name, default_value);\n'
' }\n'
' const rclcpp::Parameter parameter = node->get_parameter(name);\n'
' return parameter.template get_value<T>();\n'
'}\n'
'\n'
'template<typename T>\n'
'T getParameter(rclcpp::Node * node, const std::string & name)\n'
'{\n'
' if (!node->has_parameter(name)) {\n'
' node->declare_parameter<T>(name);\n'
' }\n'
' const rclcpp::Parameter parameter = node->get_parameter(name);\n'
' return parameter.template get_value<T>();\n'
'}\n'
'\n'
'} // namespace as2_compat\n'
'#endif // AS2_BEHAVIORS_OBJECT_PERCEPTION__AS2_COMPAT_HPP_\n'
)
print("[fix] Created as2_compat.hpp")
else:
print("[fix] as2_compat.hpp already exists")
# 2. 需要修改的文件
patch_files = [
os.path.join(base, "src/as2_behaviors_object_perception.cpp"),
os.path.join(base, "plugins/aruco/src/aruco.cpp"),
os.path.join(base, "include/as2_behaviors_object_perception/common/common.hpp"),
]
# 3. 正则替换: <receiver>->getParameter<<type>>(<args>)
# => as2_compat::getParameter<<type>>(<receiver>, <args>)
pat = re.compile(
r'(\w+)->getParameter<((?:[^<>]|<[^<>]*>)*)>+\(([^)]*)\)'
)
for fp in patch_files:
with open(fp) as f:
content = f.read()
# 添加 include(在最后一个 #include 之后)
if 'as2_compat.hpp' not in content:
lines = content.split('\n')
last_inc = -1
for i, ln in enumerate(lines):
if ln.strip().startswith('#include'):
last_inc = i
if last_inc >= 0:
lines.insert(last_inc + 1, '#include "as2_behaviors_object_perception/as2_compat.hpp"')
content = '\n'.join(lines)
# 替换调用
new_content, count = pat.subn(
lambda m: 'as2_compat::getParameter<' + m.group(2) + '>(' + m.group(1) + ', ' + m.group(3) + ')',
content
)
if count > 0:
with open(fp, 'w') as f:
f.write(new_content)
print("[fix] %s: replaced %d getParameter calls" % (fp, count))
else:
print("[fix] %s: no getParameter calls found" % fp)
PYEOF
%build
# ROS 基座环境
[ -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}
# Workaround: openEuler opencv 包未安装 contrib 模块 (face, wechat_qrcode,
# xfeatures2d) 的 .so 文件,但 OpenCV CMake config 传递性引用这些模块。
# 在可写构建目录创建指向 libopencv_core 的符号链接,通过 LIBRARY_PATH 让
# 链接器解析 -lopencv_face 等。本包不调用这三个模块的任何函数(仅传递性引入)。
mkdir -p opencv-lib-fix
for mod in opencv_face opencv_wechat_qrcode opencv_xfeatures2d; do
[ -e /usr/lib64/lib${mod}.so ] || ln -sf "$(ls /usr/lib64/libopencv_core.so.* 2>/dev/null | head -1)" opencv-lib-fix/lib${mod}.so
done
export LIBRARY_PATH="$PWD/opencv-lib-fix${LIBRARY_PATH:+:$LIBRARY_PATH}"
export LD_LIBRARY_PATH="$PWD/opencv-lib-fix${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
# monorepo 子包,进入实际构建目录
cd as2_behaviors/as2_behaviors_object_perception
mkdir -p .obj && cd .obj
%cmake3 \
-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 \
..
make %{?_smp_mflags}
%install
cd as2_behaviors/as2_behaviors_object_perception/.obj
make install DESTDIR=%{buildroot}
%files
/opt/ros/%{ros_distro}
%changelog
* Sat Oct 10 2026 ROS SIG <ros-sig@openeuler.org> - 1.1.3-1
- Initial RPM package for as2-behaviors-perception (Aerostack2 monorepo)
|