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



推荐阅读
  • 本文介绍了如何使用C#制作Java+Mysql+Tomcat环境安装程序,实现一键式安装。通过将JDK、Mysql、Tomcat三者制作成一个安装包,解决了客户在安装软件时的复杂配置和繁琐问题,便于管理软件版本和系统集成。具体步骤包括配置JDK环境变量和安装Mysql服务,其中使用了MySQL Server 5.5社区版和my.ini文件。安装方法为通过命令行将目录转到mysql的bin目录下,执行mysqld --install MySQL5命令。 ... [详细]
  • Nginx使用(server参数配置)
    本文介绍了Nginx的使用,重点讲解了server参数配置,包括端口号、主机名、根目录等内容。同时,还介绍了Nginx的反向代理功能。 ... [详细]
  • Centos7.6安装Gitlab教程及注意事项
    本文介绍了在Centos7.6系统下安装Gitlab的详细教程,并提供了一些注意事项。教程包括查看系统版本、安装必要的软件包、配置防火墙等步骤。同时,还强调了使用阿里云服务器时的特殊配置需求,以及建议至少4GB的可用RAM来运行GitLab。 ... [详细]
  • 如何使用Java获取服务器硬件信息和磁盘负载率
    本文介绍了使用Java编程语言获取服务器硬件信息和磁盘负载率的方法。首先在远程服务器上搭建一个支持服务端语言的HTTP服务,并获取服务器的磁盘信息,并将结果输出。然后在本地使用JS编写一个AJAX脚本,远程请求服务端的程序,得到结果并展示给用户。其中还介绍了如何提取硬盘序列号的方法。 ... [详细]
  • Java在运行已编译完成的类时,是通过java虚拟机来装载和执行的,java虚拟机通过操作系统命令JAVA_HOMEbinjava–option来启 ... [详细]
  • 本文介绍了Python爬虫技术基础篇面向对象高级编程(中)中的多重继承概念。通过继承,子类可以扩展父类的功能。文章以动物类层次的设计为例,讨论了按照不同分类方式设计类层次的复杂性和多重继承的优势。最后给出了哺乳动物和鸟类的设计示例,以及能跑、能飞、宠物类和非宠物类的增加对类数量的影响。 ... [详细]
  • Android系统源码分析Zygote和SystemServer启动过程详解
    本文详细解析了Android系统源码中Zygote和SystemServer的启动过程。首先介绍了系统framework层启动的内容,帮助理解四大组件的启动和管理过程。接着介绍了AMS、PMS等系统服务的作用和调用方式。然后详细分析了Zygote的启动过程,解释了Zygote在Android启动过程中的决定作用。最后通过时序图展示了整个过程。 ... [详细]
  • 开发笔记:spring boot项目打成war包部署到服务器的步骤与注意事项
    本文介绍了将spring boot项目打成war包并部署到服务器的步骤与注意事项。通过本文的学习,读者可以了解到如何将spring boot项目打包成war包,并成功地部署到服务器上。 ... [详细]
  • 本文讨论了在shiro java配置中加入Shiro listener后启动失败的问题。作者引入了一系列jar包,并在web.xml中配置了相关内容,但启动后却无法正常运行。文章提供了具体引入的jar包和web.xml的配置内容,并指出可能的错误原因。该问题可能与jar包版本不兼容、web.xml配置错误等有关。 ... [详细]
  • Jboss的EJB部署描述符standardjaws.xml配置步骤详解
    本文详细介绍了Jboss的EJB部署描述符standardjaws.xml的配置步骤,包括映射CMP实体EJB、数据源连接池的获取以及数据库配置等内容。 ... [详细]
  • 本文介绍了解决java开源项目apache commons email简单使用报错的方法,包括使用正确的JAR包和正确的代码配置,以及相关参数的设置。详细介绍了如何使用apache commons email发送邮件。 ... [详细]
  • Hadoop2.6.0 + 云centos +伪分布式只谈部署
    3.0.3玩不好,现将2.6.0tar.gz上传到usr,chmod-Rhadoop:hadophadoop-2.6.0,rm掉3.0.32.在etcp ... [详细]
  • 1.脚本功能1)自动替换jar包中的配置文件。2)自动备份老版本的Jar包3)自动判断是初次启动还是更新服务2.脚本准备进入ho ... [详细]
  • 本文介绍了RPC框架Thrift的安装环境变量配置与第一个实例,讲解了RPC的概念以及如何解决跨语言、c++客户端、web服务端、远程调用等需求。Thrift开发方便上手快,性能和稳定性也不错,适合初学者学习和使用。 ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
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社区 版权所有