Rosmin--在Android上绘制小车行进路线图并标记

本文介绍了一种在Android设备上通过获取陀螺仪和磁力计数据,实现实时显示小车行进路线及标记重要地点的方法。利用两部手机间的数据传输,一部手机收集并发送小车状态数据,另一部手机接收这些数据并在地图上绘制路线。
部署运行你感兴趣的模型镜像

转自:http://blog.youkuaiyun.com/f_season/article/details/9171523

        如何在Android显示小车的行进路线并且当遇到重要事物时在地图上标记?前面一篇文章已经讲了两台手机的socket双向通信,这里就以此进行数据信息的传输。

        我以小车上的手机作为server,以手上的手机作为client,server用于陀螺仪和磁力计信息和图像信息(摄像头获取QR码和是否找到小球的信息)发送给client,client根据获得的信息绘制出小车的行进路线图和标记图标。

        首先说说server发给client的数据格式,是四位数组  String[] a ={"S","0","0","0"},至于如何发送请看上一篇,我就不累犊了……

    a[0]中S表示停止,F表示前进,B表示后退
    a[1]存的是陀螺仪角度,和小车初始方向角处理得到当前小车朝向
    a[2]存的是磁力角角度,确定小车初始方向角
    a[3]记录发现的物体,比如 "ball" 和QR码

        client部分绘制路线图,具体思路是:借用google map为小车路线图,server获得磁力计的角度,确定小车初始位置。然后根据陀螺仪角度实时获得小车方位,从而在地图上画出具有方向性的路线图。当小车获取QR码并发送给client,地图上将标记出QR码,点击就可以获取QR信息。同理,当找到小球时,地图上也会出现图标告诉你小车是在哪找到小球的。下面是client的绘图部分:

[java]  view plain copy
  1. appState = ((RosminState)getApplicationContext());  
  2. mapView =(MapView)findViewById(R.id.map);  
  3. mapcontroller = mapView.getController();  
  4. originMaker = getResources().getDrawable(R.drawable.origin);//起点图标  
  5. currMaker = getResources().getDrawable(R.drawable.sign);      //当前位置图标  
  6. ballMaker = getResources().getDrawable(R.drawable.goal);       //发现小球图标  
  7.   
  8. lat1 = 0;  
  9. lng1 = 0;  
  10. //画出起点,小车路线原理就是画出两点并连线,周而复始  
  11. points.add(new GeoPoint((int) (lat1 * 1000000),(int) (lng1 * 1000000)));  
  12.   
  13. //添加自定义的图层  
  14. PathOverLay polyline = new PathOverLay(points);  //添加polyline图层,负责画出路线  
  15. mapView.getOverlays().add(polyline);  
  16. mapView.invalidate();  
  17. mapView.setBuiltInZoomControls(true);  
  18. //设置中心和放大倍数  
  19. GeoPoint  point=new GeoPoint((int) (lat1 * 1000000),(int) (lng1 * 1000000));  
  20. mapcontroller.setCenter(point);  
  21. mapcontroller.setZoom(15);  
  22. //这个图层负责添加图标,这里添加“起点”图标  
  23. myOverlay = new MapOverlay(originMaker);  
  24. myOverlay.setItem(point);  
  25. myOverlay.setQR("起点");  
  26. mapView.getOverlays().add(myOverlay);  
  27. mapcontroller.animateTo(point);  
小车路线原理就是画出两点并连线,周而复始……这里布置两个图层,一个负责画出路线,另一个负责标记图标。

下面具体方法,放入thread实时进行:

[java]  view plain copy
  1.   //在地图上画出路线以及做出标记  
  2.  Thread time = new Thread(new Runnable()  
  3.    {  
  4.    public void run() {  
  5.      long   t1 = 0,t2 = 0 ;  
  6.             while(true){  
  7.               while(!Control.a[0].equals("F") && !Control.a[0].equals("B"))//未获得行动命令就等待  
  8.               {  
  9.                 if(!Control.a[3].equals("0") && !Control.a[3].equals("ball"))  
  10.                 {  
  11.                    break;  
  12.                 }                      
  13.                 if(Control.a[3].equals("ball"))  
  14.                 {  
  15.                   break;                
  16.                 }  
  17.               }  
  18.                 
  19.               t1 = System.currentTimeMillis();  
  20.                 if(!Control.a[3].equals("0") && !Control.a[3].equals("ball"))  
  21.                   //发现QR码并保存,在地图上标记  
  22.                 {  
  23.                     QRmsg = Control.a[3];  
  24.                     getQR =true;  
  25.                     addMarker();          
  26.                 }  
  27.                 if(Control.a[3].equals("ball"))    
  28.                   //发现小球,在地图上标记  
  29.                 {  
  30.                   findBALL=true;  
  31.                   addMarker();  
  32.                 }  
  33.               try  
  34.              {  
  35.                Thread.sleep(50);  
  36.              }  
  37.              catch (InterruptedException e)  
  38.              {  
  39.                // TODO Auto-generated catch block  
  40.                e.printStackTrace();  
  41.              }  
  42.               t2 = System.currentTimeMillis();  
  43.               moveTimeGap = t2 -t1 ;  
  44.               Handler01.post(rDraw);  
  45.               }  
  46.          }//run  
  47.    });  
  48. time.start();  
当检测QR码时,把QR的信息保存到QRmsg中,并addMarker()在地图上添加图标。当检测到小球时,同样在地图上添加小球图标。用handler传递绘制路线。
[java]  view plain copy
  1. /**画图部分,这里使用经纬度来表示小车朝向与行进路线 
  2.  *   最初用磁力计得到方向角,然后与陀螺仪得到的角度进行处理得到当前小车朝向 
  3.  * */  
  4.    private Runnable rDraw = new Runnable()  
  5.    {  
  6.      public void run()  
  7.      {  
  8.        if(ori)  
  9.        {  
  10.        oriAngle = Integer.parseInt(Control.a[2]);  
  11.        ori = false;  
  12.        }  
  13.        gyroAngle = Integer.parseInt( Control.a[1] );  
  14.        if(Control.a[0].equals("F"))  
  15.        {  
  16.        lat1 += (moveTimeGap*0.000001)*Math.cos((oriAngle-gyroAngle)*0.017452);  
  17.        lng1 += (moveTimeGap*0.000001)*Math.sin((oriAngle-gyroAngle)*0.017452);  
  18.        points.add(new GeoPoint((int) (lat1 * 1000000),(int) (lng1 * 1000000)));  
  19.        }  
  20.        if(Control.a[0].equals("B"))  
  21.        {  
  22.          lat1 -= (moveTimeGap*0.000001)*Math.cos((oriAngle-gyroAngle)*0.017452);  
  23.          lng1 -= (moveTimeGap*0.000001)*Math.sin((oriAngle-gyroAngle)*0.017452);  
  24.          points.add(new GeoPoint((int) (lat1 * 1000000),(int) (lng1 * 1000000)));  
  25.        }  
  26.      }  
  27.    };  
当得到磁力计角度确定小车当前初始角度后就不再处理磁力计获得的角度,也就是说它只用来定位初始位置,后面的姿态都是由陀螺仪获得。因为陀螺仪的精度远远大于磁力计获得的方位角,磁力计的方位角老飘……这里通过对坐标两个值的增减来近似定出小车当前的坐标。

[java]  view plain copy
  1. private void addMarker() {  
  2.        if(getQR)  //发现QR码后,存储坐标,显示图标,记录QR信息  
  3.      {  
  4.                GeoPoint myGeoPoint = new GeoPoint((int) (lat1 * 1000000),(int) (lng1 * 1000000));  
  5.                myOverlay = new MapOverlay(currMaker);  
  6.                myOverlay.setItem(myGeoPoint);  
  7.                myOverlay.setQR(QRmsg);  
  8.                mapView.getOverlays().add(myOverlay);  
  9.                getQR = false;  
  10.     }  
  11.       if(findBALL)  //发现球后,存储坐标,显示图标,记录球信息  
  12.      {  
  13.                GeoPoint myGeoPoint = new GeoPoint((int) (lat1 * 1000000),(int) (lng1 * 1000000));  
  14.                myOverlay = new MapOverlay(ballMaker);  
  15.                myOverlay.setItem(myGeoPoint);  
  16.                myOverlay.setQR("发现小球");  
  17.                mapView.getOverlays().add(myOverlay);  
  18.                findBALL = false;  
  19.     }  
  20.    }  
如代码注解所示,不过MapOverlay具体是怎么工作的,我们继续……

[java]  view plain copy
  1. public class MapOverlay extends ItemizedOverlay<OverlayItem> {  
  2.      private List<GeoPoint> mItems = new ArrayList<GeoPoint>();  
  3.      public List<String> QRmessage = new ArrayList<String>();  
  4.   
  5.      public MapOverlay(Drawable marker) {  
  6.          super(boundCenterBottom(marker));  
  7.      }  
  8.   
  9.      public void setItems(ArrayList<GeoPoint> items) {  
  10.          mItems = items;  
  11.          populate();  
  12.      }  
  13.   
  14.      public void setItem(GeoPoint item) {  
  15.          mItems.add(item);  
  16.          populate();  
  17.      }  
  18.   
  19.      public void setQR(String s) {  
  20.        QRmessage.add(s);  
  21.        populate();  
  22.    }  
  23.   
  24.      @Override  
  25.      protected OverlayItem createItem(int i) {  
  26.          return new OverlayItem(mItems.get(i), nullnull);  
  27.      }  
  28.   
  29.      @Override  
  30.      public int size() {  
  31.          return mItems.size();  
  32.      }  
  33.   
  34.      @Override  
  35.      protected boolean onTap(int i) {  
  36.         Toast.makeText(Map.this"获得信息\n "+ QRmessage, Toast.LENGTH_SHORT).show();  
  37.          return true;  
  38.      }  
  39.  }  
这里可以看出,我们可以记录单独点坐标和单独的信息,这些数据以ArrayList的方式存储。当小车发现了小球,这时地图上就标记出了一个图标,点击就会显示“发现小球”……上面就是对专门负责画图标的MapOverlay图层进行的说明,那我再回头看看专门负责画路线的PathOverLay图层是怎么实现路线绘制功能的……

[java]  view plain copy
  1. public class PathOverLay extends Overlay {  
  2.     List<GeoPoint> points;    
  3.     Paint paint;    
  4.     
  5.     /**  
  6.      * 构造函数,使用GeoPoint List构造Polyline  
  7.      *   
  8.      * @param points  
  9.      *            GeoPoint点List  
  10.      */    
  11.     public PathOverLay(List<GeoPoint> points) {    
  12.         this.points = points;    
  13.         paint = new Paint();    
  14.         paint.setColor(Color.rgb(59,88,235));  
  15.         paint.setAlpha(150);    
  16.         paint.setAntiAlias(true);    
  17.         paint.setStyle(Paint.Style.FILL_AND_STROKE);    
  18.         paint.setStrokeWidth(4);    
  19.     }    
  20.     
  21.     /**  
  22.      * 使用GeoPoint点List和Paint对象来构造Polyline  
  23.      *   
  24.      * @param points  
  25.      *            GeoPoint点List,所有的拐点  
  26.      * @param paint  
  27.      *            Paint对象,用来控制划线样式  
  28.      */    
  29.     public PathOverLay(List<GeoPoint> points, Paint paint) {    
  30.         this.points = points;    
  31.         this.paint = paint;    
  32.     }    
  33.     
  34.     /**  
  35.      * 真正将线绘制出来 只需将线绘制到canvas上即可,主要是要转换经纬度到屏幕坐标  
  36.      */    
  37.     @Override    
  38.     public void draw(Canvas canvas, MapView mapView, boolean shadow) {    
  39.       int i;  
  40.         if (!shadow) {// 不是绘制shadow层    
  41.             Projection projection = mapView.getProjection();    
  42.             if (points != null) {    
  43.                 if (points.size() >= 2) {    
  44.                     Point start = projection.toPixels(points.get(0), null);// 需要转换坐标    
  45.                     for ( i = 1; i < points.size(); i++) {    
  46.                         Point end = projection.toPixels(points.get(i), null);                         
  47.                         canvas.drawLine(start.x, start.y, end.x, end.y, paint);// 绘制到canvas上即可    
  48.                         start = end;  
  49.                         if(i == points.size()-1)  
  50.                         {  
  51.                           paint.setColor(Color.rgb(250,20,85));  
  52.                           end = projection.toPixels(points.get(i), null);                         
  53.                           canvas.drawCircle(end.x, end.y, 6, paint);  
  54.                           paint.setColor(Color.rgb(59,88,235));  
  55.                         }  
  56.                     }    
  57.                 }    
  58.             }    
  59.         }    
  60.     }    
  61. }    
点坐标是以List的方式存储,最先是对它的粗细、颜色等进行设置。这里绘图的方法具体是:确定当前点,和前面一个点进行连线,同时将当前点设置成不同于前面的蓝色,从而明显显示当前小车位置。

PS:google map因为是google的核心技术,所以看源代码就别想了,接口的调用需要慢慢熟悉。原先google map有地图解析什么的,这是真实地图用的,我这里只是借用google map来绘制小车路线而已,所以只用了2个图层和点点连线的绘图方式,然后借用经度纬度反应出小车的具体方向。


您可能感兴趣的与本文相关的镜像

HunyuanVideo-Foley

HunyuanVideo-Foley

语音合成

HunyuanVideo-Foley是由腾讯混元2025年8月28日宣布开源端到端视频音效生成模型,用户只需输入视频和文字,就能为视频匹配电影级音效

### 关于智能小车的用例 智能小车(也称为自动导引车或AGV)是一种能够自主导航执行特定任务的小型车辆。为了更好地理解智能小车的功能及其交互方式,可以绘制其用例来展示不同参与者与系统之间的关系。 #### 参与者 - **操作员**:负责启动、停止以及监控智能小车的操作。 - **维护人员**:定期检查和维修设备以确保正常运行。 - **调度系统**:用于规划路径、分配任务给各个智能小车。 #### 主要用例 - **路径规划**:根据环境地计算最优行驶路线[^1]。 - **避障检测**:通过传感器识别障碍物调整行进方向。 - **货物搬运**:从指定位置拾取物品将它们运输到目标地点。 - **充电管理**:当电量低时寻找最近充电桩完成自我补电。 - **状态报告**:向控制系统发送当前位置和其他重要参数信息。 下面提供了一个简单的智能小车 Use Case Diagram 的 Python 绘制代码: ```python from diagrams import Cluster, Diagram from diagrams.programming.language import Python as PyLang from diagrams.onprem.client import User, Client from diagrams.generic.device import Mobile from diagrams.custom import Custom with Diagram("Smart Cart Use Cases", show=False): operator = User("Operator") maintainer = User("Maintainer") with Cluster("Smart Cart System"): cart = Custom("Smart\nCart", "./smart_cart.png") # 假设有一个名为 smart_cart.png 的标文件 path_planning = PyLang("Path Planning") obstacle_avoidance = PyLang("Obstacle Avoidance") cargo_handling = PyLang("Cargo Handling") charging_management = PyLang("Charging Management") status_reporting = PyLang("Status Reporting") cart >> [path_planning, obstacle_avoidance, cargo_handling, charging_management, status_reporting] scheduler = Client("Scheduler") operator >> cart maintainer >> cart scheduler >> cart ``` 此代码片段利用 `diagrams` 库创建了一张描述智能小车主功能和服务之间联系的概念。请注意,在实际应用中可能还需要考虑更多细节,如异常处理机制等。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值