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/安装包内容。

典型场景:

原理

数据流

.msg / .srv
    │
    ▼
 genjava(genjava_message_artifacts)
    │  扫描 ROS_PACKAGE_PATH,按 package.xml 拓扑排序
    ▼
 .java 源码
    │
    ▼
 Gradle(gradlew)
    │  依赖 rosjava_bootstrap / message_generation
    ▼
 OSGi jar → 本地 Maven 仓库(~/.rosjava/maven)

步骤说明:

  1. genjava 根据 ROS_PACKAGE_PATH 定位消息包,读取 package.xml 依赖,确定构建顺序。
  2. 为每个包生成 Gradle 工程,调用 GenerateInterfaces 将消息定义转为 Java 类。
  3. Gradle 编译并 publish 到本地 Maven;后续包通过 Maven 坐标引用前置依赖。
  4. 目标包(如业务自定义消息包)最后编译,产出最终 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

安装内容(持久化,幂等可重复执行):

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. 消息更新注意

产物

<pkg_name>-<md5>.jar

等价于传统 catkin_make 产物:

devel/share/maven/org/ros/rosjava_messages/<pkg_name>/*/<pkg_name>-*.jar

相关链接