热门标签 | 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;没写。



推荐阅读
  • 本文详细探讨了Java中的ClassLoader类加载器的工作原理,包括其如何将class文件加载至JVM中,以及JVM启动时的动态加载策略。文章还介绍了JVM内置的三种类加载器及其工作方式,并解释了类加载器的继承关系和双亲委托机制。 ... [详细]
  • 深入解析Java虚拟机(JVM)架构与原理
    本文旨在为读者提供对Java虚拟机(JVM)的全面理解,涵盖其主要组成部分、工作原理及其在不同平台上的实现。通过详细探讨JVM的结构和内部机制,帮助开发者更好地掌握Java编程的核心技术。 ... [详细]
  • 本文详细探讨了Java命令行参数的概念、使用方法及在实际编程中的应用,包括如何通过命令行传递参数给Java程序,以及如何在Java程序中解析这些参数。 ... [详细]
  • 优化ListView性能
    本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ... [详细]
  • Java 中的 BigDecimal pow()方法,示例 ... [详细]
  • Java 类成员初始化顺序与数组创建
    本文探讨了Java中类成员的初始化顺序、静态引入、可变参数以及finalize方法的应用。通过具体的代码示例,详细解释了这些概念及其在实际编程中的使用。 ... [详细]
  • 主要用了2个类来实现的,话不多说,直接看运行结果,然后在奉上源代码1.Index.javaimportjava.awt.Color;im ... [详细]
  • 本文详细介绍了 Dockerfile 的编写方法及其在网络配置中的应用,涵盖基础指令、镜像构建与发布流程,并深入探讨了 Docker 的默认网络、容器互联及自定义网络的实现。 ... [详细]
  • 本文深入探讨了 Java 中的 Serializable 接口,解释了其实现机制、用途及注意事项,帮助开发者更好地理解和使用序列化功能。 ... [详细]
  • 本文详细介绍了如何准备和安装 Eclipse 开发环境及其相关插件,包括 JDK、Tomcat、Struts 等组件的安装步骤及配置方法。 ... [详细]
  • 本文详细介绍如何在Linux系统中配置SSH密钥对,以实现从一台主机到另一台主机的无密码登录。内容涵盖密钥对生成、公钥分发及权限设置等关键步骤。 ... [详细]
  • ssm框架整合及工程分层1.先创建一个新的project1.1配置pom.xml ... [详细]
  • Spring Boot 中静态资源映射详解
    本文深入探讨了 Spring Boot 如何简化 Web 应用中的静态资源管理,包括默认的静态资源映射规则、WebJars 的使用以及静态首页的处理方法。通过本文,您将了解如何高效地管理和引用静态资源。 ... [详细]
  • Logback使用小结
    1一定要使用slf4j的jar包,不要使用apachecommons的jar。否则滚动生成文件不生效,不滚动的时候却生效~~importorg.slf ... [详细]
  • 本文详细解析了Java中throw和throws的关键区别,同时涵盖了JDK的定义、Java虚拟机的关键约定、Java的跨平台性、自动垃圾回收机制、源文件结构、包的概念及作用等多个核心知识点,旨在帮助学生更好地准备Java期末考试。 ... [详细]
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社区 版权所有