热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

ros和java通讯_Android使用ROSBridge与ROS通信简单使用

环境ROSkineticROS服务端安装sudoapt-getinstallros--rosbridge-suite启动roslaunchrosbridge_serverrosbr

环境

ROS kinetic

ROS 服务端

安装

sudo apt-get install ros--rosbridge-suite

启动

roslaunch rosbridge_server rosbridge_websocket.launch

在这之前不需要开启 roscore, 因为 rosbridge 会默认执行 roscore

Android客户端

要让 android 接收或者发送 ROS 消息的话,首先要在 Android上完成 websocket,然后按照协议解析,也很麻烦,不过又要站在巨人的肩膀上了,找到一个 开源项目:ROSBridgeClient

,这位同学使用 java-websocket 的包在Android上实现了 websocket 的应用,很棒。

直接把 src/com/jilk/ros

目录复制到 我的 Android 项目里,

当然会报错啦,这些代码依赖了第三方库,加在Android工程的libs 里面 引用

eventbus.jar 用于发送从ROS接收到的消息

java_websocket.jar 用于websocket 的实现

json-simple-1.1.jar 用于 json 解析

复制到项目包里的 代码包含了一个 example .

完全可以使用

public class Example {

public Example() {}

public static void main(String[] args) {

ROSBridgeClient client = new ROSBridgeClient("ws://162.243.238.80:9090");

client.connect();

//testTopic(client);

try {

testService(client);

}

catch (RuntimeException ex) {

ex.printStackTrace();

}

finally {

client.disconnect();

}

}

public static void testService(ROSBridgeClient client) {

try {

Service timeService =

new Service("/rosapi/get_time", Empty.class, GetTime.class, client);

timeService.verify();

//System.out.println("Time (secs): " + timeService.callBlocking(new Empty()).time.sec);

Service serviceTypeService =

new Service("/rosapi/service_type",

com.jilk.ros.rosapi.message.Service.class, Type.class, client);

serviceTypeService.verify();

String type = serviceTypeService.callBlocking(new com.jilk.ros.rosapi.message.Service("/rosapi/service_response_details")).type;

Service serviceDetails =

new Service("/rosapi/service_response_details",

Type.class, MessageDetails.class, client);

serviceDetails.verify();

//serviceDetails.callBlocking(new Type(type)).print();

Topic logTopic =

new Topic("/rosout", Log.class, client);

logTopic.verify();

/*

System.out.println("Nodes");

for (String s : client.getNodes())

System.out.println(" " + s);

System.out.println("Topics");

for (String s : client.getTopics()) {

System.out.println(s + ":");

client.getTopicMessageDetails(s).print();

}

System.out.println("Services");

for (String s : client.getServices()) {

System.out.println(s + ":");

client.getServiceRequestDetails(s).print();

System.out.println("-----------------");

client.getServiceResponseDetails(s).print();

}

*/

}

catch (InterruptedException ex) {

System.out.println("Process was interrupted.");

}

/*

Service topicService =

new Service("/rosapi/topics", Empty.class, Topics.class, client);

Service typeService =

new Service("/rosapi/topic_type", Topic.class, Type.class, client);

Service messageService =

new Service("/rosapi/message_details", Type.class, MessageDetails.class, client);

try {

Topics topics = topicService.callBlocking(new Empty());

for (String topicString : topics.topics) {

Topic topic = new Topic();

topic.topic = topicString;

Type type = typeService.callBlocking(topic);

MessageDetails details = messageService.callBlocking(type);

System.out.println("Topic: " + topic.topic + " Type: " + type.type);

details.print();

System.out.println();

}

Type type = new Type();

type.type = "time";

System.out.print("Single type check on \'time\': ");

messageService.callBlocking(type).print();

}

catch (InterruptedException ex) {

System.out.println("testService: process was interrupted.");

}

*/

}

public static void testTopic(ROSBridgeClient client) {

Topic clockTopic = new Topic("/clock", Clock.class, client);

clockTopic.subscribe();

try {Thread.sleep(20000);} catch(InterruptedException ex) {}

Clock cl = null;

try {

cl = clockTopic.take(); // just gets one

}

catch (InterruptedException ex) {}

cl.print();

cl.clock.nsecs++;

clockTopic.unsubscribe();

clockTopic.advertise();

clockTopic.publish(cl);

clockTopic.unadvertise();

}

}

example很好理解

就看了下 topic 相关的东西 testTopic,我觉得如果有很多topic就要用很多的testXXXTopic了,有点麻烦,所以我二次封装了一个 RosBridgeClientManager 来用

连接 ROS master

/**

* 连接 ROS master

* @param url ROS master IP

* @param port ROS master 端口

* @param listener 连接状态监听器

*/

public void connect(final String url, int port, final ROSClient.ConnectionStatusListener listener) {

if (url != null && url.equals(mCurUrl)) {

// already connected

} else {

mRosBridgeClient = new ROSBridgeClient("ws://" + url + ":" + port);

mRosBridgeClient.connect(new ROSClient.ConnectionStatusListener() {

@Override

public void onConnect() {

// connected successful

mCurUrl = url;

if (listener != null) {

listener.onConnect();

}

}

@Override

public void onDisconnect(boolean normal, String reason, int code) {

// client disconnected

if (listener != null) {

listener.onDisconnect(normal, reason, code);

}

}

@Override

public void onError(Exception ex) {

// connect error

if (listener != null) {

listener.onError(ex);

}

}

});

}

}

加了一个连接监听器,可以在业务层进行状态判断了。

注册topic 到 ROS

/**

* 注册topic

* @param topicName topic 名称

* @param data_type 消息类型

* @param

*/

public void advertiseTopic(String topicName, T data_type) {

AdvertiseTopicObject topic &#61; new AdvertiseTopicObject<>(topicName, data_type, mRosBridgeClient);

topic.setMessage_type(data_type);

topic.advertise();

// 利用 反射获取泛型&#xff0c;主要是得到 T.class,我也没试

// Class entityClass &#61; (Class ) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];

// Topic topic &#61; new Topic(topicName, entityClass, client);

// topic.advertise();

}

原来的 advertise 已经很简单了&#xff0c;为什么我还要弄这个东西&#xff1f;

我也不知道啊

AdvertiseTopicObject.java

public class AdvertiseTopicObject {

private T message_type;

private String topicName;

private ROSBridgeClient client;

public AdvertiseTopicObject(String topicName, T type, ROSBridgeClient rosBridgeClient) {

this.client &#61; rosBridgeClient;

this.topicName &#61; topicName;

this.message_type &#61; type;

}

public void advertise() {

Topic topic &#61; new Topic(topicName, message_type.getClass(), client);

topic.advertise();

}

}

发布topic 消息

/**

* 发布 topic 消息

* &#64;param topicName topic名称

* &#64;param msg 消息

* &#64;param 消息类型

*/

public void publishTopic(String topicName, T msg) {

PublishTopicObject publishTopicObject &#61; new PublishTopicObject<>();

publishTopicObject.setTopic(topicName);

publishTopicObject.setMsg(msg);

String msg_str &#61; mGson.toJson(publishTopicObject);

mRosBridgeClient.send(msg_str);

}

跟上面的 AdvertiseTopicObject 保持一致&#xff0c;所以有了

PublishTopicObject.java

public class PublishTopicObject {

private String op &#61; "publish";

private String topic;

private T msg;

}

订阅 topic

/**

* 订阅topic

* &#64;param topicName topic 名称

* &#64;param listener 消息监听器

*/

public void subscribeTopic(String topicName, OnRosMessageListener listener

{

SubscribeTopicObject subscribeTopicObject &#61; new SubscribeTopicObject();

subscribeTopicObject.setTopic(topicName);

String msg_str &#61; mGson.toJson(subscribeTopicObject);

mRosBridgeClient.send(msg_str);

addROSMessageListener(listener);

}

同理&#xff1a;跟上面的 PublishTopicObject 保持一致&#xff0c;所以有了

SubscribeTopicObject.java

public class SubscribeTopicObject {

private String op &#61; "subscribe";

private String topic;

public String getOp() {

return op;

}

}

取消订阅 topic

/**

* 取消订阅topic

* &#64;param topicName

* &#64;param listener

*/

public void unSubscribeTopic(String topicName, OnRosMessageListener listener) {

UnSubscribeTopicObject unSubscribeTopicObject &#61; new UnSubscribeTopicObject();

unSubscribeTopicObject.setTopic(topicName);

String msg_str &#61; mGson.toJson(unSubscribeTopicObject);

mRosBridgeClient.send(msg_str);

removeROSMessageListener(listener);

}

还有 UnSubscribeTopicObject.java

public class UnSubscribeTopicObject {

private String op &#61; "unsubscribe";

private String topic;

}

接收ROS 消息

//Receive data from ROS server, send from ROSBridgeWebSocketClient onMessage()

// using eventbus ?!

public void onEvent(final PublishEvent event) {

Log.d("TAG", event.msg);

for (int index &#61; 0 ; index

mROSListenerList.get(curIndex).onStringMessageReceive(event.name, stringData);

//mROSListenerList.get(curIndex).onImageMessageReceive(event.name, imageData);

}

}

在 ROSBridgeWebSocketClient.java 里面找到了接收消息后发出来的代码

EventBus.getDefault().post(new PublishEvent(operation,publish.topic,content));

Emmm… 用的是 EventBus&#xff0c;先用起来再说。

还有就是关于服务的封装了&#xff0c;没写。



推荐阅读
  • t-io 2.0.0发布-法网天眼第一版的回顾和更新说明
    本文回顾了t-io 1.x版本的工程结构和性能数据,并介绍了t-io在码云上的成绩和用户反馈。同时,还提到了@openSeLi同学发布的t-io 30W长连接并发压力测试报告。最后,详细介绍了t-io 2.0.0版本的更新内容,包括更简洁的使用方式和内置的httpsession功能。 ... [详细]
  • Android源码深入理解JNI技术的概述和应用
    本文介绍了Android源码中的JNI技术,包括概述和应用。JNI是Java Native Interface的缩写,是一种技术,可以实现Java程序调用Native语言写的函数,以及Native程序调用Java层的函数。在Android平台上,JNI充当了连接Java世界和Native世界的桥梁。本文通过分析Android源码中的相关文件和位置,深入探讨了JNI技术在Android开发中的重要性和应用场景。 ... [详细]
  • Android系统源码分析Zygote和SystemServer启动过程详解
    本文详细解析了Android系统源码中Zygote和SystemServer的启动过程。首先介绍了系统framework层启动的内容,帮助理解四大组件的启动和管理过程。接着介绍了AMS、PMS等系统服务的作用和调用方式。然后详细分析了Zygote的启动过程,解释了Zygote在Android启动过程中的决定作用。最后通过时序图展示了整个过程。 ... [详细]
  • Java 11相对于Java 8,OptaPlanner性能提升有多大?
    本文通过基准测试比较了Java 11和Java 8对OptaPlanner的性能提升。测试结果表明,在相同的硬件环境下,Java 11相对于Java 8在垃圾回收方面表现更好,从而提升了OptaPlanner的性能。 ... [详细]
  • 在开发中,有时候一个业务上要求的原子操作不仅仅包括数据库,还可能涉及外部接口或者消息队列。此时,传统的数据库事务无法满足需求。本文介绍了Java中如何利用java.lang.Runtime.addShutdownHook方法来保证业务线程的完整性。通过添加钩子,在程序退出时触发钩子,可以执行一些操作,如循环检查某个线程的状态,直到业务线程正常退出,再结束钩子程序。例子程序展示了如何利用钩子来保证业务线程的完整性。 ... [详细]
  • Java编程思想一书中第21章并发中关于线程间协作的一节中有个关于汽车打蜡与抛光的小例子(原书的704页)。这个例子主要展示的是两个线程如何通过wait ... [详细]
  • 我无法续订几天前过期的RHELDeveloper帐户订阅。我执行了以下步骤,但是,订 ... [详细]
  • java中的try catch_Java中的trycatchfinally异常处理
    Java中的try-catch-finally异常处理一、异常处理异常(Exception):是在运行发生的不正常情况。原始异常处理:if(条件){处理办法1处理办法 ... [详细]
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • JavaSE笔试题-接口、抽象类、多态等问题解答
    本文解答了JavaSE笔试题中关于接口、抽象类、多态等问题。包括Math类的取整数方法、接口是否可继承、抽象类是否可实现接口、抽象类是否可继承具体类、抽象类中是否可以有静态main方法等问题。同时介绍了面向对象的特征,以及Java中实现多态的机制。 ... [详细]
  • WebSocket与Socket.io的理解
    WebSocketprotocol是HTML5一种新的协议。它的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送 ... [详细]
  • Java在运行已编译完成的类时,是通过java虚拟机来装载和执行的,java虚拟机通过操作系统命令JAVA_HOMEbinjava–option来启 ... [详细]
  • 本文介绍了如何使用JSONObiect和Gson相关方法实现json数据与kotlin对象的相互转换。首先解释了JSON的概念和数据格式,然后详细介绍了相关API,包括JSONObject和Gson的使用方法。接着讲解了如何将json格式的字符串转换为kotlin对象或List,以及如何将kotlin对象转换为json字符串。最后提到了使用Map封装json对象的特殊情况。文章还对JSON和XML进行了比较,指出了JSON的优势和缺点。 ... [详细]
  • Mono为何能跨平台
    概念JIT编译(JITcompilation),运行时需要代码时,将Microsoft中间语言(MSIL)转换为机器码的编译。CLR(CommonLa ... [详细]
  • Ubuntu18.04 安装ROS Melodic && Ros2 Dashing
    https:blog.csdn.netqq_44717317articledetails104547474一、Ubuntu18.04的安装ubuntu2go的制作关于Ubuntu2 ... [详细]
author-avatar
手机用户2602914827
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有