语音控制AR.Drone的安卓上实现

1.AR.Drone的JAVA API搭建

AR.Drone的java api其实就是一个socket链接和命令发送的模块。
AR.Drone的命令格式如下:
UI_BIT:
00010001010101000000000000000000
   |   | | | |        || | ||||+--0: Button turn to left
   |   | | | |        || | |||+---1: Button altitude down (ah - ab)
   |   | | | |        || | ||+----2: Button turn to right
   |   | | | |        || | |+-----3: Button altitude up (ah - ab)
   |   | | | |        || | +------4: Button - z-axis (r1 - l1)
   |   | | | |        || +--------6: Button + z-axis (r1 - l1)
   |   | | | |        |+----------8: Button emergency reset all
   |   | | | |        +-----------9: Button Takeoff / Landing
   |   | | | +-------------------18: y-axis trim +1 (Trim increase at +/- 1??/s)
   |   | | +---------------------20: x-axis trim +1 (Trim increase at +/- 1??/s)
   |   | +-----------------------22: z-axis trim +1 (Trim increase at +/- 1??/s)
   |   +-------------------------24: x-axis +1
   +-----------------------------28: y-axis +1

AT*REF=<sequence>,<UI>
AT*PCMD=<sequence>,<enable>,<pitch>,<roll>,<gaz>,<yaw>
	(float)0.05 = (int)1028443341		(float)-0.05 = (int)-1119040307
	(float)0.1  = (int)1036831949		(float)-0.1  = (int)-1110651699
	(float)0.2  = (int)1045220557		(float)-0.2  = (int)-1102263091
	(float)0.5  = (int)1056964608		(float)-0.5  = (int)-1090519040
AT*ANIM=<sequence>,<animation>,<duration>
AT*CONFIG=<sequence>,\"<name>\",\"<value>\"

########## 命令模式 ############
Usage: java ARDrone <IP> <AT command>

altitude max2m:	java ARDrone 192.168.1.1 AT*CONFIG=1,\"control:altitude_max\",\"2000\"
Takeoff:	java ARDrone 192.168.1.1 AT*REF=1,290718208
Landing:	java ARDrone 192.168.1.1 AT*REF=1,290717696
Hovering:	java ARDrone 192.168.1.1 AT*PCMD=1,1,0,0,0,0
gaz 0.1:	java ARDrone 192.168.1.1 AT*PCMD=1,1,0,0,1036831949,0
gaz -0.1:	java ARDrone 192.168.1.1 AT*PCMD=1,1,0,0,-1110651699,0
pitch 0.1:	java ARDrone 192.168.1.1 AT*PCMD=1,1,1036831949,0,0,0
pitch -0.1:	java ARDrone 192.168.1.1 AT*PCMD=1,1,-1110651699,0,0,0
yaw 0.1:	java ARDrone 192.168.1.1 AT*PCMD=1,1,0,0,0,1036831949
yaw -0.1:	java ARDrone 192.168.1.1 AT*PCMD=1,1,0,0,0,-1110651699
roll 0.1:	java ARDrone 192.168.1.1 AT*PCMD=1,1,0,1036831949,0,0
roll -0.1:	java ARDrone 192.168.1.1 AT*PCMD=1,1,0,-1110651699,0,0
pitch -30 deg:	java ARDrone 192.168.1.1 AT*ANIM=1,0,1000
pitch 30 deg:	java ARDrone 192.168.1.1 AT*ANIM=1,1,1000
Emergency	java ARDrone 192.168.1.1 AT*REF=1,290717952

先链接链接AR.Drone,然后发送命令,代码如下:
	/*
	 * public void send_pcmd(int enable, float pitch, float roll, float gaz,
	 * float yaw) throws Exception { System.out.println("Speed: " + speed);
	 * send_at_cmd("AT*SEQ=" + get_seq()); send_at_cmd("AT*RADGP=" +
	 * (short)(pitch*25000) + ", " + (short)(roll*25000) + ", " +
	 * (short)(gaz*25000) + ", " + (short)(yaw*25000)); }
	 */
	public synchronized void send_at_cmd(String at_cmd) throws Exception {
		at_cmd_last = at_cmd;
		byte[] buf_snd = (at_cmd + "\r").getBytes();
		final DatagramPacket packet_snd = new DatagramPacket(buf_snd, buf_snd.length,
				inet_addr, ARDrone.AT_PORT);
		
		new Thread() {
			public void run() {
				try {
					socket_at.send(packet_snd);
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}	
			}
		}.start();
	}
其中  inet_addr是地址ARDrone.AT_PORT是端口, buf_snd是指令buf_snd.length是指令长度。
然后指令包装成实体指令,比如起飞。
	public void takeoff() {
		try {
			ardrone.send_at_cmd("AT*REF=" 
						+ ardrone.get_seq() 
						+ ",290718208");

		} catch (Exception e) {
			e.printStackTrace();
		}
	}
这个是AR.Drone的JAVA API的实现基本思路。
具体代码看工程文件。

2.与科大讯飞语音识别集成

集成前把 mainfest.xml文件里加几个权限配置

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.READ_CONTACTS" />
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_SETTINGS" />

主要是网络,话筒,sd卡读写权限。
然后到 科大讯飞SDK下载离线命令词识别的安卓sdk。

然后把sdk的demo里的AsrDemo复制到工程里。
import com.iflytek.cloud.ErrorCode;
import com.iflytek.cloud.GrammarListener;
import com.iflytek.cloud.InitListener;
import com.iflytek.cloud.LexiconListener;
import com.iflytek.cloud.RecognizerListener;
import com.iflytek.cloud.RecognizerResult;
import com.iflytek.cloud.SpeechConstant;
import com.iflytek.cloud.SpeechError;
import com.iflytek.cloud.SpeechRecognizer;
import com.iflytek.cloud.SpeechUtility;
import com.iflytek.cloud.util.ContactManager;
import com.iflytek.cloud.util.ContactManager.ContactListener;
import com.iflytek.cloud.util.ResourceUtil;
import com.iflytek.cloud.util.ResourceUtil.RESOURCE_TYPE;
import com.android.ardronepilot.speech.util.FucUtil;
import com.android.ardronepilot.speech.util.JsonParser;
import com.android.ardronepilot.speech.util.XmlParser;
引入科大讯飞包和方法包。
然后主要问题是语法命令配置和按语法词典识别语音命令了。
如下代码段是命令监听部分:
   /**
     * 识别监听器。
     */
    private RecognizerListener mRecognizerListener = new RecognizerListener() {
        int isConn = 0;
        @Override
        public void onVolumeChanged(int volume, byte[] data) {
            showTip("当前正在说话,音量大小:" + volume);
            Log.d(TAG, "返回音频数据:"+data.length);
        }

        @Override
        public void onResult(final RecognizerResult result, boolean isLast) {
            if (null != result && !TextUtils.isEmpty(result.getResultString())) {
                Log.d(TAG, "recognizer result:" + result.getResultString());
                String text = "";
                if (mResultType.equals("json")) {
                    text = JsonParser.parseGrammarResult(result.getResultString(), mEngineType).trim();
                } else if (mResultType.equals("xml")) {
                    text = XmlParser.parseNluResult(result.getResultString()).trim();
                }
                if(text.equals("连接")&&isConn==0){
                    new Thread() {
                        public void run() {
                            try {
                                drone = new ARDroneAPI();
                                isConn = 1;
                                ((EditText) findViewById(R.id.isr_text)).setText(drone.getStatus());
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }
                    }.start();
                } else if (text.equals("断开")&&isConn==1) {
                    drone.disbleEmergency();
                    isConn=0;
                    ((EditText) findViewById(R.id.isr_text)).setText(drone.getStatus());
                } else if (text.equals("起飞")&&isConn==1) {
                    mStarted = true;
                    drone.takeoff();
                    ((EditText) findViewById(R.id.isr_text)).setText(drone.getStatus());
                } else if (text.equals("降落")&&isConn==1) {
                    drone.landing();
                    ((EditText) findViewById(R.id.isr_text)).setText(drone.getStatus());
                } else if (text.equals("上")&&isConn==1) {
                    drone.up();
                    ((EditText) findViewById(R.id.isr_text)).setText(drone.getStatus());
                } else if (text.equals("下")&&isConn==1) {
                    drone.down();
                    ((EditText) findViewById(R.id.isr_text)).setText(drone.getStatus());
                } else if (text.equals("左")&&isConn==1) {
                    drone.rotatel();
                    ((EditText) findViewById(R.id.isr_text)).setText(drone.getStatus());
                } else if (text.equals("右")&&isConn==1) {
                    drone.rotater();
                    ((EditText) findViewById(R.id.isr_text)).setText(drone.getStatus());
                } else if (text.equals("前")&&isConn==1) {
                    drone.goForward();
                    ((EditText) findViewById(R.id.isr_text)).setText(drone.getStatus());
                } else if (text.equals("后")&&isConn==1) {
                    drone.goBackward();
                    ((EditText) findViewById(R.id.isr_text)).setText(drone.getStatus());
                } else if (text.equals("悬浮")&&isConn==1) {
                    drone.hovering();
                    ((EditText) findViewById(R.id.isr_text)).setText(drone.getStatus());
                } else if(isConn==0) {
                    Toast.makeText(getApplicationContext(), "请说连接命令", Toast.LENGTH_SHORT).show();
                }else{
                    Toast.makeText(getApplicationContext(), "无法匹配命令词,请重新发送命令", Toast.LENGTH_SHORT).show();
                }
                // 显示
                //((EditText) findViewById(R.id.isr_text)).setText(text);
            } else {
                Log.d(TAG, "recognizer result : null");
            }
        }
语音识别到相应文字以后触发java api的相应命令方法。
这个两个文件是安卓工程目录的asset文件夹下的离线语法词典和云端语法词典。离线语法词典格式如下:

#BNF+IAT 1.0 UTF-8;
!grammar call;
!slot <command>;
!start <commandStart>;
<commandStart>:<command>;
<command>:连接|断开|起飞|降落|上|下|右|左|前|后|悬浮;

云端语法词典格式如下:

#ABNF 1.0 UTF-8;
language zh-CN; 
mode voice;
root $main;
$main = $command;
$command = 连接|断开|起飞|降落|上|下|右|左|前|后|悬浮;

这两个配置好以后就可以识别在离线或云端识别语音命令了。

3.AsrDemoActivty代码

package com.android.ardronepilot;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Environment;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.EditText;
import android.widget.RadioGroup;
import android.widget.RadioGroup.OnCheckedChangeListener;
import android.widget.TextView;
import android.widget.Toast;

import com.iflytek.cloud.ErrorCode;
import com.iflytek.cloud.GrammarListener;
import com.iflytek.cloud.InitListener;
import com.iflytek.cloud.LexiconListener;
import com.iflytek.cloud.RecognizerListener;
import com.iflytek.cloud.RecognizerResult;
import com.iflytek.cloud.SpeechConstant;
import com.iflytek.cloud.SpeechError;
import com.iflytek.cloud.SpeechRecognizer;
import com.iflytek.cloud.SpeechUtility;
import com.iflytek.cloud.util.ContactManager;
import com.iflytek.cloud.util.ContactManager.ContactListener;
import com.iflytek.cloud.util.ResourceUtil;
import com.iflytek.cloud.util.ResourceUtil.RESOURCE_TYPE;
import com.android.ardronepilot.speech.util.FucUtil;
import com.android.ardronepilot.speech.util.JsonParser;
import com.android.ardronepilot.speech.util.XmlParser;

public class AsrDemo extends Activity implements OnClickListener,LocationListener,SensorEventListener {


    private ARDroneAPI drone;
    private LocationManager mLocationManager;
    private SensorManager mSensorManager;
    private Location mCurrentLocation;
    private Location mTargetLocation;
    private boolean mStarted = false;
    private double mOrientation;
    private int isConn = 0;

    private static String TAG = AsrDemo.class.getSimpleName();
    // 语音识别对象
    private SpeechRecognizer mAsr;
    private Toast mToast;
    // 缓存
    private SharedPreferences mSharedPreferences;
    // 本地语法文件
    private String mLocalGrammar = null;
    // 本地词典
    private String mLocalLexicon = null;
    // 云端语法文件
    private String mCloudGrammar = null;
    // 本地语法构建路径
    private String grmPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/pilot/test";
    // 返回结果格式,支持:xml,json
    private String mResultType = "json";

    private  final String KEY_GRAMMAR_ABNF_ID = "grammar_abnf_id";
    private  final String GRAMMAR_TYPE_ABNF = "abnf";
    private  final String GRAMMAR_TYPE_BNF = "bnf";

    private String mEngineType = "cloud";
    @SuppressLint("ShowToast")
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        this.requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.isrdemo);
        initLayout();
        StringBuffer param = new StringBuffer();
        param.append("appid=59223c87");
        param.append(",");
        // 设置使用v5+
        param.append(SpeechConstant.ENGINE_MODE+"="+SpeechConstant.MODE_MSC);
        SpeechUtility.createUtility(AsrDemo.this, param.toString());
        // 初始化识别对象
        mAsr = SpeechRecognizer.createRecognizer(this, mInitListener);

        // 初始化语法、命令词
        mLocalLexicon = "连接\n断开\n起飞\n降落\n上\n下\n右\n左\n前\n后\n悬浮\n";
        mLocalGrammar = FucUtil.readFile(this,"call.bnf", "utf-8");
        mCloudGrammar = FucUtil.readFile(this,"grammar_sample.abnf","utf-8");

        // 获取联系人,本地更新词典时使用
        mSharedPreferences = getSharedPreferences(getPackageName(),	MODE_PRIVATE);
        mToast = Toast.makeText(this,"",Toast.LENGTH_SHORT);

        mTargetLocation = new Location("target");

        mTargetLocation.setLatitude(1.0);
        mTargetLocation.setLongitude(1.0);

        mCurrentLocation = new Location("cr");

        mCurrentLocation.setLatitude(1.0);
        mCurrentLocation.setLongitude(1.0);
    }

    /**
     * 初始化Layout。
     */
    private void initLayout(){
        findViewById(R.id.isr_recognize).setOnClickListener(this);

        findViewById(R.id.isr_grammar).setOnClickListener(this);
        findViewById(R.id.isr_lexcion).setOnClickListener(this);

        findViewById(R.id.isr_stop).setOnClickListener(this);
        findViewById(R.id.isr_cancel).setOnClickListener(this);

        //选择云端or本地
        RadioGroup group = (RadioGroup)this.findViewById(R.id.radioGroup);
        group.setOnCheckedChangeListener(new OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup group, int checkedId) {
                if(checkedId == R.id.radioCloud)
                {
                    ((EditText)findViewById(R.id.isr_text)).setText(mCloudGrammar);
                    findViewById(R.id.isr_lexcion).setEnabled(false);
                    mEngineType = SpeechConstant.TYPE_CLOUD;
                }else if(checkedId == R.id.radioLocal)
                {
                    ((EditText)findViewById(R.id.isr_text)).setText(mLocalGrammar);
                    findViewById(R.id.isr_lexcion).setEnabled(true);
                    mEngineType =  SpeechConstant.TYPE_LOCAL;
                }
            }
        });
    }


    String mContent;// 语法、词典临时变量
    int ret = 0;// 函数调用返回值
    @Override
    public void onClick(View view) {
        if( null == mAsr ){
            // 创建单例失败,与 21001 错误为同样原因,参考 http://bbs.xfyun.cn/forum.php?mod=viewthread&tid=9688
            this.showTip( "创建对象失败,请确认 libmsc.so 放置正确,\n 且有调用 createUtility 进行初始化" );
            return;
        }

        if(null == mEngineType) {
            showTip("请先选择识别引擎类型");
            return;
        }
        switch(view.getId())
        {
            case R.id.isr_grammar:
                showTip("上传预设关键词/语法文件");
                // 本地-构建语法文件,生成语法id
                if (mEngineType.equals(SpeechConstant.TYPE_LOCAL)) {
                    ((EditText)findViewById(R.id.isr_text)).setText(mLocalGrammar);
                    mContent = new String(mLocalGrammar);
                    mAsr.setParameter(SpeechConstant.PARAMS, null);
                    // 设置文本编码格式
                    mAsr.setParameter(SpeechConstant.TEXT_ENCODING,"utf-8");
                    // 设置引擎类型
                    mAsr.setParameter(SpeechConstant.ENGINE_TYPE, mEngineType);
                    // 设置语法构建路径
                    mAsr.setParameter(ResourceUtil.GRM_BUILD_PATH, grmPath);
                    //使用8k音频的时候请解开注释
//					mAsr.setParameter(SpeechConstant.SAMPLE_RATE, "8000");
                    // 设置资源路径
                    mAsr.setParameter(ResourceUtil.ASR_RES_PATH, getResourcePath());
                    ret = mAsr.buildGrammar(GRAMMAR_TYPE_BNF, mContent, grammarListener);
                    if(ret != ErrorCode.SUCCESS){
                        showTip("语法构建失败,错误码:" + ret);
                    }
                }
                // 在线-构建语法文件,生成语法id
                else {
                    ((EditText)findViewById(R.id.isr_text)).setText(mCloudGrammar);
                    mContent = new String(mCloudGrammar);
                    // 指定引擎类型
                    mAsr.setParameter(SpeechConstant.ENGINE_TYPE, mEngineType);
                    // 设置文本编码格式
                    mAsr.setParameter(SpeechConstant.TEXT_ENCODING,"utf-8");
                    ret = mAsr.buildGrammar(GRAMMAR_TYPE_ABNF, mContent, grammarListener);
                    if(ret != ErrorCode.SUCCESS)
                        showTip("语法构建失败,错误码:" + ret);
                }
                break;
            // 本地-更新词典
            case R.id.isr_lexcion:
                ((EditText)findViewById(R.id.isr_text)).setText(mLocalLexicon);
                mContent = new String(mLocalLexicon);
                mAsr.setParameter(SpeechConstant.PARAMS, null);
                // 设置引擎类型
                mAsr.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_LOCAL);
                // 设置资源路径
                mAsr.setParameter(ResourceUtil.ASR_RES_PATH, getResourcePath());
                //使用8k音频的时候请解开注释
//				mAsr.setParameter(SpeechConstant.SAMPLE_RATE, "8000");
                // 设置语法构建路径
                mAsr.setParameter(ResourceUtil.GRM_BUILD_PATH, grmPath);
                // 设置语法名称
                mAsr.setParameter(SpeechConstant.GRAMMAR_LIST, "call");
                // 设置文本编码格式
                mAsr.setParameter(SpeechConstant.TEXT_ENCODING,"utf-8");
                ret = mAsr.updateLexicon("contact", mContent, lexiconListener);
                if(ret != ErrorCode.SUCCESS){
                    showTip("更新词典失败,错误码:" + ret);
                }
                break;
            // 开始识别
            case R.id.isr_recognize:
                ((EditText)findViewById(R.id.isr_text)).setText(null);// 清空显示内容
                // 设置参数
                if (!setParam()) {
                    showTip("请先构建语法。");
                    return;
                };

                ret = mAsr.startListening(mRecognizerListener);
                if (ret != ErrorCode.SUCCESS) {
                    showTip("识别失败,错误码: " + ret);
                }
                break;
            // 停止识别
            case R.id.isr_stop:
                mAsr.stopListening();
                showTip("停止识别");
                break;
            // 取消识别
            case R.id.isr_cancel:
                mAsr.cancel();
                showTip("取消识别");
                break;
        }
    }

    /**
     * 初始化监听器。
     */
    private InitListener mInitListener = new InitListener() {

        @Override
        public void onInit(int code) {
            Log.d(TAG, "SpeechRecognizer init() code = " + code);
            if (code != ErrorCode.SUCCESS) {
                showTip("初始化失败,错误码:"+code);
            }
        }
    };

    /**
     * 更新词典监听器。
     */
    private LexiconListener lexiconListener = new LexiconListener() {
        @Override
        public void onLexiconUpdated(String lexiconId, SpeechError error) {
            if(error == null){
                showTip("词典更新成功");
            }else{
                showTip("词典更新失败,错误码:"+error.getErrorCode());
            }
        }
    };

    /**
     * 构建语法监听器。
     */
    private GrammarListener grammarListener = new GrammarListener() {
        @Override
        public void onBuildFinish(String grammarId, SpeechError error) {
            if(error == null){
                if (mEngineType.equals(SpeechConstant.TYPE_CLOUD)) {
                    Editor editor = mSharedPreferences.edit();
                    if(!TextUtils.isEmpty(grammarId))
                        editor.putString(KEY_GRAMMAR_ABNF_ID, grammarId);
                    editor.commit();
                }
                showTip("语法构建成功:" + grammarId);
            }else{
                showTip("语法构建失败,错误码:" + error.getErrorCode());
            }
        }
    };
    /**
     * 识别监听器。
     */
    private RecognizerListener mRecognizerListener = new RecognizerListener() {
        int isConn = 0;
        @Override
        public void onVolumeChanged(int volume, byte[] data) {
            showTip("当前正在说话,音量大小:" + volume);
            Log.d(TAG, "返回音频数据:"+data.length);
        }

        @Override
        public void onResult(final RecognizerResult result, boolean isLast) {
            if (null != result && !TextUtils.isEmpty(result.getResultString())) {
                Log.d(TAG, "recognizer result:" + result.getResultString());
                String text = "";
                if (mResultType.equals("json")) {
                    text = JsonParser.parseGrammarResult(result.getResultString(), mEngineType).trim();
                } else if (mResultType.equals("xml")) {
                    text = XmlParser.parseNluResult(result.getResultString()).trim();
                }
                if(text.equals("连接")&&isConn==0){
                    new Thread() {
                        public void run() {
                            try {
                                drone = new ARDroneAPI();
                                isConn = 1;
                                ((EditText) findViewById(R.id.isr_text)).setText(drone.getStatus());
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }
                    }.start();
                } else if (text.equals("断开")&&isConn==1) {
                    drone.disbleEmergency();
                    isConn=0;
                    ((EditText) findViewById(R.id.isr_text)).setText(drone.getStatus());
                } else if (text.equals("起飞")&&isConn==1) {
                    mStarted = true;
                    drone.takeoff();
                    ((EditText) findViewById(R.id.isr_text)).setText(drone.getStatus());
                } else if (text.equals("降落")&&isConn==1) {
                    drone.landing();
                    ((EditText) findViewById(R.id.isr_text)).setText(drone.getStatus());
                } else if (text.equals("上")&&isConn==1) {
                    drone.up();
                    ((EditText) findViewById(R.id.isr_text)).setText(drone.getStatus());
                } else if (text.equals("下")&&isConn==1) {
                    drone.down();
                    ((EditText) findViewById(R.id.isr_text)).setText(drone.getStatus());
                } else if (text.equals("左")&&isConn==1) {
                    drone.rotatel();
                    ((EditText) findViewById(R.id.isr_text)).setText(drone.getStatus());
                } else if (text.equals("右")&&isConn==1) {
                    drone.rotater();
                    ((EditText) findViewById(R.id.isr_text)).setText(drone.getStatus());
                } else if (text.equals("前")&&isConn==1) {
                    drone.goForward();
                    ((EditText) findViewById(R.id.isr_text)).setText(drone.getStatus());
                } else if (text.equals("后")&&isConn==1) {
                    drone.goBackward();
                    ((EditText) findViewById(R.id.isr_text)).setText(drone.getStatus());
                } else if (text.equals("悬浮")&&isConn==1) {
                    drone.hovering();
                    ((EditText) findViewById(R.id.isr_text)).setText(drone.getStatus());
                } else if(isConn==0) {
                    Toast.makeText(getApplicationContext(), "请说连接命令", Toast.LENGTH_SHORT).show();
                }else{
                    Toast.makeText(getApplicationContext(), "无法匹配命令词,请重新发送命令", Toast.LENGTH_SHORT).show();
                }
                // 显示
                //((EditText) findViewById(R.id.isr_text)).setText(text);
            } else {
                Log.d(TAG, "recognizer result : null");
            }
        }

        @Override
        public void onEndOfSpeech() {
            // 此回调表示:检测到了语音的尾端点,已经进入识别过程,不再接受语音输入
            showTip("结束说话");
        }

        @Override
        public void onBeginOfSpeech() {
            // 此回调表示:sdk内部录音机已经准备好了,用户可以开始语音输入
            showTip("开始说话");
        }

        @Override
        public void onError(SpeechError error) {
            showTip("onError Code:"	+ error.getErrorCode());
        }

        @Override
        public void onEvent(int eventType, int arg1, int arg2, Bundle obj) {
            // 以下代码用于获取与云端的会话id,当业务出错时将会话id提供给技术支持人员,可用于查询会话日志,定位出错原因
            // 若使用本地能力,会话id为null
            //	if (SpeechEvent.EVENT_SESSION_ID == eventType) {
            //		String sid = obj.getString(SpeechEvent.KEY_EVENT_SESSION_ID);
            //		Log.d(TAG, "session id =" + sid);
            //	}
        }

    };



    private void showTip(final String str) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                mToast.setText(str);
                mToast.show();
            }
        });
    }

    /**
     * 参数设置
     * @param
     * @return
     */
    public boolean setParam(){
        boolean result = false;
        // 清空参数
        mAsr.setParameter(SpeechConstant.PARAMS, null);
        // 设置识别引擎
        mAsr.setParameter(SpeechConstant.ENGINE_TYPE, mEngineType);
        if("cloud".equalsIgnoreCase(mEngineType))
        {
            String grammarId = mSharedPreferences.getString(KEY_GRAMMAR_ABNF_ID, null);
            if(TextUtils.isEmpty(grammarId))
            {
                result =  false;
            }else {
                // 设置返回结果格式
                mAsr.setParameter(SpeechConstant.RESULT_TYPE, mResultType);
                // 设置云端识别使用的语法id
                mAsr.setParameter(SpeechConstant.CLOUD_GRAMMAR, grammarId);
                result =  true;
            }
        }
        else
        {
            // 设置本地识别资源
            mAsr.setParameter(ResourceUtil.ASR_RES_PATH, getResourcePath());
            // 设置语法构建路径
            mAsr.setParameter(ResourceUtil.GRM_BUILD_PATH, grmPath);
            // 设置返回结果格式
            mAsr.setParameter(SpeechConstant.RESULT_TYPE, mResultType);
            // 设置本地识别使用语法id
            mAsr.setParameter(SpeechConstant.LOCAL_GRAMMAR, "call");
            // 设置识别的门限值
            mAsr.setParameter(SpeechConstant.MIXED_THRESHOLD, "30");
            // 使用8k音频的时候请解开注释
//			mAsr.setParameter(SpeechConstant.SAMPLE_RATE, "8000");
            result = true;
        }

        // 设置音频保存路径,保存音频格式支持pcm、wav,设置路径为sd卡请注意WRITE_EXTERNAL_STORAGE权限
        // 注:AUDIO_FORMAT参数语记需要更新版本才能生效
        mAsr.setParameter(SpeechConstant.AUDIO_FORMAT,"wav");
        mAsr.setParameter(SpeechConstant.ASR_AUDIO_PATH, Environment.getExternalStorageDirectory()+"/msc/asr.wav");
        return result;
    }

    //获取识别资源路径
    private String getResourcePath(){
        StringBuffer tempBuffer = new StringBuffer();
        //识别通用资源
        tempBuffer.append(ResourceUtil.generateResourcePath(this, RESOURCE_TYPE.assets, "asr/common.jet"));
        //识别8k资源-使用8k的时候请解开注释
//		tempBuffer.append(";");
//		tempBuffer.append(ResourceUtil.generateResourcePath(this, RESOURCE_TYPE.assets, "asr/common_8k.jet"));
        return tempBuffer.toString();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if( null != mAsr ){
            // 退出时释放连接
            mAsr.cancel();
            mAsr.destroy();
        }
    }
    private void setPilotState(String s){
        TextView textview = (TextView) findViewById(R.id.statusBox);
        textview.setText(s);
    }
    @Override
    protected void onResume() {
        super.onResume();
        startSensors();
    }

    @Override
    protected void onPause() {
        stopSensors();
        super.onPause();
    }

    public void stopSensors() {
        if (mLocationManager != null) {
            mLocationManager.removeUpdates(this);
            mLocationManager = null;
        }

        if (mSensorManager != null) {
            mSensorManager.unregisterListener(this);
            mSensorManager = null;
        }
    }

    public void startSensors() {
        if (mLocationManager == null) {
            mLocationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
            if (mLocationManager != null) {
                mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
                        1000 /* minTime ms */,
                        1 /* minDistance in meters */,
                        this);
            }
        }


        if (mSensorManager == null) {
            mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
            if (mSensorManager != null) {
                mSensorManager.registerListener(this,
                        mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION)
                        , SensorManager.SENSOR_DELAY_NORMAL);

            }
        }

    }

    public void onLocationChanged(Location location) {
        // TODO Auto-generated method stub
        mCurrentLocation = location;

        Log.d("Drone","Height="+mCurrentLocation.getAltitude());
    }

    public void onProviderDisabled(String provider) {
        // TODO Auto-generated method stub

    }

    public void onProviderEnabled(String provider) {
        // TODO Auto-generated method stub

    }

    public void onStatusChanged(String provider, int status, Bundle extras) {
        // TODO Auto-generated method stub

    }

    public void onAccuracyChanged(Sensor sensor, int accuracy) {
        // TODO Auto-generated method stub

    }

    public void onSensorChanged(SensorEvent event) {
        mOrientation = event.values[0];
    }

}



交流及工程文件请QQ/Wechat: 286436416



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值