From:http://blog.youkuaiyun.com/f_season/article/details/9177545
在看文章之前,请确定你已经熟悉了ROS和rosjava,并且具备基本的android开发经验
这个机器人由上网本作为核心,在ubuntu上运行ROS系统,由android端辅助控制。这里主要将android的ROSjava部分,会在以后分篇详述。
第一篇,总体介绍ROSjava-android在这个机器人设计中发挥了怎么样的作用。这个android控制程序有如下功能:英文语音识别,能在脱机状况下语音控制机器人的基本运动;中文语音识别,语音控制并可以布置机器人任务(比如去某地区寻找某物体,和人对话等);最基本的按键控制和舵机控制
整个rosjava程序由主程序PocketSphinxROS.java、处理发送命令的dispose.java、IsrActivity.java中文语音识别、R开头的几个英文语音识别文件和Talk开头的几个负责发送各种命令的文件组成。这里就先介绍下PocketSphinxROS.java,为什么取这个名字,因为最开始主要为了开发PocketSphinx英文语音,后来功能增多名字也就没改。
- package rosjava.wtf.pocketsphinx.version1;
- import java.util.Date;
- import android.app.ProgressDialog;
- import android.content.Intent;
- import android.os.Bundle;
- import android.os.Handler;
- import android.util.Log;
- import android.view.MotionEvent;
- import android.view.View;
- import android.view.View.OnTouchListener;
- import android.widget.Button;
- import android.widget.SeekBar;
- import android.widget.TextView;
- import android.widget.SeekBar.OnSeekBarChangeListener;
- import org.ros.address.InetAddressFactory;
- 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 rosjava.wtf.pocketsphinx.version1.IsrActivity;
- import rosjava.wtf.pocketsphinx.version1.RecognitionListener;
- import rosjava.wtf.pocketsphinx.version1.RecognizerTask;
- import rosjava.wtf.pocketsphinx.version1.TalkChnString;
- import rosjava.wtf.pocketsphinx.version1.TalkEnString;
- import rosjava.wtf.pocketsphinx.version1.TalkParam;
- import edu.cmu.pocketsphinx.demo.R;
- public class PocketSphinxROS extends RosActivity implements OnTouchListener, RecognitionListener {
- private RosTextView<std_msgs.String> rosTextView;
- private TalkParam talker;
- private TalkEnString talkerenstring;
- private TalkChnString talkerchnstring;
- private TalkServo talkerserver;
- private TalkObject talkerobject;
- public Button forward,back,right,left,stop,btn_isr_demo,revive;
- public static boolean send=false,sendenstring=false,sendchnstring=false,sendservo=true,sendobject=false;
- public Handler handler = new Handler(){};
- //servo
- public TextView Value01,Value02;
- public static SeekBar servo1;
- public static SeekBar servo2;
- public PocketSphinxROS() {
- // The RosActivity constructor configures the notification title and ticker
- // messages.
- super("Pubsub Tutorial", "Pubsub Tutorial");
- }
- //*pocketsphinx***************************************************************************************
- static {
- System.loadLibrary("pocketsphinx_jni");
- }
- /**
- * Recognizer task, which runs in a worker thread.
- */
- RecognizerTask rec;
- /**
- * Thread in which the recognizer task runs.
- */
- Thread rec_thread;
- /**
- * Time at which current recognition started.
- */
- Date start_date;
- /**
- * Number of seconds of speech.
- */
- float speech_dur;
- /**
- * Are we listening?
- */
- boolean listening;
- /**
- * Progress dialog for final recognition.
- */
- ProgressDialog rec_dialog;
- /**
- * Performance counter view.
- */
- static TextView performance_text;
- /**
- * Editable text view.
- */
- public boolean onTouch(View v, MotionEvent event) {
- switch (event.getAction()) {
- case MotionEvent.ACTION_DOWN:
- start_date = new Date();
- this.listening = true;
- this.rec.start();
- break;
- case MotionEvent.ACTION_UP:
- if (this.listening) {
- Log.d(getClass().getName(), "Showing Dialog");
- this.rec_dialog = ProgressDialog.show(this, "", "Recognizing speech...", true);
- this.rec_dialog.setCancelable(false);
- this.listening = false;
- }
- this.rec.stop();
- break;
- default:
- ;
- }
- /* Let the button handle its own state */
- return false;
- }
- //****************************************************************************************
- @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("recognizer/output");
- 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();
- }
- });
- this.rec = new RecognizerTask();
- this.rec_thread = new Thread(this.rec);
- this.listening = false;
- Button voice = (Button) findViewById(R.id.Voice);
- voice.setOnTouchListener(this);
- performance_text = (TextView) findViewById(R.id.PerformanceText);
- this.rec.setRecognitionListener(this);
- this.rec_thread.start();
- forward = (Button)findViewById(R.id.forward);
- back = (Button)findViewById(R.id.back);
- right = (Button)findViewById(R.id.right);
- left = (Button)findViewById(R.id.left);
- stop = (Button)findViewById(R.id.stop);
- revive = (Button)findViewById(R.id.revive);
- btn_isr_demo=(Button)findViewById(R.id.btn_isr_demo);
- Value01 = (TextView)findViewById(R.id.value1);
- Value02 = (TextView)findViewById(R.id.value2);
- final SeekBar servo1 = (SeekBar)findViewById(R.id.servo1); //左右
- final SeekBar servo2 = (SeekBar)findViewById(R.id.servo2); //上下
- servo1.setMax(180);
- servo1.setProgress(73);
- servo2.setMax(150);
- servo2.setProgress(145);
- forward.setOnTouchListener(new OnTouchListener(){
- @Override
- public boolean onTouch(View v, MotionEvent event) {
- if (event.getAction() == MotionEvent.ACTION_DOWN)
- {
- dispose.control("forward");
- send=true;
- }
- else if(event.getAction() == MotionEvent.ACTION_UP)
- {
- send=false;
- sendenstring=true;
- sendchnstring=true;
- }
- return false;
- }
- });
- back.setOnTouchListener(new OnTouchListener(){
- @Override
- public boolean onTouch(View v, MotionEvent event) {
- if (event.getAction() == MotionEvent.ACTION_DOWN)
- {
- dispose.control("back");
- send=true;
- }
- else if(event.getAction() == MotionEvent.ACTION_UP)
- {
- send=false;
- sendenstring=true;
- sendchnstring=true;
- }
- return false;
- }
- });
- left.setOnTouchListener(new OnTouchListener(){
- @Override
- public boolean onTouch(View v, MotionEvent event) {
- if (event.getAction() == MotionEvent.ACTION_DOWN)
- {
- dispose.control("left");
- send=true;
- }
- else if(event.getAction() == MotionEvent.ACTION_UP)
- {
- send=false;
- sendenstring=true;
- sendchnstring=true;
- }
- return false;
- }
- });
- right.setOnTouchListener(new OnTouchListener(){
- @Override
- public boolean onTouch(View v, MotionEvent event) {
- if (event.getAction() == MotionEvent.ACTION_DOWN)
- {
- dispose.control("right");
- send=true;
- }
- else if(event.getAction() == MotionEvent.ACTION_UP)
- {
- send=false;
- sendenstring=true;
- sendchnstring=true;
- }
- return false;
- }
- });
- stop.setOnTouchListener(new OnTouchListener(){
- @Override
- public boolean onTouch(View v, MotionEvent event) {
- if (event.getAction() == MotionEvent.ACTION_DOWN)
- {
- dispose.control("stop");
- send = false;
- }
- else if(event.getAction() == MotionEvent.ACTION_UP)
- {
- sendenstring=true;
- sendchnstring=true;
- }
- return false;
- }
- });
- btn_isr_demo.setOnTouchListener(new OnTouchListener(){
- @Override
- public boolean onTouch(View v, MotionEvent event) {
- if (event.getAction() == MotionEvent.ACTION_DOWN)
- {
- }
- else if(event.getAction() == MotionEvent.ACTION_UP)
- {
- Intent intent = new Intent();
- intent.setClass(PocketSphinxROS.this,IsrActivity.class);
- startActivity(intent);
- }
- return false;
- }
- });
- revive.setOnTouchListener(new OnTouchListener(){
- @Override
- public boolean onTouch(View v, MotionEvent event) {
- if (event.getAction() == MotionEvent.ACTION_DOWN)
- {
- dispose.control("revive");
- }
- else if(event.getAction() == MotionEvent.ACTION_UP)
- {
- send=false;
- servo1.setProgress(73);
- servo2.setProgress(145);
- }
- return false;
- }
- });
- servo1.setOnSeekBarChangeListener(new OnSeekBarChangeListener(){
- @Override
- public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser)
- {
- if(progress > 150){
- Value01.setText("当前角度:" + 0.6 );
- TalkServo.pos[0]=0.6;
- }
- else{
- Value01.setText("当前角度:" + ((float)(progress-90)/100 ));
- TalkServo.pos[0]=(float)(progress-90)/100;
- }
- sendservo=true;
- }
- @Override
- public void onStartTrackingTouch(SeekBar seekBar)
- {
- }
- @Override
- public void onStopTrackingTouch(SeekBar seekBar)
- {
- }
- });
- servo2.setOnSeekBarChangeListener(new OnSeekBarChangeListener(){
- @Override
- public void onProgressChanged(SeekBar seekBar, int progress,boolean fromUser)
- {
- Value02.setText("当前角度:" +((float)(progress-75)/100));
- TalkServo.pos[1]=(float)(progress-75)/100;
- sendservo=true;
- }
- @Override
- public void onStartTrackingTouch(SeekBar seekBar)
- {
- }
- @Override
- public void onStopTrackingTouch(SeekBar seekBar)
- {
- }
- });
- }
- //Voice Control
- /** Called when partial results are generated. */
- public void onPartialResults(Bundle b) {
- final String hyp = b.getString("hyp");
- handler.post(new Runnable() {
- public void run() {
- performance_text.setText(hyp);
- }
- });
- }
- /** Called with full results are generated. */
- public void onResults(Bundle b) {
- final String hyp = b.getString("hyp");
- final PocketSphinxROS that = this;
- handler.post(new Runnable() {
- public void run() {
- performance_text.setText(hyp);
- dispose.control(hyp);
- sendenstring=true;
- send=true;
- Log.d(getClass().getName(), "Hiding Dialog");
- that.rec_dialog.dismiss();
- }
- });
- }
- public void onError(int err) {
- }
- @Override
- protected void init(NodeMainExecutor nodeMainExecutor) {
- // TODO Auto-generated method stub
- talker = new TalkParam();
- talkerenstring = new TalkEnString();
- talkerchnstring = new TalkChnString();
- talkerserver = new TalkServo();
- talkerobject = new TalkObject();
- NodeConfiguration nodeConfiguration = NodeConfiguration.newPublic(InetAddressFactory.newNonLoopback().getHostAddress(), getMasterUri());
- // 这里用户已经被提示输入master的URI来开始或启动本地master
- nodeConfiguration.setMasterUri(getMasterUri());
- nodeMainExecutor.execute(talker, nodeConfiguration);
- nodeMainExecutor.execute(talkerenstring, nodeConfiguration);
- nodeMainExecutor.execute(talkerchnstring, nodeConfiguration);
- nodeMainExecutor.execute(talkerserver, nodeConfiguration);
- nodeMainExecutor.execute(talkerobject, nodeConfiguration);
- // RosTextView作为显示输入信息是必须存在的
- nodeMainExecutor.execute(rosTextView, nodeConfiguration);
- }
- }
开发过pocketsphinx语音识别的一定很熟悉其中部分代码,这个是pocketsphinx的固定套路。中文语音我用了讯飞的引擎,联网的状况下效果很好。信息通道建立部分,我建了6个ROS节点,talker(TalkParam)负责发送控制电机的参数命令,使用geometry_msgs/Twist格式。talkerchnstring(TalkChnString)负责发送中文语音识别信息到PC的ROS,使用std_msgs.String._TYPE格式。talkerenstring(TalkEnString)负责发送英文语音识别信息。这里要说明,中文使用讯飞是需要联网才能识别的,而英文pocketsphinx是可以脱机小范围语音识别,用于应对恶劣情况(没网络)。talkerserver(TalkServo)是负责发送控制舵机的命令,使用sensor_msgs/JointState格式。talkerobject(TalkObject)负责把需要寻找的物体名发给机器人,使用std_msgs.String._TYPE格式。这里说明下,我们的机器人具有物体识别能力,通过发送物体名称给机器人,机器人就会明白自己的任务,然后去寻找该物体。
总结,以上代码是由3部分组成:RosActivity中固定格式,包括master连接和节点以及主题的建立;各个功能按键的设定;pocketsphinx英文语音。详细的请看后续文章。
by:season