rosjava service 与 server 通讯失败 md
开发ROS android 端遇到的问题 之 java 反射规则不符合校验要求失败的问题
当我们尝试与ros service 通讯时,通讯失败,收到的提示。以前在项目中都是使用ros node 进行topic 通讯,第一次和同事在app 实现rosservice. 费了很大的劲,搭建起开发环境开始做技术尝试,这几篇文章记录这个项目遇到的相关问题。并简要说明我们采用的解决方案。
2019-12-20 17:46:08.192 26580-26807/com.anzer.robot.navigation E/AndroidRuntime: FATAL EXCEPTION: pool-1-thread-96 Process: com.anzer.robot.navigation, PID: 26580 org.ros.exception.RosRuntimeException: client wants service /add_two_ints to have md5sum 6ba90081e934800663a867fb3cb76f5a, but it has e3aba31982a34e28270141afefced002. Dropping connection. at org.ros.internal.node.service.DefaultServiceClient.connect(DefaultServiceClient.java:140) at org.ros.internal.node.service.ServiceFactory.newClient(ServiceFactory.java:146) at org.ros.internal.node.DefaultNode.newServiceClient(DefaultNode.java:378) at org.ros.internal.node.DefaultNode.newServiceClient(DefaultNode.java:385) at com.anzer.robot.navigation.AddTwoIntService.add(AddTwoIntService.java:29) at com.anzer.robot.navigation.AddTwoIntService.onStart(AddTwoIntService.java:69) at org.ros.internal.node.DefaultNode$5.run(DefaultNode.java:520) at org.ros.internal.node.DefaultNode$5.run(DefaultNode.java:517) at org.ros.concurrent.EventDispatcher.loop(EventDispatcher.java:43) at org.ros.concurrent.CancellableLoop.run(CancellableLoop.java:56) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607) at java.lang.Thread.run(Thread.java:776)
app 取到这个日志,在ros service 后台也取到log
client wants service /add_two_ints to have md5sum 6ba90081e934800663a867fb3cb76f5a, but it has e3aba31982a34e28270141afefced002. Dropping connection.
拿到这个粒度的日志,首先分析日志。在这个过程中,client 端是app 发起的请求,它对应的md5 是 6ba90081e934800663a867fb3cb76f5a,不过server 端对应的是 e3aba31982a34e28270141afefced002,不匹配,所以切断连接。
通过不断尝试,对照相关网络上的资料,后来才理解。
原来ROS service 端会把 AddTwoInts.srv中的文本内容计算 md5 的指纹和app 端的定义的message 类型。如果这两个md5不匹配就返回上述的异常信息。
app 端的服务定义如下:
package cloud_msgs;
import org.ros.internal.message.Message;
public interface AddTwoIntsextends Message {
String_TYPE ="cloud_msgs/AddTwoInts";
String_DEFINITION ="int64 a\nint64 b\n---\nint64 sum\n";
}
在不清楚rosjava 创建services 的流程,约束条件。解决问题的思路是找一个逻辑接近的场景,可以运行起来的程序,想起以前学习ros service 时,对两个数值求和的例子。
1. 只有一个基本数据类型的情况
2. 如果弄清楚转换规则,再添加一个参数
3. 逐步把我们需要的参数都添加进去,构成项目中的自定义数据类型
多次试验得知:
+ 通过_TYPE反射生成对象,把“/” 替换为“.”,生成包路径为 cloud_msgs.AddTwoInts 的对象
+ 根据 _DEFINITION 反射生成 request 和response 接口
+ 刚开始我把 _DEFINITION 理解为注释,就遇到到各种不同的md5 校验失败的日志,参考别的msgs,如果要当做注释,需要表达为 _DEFINITION="# comment"
c++ java
int32 int
float32 float
bool boolean
int32[] int[]
string String/List
映射为这种关系,一步一步测试通过即可。