基于ROS和安卓手机的IMU参数的通信软件
来源:互联网 发布:js导致硬件死机 编辑:程序博客网 时间:2024/05/21 07:53
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签(空格分隔): rosjava android手机 IMU
前提是成功安装好ROS和android studio,并且能够成功运行android_core中实例。
本文采用的是在别人建好的app中新建一个ros android app,简单快速度的一种方法。
1、下载相关的app
注意要和你安装的ROS版本对应,我采用的是indigo版本。
https://github.com/rosjava/android_apps/tree/indigo
2、导入android_apps
在android studio 中导入下载好的android_apps,在弹出的是否更新build.gradle窗口选择【cancle】,选择其中一个moudle进行编译运行,成功后就可以新建自己需要的app
3、新建app
在android_core中新建moudle,最小api设置为10,选择empty Activity 的moudle。
(1) 将MainActivity继承RosActivity,点击RosActivity后使用【alt+enter】添加RosActivity的依赖库,接着导入包import org.ros.android.RosActivity;
(2) 重写init方法和一个结构体。先编写 rosjava发布者ImuPublisher,新建一个ImuPublisher.class类,具体代码如下:
public class ImuPublisher implements NodeMain { private ImuThread imuThread; private SensorListener sensorListener; private SensorManager sensorManager; private Publisher<Imu> publisher; public ImuPublisher(SensorManager msensorManager) { this.sensorManager = msensorManager; } @Override public GraphName getDefaultNodeName() { return GraphName.of("android_sensors_driver/imuPublisher"); } public interface NodeMain extends NodeListener { GraphName getDefaultNodeName(); } @Override public void onStart(ConnectedNode connectedNode) { try { //主题为"android/imu" 消息类型为 "sensor_msgs/Imu" ,是标准类型的消息 this.publisher = connectedNode.newPublisher("android/imu","sensor_msgs/Imu"); int i = this.sensorManager.getSensorList(1).size(); boolean hasAccel = false; if (i > 0) hasAccel = true; int j = this.sensorManager.getSensorList(4).size(); boolean hasGyro = false; if (j > 0) hasGyro = true; int k = this.sensorManager.getSensorList(11).size(); boolean hasQuat = false; if (k > 0) hasQuat = true; this.sensorListener = new SensorListener(publisher, hasAccel, hasGyro, hasQuat); this.imuThread = new ImuThread(this.sensorManager, sensorListener); this.imuThread.start(); }catch (Exception e){ if(connectedNode != null) { connectedNode.getLog().fatal(e); }else { e.printStackTrace(); } } } @Override public void onShutdown(Node node) { this.imuThread.shutdown(); try { this.imuThread.join(); return; } catch (InterruptedException localInterruptedException) { localInterruptedException.printStackTrace(); } } @Override public void onShutdownComplete(Node node) { } @Override public void onError(Node node, Throwable throwable) { } /** * run(){}注册传感器监听事件 * shutdown(){}注销传感器监听事件 */ private class ImuThread extends Thread{ private final SensorManager sensorManager; private ImuPublisher.SensorListener sensorListener; private Looper threadLooper; private final Sensor accelSensor; private final Sensor gyroSensor; private final Sensor quatSensor; private ImuThread(SensorManager sensorManager,ImuPublisher.SensorListener sensorListener){ this.sensorManager = sensorManager; this.sensorListener = sensorListener; this.accelSensor =this.sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);//加速度(重力)传感器: this.gyroSensor =this.sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE); this.quatSensor =this.sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR); } @Override public void run() { Looper.prepare(); this.threadLooper =Looper.myLooper(); this.sensorManager.registerListener(this.sensorListener,this.accelSensor,SensorManager.SENSOR_DELAY_UI); this.sensorManager.registerListener(this.sensorListener,this.gyroSensor,SensorManager.SENSOR_DELAY_UI); this.sensorManager.registerListener(this.sensorListener,this.quatSensor,SensorManager.SENSOR_DELAY_UI); Looper.loop(); } public void shutdown() { this.sensorManager.unregisterListener(this.sensorListener); if(this.threadLooper !=null) { this.threadLooper.quit(); } } } /** * 传感器事件监听 * onAccuracyChanged(){}传感器精度发生变化进行监听 * onSensorChanged(){}传感器数据发生变化进行监听 */ static class SensorListener implements SensorEventListener { private long count = 0; private Publisher<Imu> publisher; private long accelTime; private long gyroTime; private long quatTime; private boolean hasAccel; private boolean hasGyro; private boolean hasQuat; private Imu imu; private SensorListener(Publisher<Imu> publisher,boolean hasAccel,boolean hasGyro,boolean hasQuat){ this.publisher = publisher; this.hasAccel = hasAccel; this.hasGyro = hasGyro; this.hasQuat = hasQuat; this.imu =this.publisher.newMessage(); } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { } @Override public void onSensorChanged(SensorEvent event) { count ++; float[] values = event.values; StringBuilder sb = new StringBuilder(); sb.append("\n传感器取值频率为:\n"); sb.append(1000 / ((System.currentTimeMillis() - MainActivity.start_time) / count)); Bundle b = new Bundle(); b.putString("result", sb.toString()); Message msg = new Message(); msg.setData(b); MainActivity.handler.sendMessage(msg); //加速度 this.imu.getLinearAcceleration().setX(event.values[0]); this.imu.getLinearAcceleration().setY(event.values[1]); this.imu.getLinearAcceleration().setZ(event.values[2]); double[] tmpCov1 = { 0.01D, 0.0D, 0.0D, 0.0D, 0.01D, 0.0D, 0.0D, 0.0D, 0.01D }; this.imu.setLinearAccelerationCovariance(tmpCov1); this.accelTime = event.timestamp; //角速度 this.imu.getAngularVelocity().setX(event.values[0]); this.imu.getAngularVelocity().setY(event.values[1]); this.imu.getAngularVelocity().setZ(event.values[2]); double[] tmpCov2 ={0.0025,0,0,0,0.0025,0,0,0,0.0025};// TODO Make Parameter this.imu.setAngularVelocityCovariance(tmpCov2); this.gyroTime = event.timestamp; //方向 float[] quaternion = new float[4]; SensorManager.getQuaternionFromVector(quaternion, event.values); this.imu.getOrientation().setW(quaternion[0]); this.imu.getOrientation().setX(quaternion[1]); this.imu.getOrientation().setY(quaternion[2]); this.imu.getOrientation().setZ(quaternion[3]); double[] tmpCov3 ={0.001,0,0,0,0.001,0,0,0,0.001};// TODO Make Parameter this.imu.setOrientationCovariance(tmpCov3); this.quatTime = event.timestamp; //求取获取传感器参数的频率 long time_delta_millis =System.currentTimeMillis()- SystemClock.uptimeMillis(); this.imu.getHeader().setStamp(Time.fromMillis(time_delta_millis + event.timestamp/1000000)); this.imu.getHeader().setFrameId("/imu");// TODO Make parameter //前面组装消息 后面发布消息 publisher.publish(this.imu); // Create a new message ,清空了this.imu this.imu =this.publisher.newMessage(); this.accelTime =0L; this.gyroTime =0L; this.quatTime =0L; } }}
(3)编写MainActivity.class,见如下代码:
public class MainActivity extends RosActivity { private ImuPublisher imu_pub; private SensorManager msensorManager; private EditText et; public static Handler handler; public static long start_time; public MainActivity() { super("android_sensors_driver", "android_sensors_driver"); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_main); start_time = System.currentTimeMillis(); et = (EditText)findViewById(R.id.et); //获取系统的传感器管理服务 msensorManager = (SensorManager) this.getSystemService(SENSOR_SERVICE); handler = new Handler(){ @Override public void handleMessage(Message msg) { Bundle bundle = msg.getData(); txt1.setText(bundle.get("result").toString()); super.handleMessage(msg); } }; } @Override protected void onResume() { super.onResume(); } //是从父类继承过来的,父类再启动中会startServic @Override protected void init(final NodeMainExecutor nodeMainExecutor) { NodeConfiguration nodeConfiguration1 = NodeConfiguration.newPublic(InetAddressFactory.newNonLoopback().getHostAddress()); nodeConfiguration1.setMasterUri(getMasterUri()); nodeConfiguration1.setNodeName("android_sensors_driver"); this.imu_pub = new ImuPublisher(msensorManager); nodeMainExecutor.execute(this.imu_pub,nodeConfiguration1); } @Override public boolean onTouchEvent(MotionEvent event) { return true; }}
(4)android studio 的布局文件如下:
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.example.betty.app.MainActivity"> <EditText android:id="@+id/et" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:hint="test" android:text="hello_world" tools:context=".MainActivity" /></RelativeLayout>
(5) 功能清单文件如下:AndroidManifest.xml
“`
rostopic echo [ /android/imu]
在终端会显示加速度、角速度、方向的三个传感器参数。
至此,ROS和安卓手机的IMU参数的通信完成
- 基于ROS和安卓手机的IMU参数的通信软件
- ROS实时采集Android的图像和IMU数据
- ROS采集Android的图像和IMU数据的一些设置
- razor imu 9dof的使用,先锋机器人rosaria 理解,配置STM32-ROS通信等疑难杂症(持续更新中)
- 基于matlab的双目+IMU标定
- 基于EKF的IMU姿态结算
- 安卓手机和单片机音频通信
- 安卓手机和单片机音频通信
- 安卓 手机和蓝牙通信连接
- 安卓手机与蓝牙串口模块的通信
- ROS和MATLAB通信的一个测试
- 获取运行软件的手机的安卓版本
- 安卓软件定做-华为Mate7手机高配版和标准版的区别
- 安卓手机与ROS通信遥控Gazebo中仿真机器人小车运动(ROS_indigo)
- 基于安卓手机的WAPI证书安装使用详解
- 安卓手机安装软件提示存储空间不足的解决方法
- 安卓手机安装软件提示存储空间不足的解决方法
- 基于单片机蓝牙通信的安卓上位机应用
- Linux strace 命令
- nginx tomcat 区别
- C#如何向js传递数组
- 随机数游戏
- ABAP开发中常用的两个F4搜索帮助函数的区别
- 基于ROS和安卓手机的IMU参数的通信软件
- HALCON仿射变换基础
- Postman Tests中设置环境变量,结果转json数值失去精度
- VMware Fusion 8.0.0 for Mac序列号(亲测可用)
- Linux 创建用户和工作组
- HTML基础知识笔记总结20171117
- 【笔记】在主函数内声明int a[1000000],运行出错
- 公共钥匙盒 Java算法
- SpringMVC与Struts2区别与比较总结