创建雷达屏幕以可视化传感器数据

在构建移动机器人系统的过程中,经常需要将传感器的测量数据可视化。本文将介绍如何使用Android系统创建一个雷达屏幕,以实现这一目的。

在开发移动机器人系统时,需要可视化来自传感器的测量数据。在互联网上寻找类似项目的过程中,发现了Larry的主页()。但那个示例对并无帮助,因为它是基于PC的代码,使用了Processing编译器。因此,决定开发一个新的数据可视化程序,基于Android系统,因为计划通过移动设备远程控制机器人系统。Larry的主页对帮助很大,在此向Larry先生表示感谢。

使用代码

要将这段代码用于项目,首先需要将RadarView.java添加到项目中。然后,编辑想要显示的activity文件的资源文件。

enum radarColor {LAY, PREVSWEEP, CURSWEEP, AVRSWEEP} 这是一个枚举值,用于设置扫描值的颜色。

void setDisplayColor(radarColor what, int color) 通过Color.argb()设置颜色变量,它具有alpha、red、green、blue属性。

void setDrawMode(boolean bPreSweep, boolean bCurSweep, boolean bAvrSweep) 这是选项,用于决定三种数据的每个值是否可见。 bPreSweep:是否启用以前的数据可视化 bCurSweep:是否启用当前数据可视化 bAvrSweep:是否启用平均数据可视化 [平均值 = (以前的数据 + 当前数据) / 2]

void setHalfSweep(boolean ck) 如果输入变量为true,则显示屏幕将是半圆形,否则将是全圆形。半圆形的显示数据范围为0到180度,全圆形为0到360度。

void setMaxDistance(int val) 这个函数用于设置检测距离的最大指示值。

void setValue(int index, int val) 这是一个设置当前值的函数。 index:扫描角度,以度为单位 val:检测到的距离值

资源

在layout.xml文件中添加以下代码资源。需要更改这个包名(com.example.bskim)。

实现

雷达数据通过从原点到感应点的实线描述。线的长度是传感器和任何物体之间的距离,线的角度是从基线(x轴)检测到的方向。

检测物体的扫描运动是通过扇形实现的。

以下是RadarView类的实现代码。

public class RadarView extends View { ...... void DrawDisplay(Canvas canvas, int radius, int centerx, int centery) { float x, y; boolean clockwise = false; float ratio = (float)radius / (float)widthp * 3.0f; int textsize = (int)(25.0 * ratio); if ((dectAngle - oldDectAngle) >= 0) { clockwise = false; } else { clockwise = true; } Paint paint=new Paint(); paint.setStyle(Paint.Style.FILL_AND_STROKE); // previous sweep if (mbPrevSweep == true) { paint.setARGB(64, 0, 32, 0); Path path1st = new Path(); path1st.reset(); path1st.moveTo(centerx, centery); for (int i = 0; i < sweepAngle; i++) { x = centerx + (int) (Math.cos(Math.toRadians((-i))) * ((float) oldDistValue[i])); y = centery + (int) (Math.sin(Math.toRadians((-i))) * ((float) oldDistValue[i])); path1st.lineTo(x, y); } canvas.drawPath(path1st, paint); } // current sweep if (mbCurSweep == true) { paint.setARGB(128, 0, 200, 0); Path path2nd = new Path(); path2nd.reset(); path2nd.moveTo(centerx, centery); for (int i = 0; i < sweepAngle; i++) { x = centerx + (int) (Math.cos(Math.toRadians((-i))) * ((float) distValue[i])); y = centery + (int) (Math.sin(Math.toRadians((-i))) * ((float) distValue[i])); path2nd.lineTo(x, y); } canvas.drawPath(path2nd, paint); } // average if (mbAvrSweep == true) { paint.setStyle(Paint.Style.STROKE); paint.setARGB(255, 0, 0, 255); Path pathavg = new Path(); pathavg.reset(); pathavg.moveTo(centerx, centery); for (int i = 0; i < sweepAngle; i++) { x = centerx + (int) (Math.cos(Math.toRadians((-i))) * ((float) ((distValue[i] + oldDistValue[i]) / 2))); y = centery + (int) (Math.sin(Math.toRadians((-i))) * ((float) ((distValue[i] + oldDistValue[i]) / 2))); pathavg.lineTo(x, y); } canvas.drawPath(pathavg, paint); } // sweep motion if (mbSweepMotion == true) { // sweep motion paint.setAntiAlias(true); paint.setStrokeWidth(7); int gradationAngle = 30; if (dectAngle < gradationAngle) gradationAngle = dectAngle; if (dectAngle > (sweepAngle-gradationAngle)) gradationAngle = sweepAngle-dectAngle; // scan motion drawing if (clockwise == false) { for (int i = gradationAngle; i >= 0; i--) { if (i == 0) paint.setColor(mLayColor); else paint.setARGB(128, 150+(100/gradationAngle * i), 150+(100/gradationAngle * i), 150+(100/gradationAngle * i)); canvas.drawLine(centerx, centery, centerx + (int)(Math.cos(Math.toRadians(-dectAngle + (i))) * (float)radius), centery + (int) (Math.sin(Math.toRadians(-dectAngle + (i))) * (float)radius), paint); } } else { for (int i = 0; i <= gradationAngle; i++) { if (i == 0) paint.setColor(mLayColor); else paint.setARGB(128, 150+(100/gradationAngle * i), 150+(100/gradationAngle * i), 150+(100/gradationAngle * i)); canvas.drawLine(centerx, centery, centerx + (int) (Math.cos(Math.toRadians(-dectAngle + (-i))) * (float) radius), centery + (int) (Math.sin(Math.toRadians(-dectAngle + (-i))) * (float) radius), paint); } } } } }

创建视图和使用示例

创建RadarView的对象实例并配置其属性。例如,全圆形模式,扫描线颜色为绿色。扫描距离范围由常量MAX_DISTANCE设置,可以使用预定义的XML文件中的资源,通过findViewById()获取。

RadarView mRadarView; mRadarView = (RadarView) findViewById(R.id.RadarView); mRadarView.setHalfSweep(false); mRadarView.setDisplayColor(RadarView.radarColor.LAY, Color.argb(255, 0, 255, 0)); mRadarView.setMaxDistance(MAX_DISTANCE); mRadarView.setSweepMotion(true);

以下代码展示了这个类的使用。要绘制的数据缓冲区通过setValue(..)填充,并且使用handler以安全的方式更新视图。

TimerTask mTask; Timer mTimer; mTask = new TimerTask() { @Override public void run() { if (mRadarView.isHalfMode() == true) { if (angle > 180) flag = 0; if (angle <= 0) flag = 1; if (flag == 0) angle--; else angle++; } else { if (angle > 360) angle = 0; else angle++; } int distance = mRandVal.nextInt(MAX_DISTANCE); mRadarView.setValue(angle, distance); RadarViewInvalidate(); } }; mTimer = new Timer(); mTimer.schedule(mTask, 500, 100); // every 100ms after 500ms.

在使用setValue(..)输入新的传感器数据后,应该调用RadaViewInvalidate()来更新视图。

Handler mDrawHandler = new Handler(); private void RadarViewInvalidate() { mDrawHandler.post(new Runnable() { @Override public void run() { mRadarView.invalidate(); } }); }
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485