rosjava-msg-to-jar 1
ROS 消息编译为 Java Jar(rosjava / genjava)
个人笔记:记录将 ROS
.msg/.srv编译为 Android APK 可用 jar 的原理与流程。
环境:Ubuntu 20.04 + ROS Noetic,宿主机 amd64 native 构建(与 arm 交叉编译分离)。
背景
机器人端导航栈使用 ROS 消息;Android APK 通过 rosjava 消费同名消息类型。需要在宿主机将消息包编译为 jar,不参与机器人端 deb/安装包内容。
典型场景:
- 主工程做 arm64 交叉编译、打包
- 打包完成后,在宿主机 native 环境单独构建消息 jar
- CI 将 jar 作为独立 artifact 发布
原理
数据流
.msg / .srv
│
▼
genjava(genjava_message_artifacts)
│ 扫描 ROS_PACKAGE_PATH,按 package.xml 拓扑排序
▼
.java 源码
│
▼
Gradle(gradlew)
│ 依赖 rosjava_bootstrap / message_generation
▼
OSGi jar → 本地 Maven 仓库(~/.rosjava/maven)
步骤说明:
- genjava 根据
ROS_PACKAGE_PATH定位消息包,读取package.xml依赖,确定构建顺序。 - 为每个包生成 Gradle 工程,调用
GenerateInterfaces将消息定义转为 Java 类。 - Gradle 编译并
publish到本地 Maven;后续包通过 Maven 坐标引用前置依赖。 - 目标包(如业务自定义消息包)最后编译,产出最终 jar。
为何不能直接用 rosjava_mvn_repo
rosjava_mvn_repo 中的预编译消息版本偏旧(例如 std_msgs 0.5.11),而 Noetic 系统包版本更高(例如 0.5.14)。版本不一致时 Gradle 解析失败。
处理方式:自动解析目标包的全部消息依赖,按拓扑序从 /opt/ros/noetic 逐级本地编译,再编译目标包。
关键环境变量
| 变量 | 作用 |
|---|---|
ROS_PACKAGE_PATH |
genjava 查找消息包(工作空间 src + /opt/ros/noetic/share) |
ROS_MAVEN_DEPLOYMENT_REPOSITORY |
Gradle publish 目录;未设置会写入 file:/null 导致失败 |
ROS_MAVEN_PATH |
读取已 publish 的本地消息 jar |
ROS_MAVEN_REPOSITORY |
远程或本地备用 Maven 仓库 |
JAVA_HOME |
必须为 OpenJDK 8(rosjava 工具链要求) |
Gradle 依赖镜像(rosjava_init.gradle)
rosjava 默认拉取已下线的 repository.springsource.com。通过 Gradle init 脚本注入 Liferay、Maven Central、rosjava_mvn_repo 等镜像,解决 message_generation 等基础依赖下载失败。
与历史方案(Melodic)的对比
| 项目 | Ubuntu 18.04 / Melodic | Ubuntu 20.04 / Noetic(当前) |
|---|---|---|
| rosjava 安装 | apt 或源码三工作空间 | 无 apt;pip + genjava 独立构建 |
| 构建方式 | rosjava_tools + ros_common_msgs + catkin_make |
genjava_message_artifacts |
| 产物路径 | devel/share/maven/... |
同名 jar,语义等价 |
| Python 兼容 | Python 2 生态 | kinetic 工具链与 Noetic catkin devel 有兼容问题 |
脚本职责(通用)
| 脚本 | 职责 |
|---|---|
setup_rosjava_env.sh |
一次性环境配置(apt、pip、Maven 镜像、profile) |
build_rosjava_jar.sh |
执行构建,输出带 MD5 的 jar |
rosjava_init.gradle |
Gradle 依赖仓库镜像 |
使用流程
1. 一次性环境配置
在 CI Runner、宿主机或长期运行的构建容器 内执行(容器重建后需重装):
sudo bash <workspace>/src/<pkg>/scripts/setup_rosjava_env.sh --warm-cache
source /etc/profile.d/rosjava_build.sh
安装内容(持久化,幂等可重复执行):
- apt:
openjdk-8-jdk、python-is-python3、Noetic 消息工具链及基础消息包 - pip:
genjava、rosjava_build_tools - 可选:克隆
rosjava_mvn_repo到/opt/rosjava/作离线加速 /etc/profile.d/rosjava_build.sh写入环境变量--warm-cache:预编译std_msgs等依赖,加速后续构建
2. 手动构建
source /etc/profile.d/rosjava_build.sh
cd <ros_workspace>
bash src/<pkg>/scripts/build_rosjava_jar.sh "$(pwd)"
# 输出: <pkg>-<md5>.jar
<md5> 为 jar 内容哈希,消息变更后文件名变化,便于 APK 侧校验版本。
3. CI 集成
平台打包脚本在 deb/zip 完成后调用 build_rosjava_jar.sh;CI 将 *-*.jar 作为 build artifact 上传。
4. 环境是否只装一次?
同一台机器 / 同一长期容器:装一次即可。 之后每次构建只需 source 环境 + 运行 build 脚本。
需重装的情况:新机器、容器重建、系统重装、手动删除 ~/.rosjava/maven 或 ~/.gradle 缓存。
5. 消息更新注意
- 通常只改
msg/、srv/即可。 - 新增 ROS 消息依赖时,同步更新
package.xml与CMakeLists.txt,并确保依赖包在ROS_PACKAGE_PATH可达。 - 构建偶发失败可先重试;持续失败检查网络(Gradle 拉依赖)及环境是否已配置。
产物
<pkg_name>-<md5>.jar
等价于传统 catkin_make 产物:
devel/share/maven/org/ros/rosjava_messages/<pkg_name>/*/<pkg_name>-*.jar