【笔记】Android上ROS开发——android_core创建一个android应用

前面已经讲了很多android_core,rosjava的介绍,如果你配置好了android_core,接下来就可以开发rosjava-android程序了。

首先在eclipse下创建一个android程序,然后使用RosActivity,下面给出官方范例详细介绍。

RosActivity是所有ROS Android应用的基本类,我们给出android_tutorial_pubsub来介绍如何写最基本ROS的Publisher和Subscriber。当学会Publisher和Subscriber也就相当于学会ROSjava一大半了,因为ROS机器人的所有行为都是建立在信息的发送与订阅的基础上。

原始地址来自:http://docs.rosjava.googlecode.com/hg/android_core/html/getting_started.html

package org.ros.android.android_tutorial_pubsub;

import android.os.Bundle;
import org.ros.android.MessageCallable;
import org.ros.android.RosActivity;
import org.ros.android.view.RosTextView;
import org.ros.node.NodeConfiguration;
import org.ros.node.NodeMainExecutor;
import org.ros.rosjava_tutorial_pubsub.Talker;

/**
 * @author [email protected] (Damon Kohler)
 */
public class MainActivity extends RosActivity {

  private RosTextView<std_msgs.String> rosTextView;
  private Talker talker;

  public MainActivity() {
    // The RosActivity constructor configures the notification title and ticker
    // messages.
    super("Pubsub Tutorial", "Pubsub Tutorial");
  }

  @SuppressWarnings("unchecked")
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    rosTextView = (RosTextView<std_msgs.String>) findViewById(R.id.text);
    rosTextView.setTopicName("chatter");
    rosTextView.setMessageType(std_msgs.String._TYPE);
    rosTextView.setMessageToStringCallable(new MessageCallable<String, std_msgs.String>() {
      @Override
      public String call(std_msgs.String message) {
        return message.getData();
      }
    });
  }

  @Override
  protected void init(NodeMainExecutor nodeMainExecutor) {
    talker = new Talker();
    NodeConfiguration nodeConfiguration = NodeConfiguration.newPrivate();
    // At this point, the user has already been prompted to either enter the URI
    // of a master to use or to start a master locally.
    nodeConfiguration.setMasterUri(getMasterUri());
    nodeMainExecutor.execute(talker, nodeConfiguration);
    // The RosTextView is also a NodeMain that must be executed in order to
    // start displaying incoming messages.
    nodeMainExecutor.execute(rosTextView, nodeConfiguration);
  }
}
在第14行,我们需要extends RosActivity。这样当activity启动时:

1.在前台启动NodeMainExecutorService

2.开始一个 MasterChooser activity来提示用户填写master URI,并且显示正在进行的通告信息通知用户ROS节点正在后台运行。

第22行的超构造函数中,两个字符串是Android通告的标题和断续器信息。用户只需要关闭这个通告就可以关闭与该应用联系的所有ROS节点。

第28-30行,android开发者都熟悉。

第42行我们定义抽象函数 RosActivity.init,这里我们开始了 NodeMain。与用户填写的masterURI建立连接,执行talker发布信息,执行rosTextView显示输入信息。而且这里RosAcitivity操纵着其他应用的生命周期的管理,包括:

1.获取和释放WakeLocksWifiLocks

2.捆绑或者松绑NodeMainExecutorService

3.当应用关闭时结束NodeMain

看完上面的代码,其实我们应该明白具体怎么发送信息关键在于Talker类,下面就来段代码解释下

package rosjava.wtf.pocketsphinx.version1;

import org.ros.concurrent.CancellableLoop;
import org.ros.namespace.GraphName;
import org.ros.node.AbstractNodeMain;
import org.ros.node.ConnectedNode;
import org.ros.node.topic.Publisher;

public class Talker extends AbstractNodeMain {

	  
  @Override
  public GraphName getDefaultNodeName() {
    return GraphName.of("rosjava_tutorial_pubsub/talker");
  }

  @Override
  public void onStart(final ConnectedNode connectedNode) {
    final Publisher<std_msgs.String> publisher =
        connectedNode.newPublisher("recognizer/output", std_msgs.String._TYPE);
    // This CancellableLoop will be canceled automatically when the node shuts
    // down.
    connectedNode.executeCancellableLoop(new CancellableLoop() {
    	
      @Override
      protected void setup() {
      }

      @Override
      public void loop() throws InterruptedException {
          std_msgs.String str = publisher.newMessage();
        str.setData( TalkParam.tmpstring );
        publisher.publish(str);
       Thread.sleep(250);
      }
    });
  }
}
第9行,需要extends AbstractNodeMain。第19-20行,我们设置信息格式为std_msgs.String._TYPE,这个是发送字符串信息,发送给recognizer/output主题,这两点是publisher的关键。

后面就是进入loop()循环发送信息。补充下,控制电机的信息选用geometry_msgs/Twist格式,控制舵机的选用sensor_msgs/JointState格式,后续文章会详细提到。

接下来描述下subscribe。这个android_core堆提供了许多Android实现NodeMain的视图方法。例如,我们接下来要看的RosTextView的实现。这个视图的目的就是用文本表示发布的消息并显示。

package org.ros.android.view;

import android.content.Context;
import android.util.AttributeSet;
import android.widget.TextView;
import org.ros.android.MessageCallable;
import org.ros.message.MessageListener;
import org.ros.namespace.GraphName;
import org.ros.node.ConnectedNode;
import org.ros.node.Node;
import org.ros.node.NodeMain;
import org.ros.node.topic.Subscriber;

/**
 * @author [email protected] (Damon Kohler)
 */
public class RosTextView<T> extends TextView implements NodeMain {

  private String topicName;
  private String messageType;

  public void setTopicName(String topicName) {
    this.topicName = topicName;
  }

  public void setMessageType(String messageType) {
    this.messageType = messageType;
  }

  public void setMessageToStringCallable(MessageCallable<String, T> callable) {
    this.callable = callable;
  }

  @Override
  public GraphName getDefaultNodeName() {
    return new GraphName("android_gingerbread/ros_text_view");
  }

  @Override
  public void onStart(ConnectedNode connectedNode) {
    Subscriber<T> subscriber = connectedNode.newSubscriber(topicName, messageType);
    subscriber.addMessageListener(new MessageListener<T>() {
      @Override
      public void onNewMessage(final T message) {
        if (callable != null) {
          post(new Runnable() {
            @Override
            public void run() {
              setText(callable.call(message));
            }
          });
        } else {
          post(new Runnable() {
            @Override
            public void run() {
              setText(message.toString());
            }
          });
        }
        postInvalidate();
      }
    });
  }

  @Override
  public void onShutdown(Node node) {
  }

  @Override
  public void onShutdownComplete(Node node) {
  }

  @Override
  public void onError(Node node, Throwable throwable) {
  }
}
这个视图已经配置了主 题topicName和信息格式messageType以及MessageCallable 在40行的   NodeMain.onStart 类函数中,我们创建一个Subscriber来订阅已经配置的主题和信息格式。

在49行我们将新接收到的信息转变成一个字符串。如果没有收到信息,就像56行,我们就使用默认的toString(),然后发送文本到视图上来显示收到的信息。

就像其他NodeMain一样,RosTextView被NodeMainExecutor执行。在上述RosActivity示例中,我们在RosActivity.init中执行了它,并且使用它在Talker节点中显示传入的消息。



by:season


猜你喜欢

转载自blog.csdn.net/F_season/article/details/9177931