فهرست منبع

add RemoteCtrl_Thread. but not complete.

yuchuli 3 سال پیش
والد
کامیت
213ab88a41
33فایلهای تغییر یافته به همراه3943 افزوده شده و 0 حذف شده
  1. 350 0
      src/driver/driver_cloud_grpc_pc_thread/grpcpc.cpp
  2. 92 0
      src/driver/driver_cloud_grpc_pc_thread/grpcpc.h
  3. 341 0
      src/tool/RemoteCtrl_Thread/BaiDuMap.html
  4. 120 0
      src/tool/RemoteCtrl_Thread/RemoteCtrl _Thread.pro
  5. 11 0
      src/tool/RemoteCtrl_Thread/RemoteCtrl.xml
  6. BIN
      src/tool/RemoteCtrl_Thread/car.png
  7. 100 0
      src/tool/RemoteCtrl_Thread/dialogbigpic.cpp
  8. 52 0
      src/tool/RemoteCtrl_Thread/dialogbigpic.h
  9. 18 0
      src/tool/RemoteCtrl_Thread/dialogbigpic.ui
  10. 102 0
      src/tool/RemoteCtrl_Thread/dialogpic.cpp
  11. 49 0
      src/tool/RemoteCtrl_Thread/dialogpic.h
  12. 19 0
      src/tool/RemoteCtrl_Thread/dialogpic.ui
  13. 52 0
      src/tool/RemoteCtrl_Thread/driver_cloud_grpc_pc.yaml
  14. 155 0
      src/tool/RemoteCtrl_Thread/ivpicsave.cpp
  15. 44 0
      src/tool/RemoteCtrl_Thread/ivpicsave.h
  16. 112 0
      src/tool/RemoteCtrl_Thread/ivpicview.cpp
  17. 40 0
      src/tool/RemoteCtrl_Thread/ivpicview.h
  18. 25 0
      src/tool/RemoteCtrl_Thread/ivview.cpp
  19. 34 0
      src/tool/RemoteCtrl_Thread/ivview.h
  20. 161 0
      src/tool/RemoteCtrl_Thread/joyreadthread.cpp
  21. 39 0
      src/tool/RemoteCtrl_Thread/joyreadthread.h
  22. 76 0
      src/tool/RemoteCtrl_Thread/main.cpp
  23. 841 0
      src/tool/RemoteCtrl_Thread/mainwindow.cpp
  24. 183 0
      src/tool/RemoteCtrl_Thread/mainwindow.h
  25. 499 0
      src/tool/RemoteCtrl_Thread/mainwindow.ui
  26. 120 0
      src/tool/RemoteCtrl_Thread/myview.cpp
  27. 35 0
      src/tool/RemoteCtrl_Thread/myview.h
  28. 2 0
      src/tool/RemoteCtrl_Thread/pos.txt
  29. 16 0
      src/tool/RemoteCtrl_Thread/pos_def.h
  30. BIN
      src/tool/RemoteCtrl_Thread/remotectrl.png
  31. 5 0
      src/tool/RemoteCtrl_Thread/remotectrl.qrc
  32. 199 0
      src/tool/RemoteCtrl_Thread/speed.cpp
  33. 51 0
      src/tool/RemoteCtrl_Thread/speed.h

+ 350 - 0
src/driver/driver_cloud_grpc_pc_thread/grpcpc.cpp

@@ -0,0 +1,350 @@
+#include "grpcpc.h"
+
+
+static grpcpc * ggrpcpc;
+
+void ListenData(const char * strdata,const unsigned int nSize,const unsigned int index,const QDateTime * dt,const char * strmemname)
+{
+    ggrpcpc->UpdateData(strdata,nSize,strmemname);
+}
+
+
+grpcpc::grpcpc(std::string stryamlpath)
+{
+    ggrpcpc = this;
+    dec_yaml(stryamlpath.data());
+    int i;
+    for(i=0;i<mvectormsgunit.size();i++)
+    {
+        mvectormsgunit[i].mpa = iv::modulecomm::RegisterSend(mvectormsgunit[i].mstrmsgname,mvectormsgunit[i].mnBufferSize,mvectormsgunit[i].mnBufferCount);
+    }
+
+    for(i=0;i<mvectorctrlmsgunit.size();i++)
+    {
+        mvectorctrlmsgunit[i].mpa = iv::modulecomm::RegisterRecv(mvectorctrlmsgunit[i].mstrmsgname,ListenData);
+    }
+}
+
+
+void grpcpc::run()
+{
+    int nsize = mvectormsgunit.size();
+    int nctrlsize = mvectorctrlmsgunit.size();
+    int i;
+
+    qint64 nlasttime = 0;
+
+    int ninterval = atoi(gstruploadinterval.data());
+    if(ninterval<=0)ninterval = 100;
+
+    QTime xTime;
+    xTime.start();
+    int nlastsend = xTime.elapsed();
+
+    std::string target_str = gstrserverip+":";
+    target_str = target_str + gstrserverport ;//std::to_string()
+    auto cargs = grpc::ChannelArguments();
+    cargs.SetMaxReceiveMessageSize(1024 * 1024 * 1024); // 1 GB
+    cargs.SetMaxSendMessageSize(1024 * 1024 * 1024);
+
+    std::shared_ptr<Channel> channel = grpc::CreateCustomChannel(
+             target_str, grpc::InsecureChannelCredentials(),cargs);
+
+    std::unique_ptr<iv::UploadThread::Stub> stub_ = iv::UploadThread::NewStub(channel);
+
+
+    iv::queryReqThread request;
+    iv::queryReplyThread xreply;
+
+    int nid = 0;
+    int nctrlid = 0;
+
+    // Container for the data we expect from the server.
+//    iv::queryReply reply;
+
+    gpr_timespec timespec;
+      timespec.tv_sec = 30;//设置阻塞时间为2秒
+      timespec.tv_nsec = 0;
+      timespec.clock_type = GPR_TIMESPAN;
+
+
+    while(!QThread::isInterruptionRequested())
+    {
+        std::this_thread::sleep_for(std::chrono::milliseconds(1));
+        if(abs(xTime.elapsed()-nlastsend)<ninterval)
+        {
+            continue;
+        }
+
+        bool bImportant = false;
+        int nkeeptime = 0;
+
+            iv::cloud::cloudmsg xmsg;
+            xmsg.set_xtime(QDateTime::currentMSecsSinceEpoch());
+            nlastsend = xTime.elapsed();
+            gMutexMsg.lock();
+
+  //          std::vector<iv::msgunit> xv = mvectorctrlmsgunit;
+            for(i=0;i<nctrlsize;i++)
+            {
+                if(mvectorctrlmsgunit[i].mbRefresh)
+                {
+                    mvectorctrlmsgunit[i].mbRefresh = false;
+
+                    if(mvectorctrlmsgunit[i].mbImportant)
+                    {
+                        bImportant = true;
+                    }
+                    if(mvectorctrlmsgunit[i].mnkeeptime > nkeeptime)
+                    {
+                        nkeeptime = mvectorctrlmsgunit[i].mnkeeptime;
+                    }
+                    iv::cloud::cloudunit xcloudunit;
+                    xcloudunit.set_msgname(mvectorctrlmsgunit[i].mstrmsgname);
+                    xcloudunit.set_data(mvectorctrlmsgunit[i].mpstrmsgdata.get(),mvectorctrlmsgunit[i].mndatasize);
+                    iv::cloud::cloudunit * pcu = xmsg.add_xclouddata();
+                    pcu->CopyFrom(xcloudunit);
+                }
+
+            }
+            gMutexMsg.unlock();
+
+
+            {
+
+                ClientContext context ;
+                context.set_deadline(timespec);
+ //               qint64 time1 = QDateTime::currentMSecsSinceEpoch();
+
+                request.set_strquerymd5(gstrqueryMD5);
+                request.set_strvin(gstrVIN);
+
+                request.set_nlasttime(nlasttime);
+
+                request.set_id(nctrlid);nctrlid++;
+                request.set_strctrlmd5(gstrctrlMD5);
+                request.set_strvin(gstrVIN);
+                request.set_ntime(QDateTime::currentMSecsSinceEpoch());
+                request.set_bimportant(bImportant);
+                request.set_kepptime(nkeeptime);
+                if(xmsg.xclouddata_size()>0)
+                {
+                    int nbytesize = xmsg.ByteSize();
+                    std::vector<char> pvectordata;
+                    pvectordata.resize(nbytesize);
+                    if(xmsg.SerializeToArray(pvectordata.data(),nbytesize))
+                    {
+
+                        request.set_xdata(pvectordata.data(),pvectordata.size());
+
+                    }
+                }
+
+
+                QDateTime xTime;
+                xTime.fromMSecsSinceEpoch(1607905685318);  //1607914763641
+//                qDebug("time:%s",xTime.toString("yyyy-MM-dd:hh:mm:ss:zzz").toLatin1().data());
+                qDebug("nlasttime is %ld",nlasttime);//1607905685318
+                nid++;
+                // The actual RPC.
+                Status status = stub_->queryctrl(&context, request, &xreply);
+                if (status.ok()) {
+                    std::cout<<nid<<" query successfully, res is "<<xreply.nres()<<std::endl;
+                    if(xreply.nres() == 1)
+                    {
+
+                        if(nlasttime != xmsg.xtime())
+                        {
+                            iv::cloud::cloudmsg xmsg;
+                            if(xmsg.ParseFromArray(xreply.xdata().data(),xreply.xdata().size()))
+                            {
+                                sharequerymsg(&xmsg);
+                            }
+                        }
+
+                        nlasttime = xreply.ntime();
+                    }
+                } else {
+                  std::cout << status.error_code() << ": " << status.error_message()
+                            << std::endl;
+                  std::cout<<"RPC failed"<<std::endl;
+
+                  if(status.error_code() == 4)
+                  {
+                      std::cout<<" RPC Exceed Time, Create New stub_"<<std::endl;
+                      channel = grpc::CreateCustomChannel(
+                               target_str, grpc::InsecureChannelCredentials(),cargs);
+
+                      stub_ = iv::UploadThread::NewStub(channel);
+                  }
+                  std::this_thread::sleep_for(std::chrono::milliseconds(900));
+
+                }
+
+            }
+
+
+
+    }
+}
+
+
+void grpcpc::dec_yaml(const char *stryamlpath)
+{
+    YAML::Node config;
+    try
+    {
+        config = YAML::LoadFile(stryamlpath);
+    }
+    catch(YAML::BadFile e)
+    {
+        qDebug("load error.");
+        return;
+    }
+
+    std::vector<std::string> vecmodulename;
+
+
+    if(config["server"])
+    {
+        gstrserverip = config["server"].as<std::string>();
+    }
+    if(config["port"])
+    {
+        gstrserverport = config["port"].as<std::string>();
+    }
+    if(config["uploadinterval"])
+    {
+        gstruploadinterval = config["uploadinterval"].as<std::string>();
+    }
+
+
+    if(config["VIN"])
+    {
+        gstrVIN = config["VIN"].as<std::string>();
+    }
+
+    if(config["queryMD5"])
+    {
+        gstrqueryMD5 = config["queryMD5"].as<std::string>();
+    }
+
+    if(config["ctrlMD5"])
+    {
+        gstrctrlMD5 = config["ctrlMD5"].as<std::string>();
+    }
+
+
+    std::string strmsgname;
+
+    if(config["querymessage"])
+    {
+
+        for(YAML::const_iterator it= config["querymessage"].begin(); it != config["querymessage"].end();++it)
+        {
+            std::string strtitle = it->first.as<std::string>();
+            std::cout<<strtitle<<std::endl;
+
+            if(config["querymessage"][strtitle]["msgname"]&&config["querymessage"][strtitle]["buffersize"]&&config["querymessage"][strtitle]["buffercount"])
+            {
+                iv::msgunit xmu;
+                strmsgname = config["querymessage"][strtitle]["msgname"].as<std::string>();
+                strncpy(xmu.mstrmsgname,strmsgname.data(),255);
+                xmu.mnBufferSize = config["querymessage"][strtitle]["buffersize"].as<int>();
+                xmu.mnBufferCount = config["querymessage"][strtitle]["buffercount"].as<int>();
+                mvectormsgunit.push_back(xmu);
+
+
+            }
+        }
+    }
+    else
+    {
+
+    }
+
+    if(config["ctrlmessage"])
+    {
+        std::string strnodename = "ctrlmessage";
+        for(YAML::const_iterator it= config[strnodename].begin(); it != config[strnodename].end();++it)
+        {
+            std::string strtitle = it->first.as<std::string>();
+            std::cout<<strtitle<<std::endl;
+
+            if(config[strnodename][strtitle]["msgname"]&&config[strnodename][strtitle]["buffersize"]&&config[strnodename][strtitle]["buffercount"])
+            {
+                iv::msgunit xmu;
+                strmsgname = config[strnodename][strtitle]["msgname"].as<std::string>();
+                strncpy(xmu.mstrmsgname,strmsgname.data(),255);
+                xmu.mnBufferSize = config[strnodename][strtitle]["buffersize"].as<int>();
+                xmu.mnBufferCount = config[strnodename][strtitle]["buffercount"].as<int>();
+
+                if(config[strnodename][strtitle]["bimportant"])
+                {
+                   std::string strimportant =    config[strnodename][strtitle]["bimportant"].as<std::string>();
+                   if(strimportant == "true")
+                   {
+                       xmu.mbImportant = true;
+                   }
+                }
+                if(config[strnodename][strtitle]["keeptime"])
+                {
+                   std::string strkeep =    config[strnodename][strtitle]["keeptime"].as<std::string>();
+                   xmu.mnkeeptime = atoi(strkeep.data());
+                }
+                mvectorctrlmsgunit.push_back(xmu);
+            }
+        }
+    }
+    else
+    {
+
+    }
+
+    return;
+}
+
+void grpcpc::sharequerymsg(iv::cloud::cloudmsg *pxmsg)
+{
+    int i;
+    int nsize = pxmsg->xclouddata_size();
+    for(i=0;i<nsize;i++)
+    {
+        int j;
+        int nquerysize = mvectormsgunit.size();
+        for(j=0;j<nquerysize;j++)
+        {
+            if(strncmp(pxmsg->xclouddata(i).msgname().data(), mvectormsgunit[j].mstrmsgname,255) == 0)
+            {
+                qDebug("size is %d ",pxmsg->xclouddata(i).data().size());
+                iv::modulecomm::ModuleSendMsg(mvectormsgunit[j].mpa,pxmsg->xclouddata(i).data().data(),pxmsg->xclouddata(i).data().size());
+                break;
+            }
+        }
+    }
+}
+
+void grpcpc::UpdateData(const char *strdata, const unsigned int nSize,const char * strmemname)
+{
+    int nsize = mvectorctrlmsgunit.size();
+    int i;
+    for(i=0;i<nsize;i++)
+    {
+        if(strncmp(strmemname,mvectorctrlmsgunit[i].mstrmsgname,255) == 0)
+        {
+            gMutexMsg.lock();
+            char * strtem = new char[nSize];
+            memcpy(strtem,strdata,nSize);
+            mvectorctrlmsgunit[i].mpstrmsgdata.reset(strtem);
+            mvectorctrlmsgunit[i].mndatasize = nSize;
+            mvectorctrlmsgunit[i].mbRefresh = true;
+            gMutexMsg.unlock();
+            break;
+        }
+    }
+}
+
+std::string grpcpc::GetVIN()
+{
+    return gstrVIN;
+}

+ 92 - 0
src/driver/driver_cloud_grpc_pc_thread/grpcpc.h

@@ -0,0 +1,92 @@
+#ifndef GRPCPC_H
+#define GRPCPC_H
+
+#include <QThread>
+
+#include <yaml-cpp/yaml.h>
+
+#include <QDateTime>
+
+#include <iostream>
+
+#include <vector>
+
+#include <memory>
+
+#include <QMutex>
+
+#include <thread>
+
+#include "modulecomm.h"
+
+
+#include "cloud.pb.h"
+
+#include <iostream>
+#include <memory>
+#include <string>
+
+#include <grpcpp/grpcpp.h>
+
+#include "uploadthreadmsg.grpc.pb.h"
+
+using grpc::Channel;
+using grpc::ClientContext;
+using grpc::Status;
+
+namespace iv {
+struct msgunit
+{
+    char mstrmsgname[256];
+    int mnBufferSize = 10000;
+    int mnBufferCount = 1;
+    void * mpa;
+    std::shared_ptr<char> mpstrmsgdata;
+    int mndatasize = 0;
+    bool mbRefresh = false;
+    bool mbImportant = false;
+    int mnkeeptime = 100;
+};
+}
+
+class grpcpc : public QThread
+{
+public:
+    grpcpc(std::string stryamlpath);
+
+private:
+    void run();
+
+private:
+    std::string gstrserverip =  "140.143.237.38";
+    std::string gstrserverport = "9000";
+    std::string gstruploadinterval = "100";
+    void * gpa;
+    QMutex gMutexMsg;
+    std::vector<iv::msgunit> mvectormsgunit;
+
+    std::vector<iv::msgunit> mvectorctrlmsgunit;
+
+
+    std::string gstrVIN = "AAAAAAAAAAAAAAAAA";
+    std::string gstrqueryMD5 = "5d41402abc4b2a76b9719d911017c592";
+    std::string gstrctrlMD5 = "5d41402abc4b2a76b9719d911017c592";
+
+
+
+
+    int gindex = 0;
+
+
+private:
+    void dec_yaml(const char * stryamlpath);
+    void sharequerymsg(iv::cloud::cloudmsg * pxmsg);
+
+public:
+    void UpdateData(const char * strdata,const unsigned int nSize,const char * strmemname);
+    std::string GetVIN();
+
+
+};
+
+#endif // GRPCPC_H

+ 341 - 0
src/tool/RemoteCtrl_Thread/BaiDuMap.html

@@ -0,0 +1,341 @@
+
+
+<!DOCTYPE html>
+<html>
+<head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    <meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
+    <style type="text/css">
+        body, html, #allmap {
+            width: 100%;
+            height: 100%;
+            overflow: hidden;
+            margin: 0;
+            font-family: "微软雅黑";
+        }
+    </style>
+    <script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=EVi8PXiYpKBGvBr7tgGMzcbdwzWWNf2o"></script>
+
+    
+    <title>野火GPS地图</title>
+</head>
+<body>
+    <div id="allmap"></div>
+
+
+
+</body>
+</html>
+
+
+
+<script type="text/javascript">
+    try {
+
+   
+    // 百度地图API功能
+    var map = new BMap.Map("allmap");            // 创建Map实例
+
+    //添加拖拽和缩放功能
+    map.enableScrollWheelZoom(true);
+    map.enableDragging();   
+
+    //添加控件和比例尺
+    var top_right_control = new BMap.ScaleControl({ anchor: BMAP_ANCHOR_BOTTOM_LEFT });// 左下角,添加比例尺
+    var top_right_navigation = new BMap.NavigationControl({ anchor: BMAP_ANCHOR_BOTTOM_LEFT });  //左下角,添加默认缩放平移控件
+
+    map.addControl(top_right_control);
+    map.addControl(top_right_navigation);
+
+
+    //添加地图类型
+    var mapType1 = new BMap.MapTypeControl({ mapTypes: [BMAP_NORMAL_MAP, BMAP_HYBRID_MAP] });
+    var mapType2 = new BMap.MapTypeControl({ anchor: BMAP_ANCHOR_TOP_LEFT });
+
+    //添加地图类型和缩略图
+   
+    map.addControl(mapType1);          //2D图,卫星图
+    map.addControl(mapType2);          //左上角,默认地图控件
+
+    var drawtrail = 0;
+
+    var grotation = 0;
+
+
+    //创建点
+    //map.clearOverlays();
+    var point = new BMap.Point(117.355, 39.066);
+    var markerCur = new BMap.Marker(point);
+    var markerObj = new BMap.Marker(point);
+    var havepointlast = 0;
+    var pointlast = new BMap.Point(116,39);
+    var pointobj = new BMap.Point(116,39);
+    var bobjset = 0;
+    var gtracelist = []; 
+    var gtraceraw = [];
+    var tracenow = 0;
+    var tracenum = 0;
+    map.centerAndZoom(point, 18);
+    var convertor = new BMap.Convertor();
+    var polylineTrace;
+/*
+    var polylineTrace =new BMap.Polyline(gtracelist, {
+    enableEditing: false,//是否启用线编辑,默认为false
+    enableClicking: false,//是否响应点击事件,默认为true
+    strokeWeight:'4',//折线的宽度,以像素为单位
+    strokeOpacity: 0.8,//折线的透明度,取值范围0 - 1
+    strokeColor:"red" //折线颜色
+    });*/
+    //var marker = new BMap.Marker(point);  // 创建标注
+    //map.addOverlay(marker);               // 将标注添加到地图中
+    
+    //根据IP定位城市
+    function myFun(result) {
+        var cityName = result.name;
+        map.setCenter(cityName);
+    }
+    var myCity = new BMap.LocalCity();
+    myCity.get(myFun);
+
+	var icon = new BMap.Icon('car.png',new BMap.Size(15,30));
+        icon.imageSize = new BMap.Size(15,30);
+        icon.anchor = new BMap.Size(8,15);
+        
+
+    //showalert(testmsg);
+
+    //对传入的经纬度进行标注:纬度,经度
+   // var Latt = 116.404;
+   // var Lott = 39.915;
+
+   // theLocation(Latt, Lott);
+   // testAlert();
+
+    function SetDrawTrail(x)
+   {
+	
+	if(x == 1)drawtrail = 1;
+	else drawtrail = 0;
+   }    
+
+
+    function clear()
+    {
+	gtracelist = [];
+    }
+
+   
+        // 用经纬度设置地图中心点
+    function objLocation(Longitude,Latitude) {
+
+        var gpsPoint = new BMap.Point(Longitude, Latitude);
+
+	var pointArr = [];
+	pointArr.push(gpsPoint);
+        convertor.translate(pointArr, 1, 5, translateCallbackobj)
+        //gps坐标纠偏
+ //       BMap.Convertor.translate(gpsPoint, 0, translateCallbackobj);     //真实经纬度转成百度坐标
+
+
+    }
+
+    // 用经纬度设置地图中心点
+    function theLocation(Longitude,Latitude,rotation) {
+        
+        grotation = rotation;
+        var gpsPoint = new BMap.Point(Longitude, Latitude);
+
+        //gps坐标纠偏
+
+
+var pointArr = [];
+pointArr.push(gpsPoint);
+        convertor.translate(pointArr, 1, 5, translateCallback)
+//convertor.translate(gpsPoint, 0, translateCallback);     //真实经纬度转成百度坐标
+ //       BMap.Convertor.translate(gpsPoint, 0, translateCallback);     //真实经纬度转成百度坐标
+
+
+            //map.clearOverlays();
+            //var new_point = new BMap.Point(Longitude,Latitude );
+            //var marker = new BMap.Marker(new_point);  // 创建标注
+            //map.addOverlay(marker);              // 将标注添加到地图中
+            //map.panTo(new_point);
+            //marker.setAnimation(BMAP_ANIMATION_BOUNCE); //跳动的动画
+
+    }
+
+
+function settrace(numlist,num2list)                    //仅把qt传来的数组转换成可用的list
+{
+    //alert(numlist);
+    var num_list,num2_list;                         //以下为格式转换,分割成可用的数组
+    num_list = numlist.substring(1,numlist.length-1);
+    num2_list = num2list.substring(1,num2list.length-1);
+    num_list = num_list.split(",");
+    num2_list = num2_list.split(",");
+    //alert("the num_list is: "+num_list[0]+" "+num_list[1]);
+
+    
+    gtraceraw = [];
+    gtracelist = [];
+    for(i=0;i<num_list.length;i++)
+    {
+        point= new BMap.Point(num_list[i],num2_list[i]);
+        gtraceraw.push(point);                                  
+    }
+    tracenum = num_list.length;
+    tracenow = 0;
+
+    setTimeout("converttrace()", 30);// 调用画轨迹的函数
+
+    
+}
+
+function converttrace() 
+{
+    var tracelist = [];     //为轨迹做准备,把所有的点扔里面,但不对每个点标注
+    var index = 0;
+    for(i=tracenow;i<tracenum;i++)
+    {
+	tracelist.push(gtraceraw[i]);
+	index++;
+	if(index>=10)break;
+    }
+    if(index>0)
+    {
+	
+        convertor.translate(tracelist, 1,5,translateCallbacktrace);     //真实经纬度转成百度坐标
+     }
+
+}
+
+
+translateCallbacktrace = function (data){
+      if(data.status == 0) {
+        for (var i = 0; i < data.points.length; i++) {
+	gtracelist.push(data.points[i]);
+        }
+	tracenow = tracenow + data.points.length;
+      }
+
+    map.removeOverlay(polylineTrace);
+    polylineTrace =new BMap.Polyline(gtracelist, {
+    enableEditing: false,//是否启用线编辑,默认为false
+    enableClicking: false,//是否响应点击事件,默认为true
+    strokeWeight:'4',//折线的宽度,以像素为单位
+    strokeOpacity: 0.8,//折线的透明度,取值范围0 - 1
+    strokeColor:"red" //折线颜色
+    });
+    map.addOverlay(polylineTrace);          //增加折线
+      setTimeout("converttrace()", 250);// 调用画轨迹的函数
+	
+}
+
+
+
+
+    // 用经纬度设置地图中心点
+    function testAlert(msg) {
+
+        var str = new String;
+        str =  msg.toString()
+       // str = "test"
+
+        alert(str);
+    }
+
+    function enableZoomDrag()
+    {
+        //添加拖拽和缩放功能
+        map.enableScrollWheelZoom(true);
+        map.enableDragging();
+    }
+
+        //坐标转换完之后的回调函数
+    translateCallbackmap = function (point) {
+
+	gtracelist.push(point);       
+ //       map.setCenter(point);
+      //  marker.setAnimation(BMAP_ANIMATION_BOUNCE); //跳动的动画
+    }
+
+        //坐标转换完之后的回调函数
+    translateCallbacktr = function (point) {
+
+	gtracelist.push(point);       
+ //       map.setCenter(point);
+      //  marker.setAnimation(BMAP_ANIMATION_BOUNCE); //跳动的动画
+    }
+
+    //坐标转换完之后的回调函数
+    translateCallbackobj = function (data) {
+	if(data.status === 0) {
+         var point = data.points[0];
+	pointobj = point;
+	bobjset = 1;
+ //       map.clearOverlays();
+	map.removeOverlay(markerObj);
+        markerObj = new BMap.Marker(point);
+
+        map.addOverlay(markerObj);
+	}
+
+ //       map.setCenter(point);
+      //  marker.setAnimation(BMAP_ANIMATION_BOUNCE); //跳动的动画
+    }
+
+
+    //坐标转换完之后的回调函数
+    translateCallback = function (data) {
+
+if(data.status === 0) {
+         var point = data.points[0]
+        map.removeOverlay(markerCur);
+        markerCur = new BMap.Marker(point);
+        if(havepointlast == 1)
+	{
+		if(drawtrail == 1)
+		{
+		var line = new BMap.Polyline([pointlast, point], {strokeColor: "green", strokeWeight: 1, strokeOpacity: 1});
+		map.addOverlay(line);  
+		line.disableMassClear();
+		}
+	}
+        pointlast = point;
+        havepointlast = 1;
+
+	markerCur.setOffset(-30,-30);
+	markerCur.setIcon(icon); 
+	markerCur.setShadow(icon) 
+	markerCur.setRotation(grotation);
+        map.addOverlay(markerCur);
+        map.setCenter(point);
+      }
+//	return;
+//        map.clearOverlays();
+
+/*
+	if(bobjset == 1)
+	{
+		map.removeOverlay(markerObj);
+        	markerObj = new BMap.Marker(pointobj);
+
+        	map.addOverlay(markerObj);
+	}
+
+*/
+
+      //  marker.setAnimation(BMAP_ANIMATION_BOUNCE); //跳动的动画
+    }
+
+    } catch (e) {
+
+        alert("地图加载失败,请检查网络!");
+
+    }
+
+   
+</script>
+
+
+

+ 120 - 0
src/tool/RemoteCtrl_Thread/RemoteCtrl _Thread.pro

@@ -0,0 +1,120 @@
+
+
+!include(../../../include/common.pri ) {
+    error( "Couldn't find the common.pri file!" )
+}
+
+
+contains(QMAKE_HOST.arch, aarch64){
+    QT       += core gui  xml #webenginewidgets    #AGX
+    DEFINES += NVIDIA_AGX
+}else{
+    QT       += core gui  xml webenginewidgets    #x86
+}
+
+greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
+
+
+system(protoc -I=./../../include/proto3 --cpp_out=./../../include/msgtype   ./../../include/proto3/uploadthreadmsg.proto)
+# The following define makes your compiler emit warnings if you use
+# any Qt feature that has been marked deprecated (the exact warnings
+# depend on your compiler). Please consult the documentation of the
+# deprecated API in order to know how to port your code away from it.
+DEFINES += QT_DEPRECATED_WARNINGS
+
+# You can also make your code fail to compile if it uses deprecated APIs.
+# In order to do so, uncomment the following line.
+# You can also select to disable deprecated APIs only up to a certain version of Qt.
+#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0
+
+SOURCES += \
+    ../../include/msgtype/gps.pb.cc \
+    ../../include/msgtype/gpsimu.pb.cc \
+    ../../include/msgtype/imu.pb.cc \
+    ../../include/msgtype/rawpic.pb.cc \
+    ../../include/msgtype/remotectrl.pb.cc \
+    dialogbigpic.cpp \
+    ivpicview.cpp \
+    ivview.cpp \
+    joyreadthread.cpp \
+    main.cpp \
+    mainwindow.cpp \
+    myview.cpp \
+    speed.cpp \
+    ../../driver/driver_cloud_grpc_pc_thread/grpcpc.cpp \
+    ../../driver/driver_cloud_grpc_thread/uploadthreadmsg.grpc.pb.cc \
+    ../../include/msgtype/cloud.pb.cc \
+    dialogpic.cpp \
+    ivpicsave.cpp \
+    ../../include/msgtype/uploadthreadmsg.pb.cc
+
+HEADERS += \
+    ../../include/msgtype/gps.pb.h \
+    ../../include/msgtype/gpsimu.pb.h \
+    ../../include/msgtype/imu.pb.h \
+    ../../include/msgtype/rawpic.pb.h \
+    ../../include/msgtype/remotectrl.pb.h \
+    dialogbigpic.h \
+    ivpicview.h \
+    ivview.h \
+    joyreadthread.h \
+    mainwindow.h \
+    myview.h \
+    pos_def.h \
+    speed.h \
+    ../../driver/driver_cloud_grpc_pc_thread/grpcpc.h \
+    ../../driver/driver_cloud_grpc_thread/uploadthreadmsg.grpc.pb.h \
+    ../../include/msgtype/cloud.pb.h \
+    dialogpic.h \
+    ivpicsave.h \
+    ../../include/msgtype/uploadthreadmsg.pb.h
+
+FORMS += \
+    dialogbigpic.ui \
+    mainwindow.ui \
+    dialogpic.ui
+
+# Default rules for deployment.
+qnx: target.path = /tmp/$${TARGET}/bin
+else: unix:!android: target.path = /opt/$${TARGET}/bin
+!isEmpty(target.path): INSTALLS += target
+
+INCLUDEPATH += /usr/include/opencv4
+
+
+
+INCLUDEPATH += $$PWD/../../driver/driver_cloud_grpc_pc_thread
+INCLUDEPATH += $$PWD/../../driver/driver_cloud_grpc_thread
+
+
+LIBS += -lprotobuf -lyaml-cpp
+
+
+LIBS += -lopencv_highgui -lopencv_core -lopencv_imgproc -lopencv_imgcodecs -lopencv_video  -lopencv_videoio -lpthread #-lopencv_shape
+
+
+#INCLUDEPATH += $$PWD/../../../include/
+#LIBS += -L$$PWD/../../../bin/ -lxmlparam -lmodulecomm -livbacktrace #-livlog -livfault
+
+INCLUDEPATH += $$PWD/../../../thirdpartylib/AGX/qtwebenginewidgets/include/include     # If AGX, Need this line,if x86 please comment this line
+
+contains(QMAKE_HOST.arch, aarch64){
+    LIBS += -lQt5WebEngineWidgets  # If AGX, sudo apt-get install libqt5webenginewidgets5, If x86 comment this line
+}
+
+
+RESOURCES += \
+    remotectrl.qrc
+
+LIBS += -lboost_system
+
+INCLUDEPATH += $$PWD/../../../thirdpartylib/grpc/include
+
+LIBS += -L$$PWD/../../../thirdpartylib/grpc/lib
+
+
+LIBS += -lgrpc++_unsecure -lgrpc++_reflection -labsl_raw_hash_set -labsl_hashtablez_sampler -labsl_exponential_biased -labsl_hash -labsl_bad_variant_access -labsl_city -labsl_status -labsl_cord -labsl_str_format_internal -labsl_synchronization -labsl_graphcycles_internal -labsl_symbolize -labsl_demangle_internal -labsl_stacktrace -labsl_debugging_internal -labsl_malloc_internal -labsl_time -labsl_time_zone -labsl_civil_time -labsl_strings -labsl_strings_internal -labsl_throw_delegate -labsl_int128 -labsl_base -labsl_spinlock_wait -labsl_bad_optional_access -labsl_raw_logging_internal -labsl_log_severity
+
+
+
+

+ 11 - 0
src/tool/RemoteCtrl_Thread/RemoteCtrl.xml

@@ -0,0 +1,11 @@
+<xml>	
+	<node name="RemoteCtrl">
+		<param name="gpsimu" value="hcp2_gpsimu" />
+		<param name="PicFront" value="picfront" />
+		<param name="PicRear" value="picrear" />
+		<param name="PicLeft" value="picleft" />
+		<param name="PicRight" value="picright" />
+		<param name="joypath" value="/dev/input/js0" />
+		<param name="yamlpath" value="./driver_cloud_grpc_pc.yaml" />
+	</node>
+</xml>

BIN
src/tool/RemoteCtrl_Thread/car.png


+ 100 - 0
src/tool/RemoteCtrl_Thread/dialogbigpic.cpp

@@ -0,0 +1,100 @@
+#include "dialogbigpic.h"
+#include "ui_dialogbigpic.h"
+
+#include "mainwindow.h"
+extern iv::vision::rawpic grawpic[CAMERA_NUM];
+extern qint64 gTimeRawPic[CAMERA_NUM] ;
+extern QMutex gMutexPic[CAMERA_NUM];
+
+
+DialogBigPic::DialogBigPic(QWidget *parent) :
+    QDialog(parent),
+    ui(new Ui::DialogBigPic)
+{
+    ui->setupUi(this);
+
+    mpview = new MyView(this);
+    mpview->setObjectName(QStringLiteral("graphicsView"));
+    mpview->setGeometry(QRect(30, 30, 600, 600));
+    mpview->setCacheMode(mpview->CacheBackground);
+
+    mscene = new QGraphicsScene;
+
+    mpPicView = new IVPicView();
+    mpPicView->start();
+    mnLastPicTime = 0;
+    mbDraw = false;
+    connect(mpPicView,SIGNAL(painterupadate()),this,SLOT(onPainterUpdate()));
+
+    QTimer * timer = new QTimer();
+    connect(timer,SIGNAL(timeout()),this,SLOT(onTimerPic()));
+    timer->start(10);
+
+    setWindowTitle("View Picture");
+}
+
+DialogBigPic::~DialogBigPic()
+{
+    delete ui;
+}
+
+void DialogBigPic::onTimerPic()
+{
+
+    if(mbRefresh == false)return;
+
+    bool bUpdate = false;
+
+    int ncam = mnCamera;
+    if((mnLastPicTime != gTimeRawPic[ncam])&&(gTimeRawPic[ncam]!= 0))
+    {
+        gMutexPic[ncam].lock();
+        mpPicView->SetPic(grawpic[ncam]);
+        gMutexPic[ncam].unlock();
+        bUpdate = true;
+        mbDraw = true;
+    }
+
+
+//    if(bUpdate)update();
+
+}
+
+void DialogBigPic::paintEvent(QPaintEvent *)
+{
+
+    if(mbDraw)
+    {
+        QImage image = mpPicView->GetImage();
+        mscene->clear();
+        mscene->addPixmap(QPixmap::fromImage(image));
+        mpview->setScene(mscene);
+        mpview->show();
+    }
+
+}
+
+void DialogBigPic::resizeEvent(QResizeEvent *event)
+{
+    (void)event;
+     QRect rect = this->geometry();
+     double fwidth = rect.width()/1;
+     double fheight = rect.height()/1;
+     mpview->setGeometry(0,0,fwidth,fheight);
+//     rect.setX(rect.x());
+}
+
+void DialogBigPic::setRefresh(bool brefresh)
+{
+    mbRefresh = brefresh;
+}
+
+void DialogBigPic::onPainterUpdate()
+{
+    update();
+}
+
+void DialogBigPic::setCamera(int n)
+{
+    mnCamera = n;
+}

+ 52 - 0
src/tool/RemoteCtrl_Thread/dialogbigpic.h

@@ -0,0 +1,52 @@
+#ifndef DIALOGBIGPIC_H
+#define DIALOGBIGPIC_H
+
+#include <QDialog>
+
+
+
+namespace Ui {
+class DialogBigPic;
+}
+
+#include "ivpicview.h"
+#include "myview.h"
+
+class DialogBigPic : public QDialog
+{
+    Q_OBJECT
+
+public:
+    explicit DialogBigPic(QWidget *parent = nullptr);
+    ~DialogBigPic();
+
+private slots:
+    virtual void paintEvent(QPaintEvent *);
+    void onTimerPic();
+   void onPainterUpdate();
+
+public:
+     void resizeEvent(QResizeEvent *event);
+
+     void setRefresh(bool brefresh);
+
+     void setCamera(int n);
+
+private:
+    Ui::DialogBigPic *ui;
+
+    MyView * mpview;
+    QGraphicsScene *mscene;
+
+    IVPicView * mpPicView;
+
+    qint64 mnLastPicTime;
+
+    bool mbDraw;
+
+    bool mbRefresh= false;
+
+    int mnCamera = 0;
+};
+
+#endif // DIALOGBIGPIC_H

+ 18 - 0
src/tool/RemoteCtrl_Thread/dialogbigpic.ui

@@ -0,0 +1,18 @@
+<ui version="4.0">
+ <class>DialogBigPic</class>
+ <widget class="QDialog" name="DialogBigPic">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>400</width>
+    <height>300</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Dialog</string>
+  </property>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>

+ 102 - 0
src/tool/RemoteCtrl_Thread/dialogpic.cpp

@@ -0,0 +1,102 @@
+#include "dialogpic.h"
+#include "ui_dialogpic.h"
+#include "mainwindow.h"
+
+extern iv::vision::rawpic grawpic[CAMERA_NUM];
+extern qint64 gTimeRawPic[CAMERA_NUM] ;
+extern QMutex gMutexPic[CAMERA_NUM];
+
+
+
+DialogPic::DialogPic(QWidget *parent) :
+    QDialog(parent),
+    ui(new Ui::DialogPic)
+{
+    ui->setupUi(this);
+
+    int i;
+    for(i=0;i<4;i++)
+    {
+        mpview[i] = new MyView(this);
+        mpview[i]->setObjectName(QStringLiteral("graphicsView"));
+        mpview[i]->setGeometry(QRect(30, 30, 600, 600));
+        mpview[i]->setCacheMode(mpview[i]->CacheBackground);
+
+        mscene[i] = new QGraphicsScene;
+
+        mpPicView[i] = new IVPicView();
+        mpPicView[i]->start();
+        mnLastPicTime[i] = 0;
+        mbDraw[i] = false;
+    }
+
+    QTimer * timer = new QTimer();
+    connect(timer,SIGNAL(timeout()),this,SLOT(onTimerPic()));
+    timer->start(10);
+
+    setWindowTitle("View All Picture");
+}
+
+DialogPic::~DialogPic()
+{
+    qDebug("delete dialog");
+    delete ui;
+}
+
+void DialogPic::resizeEvent(QResizeEvent *event)
+{
+    (void)event;
+     QRect rect = this->geometry();
+     double fwidth = rect.width()/2;
+     double fheight = rect.height()/2;
+     mpview[0]->setGeometry(0,0,fwidth,fheight);
+     mpview[1]->setGeometry(fwidth,0,fwidth,fheight);
+     mpview[2]->setGeometry(0,fheight,fwidth,fheight);
+     mpview[3]->setGeometry(fwidth,fheight,fwidth,fheight);
+//     rect.setX(rect.x());
+}
+
+void DialogPic::onTimerPic()
+{
+    int i;
+
+    if(mbRefresh == false)return;
+
+    bool bUpdate = false;
+    for(i=0;i<4;i++)
+    {
+        if(mnLastPicTime[i] != gTimeRawPic[i])
+        {
+            gMutexPic[i].lock();
+            mpPicView[i]->SetPic(grawpic[i]);
+            gMutexPic[i].unlock();
+            bUpdate = true;
+            mbDraw[i] = true;
+        }
+    }
+
+    if(bUpdate)update();
+
+}
+
+void DialogPic::paintEvent(QPaintEvent *)
+{
+    int i;
+    for(i=0;i<4;i++)
+    {
+        if(mbDraw[i])
+        {
+            QImage image = mpPicView[i]->GetImage();
+            mscene[i]->clear();
+            mscene[i]->addPixmap(QPixmap::fromImage(image));
+            mpview[i]->setScene(mscene[i]);
+            mpview[i]->show();
+        }
+        mbDraw[i] = false;
+    }
+}
+
+void DialogPic::setRefresh(bool brefresh)
+{
+    mbRefresh = brefresh;
+}

+ 49 - 0
src/tool/RemoteCtrl_Thread/dialogpic.h

@@ -0,0 +1,49 @@
+#ifndef DIALOGPIC_H
+#define DIALOGPIC_H
+
+#include <QDialog>
+
+namespace Ui {
+class DialogPic;
+}
+
+#include "ivpicview.h"
+#include "myview.h"
+
+
+class DialogPic : public QDialog
+{
+    Q_OBJECT
+
+public:
+    explicit DialogPic(QWidget *parent = 0);
+    ~DialogPic();
+
+private slots:
+    void onTimerPic();
+
+    virtual void paintEvent(QPaintEvent *);
+
+
+
+public:
+     void resizeEvent(QResizeEvent *event);
+
+     void setRefresh(bool brefresh);
+private:
+    Ui::DialogPic *ui;
+
+    MyView * mpview[4];
+    QGraphicsScene *mscene[4];
+
+    IVPicView * mpPicView[4];
+
+    qint64 mnLastPicTime[4];
+
+    bool mbDraw[4];
+
+    bool mbRefresh= false;
+
+};
+
+#endif // DIALOGPIC_H

+ 19 - 0
src/tool/RemoteCtrl_Thread/dialogpic.ui

@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>DialogPic</class>
+ <widget class="QDialog" name="DialogPic">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>931</width>
+    <height>648</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Dialog</string>
+  </property>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>

+ 52 - 0
src/tool/RemoteCtrl_Thread/driver_cloud_grpc_pc.yaml

@@ -0,0 +1,52 @@
+server : 47.96.250.93
+port : 50051
+uploadinterval : 100
+
+VIN : AAAAAAAAAAAAAAAAA
+queryMD5 : 5d41402abc4b2a76b9719d911017c592
+ctrlMD5  : 5d41402abc4b2a76b9719d911017c592
+
+querymessage:
+  picfront:
+    msgname: picfront
+    buffersize: 10000000
+    buffercount: 1
+  picrear:
+    msgname: picrear
+    buffersize: 10000000
+    buffercount: 1
+  picleft:
+    msgname: picleft
+    buffersize: 10000000
+    buffercount: 1
+  picright:
+    msgname: picright
+    buffersize: 10000000
+    buffercount: 1
+  hcp2_gpsimu:
+    msgname: hcp2_gpsimu
+    buffersize: 10000
+    buffercount: 1
+  simpletrace:
+    msgname: simpletrace
+    buffersize: 100000
+    buffercount: 1
+
+ctrlmessage:
+  xodrdst:
+    msgname: xodrdst
+    buffersize: 1000
+    buffercount: 1
+  xodrreq:
+    msgname: xodrreq
+    buffersize: 1000
+    buffercount: 1
+    bimportant: true
+    keeptime: 3000
+  remotectrl:
+    msgname: remotectrl
+    buffersize: 1000
+    buffercount: 1
+
+
+

+ 155 - 0
src/tool/RemoteCtrl_Thread/ivpicsave.cpp

@@ -0,0 +1,155 @@
+#include "ivpicsave.h"
+
+#include <QDateTime>
+
+#include <opencv2/opencv.hpp>
+#include <opencv2/core.hpp>
+
+#ifdef NVIDIA_AGX
+#include <opencv2/imgcodecs/legacy/constants_c.h>    //OpenCV4 use this line
+#include <opencv2/imgproc/types_c.h>   //OpenCV4 use this line
+#endif
+
+ivpicsave::ivpicsave(QString strdir,QString strsuffix,std::string strvin)
+{
+    mstrdir = strdir;
+    mstrsuffix = strsuffix;
+    mstrvin = strvin;
+    mnWriteIndex = 0;
+}
+
+void ivpicsave::SetPic(iv::vision::rawpic pic)
+{
+    if((mbGetPicSize == true ) && (mbSave == false))
+    {
+        return;
+    }
+    mMutex.lock();
+    mrawpic.CopyFrom(pic);
+    mnWriteIndex++;
+    mMutex.unlock();
+}
+
+void ivpicsave::run()
+{
+    int nReadIndex = 0;
+    std::vector<iv::vision::rawpic> xvectorpic;
+    bool bgetfps = false;
+    double ffps = 30;
+    while(!QThread::isInterruptionRequested())
+    {
+        if((mbSave == false)&&(bgetfps))
+        {
+            msleep(100);
+            continue;
+        }
+        bool bNew = false;
+        iv::vision::rawpic pic;
+        if(mnWriteIndex != nReadIndex)
+        {
+
+            mMutex.lock();
+            pic.CopyFrom(mrawpic);
+            mMutex.unlock();
+            if(bgetfps == false)
+            {
+                xvectorpic.push_back(pic);
+                if(xvectorpic.size()>=10)
+                {
+                    std::vector<qint64> xtimediff;
+                    int j;
+                    for(j=1;j<xvectorpic.size();j++)
+                    {
+                        qint64 diff = xvectorpic[j].time() - xvectorpic[j-1].time();
+                        xtimediff.push_back(diff);
+                    }
+                    qint64 totaldiff = 0;
+                    for(j=0;j<xtimediff.size();j++)
+                    {
+                        totaldiff = totaldiff + xtimediff[j];
+                    }
+                    qint64 avgdiff = totaldiff/xtimediff.size();
+                    ffps = avgdiff;
+                    if(ffps<1.0)ffps =1.0;
+                    if(ffps>1000.0)ffps = 1000.0;
+                    ffps = 1000.0/ffps;
+                    mMutexSave.lock();
+                    mfps = ffps;
+                    mnpicheight = xvectorpic[0].height();
+                    mnpicwidth = xvectorpic[0].width();
+                    mMutexSave.unlock();
+                    mbGetPicSize = true;
+                    bgetfps = true;
+                    xvectorpic.clear();
+                    xtimediff.clear();
+                }
+            }
+            nReadIndex++;
+            bNew = true;
+        }
+
+        if(mbSave == false)
+        {
+            msleep(1);
+            continue;
+        }
+        if(bNew)
+        {
+            cv::Mat mat(pic.height(),pic.width(),pic.mattype());
+
+            if(mbSave)
+            {
+                if(pic.type() == 1)
+                    memcpy(mat.data,pic.picdata().data(),mat.rows*mat.cols*mat.elemSize());
+                else
+                {
+                    std::vector<unsigned char> buff(pic.picdata().data(),pic.picdata().data()+pic.picdata().size());
+                    mat = cv::imdecode(buff,CV_LOAD_IMAGE_COLOR);
+                }
+                int font = cv::FONT_HERSHEY_DUPLEX;
+                QDateTime xrecvtime = QDateTime::fromMSecsSinceEpoch(pic.time());
+         //       char strtext[256];
+          //      snprintf(strtext,"%s",xrecvtime.toString("yyyy-MM-dd hh:mm:ss:zzz").toLatin1().data());
+                std::string strtext = xrecvtime.toString("yyyy-MM-dd hh:mm:ss:zzz").toStdString();
+                double fratio = pic.width()/640;
+                int fontsize = 0.5*fratio;
+                if(fontsize<1)fontsize = 1;
+                cv::putText(mat,strtext,cv::Point(pic.width() - 230*fratio,30*fratio),font,0.5*fratio,cv::Scalar(0,255,0),fontsize);
+                cv::putText(mat,mstrvin,cv::Point(10,30*fratio),font,0.5*fratio,cv::Scalar(0,255,0),fontsize);
+            }
+
+
+            mMutexSave.lock();
+            if(mbSave)
+            {
+                mWriter<<mat;
+            }
+            mMutexSave.unlock();
+        }
+        msleep(10);
+    }
+}
+
+void ivpicsave::startsave()
+{
+    std::string strfilename;
+    strfilename = mstrdir.toStdString() + QDateTime::currentDateTime().toString("yyyy-MM-dd-hh-mm-ss-zzz").toStdString() +"-" + mstrsuffix.toStdString() +".avi";
+    mMutexSave.lock();
+    mWriter.open(strfilename,cv::VideoWriter::fourcc('M','P','4','2'),10.0,cv::Size(mnpicwidth,mnpicheight),1);
+    if(mWriter.isOpened())
+    {
+        mbSave = true;
+    }
+    mMutexSave.unlock();
+}
+
+void ivpicsave::stopsave()
+{
+    if(mbSave)
+    {
+        mMutexSave.lock();
+        mbSave = false;
+        mWriter.release();
+        mMutexSave.unlock();
+    }
+}

+ 44 - 0
src/tool/RemoteCtrl_Thread/ivpicsave.h

@@ -0,0 +1,44 @@
+#ifndef IVPICSAVE_H
+#define IVPICSAVE_H
+
+#include "rawpic.pb.h"
+
+#include <QMutex>
+
+#include <QThread>
+
+#include "opencv2/video.hpp"
+#include "opencv2/videoio.hpp"
+
+class ivpicsave : public QThread
+{
+public:
+    ivpicsave(QString strdir,QString strsuffix,std::string strvin);
+
+private:
+    iv::vision::rawpic mrawpic;
+    QMutex mMutex;
+    QMutex mMutexSave;
+    int mnWriteIndex = 0;
+    cv::VideoWriter mWriter;
+    bool mbSave = false;
+    QString mstrdir;
+    QString mstrsuffix;
+    std::string mstrvin;
+    double mfps;
+    int mnpicwidth = 1920;
+    bool mbGetPicSize = false;
+    int mnpicheight = 1080;
+
+    void run();
+
+public:
+    void SetPic(iv::vision::rawpic pic);
+
+    void startsave();
+    void stopsave();
+
+
+};
+
+#endif // IVPICSAVE_H

+ 112 - 0
src/tool/RemoteCtrl_Thread/ivpicview.cpp

@@ -0,0 +1,112 @@
+#include "ivpicview.h"
+
+#include <QDateTime>
+
+#include <opencv2/opencv.hpp>
+#include <opencv2/core.hpp>
+
+#ifdef NVIDIA_AGX
+#include <opencv2/imgcodecs/legacy/constants_c.h>    //OpenCV4 use this line
+#include <opencv2/imgproc/types_c.h>   //OpenCV4 use this line
+#endif
+
+#define VIEW_WIDTH 640
+#define VIEW_HEIGHT 480
+
+IVPicView::IVPicView()
+{
+    mimagepaint = new QImage(VIEW_WIDTH, VIEW_HEIGHT, QImage::Format_RGB32);//画布的初始化大小设为300*300,使用32位颜色
+}
+
+void IVPicView::run()
+{
+    while(!QThread::isInterruptionRequested())
+    {
+        if(mnReadIndex != mnWriteIndex)
+        {
+            paint();
+            mnReadIndex = mnWriteIndex;
+            mbImageUpdate = true;
+        }
+        else
+        {
+            msleep(10);
+        }
+    }
+}
+
+
+
+void IVPicView::paint()
+{
+    iv::vision::rawpic pic;
+    mMutex.lock();
+    pic.CopyFrom(mrawpic);
+    mMutex.unlock();
+
+    cv::Mat mat(pic.height(),pic.width(),pic.mattype());
+
+    if(pic.type() == 1)
+        memcpy(mat.data,pic.picdata().data(),mat.rows*mat.cols*mat.elemSize());
+    else
+    {
+
+//        qDebug("jpg");
+        std::vector<unsigned char> buff(pic.picdata().data(),pic.picdata().data()+pic.picdata().size());
+        mat = cv::imdecode(buff,CV_LOAD_IMAGE_COLOR);
+        int font = cv::FONT_HERSHEY_DUPLEX;
+        QDateTime xrecvtime = QDateTime::fromMSecsSinceEpoch(pic.time());
+ //       char strtext[256];
+  //      snprintf(strtext,"%s",xrecvtime.toString("yyyy-MM-dd hh:mm:ss:zzz").toLatin1().data());
+        std::string strtext = xrecvtime.toString("yyyy-MM-dd hh:mm:ss:zzz").toStdString();
+        double fratio = pic.width()/640;
+        cv::putText(mat,strtext,cv::Point(pic.width() - 230*fratio,30*fratio),font,0.5*fratio,cv::Scalar(0,255,0),0.5*fratio);
+    }
+
+    cv::cvtColor(mat, mat, CV_BGR2RGB);
+    QImage image2 = QImage((uchar*)(mat.data), mat.cols, mat.rows,  QImage::Format_RGB888);
+
+    mMutexPaint.lock();
+
+//    delete mimagepaint;
+//    mimagepaint = new  QImage(mat.cols, mat.rows,  QImage::Format_RGB888);
+    *mimagepaint = image2.copy();
+    //  *mimagepaint = image2;
+ //   mimagepaint = new QImage(image2);
+    mMutexPaint.unlock();
+
+    mat.release();
+
+    emit painterupadate();
+}
+
+QImage IVPicView::GetImage()
+{
+
+    mMutexPaint.lock();
+//    QImage imagertn(*mimagepaint);
+//    QImage imagertn(mimagepaint->width(), mimagepaint->height(), QImage::Format_RGB32);
+    QImage imagertn = mimagepaint->copy();
+    mMutexPaint.unlock();
+    mbImageUpdate = false;
+    return imagertn;
+}
+
+bool IVPicView::IsHaveNew()
+{
+    return mbImageUpdate;
+}
+
+int IVPicView::GetType()
+{
+    return 2;
+}
+
+void IVPicView::SetPic(iv::vision::rawpic pic)
+{
+    mMutex.lock();
+    mrawpic.CopyFrom(pic);
+    mnWriteIndex++;
+    mMutex.unlock();
+}
+

+ 40 - 0
src/tool/RemoteCtrl_Thread/ivpicview.h

@@ -0,0 +1,40 @@
+#ifndef IVPICVIEW_H
+#define IVPICVIEW_H
+
+#include "ivview.h"
+
+#include "rawpic.pb.h"
+
+class IVPicView : public IVView
+{
+    Q_OBJECT
+public:
+    IVPicView();
+
+public:
+    QImage GetImage();
+    bool IsHaveNew();
+    int GetType();
+private:
+    void run();
+    int mnWriteIndex = 0;
+    int mnReadIndex = 0;
+
+private:
+    bool mbImageUpdate = false;
+    QMutex mMutex;
+    QMutex mMutexPaint;
+
+private:
+    void paint();
+    QImage * mimagepaint;
+signals:
+    void painterupadate();
+
+private:
+    iv::vision::rawpic mrawpic;
+public:
+    void SetPic(iv::vision::rawpic pic);
+};
+
+#endif // IVPICVIEW_H

+ 25 - 0
src/tool/RemoteCtrl_Thread/ivview.cpp

@@ -0,0 +1,25 @@
+#include "ivview.h"
+
+IVView::IVView()
+{
+
+
+}
+
+QImage IVView::GetImage()
+{
+    QImage * pimage = new QImage(100,100,QImage::Format_RGB32);
+    return *pimage;
+
+
+}
+
+bool IVView::IsHaveNew()
+{
+    return false;
+}
+
+int IVView::GetType()
+{
+    return 0;
+}

+ 34 - 0
src/tool/RemoteCtrl_Thread/ivview.h

@@ -0,0 +1,34 @@
+#ifndef IVVIEW_H
+#define IVVIEW_H
+
+#include <QImage>
+#include <QGraphicsScene>
+#include <QTimer>
+#include <QPainter>
+
+#include <QThread>
+
+#include <QMutex>
+
+//#include <pcl/conversions.h>
+//#include <pcl/point_cloud.h>
+//#include <pcl/point_types.h>
+
+
+class IVView : public QThread
+{
+public:
+    IVView();  
+
+public:
+    virtual QImage GetImage();
+    virtual bool IsHaveNew();
+    virtual int GetType();
+
+private:
+
+
+
+};
+
+#endif // IVVIEW_H

+ 161 - 0
src/tool/RemoteCtrl_Thread/joyreadthread.cpp

@@ -0,0 +1,161 @@
+#include "joyreadthread.h"
+
+#include <assert.h>
+#include <math.h>
+#include <algorithm>
+#include <iostream>
+#include <stdexcept>
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sstream>
+#include <unistd.h>
+#include <linux/joystick.h>
+
+#include <QFile>
+
+extern std::string gstrjoy_path;
+
+JoyReadThread::JoyReadThread()
+{
+
+    if ((fd = open(gstrjoy_path.data(), O_RDONLY)) < 0)
+    {
+        mbJoyOK = false;
+      std::ostringstream str;
+//      str << filename << ": " << strerror(errno);
+//      throw std::runtime_error(str.str());
+
+    }
+    else
+    {
+      // ok
+      uint8_t num_axis   = 0;
+      uint8_t num_button = 0;
+      ioctl(fd, JSIOCGAXES,    &num_axis);
+      ioctl(fd, JSIOCGBUTTONS, &num_button);
+      axis_count   = num_axis;
+      button_count = num_button;
+
+      // Get Name
+      char name_c_str[1024];
+      if (ioctl(fd, JSIOCGNAME(sizeof(name_c_str)), name_c_str) < 0)
+      {
+          mbJoyOK = false;
+          std::ostringstream str;
+    //      str << filename << ": " << strerror(errno);
+          str << "joy:" << ": " << strerror(errno);
+  //        throw std::runtime_error(str.str());
+      }
+      else
+      {
+          orig_name = name_c_str;
+//          try {
+//              name = Glib::convert_with_fallback(name_c_str, "UTF-8", "ISO-8859-1");
+//          } catch(Glib::ConvertError& err) {
+//              std::cout << err.what() << std::endl;
+//          }
+      }
+
+//      axis_state.resize(axis_count);
+    }
+}
+
+void JoyReadThread::run()
+{
+    if(mbJoyOK == false)return;
+    while(!QThread::isInterruptionRequested())
+    {
+        struct js_event event;
+
+        ssize_t len = read(fd, &event, sizeof(event));
+
+        if(len < 0)
+        {
+//            qDebug("fail.");
+            mbJoyOK = false;
+            break;
+        }
+
+ //       if(len >0)qDebug("len = %d",len);
+
+        if(len == sizeof(js_event))
+        {
+            switch (event.number) {
+            case 0:
+                mfWheel = event.value;
+                break;
+            case 2:
+                mfAcc = event.value;
+                break;
+            case 3:
+                mfBrake = event.value;
+                break;
+            case 12:
+                if(event.value ==1 ) mnShift = 1;
+                else mnShift = 0;
+                break;
+            case 13:
+                if(event.value ==1 ) mnShift = 2;
+                else mnShift = 0;
+                break;
+            case 14:
+                if(event.value ==1 ) mnShift = 3;
+                else mnShift = 0;
+                break;
+            case 15:
+                if(event.value ==1 ) mnShift = 4;
+                else mnShift = 0;
+                break;
+            case 16:
+                if(event.value ==1 ) mnShift = 5;
+                else mnShift = 0;
+                break;
+            case 17:
+                if(event.value ==1 ) mnShift = 6;
+                else mnShift = 0;
+                break;
+            case 18:
+                if(event.value ==1 ) mnShift = -1;
+                else mnShift = 0;
+                break;
+            default:
+                break;
+            }
+            qDebug("shift = %d",mnShift);
+//            qDebug("type = %d number = %d value = %d ",event.type,event.number,event.value);
+//            qDebug("wheel:%g acc:%g brake:%g",mfWheel,mfAcc,mfBrake);
+        }
+    }
+    close(fd);
+    mbJoyOK = false;
+}
+
+bool JoyReadThread::isOK()
+{
+    return mbJoyOK;
+}
+
+double JoyReadThread::GetAcc()
+{
+    return mfAcc;
+}
+
+double JoyReadThread::GetBrake()
+{
+    return mfBrake;
+}
+
+double JoyReadThread::GetWheel()
+{
+    return mfWheel;
+}
+
+int JoyReadThread::GetShift()
+{
+    return mnShift;
+}

+ 39 - 0
src/tool/RemoteCtrl_Thread/joyreadthread.h

@@ -0,0 +1,39 @@
+#ifndef JOYREADTHREAD_H
+#define JOYREADTHREAD_H
+
+#include <QThread>
+
+#include <QFile>
+
+class JoyReadThread : public QThread
+{
+public:
+    JoyReadThread();
+
+public:
+    bool isOK();
+    double GetWheel();
+    double GetAcc();
+    double GetBrake();
+    int GetShift();
+private:
+    void run();
+
+private:
+    int fd;
+    int axis_count;
+    int button_count;
+    std::string orig_name;
+
+    QFile mxFile;
+    QFile * mpFile;
+    bool mbJoyOK = true;
+
+    double mfWheel = 0;
+    double mfAcc = 32767;
+    double mfBrake = 32767;
+
+    int mnShift = 0; //0 N >0 D -1 R
+};
+
+#endif // JOYREADTHREAD_H

+ 76 - 0
src/tool/RemoteCtrl_Thread/main.cpp

@@ -0,0 +1,76 @@
+#include "mainwindow.h"
+
+#include <QApplication>
+#include <QList>
+
+#include <vector>
+
+#include "pos_def.h"
+
+#include "xmlparam.h"
+#include "ivversion.h"
+
+std::string gstrmem_gpsimu;
+std::string gstrmem_pic[CAMERA_NUM];
+std::string gstryaml_path;
+std::string gstrjoy_path;
+
+std::vector<iv::pos_def> gvectorpos;
+
+
+void LoadPos(std::string strfilepath)
+{
+    QFile xFile;
+    xFile.setFileName(strfilepath.data());
+    if(xFile.open(QIODevice::ReadOnly))
+    {
+        QByteArray ba = xFile.readAll();
+        QList<QByteArray> baline =  ba.split('\n');
+        int nline = baline.size();
+        int i;
+        for(i=0;i<nline;i++)
+        {
+            QList<QByteArray> badata = baline[i].split('\t');
+            if(badata.size()>=3)
+            {
+                iv::pos_def xposdef;
+                xposdef.mstrstationname = badata[0].toStdString();
+                xposdef.mflon = badata[1].toDouble();
+                xposdef.mflat = badata[2].toDouble();
+                gvectorpos.push_back(xposdef);
+
+            }
+
+        }
+    }
+    xFile.close();
+}
+
+
+#include "ivbacktrace.h"
+
+int main(int argc, char *argv[])
+{
+
+    showversion("RemoteCtl");
+    QApplication a(argc, argv);
+
+    RegisterIVBackTrace();
+
+
+
+    iv::xmlparam::Xmlparam xp("RemoteCtrl.xml");
+    gstrmem_gpsimu = xp.GetParam("gpsimu","hcp2_gpsimu");
+    gstrmem_pic[0] = xp.GetParam("PicFront","picfront");
+    gstrmem_pic[1] = xp.GetParam("PicRear","picrear");
+    gstrmem_pic[2] = xp.GetParam("PicLeft","picleft");
+    gstrmem_pic[3] = xp.GetParam("PicRight","picright");
+    gstrjoy_path = xp.GetParam("joypath","/dev/input/js0");
+    gstryaml_path = xp.GetParam("yamlpath","./driver_cloud_grpc_pc.yaml");
+
+    LoadPos("pos.txt");
+
+    MainWindow w;
+    w.show();
+    return a.exec();
+}

+ 841 - 0
src/tool/RemoteCtrl_Thread/mainwindow.cpp

@@ -0,0 +1,841 @@
+#include "mainwindow.h"
+#include "ui_mainwindow.h"
+#include "pos_def.h"
+
+MainWindow * gw;
+//#include "QStringLiteral"
+
+#ifdef NVIDIA_AGX
+#include "opencv2/imgcodecs/legacy/constants_c.h"   //OpenCV4 use this line
+#include <opencv2/imgproc/types_c.h>   //OpenCV4 use this line
+#endif
+
+#include <opencv2/opencv.hpp>
+#include <opencv2/core.hpp>
+
+iv::gps::gpsimu ggpsimu;
+qint64 gTimeGPSIMUUpdate = 0;
+
+iv::vision::rawpic grawpic[CAMERA_NUM];
+qint64 gTimeRawPic[CAMERA_NUM] = {0,0,0,0};
+QMutex gMutexPic[CAMERA_NUM];
+
+extern std::string gstrmem_gpsimu;
+extern std::string gstrmem_pic[CAMERA_NUM];
+extern std::vector<iv::pos_def> gvectorpos;
+extern std::string gstryaml_path;
+
+class xodrobj
+{
+public:
+    double flatsrc;
+    double flonsrc;
+    double fhgdsrc;
+    double flat;
+    double flon;
+    int lane;
+};
+
+namespace iv {
+struct simpletrace
+{
+    double gps_lat = 0;//纬度
+    double gps_lng = 0;//经度
+
+    double gps_x = 0;
+    double gps_y = 0;
+    double gps_z = 0;
+
+
+    double ins_heading_angle = 0;	//航向角
+};
+}
+
+std::vector<iv::simpletrace> gvectorsimplerace;
+QMutex gMutexTrace;
+qint64 gTimeTrace = 0;
+
+void Listenpic(const char * strdata,const unsigned int nSize,const unsigned int index,const QDateTime * dt,const char * strmemname)
+{
+    if(nSize<1000)return;
+    iv::vision::rawpic pic;
+    if(false == pic.ParseFromArray(strdata,nSize))
+    {
+        std::cout<<"picview Listenpic fail."<<std::endl;
+        return;
+    }
+    int indexpic = -1;
+    for(int i =0;i<CAMERA_NUM;i++)
+    {
+        if(strncmp(strmemname,gstrmem_pic[i].data(),256) == 0)
+        {
+            indexpic = i;
+            break;
+        }
+    }
+    if(indexpic >= 0)
+    {
+    gMutexPic[indexpic].lock();
+    grawpic[indexpic].CopyFrom(pic);
+    gTimeRawPic[indexpic] = QDateTime::currentMSecsSinceEpoch();
+    gMutexPic[indexpic].unlock();
+    gw->saveavi(indexpic);
+    }
+}
+
+void Listensimpletrace(const char * strdata,const unsigned int nSize,const unsigned int index,const QDateTime * dt,const char * strmemname)
+{
+    int npoint = nSize/sizeof(iv::simpletrace);
+    if(npoint < 1)
+    {
+        std::cout<<"simple trace is very smalll"<<std::endl;
+        return;
+    }
+
+    gMutexTrace.lock();
+    gvectorsimplerace.clear();
+    gvectorsimplerace.resize(npoint);
+    memcpy(gvectorsimplerace.data(),strdata,npoint*sizeof(iv::simpletrace));
+    gTimeTrace = QDateTime::currentMSecsSinceEpoch();
+    gMutexTrace.unlock();
+
+
+}
+
+void Listengpsimu(const char * strdata,const unsigned int nSize,const unsigned int index,const QDateTime * dt,const char * strmemname)
+{
+//        ggpsimu->UpdateGPSIMU(strdata,nSize);
+
+    iv::gps::gpsimu xgpsimu;
+    if(!xgpsimu.ParseFromArray(strdata,nSize))
+    {
+        std::cout<<"ListenRaw Parse error."<<std::endl;
+    }
+    ggpsimu.CopyFrom(xgpsimu);
+    gTimeGPSIMUUpdate = QDateTime::currentMSecsSinceEpoch();
+
+}
+
+MainWindow::MainWindow(QWidget *parent)
+    : QMainWindow(parent)
+    , ui(new Ui::MainWindow)
+{
+    gw = this;
+    ui->setupUi(this);
+
+//    int * pax = 0;
+//    *pax = 1;
+
+    mpJRT = new JoyReadThread();
+    mpJRT->start();
+
+    void * pa = iv::modulecomm::RegisterRecv(gstrmem_gpsimu.data(),Listengpsimu);
+    int i;
+    for(i=0;i<CAMERA_NUM;i++)
+        pa = iv::modulecomm::RegisterRecv(gstrmem_pic[i].data(),Listenpic);
+
+
+    CreateView();
+
+    mpPicView = new IVPicView();
+    mpPicView->start();
+
+
+
+    int nstation = gvectorpos.size();
+    for(i=0;i<nstation;i++)
+    {
+        ui->comboBox_Station->addItem(gvectorpos[i].mstrstationname.data());
+    }
+
+    ui->radioButton_auto->setChecked(true);
+
+    mpa = iv::modulecomm::RegisterSend("remotectrl",10000,1);
+
+    mpTimerManual = new QTimer(this);
+    connect(mpTimerManual,SIGNAL(timeout()),this,SLOT(onTimerManual()));
+
+    mpTimerRemote = new QTimer(this);
+    connect(mpTimerRemote,SIGNAL(timeout()),this,SLOT(onTimerRemote()));
+    mpTimerRemote->start(10);
+
+    mpTimerUpdateView = new QTimer(this);
+    connect(mpTimerUpdateView,SIGNAL(timeout()),this,SLOT(onTimerUpdateView()));
+    mpTimerUpdateView->start(1000);
+
+    QTimer * timer = new QTimer(this);
+    connect(timer,SIGNAL(timeout()),this,SLOT(onTimerUpdatePic()));
+    timer->start(10);
+
+    mpadst = iv::modulecomm::RegisterSend("xodrreq",1000,1);
+    mpasimpletrace = iv::modulecomm::RegisterRecv("simpletrace",Listensimpletrace);
+
+    mgrpcpc = new grpcpc(gstryaml_path);
+    mgrpcpc->start();
+
+    mstrVIN = mgrpcpc->GetVIN().data();
+    mstrVIN = " VIN:"+ mstrVIN+" ";
+
+    mpPicSave[0] = new ivpicsave("./","front",mstrVIN.toStdString());
+    mpPicSave[1] = new ivpicsave("./","rear",mstrVIN.toStdString());
+    mpPicSave[2] = new ivpicsave("./","left",mstrVIN.toStdString());
+    mpPicSave[3] = new ivpicsave("./","right",mstrVIN.toStdString());
+
+    for(i=0;i<4;i++)
+    {
+        mpPicSave[i]->start();
+    }
+
+    mppicdlg = new DialogPic(this);
+    mppicdlg->setModal(false);
+    connect(mppicdlg,SIGNAL(finished(int)),this,SLOT(onCloseDlg()));
+
+    mpbigpicdlg = new DialogBigPic(this);
+    mpbigpicdlg->setModal(false);
+    connect(mpbigpicdlg,SIGNAL(finished(int)),this,SLOT(onCloseBigDlg()));
+
+    setWindowTitle(mstrProgName +mstrVIN+  mstrGPSTime + mstrPicTime);
+
+}
+
+MainWindow::~MainWindow()
+{
+
+    delete ui;
+}
+
+void MainWindow::CreateView()
+{
+    mMapview = new QWebEngineView(ui->centralwidget);
+//    qDebug((QDir::currentPath()).toLatin1().data());
+    mMapview->load(QUrl(QString("file:///%1/%2").arg(QApplication::applicationDirPath()).arg("BaiDuMap.html")));
+
+    mMapview->setGeometry(10,10,800,800);
+
+//    mMapview->page()->runJavaScript("theLocation(117.355,39.066);");  //117.355,39.066
+
+    mpWheel = new Speed(ui->groupBox_rem);
+    mpWheel->settitle(QStringLiteral("方向盘"));
+
+    mpAcc = new Speed(ui->groupBox_rem);
+
+    mpAcc->settitle(QStringLiteral("油门"));
+    mpAcc->updatevalue(0);
+    mpAcc->setminvalue(0);
+    mpAcc->setmaxvalue(100);
+
+    mpBrake = new Speed(ui->groupBox_rem);
+    mpBrake->settitle(QStringLiteral("刹车"));
+    mpBrake->updatevalue(0);
+    mpBrake->setminvalue(0);
+    mpBrake->setmaxvalue(100);
+
+    mmyview = new MyView(ui->centralwidget);
+    mmyview->setObjectName(QStringLiteral("graphicsView"));
+    mmyview->setGeometry(QRect(30, 30, 600, 600));
+
+    mmyview->setCacheMode(mmyview->CacheBackground);
+
+    mscene = new QGraphicsScene;
+
+    ui->radioButton_Null->setChecked(true);
+
+    ui->radioButton_picfront->setChecked(true);
+
+
+}
+
+
+void MainWindow::keyPressEvent(QKeyEvent *event)
+{
+
+    //按键按下,key值放入容器,如果是长按触发的repeat就不判断
+    if(!event->isAutoRepeat())
+        mPressKeys.insert(event->key());
+
+
+}
+
+void MainWindow::keyReleaseEvent(QKeyEvent *event)
+{
+    if(!event->isAutoRepeat())mPressKeys.remove(event->key());
+    qDebug("key count is %d",mPressKeys.count());
+}
+
+void MainWindow::resizeEvent(QResizeEvent *event)
+{
+    QSize sizemain = ui->centralwidget->size();
+    qDebug("size x = %d y=%d",sizemain.width(),sizemain.height());
+
+    mMapview->setGeometry(10,10,sizemain.width()/2,sizemain.height()*3/5);
+
+    mmyview->setGeometry(10+sizemain.width()/2+10,10,sizemain.width()/2-30,sizemain.height()*3/5);
+
+    ui->lineEdit_lat->setGeometry(sizemain.width()-100,10,90,30);
+    ui->lineEdit_lon->setGeometry(sizemain.width()-100,50,90,30);
+    ui->pushButton_test->setGeometry(sizemain.width()-100,90,90,30);
+
+//    mpWheel->setGeometry(sizemain.width()/2 + 20,10,200,200);
+
+    int grouppos_x = 10;
+    int grouppos_y = 20 + sizemain.height() *3/5;
+    int grouppos_width = sizemain.width()*6/10;
+    int grouppos_height = sizemain.height()*2/5 - 20;
+
+
+    int speed_width = grouppos_height-40;
+    if((speed_width*3 + 150)>grouppos_width)speed_width = (grouppos_width - 150)/3;
+
+    mpWheel->setGeometry(100,30,speed_width,speed_width);
+    mpBrake->setGeometry(120 + speed_width,30,speed_width,speed_width);
+    mpAcc->setGeometry(140 + 2*speed_width,30,speed_width,speed_width);
+    ui->groupBox_rem->setGeometry(grouppos_x,grouppos_y,grouppos_width,grouppos_height);
+
+    int grouppic_x = 10 + sizemain.width()*6/10 + 10;
+    int grouppic_y = 20 + sizemain.height() *3/5;
+    int grouppic_width = sizemain.width()*4/10 - 30;
+    int grouppic_height = sizemain.height()*1/10;
+
+    ui->groupBox_picsel->setGeometry(grouppic_x,grouppic_y,grouppic_width,grouppic_height);
+
+    int groupmap_x = 10 + sizemain.width()*6/10 + 10;
+    int groupmap_y = 20 + sizemain.height() *7/10;
+    int groupmap_width = sizemain.width()*4/10 - 30;
+    int groupmap_height = sizemain.height()*1/10;
+
+    ui->comboBox_Station->setGeometry(10,30,groupmap_width*3/5,30);
+    ui->pushButton_Go->setGeometry(20 + groupmap_width*3/5,30,groupmap_width*2/5 - 30,30);
+
+    ui->groupBox_map->setGeometry(groupmap_x,groupmap_y,groupmap_width,groupmap_height);
+
+    int groupgps_x = 10 + sizemain.width()*6/10 + 10;
+    int groupgps_y = 30 + sizemain.height() *8/10;
+    int groupgps_width = sizemain.width()*4/10 - 30;
+    int groupgps_height = sizemain.height()*2/10 - 30;
+
+    ui->groupBox_gps->setGeometry(groupgps_x,groupgps_y,groupgps_width,groupgps_height);
+
+    int lablewidth = (groupgps_width-50)*2/10;
+    int lewidth = (groupgps_width-50)*3/10;
+    int leheight = 26;
+
+    int nypos = 40;
+    ui->label_gpsins->setGeometry(10,nypos,lablewidth,leheight);
+    ui->lineEdit_gpsins->setGeometry(20+lablewidth,nypos,lewidth,leheight);
+    ui->label_gpsrtk->setGeometry(30+lablewidth+lewidth,nypos,lablewidth,leheight);
+    ui->lineEdit_gpsrtk->setGeometry(40+2*lablewidth +lewidth,nypos,lewidth,leheight);
+
+    nypos = nypos + leheight*11/10;
+    ui->label_gpslon->setGeometry(10,nypos,lablewidth,leheight);
+    ui->lineEdit_gpslon->setGeometry(20+lablewidth,nypos,lewidth,leheight);
+    ui->label_gpslat->setGeometry(30+lablewidth+lewidth,nypos,lablewidth,leheight);
+    ui->lineEdit_gpslat->setGeometry(40+2*lablewidth +lewidth,nypos,lewidth,leheight);
+
+    nypos = nypos + leheight*11/10;
+    ui->label_gpsheading->setGeometry(10,nypos,lablewidth,leheight);
+    ui->lineEdit_gpsheading->setGeometry(20+lablewidth,nypos,lewidth,leheight);
+    ui->label_gpsheight->setGeometry(30+lablewidth+lewidth,nypos,lablewidth,leheight);
+    ui->lineEdit_gpsheight->setGeometry(40+2*lablewidth +lewidth,nypos,lewidth,leheight);
+
+    nypos = nypos + leheight*11/10;
+    ui->label_gpsspeed->setGeometry(10,nypos,lablewidth,leheight);
+    ui->lineEdit_gpsspeed->setGeometry(20+lablewidth,nypos,lewidth,leheight);
+    ui->label_gpssat->setGeometry(30+lablewidth+lewidth,nypos,lablewidth,leheight);
+    ui->lineEdit_gpssat->setGeometry(40+2*lablewidth +lewidth,nypos,lewidth,leheight);
+
+
+}
+
+
+void MainWindow::on_pushButton_test_clicked()
+{
+    double flat = ui->lineEdit_lat->text().toDouble();
+    double flon = ui->lineEdit_lon->text().toDouble();
+
+    char strscript[256];
+    snprintf(strscript,255,"theLocation(%11.7f,%11.7f);",flon,flat);
+    mMapview->page()->runJavaScript(strscript);
+}
+
+void MainWindow::on_radioButton_manual_clicked()
+{
+    ui->radioButton_manual->setChecked(true);
+    mPressKeys.clear();
+    mfAcc = 0;
+    mfWheel = 0;
+    mfBrake = 0;
+    mpWheel->updatevalue(mfWheel);
+    mpAcc->updatevalue(mfAcc);
+    mpBrake->updatevalue(mfBrake);
+    mManualTime.restart();
+    mnLastTime = mManualTime.elapsed();
+    mpTimerManual->start(10);
+}
+
+void MainWindow::onTimerManual()
+{
+
+
+    double fOldWheel = mfWheel;
+    double fOldAcc = mfAcc;
+    double fOldBrake = mfBrake;
+    int timediff = mManualTime.elapsed() - mnLastTime;
+    mnLastTime = mManualTime.elapsed();
+
+    int nOldShift = mnShift;
+
+    if(mpJRT->isOK())
+    {
+        mfWheel = mpJRT->GetWheel() * (-100.0)/32768.0;
+        mfAcc = ((mpJRT->GetAcc()-32767.0)/65535)*(-100.0);
+        mfBrake = ((mpJRT->GetBrake()-32767.0)/65535)*(-100.0);
+        if(mfWheel != fOldWheel)mpWheel->updatevalue(mfWheel);
+        if(mfAcc != fOldAcc)mpAcc->updatevalue(mfAcc);
+        if(mfBrake != fOldBrake)mpBrake->updatevalue(mfBrake);
+
+        int x = mpJRT->GetShift();
+        if(x > 0)mnShift = 1;
+        if(x == 0)mnShift = 0;
+        if(x < 0)mnShift = -1;
+        if(mnShift != nOldShift)
+        {
+            switch (mnShift) {
+            case 1:
+                ui->radioButton_Drive->setChecked(true);
+                ui->radioButton_picfront->setChecked(true);
+                on_radioButton_picfront_clicked();
+                break;
+            case 0:
+                ui->radioButton_Null->setChecked(true);
+                break;
+            case -1:
+                ui->radioButton_Rear->setChecked(true);
+                ui->radioButton_picrear->setChecked(true);
+                on_radioButton_picrear_clicked();
+                break;
+            default:
+                break;
+            }
+        }
+        return;
+    }
+
+
+    if(mPressKeys.contains(Qt::Key_A)&&(mPressKeys.contains((Qt::Key_D))))
+    {
+        mfWheel = mfWheel;
+    }
+    else
+    {
+        if(mPressKeys.contains(Qt::Key_A))
+        {
+            if(mfWheel<0)mfWheel = 0;
+            else
+            {
+                mfWheel = mfWheel + timediff*mfWheelSpeed/1000;
+                if(mfWheel < -100)mfWheel = -100;
+                if(mfWheel > 100 )mfWheel = 100;
+            }
+        }
+
+        if(mPressKeys.contains(Qt::Key_D))
+        {
+            if(mfWheel>0)mfWheel = 0;
+            else
+            {
+                mfWheel = mfWheel - timediff*mfWheelSpeed/1000;
+                if(mfWheel < -100)mfWheel = -100;
+                if(mfWheel > 100 )mfWheel = 100;
+            }
+        }
+
+
+    }
+
+    if(!mPressKeys.contains(Qt::Key_A)&&(!mPressKeys.contains((Qt::Key_D))))
+    {
+        if(mfWheel != 0)
+        {
+            if(mfWheel > 0)mfWheel = mfWheel - timediff*mfWheelAutoDownSpeed/1000;
+            else mfWheel = mfWheel + timediff*mfWheelAutoDownSpeed/1000;
+            if(fabs(mfWheel)< 10)mfWheel =0;
+        }
+    }
+
+    if(mPressKeys.contains(Qt::Key_W)&&(mPressKeys.contains((Qt::Key_S))))
+    {
+        mfAcc = 0;
+        mfBrake = mfBrake + timediff*mfBrakeSpeed/1000;
+        if(mfBrake<0)mfBrake = 0;
+        if(mfBrake > 100)mfBrake = 100;
+    }
+    else
+    {
+        if(mPressKeys.contains(Qt::Key_W))
+        {
+            mfBrake = 0;
+            mfAcc = mfAcc + timediff*mfAccSpeed/1000;
+            if(mfAcc<0)mfAcc = 0;
+            if(mfAcc > 100)mfAcc = 100;
+
+        }
+
+        if(mPressKeys.contains(Qt::Key_S))
+        {
+            mfAcc = 0;
+            mfBrake = mfBrake + timediff*mfBrakeSpeed/1000;
+            if(mfBrake<0)mfBrake = 0;
+            if(mfBrake > 100)mfBrake = 100;
+        }
+
+
+    }
+
+
+    if(!mPressKeys.contains(Qt::Key_W)&&(!mPressKeys.contains((Qt::Key_S))))
+    {
+        if(mfBrake != 0)
+        {
+            mfBrake = mfBrake - timediff*mfBrakeAutoDownSpeed/1000;
+            if(mfBrake<0)mfBrake = 0;
+            if(mfBrake > 100)mfBrake = 100;
+        }
+
+        if(mfAcc != 0)
+        {
+            mfAcc = mfAcc - timediff*mfAccAutoDownSpeed/1000;
+            if(mfAcc<0)mfAcc = 0;
+            if(mfAcc > 100)mfAcc = 100;
+        }
+    }
+
+    if(mfWheel != fOldWheel)mpWheel->updatevalue(mfWheel);
+    if(mfAcc != fOldAcc)mpAcc->updatevalue(mfAcc);
+    if(mfBrake != fOldBrake)mpBrake->updatevalue(mfBrake);
+}
+
+void MainWindow::on_radioButton_auto_clicked()
+{
+    ui->radioButton_auto->setChecked(true);
+    mPressKeys.clear();
+    mpTimerManual->stop();
+
+}
+
+void MainWindow::onTimerRemote()
+{
+    if(ui->radioButton_auto->isChecked())
+    {
+        mremotectrl.set_ntype(iv::remotectrl_CtrlType_AUTO);
+//        mfAcc = 0;
+//        mfBrake = 0;
+//        mfWheel =0;
+//        mpWheel->updatevalue(mfWheel);
+//        mpAcc->updatevalue(mfAcc);
+//        mpBrake->updatevalue(mfBrake);
+
+
+    }
+    else
+    {
+        mremotectrl.set_ntype(iv::remotectrl_CtrlType_REMOTE);
+
+    }
+    mremotectrl.set_acc(mfAcc);
+    mremotectrl.set_brake(mfBrake);
+    mremotectrl.set_wheel(mfWheel);
+    mremotectrl.set_shift(mnShift);
+
+    int nsersize = mremotectrl.ByteSize();
+    char * strbuf = new char[nsersize];
+    if(mremotectrl.SerializeToArray(strbuf,nsersize))
+    {
+        iv::modulecomm::ModuleSendMsg(mpa,strbuf,nsersize);
+    }
+    delete strbuf;
+}
+
+void MainWindow::onTimerUpdatePic()
+{
+    static qint64 time_pic = 0;
+
+    static qint64 time_trace = 0;
+    static int pos = 0;
+    static std::vector<iv::simpletrace> xvectorsimpletrace;
+
+    if((mnSelPic>=0)&&(mnSelPic<4))
+    {
+        if((gTimeRawPic[mnSelPic] != time_pic) && (gTimeRawPic[mnSelPic] != 0))
+  //      if((gTimeRawPic[mnSelPic] != time_pic))
+        {
+            time_pic = gTimeRawPic[mnSelPic];
+            iv::vision::rawpic xpic;
+            gMutexPic[mnSelPic].lock();
+            xpic.CopyFrom(grawpic[mnSelPic]);
+            gMutexPic[mnSelPic].unlock();
+            mpPicView->SetPic(xpic);
+
+        }
+    }
+
+    if(mpPicView->IsHaveNew())update();
+
+    if(gTimeTrace != time_trace)
+    {
+        time_trace = gTimeTrace;
+
+        gMutexTrace.lock();
+        xvectorsimpletrace = gvectorsimplerace;
+        gMutexTrace.unlock();
+        pos = 0;
+        if(xvectorsimpletrace.size()> 0)
+        {
+            QJsonArray num_json,num2_json;                       //声明QJsonArray
+            QJsonDocument num_document,num2_document;    //将QJsonArray改为QJsonDocument类
+            QByteArray num_byteArray,num2_byteArray;      //
+
+            int i=0;
+            for(i=0;i<xvectorsimpletrace.size();i++)                            //将数组传入压入num_json
+            {
+                num_json.append(xvectorsimpletrace[i].gps_lng);
+                num2_json.append(xvectorsimpletrace[i].gps_lat);
+            }
+
+            num_document.setArray(num_json);
+            num2_document.setArray(num2_json);
+            num_byteArray = num_document.toJson(QJsonDocument::Compact);
+            num2_byteArray = num2_document.toJson(QJsonDocument::Compact);
+            QString numJson(num_byteArray);             //再转为QString
+            QString num2Json(num2_byteArray);             //再转为QString
+
+
+            QString cmd = QString("settrace(\"%1\",\"%2\")").arg(numJson).arg(num2Json);
+            mMapview->page()->runJavaScript(cmd);
+        }
+
+    }
+
+//    if(pos<xvectorsimpletrace.size())
+//    {
+//        if(pos == 0)
+//        {
+//            mMapview->page()->runJavaScript("clear()");
+//        }
+
+//        char strscript[256];
+//        snprintf(strscript,255,"mapLocation(%11.7f,%11.7f);",xvectorsimpletrace[pos].gps_lng,xvectorsimpletrace[pos].gps_lat);
+//        mMapview->page()->runJavaScript(strscript);
+//        pos++;
+
+//    }
+}
+
+void MainWindow::onTimerUpdateView()
+{
+    static qint64 time_gps = 0;
+
+
+
+    if(gTimeGPSIMUUpdate != time_gps)
+    {
+        time_gps = gTimeGPSIMUUpdate;
+        char strscript[256];
+        snprintf(strscript,255,"theLocation(%11.7f,%11.7f,%11.3f);",ggpsimu.lon(),ggpsimu.lat(),ggpsimu.heading());
+        mMapview->page()->runJavaScript(strscript);
+
+        iv::gps::gpsimu xgpsimu;
+        xgpsimu.CopyFrom(ggpsimu);
+
+        ui->lineEdit_gpsins->setText(QString::number(xgpsimu.ins_state()));
+        ui->lineEdit_gpsrtk->setText(QString::number(xgpsimu.rtk_state()));
+        ui->lineEdit_gpslon->setText(QString::number(xgpsimu.lon(),'f',7));
+        ui->lineEdit_gpslat->setText(QString::number(xgpsimu.lat(),'f',7));
+        ui->lineEdit_gpsheading->setText(QString::number(xgpsimu.heading(),'f',2));
+        ui->lineEdit_gpsheight->setText(QString::number(xgpsimu.height(),'f',2));
+        ui->lineEdit_gpsspeed->setText(QString::number(xgpsimu.speed(),'f',2));
+        ui->lineEdit_gpssat->setText(QString::number(xgpsimu.satnum1()));
+
+        mstrGPSTime =  QDateTime::fromMSecsSinceEpoch(xgpsimu.msgtime()).toString("GPS: yyyy-MM-dd hh:mm:ss  ");
+        setWindowTitle(mstrProgName + mstrVIN + mstrGPSTime + mstrPicTime);
+    }
+
+
+
+
+
+}
+
+void MainWindow::paintEvent(QPaintEvent *)
+{
+    if(!mpPicView->IsHaveNew())
+    {
+        return;
+    }
+    else
+    {
+        QImage image = mpPicView->GetImage();
+        mscene->clear();
+        mscene->addPixmap(QPixmap::fromImage(image));
+        mmyview->setScene(mscene);
+        mmyview->show();
+    }
+}
+
+void MainWindow::on_pushButton_Go_clicked()
+{
+
+
+
+    if(ui->comboBox_Station->currentIndex() < 0)return;
+    int index = ui->comboBox_Station->currentIndex();
+
+    if(index<0 ||  index>= gvectorpos.size())
+    {
+        std::cout<<"out range."<<std::endl;
+        return;
+    }
+    iv::pos_def xpos = gvectorpos[index];
+
+    double lon,lat;
+    lon = xpos.mflon;
+    lat = xpos.mflat;
+
+    xodrobj xo;
+    xo.flon = lon;
+    xo.flat = lat;
+    xo.lane = 3;
+
+    iv::modulecomm::ModuleSendMsg(mpadst,(char *)&xo,sizeof(xodrobj));
+}
+
+void MainWindow::on_comboBox_Station_currentIndexChanged(int index)
+{
+    if(index<0 ||  index>= gvectorpos.size())
+    {
+        std::cout<<"out range."<<std::endl;
+        return;
+    }
+    iv::pos_def xpos = gvectorpos[index];
+
+    char strscript[256];
+    snprintf(strscript,255,"objLocation(%11.7f,%11.7f);",xpos.mflon,xpos.mflat);
+    mMapview->page()->runJavaScript(strscript);
+
+}
+
+void MainWindow::on_checkBox_Drive_stateChanged(int arg1)
+{
+
+}
+
+void MainWindow::on_checkBox_Drive_clicked()
+{
+}
+
+void MainWindow::on_checkBox_Null_clicked()
+{
+
+}
+
+void MainWindow::on_checkBox_Rear_clicked()
+{
+
+}
+
+void MainWindow::on_radioButton_Drive_clicked()
+{
+    mnShift = 1;
+    ui->radioButton_picfront->setChecked(true);
+    on_radioButton_picfront_clicked();
+}
+
+void MainWindow::on_radioButton_Null_clicked()
+{
+    mnShift = 0;
+}
+
+void MainWindow::on_radioButton_Rear_clicked()
+{
+    mnShift = -1;
+    ui->radioButton_picrear->setChecked(true);
+    on_radioButton_picrear_clicked();
+}
+
+void MainWindow::on_radioButton_picfront_clicked()
+{
+    mnSelPic = 0;
+    mpbigpicdlg->setCamera(mnSelPic);
+}
+
+void MainWindow::on_radioButton_picrear_clicked()
+{
+    mnSelPic = 1;
+    mpbigpicdlg->setCamera(mnSelPic);
+}
+
+void MainWindow::on_radioButton_picleft_clicked()
+{
+    mnSelPic = 2;
+    mpbigpicdlg->setCamera(mnSelPic);
+}
+
+void MainWindow::on_radioButton_picright_clicked()
+{
+    mnSelPic = 3;
+    mpbigpicdlg->setCamera(mnSelPic);
+}
+
+
+
+void MainWindow::on_pushButton_AllPic_clicked()
+{
+
+    mppicdlg->show();
+    mppicdlg->setRefresh(true);
+}
+
+void MainWindow::onCloseDlg()
+{
+    mppicdlg->setRefresh(false);
+    qDebug("cloase");
+}
+
+void MainWindow::on_checkBox_clicked()
+{
+    int i;
+    if(ui->checkBox->isChecked())
+    {
+        for(i=0;i<4;i++)
+        {
+            mpPicSave[i]->startsave();
+        }
+        mbSavePic = true;
+    }
+    else
+    {
+        for(i=0;i<4;i++)
+        {
+            mpPicSave[i]->stopsave();
+        }
+        mbSavePic = false;
+    }
+}
+
+void MainWindow::saveavi(int index)
+{
+//    if(mbSavePic == false)return;
+    gMutexPic[index].lock();
+    mpPicSave[index]->SetPic(grawpic[index]);
+    gMutexPic[index].unlock();
+}
+
+void MainWindow::on_pushButton_big_clicked()
+{
+    mpbigpicdlg->show();
+    mpbigpicdlg->setRefresh(true);
+}
+
+void MainWindow::onCloseBigDlg()
+{
+    mpbigpicdlg->setRefresh(false);
+}

+ 183 - 0
src/tool/RemoteCtrl_Thread/mainwindow.h

@@ -0,0 +1,183 @@
+#ifndef MAINWINDOW_H
+#define MAINWINDOW_H
+
+
+#define CAMERA_NUM 4
+
+#include <QMainWindow>
+
+#include <QtWidgets>
+#include <QtWebEngineWidgets/QtWebEngineWidgets>
+#include <QSet>
+#include <QMutex>
+
+#include <iostream>
+
+#include <speed.h>
+
+#include "remotectrl.pb.h"
+#include "gpsimu.pb.h"
+#include "rawpic.pb.h"
+
+#include "ivpicview.h"
+#include "ivpicsave.h"
+#include "myview.h"
+#include "grpcpc.h"
+
+#include "dialogpic.h"
+#include "dialogbigpic.h"
+
+#include "modulecomm.h"
+
+#include "joyreadthread.h"
+
+
+QT_BEGIN_NAMESPACE
+namespace Ui { class MainWindow; }
+QT_END_NAMESPACE
+
+class MainWindow : public QMainWindow
+{
+    Q_OBJECT
+
+public:
+    MainWindow(QWidget *parent = nullptr);
+    ~MainWindow();
+
+private slots:
+    void on_pushButton_test_clicked();
+
+    virtual void paintEvent(QPaintEvent *);
+
+    void on_radioButton_manual_clicked();
+
+    void onTimerManual();
+
+    void onTimerRemote();
+
+    void onTimerUpdateView();
+
+    void onTimerUpdatePic();
+
+    void on_radioButton_auto_clicked();
+
+//    virtual void paintEvent(QPaintEvent *);
+
+
+
+    void on_pushButton_Go_clicked();
+
+    void on_comboBox_Station_currentIndexChanged(int index);
+
+    void on_checkBox_Drive_stateChanged(int arg1);
+
+    void on_checkBox_Drive_clicked();
+
+    void on_checkBox_Null_clicked();
+
+    void on_checkBox_Rear_clicked();
+
+    void on_radioButton_Drive_clicked();
+
+    void on_radioButton_Null_clicked();
+
+    void on_radioButton_Rear_clicked();
+
+
+    void on_radioButton_picfront_clicked();
+
+    void on_radioButton_picrear_clicked();
+
+    void on_radioButton_picleft_clicked();
+
+    void on_radioButton_picright_clicked();
+
+    void on_pushButton_AllPic_clicked();
+
+    void onCloseDlg();
+    void onCloseBigDlg();
+
+    void on_checkBox_clicked();
+
+    void on_pushButton_big_clicked();
+
+public:
+     void resizeEvent(QResizeEvent *event);
+
+     void keyPressEvent(QKeyEvent *event) Q_DECL_OVERRIDE;
+
+     void keyReleaseEvent(QKeyEvent *event) Q_DECL_OVERRIDE;
+
+
+
+private:
+    Ui::MainWindow *ui;
+
+
+    QWebEngineView * mMapview;
+
+    Speed * mpWheel, * mpAcc, * mpBrake;
+
+     QSet<int> mPressKeys;
+
+     QTimer * mpTimerManual;
+     QTimer * mpTimerRemote;
+
+     double mfWheel = 0;
+     double mfAcc = 0;
+     double mfBrake = 0;
+
+     int mnLastTime;
+     QTime mManualTime;
+
+     double mfWheelSpeed = 100; //100degree/s
+     double mfAccSpeed = 30; //30/s
+     double mfBrakeSpeed = 100; //100/s
+
+     double mfWheelAutoDownSpeed = 30;
+     double mfAccAutoDownSpeed = 10;
+     double mfBrakeAutoDownSpeed = 30;
+
+     iv::remotectrl mremotectrl;
+
+     void * mpa;
+
+     QTimer * mpTimerUpdateView;
+
+     MyView * mmyview;
+     QGraphicsScene *mscene;
+     IVPicView * mpPicView;
+
+     ivpicsave * mpPicSave[4];
+
+     void * mpadst;
+     void * mpasimpletrace;
+
+     grpcpc * mgrpcpc;
+
+     QString mstrProgName = "ADC IV Remote Control  ";
+     QString mstrGPSTime = " GPS:";
+     QString mstrPicTime = " Pic:";
+
+     QString mstrVIN;
+
+     JoyReadThread * mpJRT;
+
+     int mnShift = 0;
+
+     int mnSelPic = 0;
+
+     DialogPic * mppicdlg;
+     DialogBigPic * mpbigpicdlg;
+
+
+     bool mbSavePic = false;
+
+public:
+     void saveavi(int index);
+
+
+private:
+    void CreateView();
+};
+#endif // MAINWINDOW_H

+ 499 - 0
src/tool/RemoteCtrl_Thread/mainwindow.ui

@@ -0,0 +1,499 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MainWindow</class>
+ <widget class="QMainWindow" name="MainWindow">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>1183</width>
+    <height>722</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>MainWindow</string>
+  </property>
+  <property name="windowIcon">
+   <iconset resource="remotectrl.qrc">
+    <normaloff>:/remotectrl.png</normaloff>:/remotectrl.png</iconset>
+  </property>
+  <widget class="QWidget" name="centralwidget">
+   <widget class="QLineEdit" name="lineEdit_lat">
+    <property name="geometry">
+     <rect>
+      <x>940</x>
+      <y>50</y>
+      <width>113</width>
+      <height>25</height>
+     </rect>
+    </property>
+   </widget>
+   <widget class="QLineEdit" name="lineEdit_lon">
+    <property name="geometry">
+     <rect>
+      <x>940</x>
+      <y>110</y>
+      <width>113</width>
+      <height>25</height>
+     </rect>
+    </property>
+   </widget>
+   <widget class="QPushButton" name="pushButton_test">
+    <property name="geometry">
+     <rect>
+      <x>950</x>
+      <y>190</y>
+      <width>89</width>
+      <height>25</height>
+     </rect>
+    </property>
+    <property name="text">
+     <string>Test</string>
+    </property>
+   </widget>
+   <widget class="QGroupBox" name="groupBox_rem">
+    <property name="geometry">
+     <rect>
+      <x>870</x>
+      <y>270</y>
+      <width>291</width>
+      <height>311</height>
+     </rect>
+    </property>
+    <property name="title">
+     <string>Control</string>
+    </property>
+    <widget class="QRadioButton" name="radioButton_manual">
+     <property name="geometry">
+      <rect>
+       <x>10</x>
+       <y>40</y>
+       <width>61</width>
+       <height>23</height>
+      </rect>
+     </property>
+     <property name="text">
+      <string>远程</string>
+     </property>
+    </widget>
+    <widget class="QRadioButton" name="radioButton_auto">
+     <property name="geometry">
+      <rect>
+       <x>10</x>
+       <y>70</y>
+       <width>61</width>
+       <height>23</height>
+      </rect>
+     </property>
+     <property name="text">
+      <string>自动</string>
+     </property>
+    </widget>
+    <widget class="QGroupBox" name="groupBox">
+     <property name="geometry">
+      <rect>
+       <x>10</x>
+       <y>110</y>
+       <width>71</width>
+       <height>101</height>
+      </rect>
+     </property>
+     <property name="title">
+      <string>档位</string>
+     </property>
+     <widget class="QRadioButton" name="radioButton_Drive">
+      <property name="geometry">
+       <rect>
+        <x>10</x>
+        <y>30</y>
+        <width>112</width>
+        <height>23</height>
+       </rect>
+      </property>
+      <property name="text">
+       <string>前进</string>
+      </property>
+     </widget>
+     <widget class="QRadioButton" name="radioButton_Null">
+      <property name="geometry">
+       <rect>
+        <x>10</x>
+        <y>50</y>
+        <width>112</width>
+        <height>23</height>
+       </rect>
+      </property>
+      <property name="text">
+       <string>空档</string>
+      </property>
+     </widget>
+     <widget class="QRadioButton" name="radioButton_Rear">
+      <property name="geometry">
+       <rect>
+        <x>10</x>
+        <y>70</y>
+        <width>112</width>
+        <height>23</height>
+       </rect>
+      </property>
+      <property name="text">
+       <string>后退</string>
+      </property>
+     </widget>
+    </widget>
+   </widget>
+   <widget class="QGroupBox" name="groupBox_map">
+    <property name="geometry">
+     <rect>
+      <x>280</x>
+      <y>320</y>
+      <width>351</width>
+      <height>121</height>
+     </rect>
+    </property>
+    <property name="title">
+     <string>Map</string>
+    </property>
+    <widget class="QPushButton" name="pushButton_Go">
+     <property name="geometry">
+      <rect>
+       <x>240</x>
+       <y>50</y>
+       <width>91</width>
+       <height>41</height>
+      </rect>
+     </property>
+     <property name="text">
+      <string>前往</string>
+     </property>
+    </widget>
+    <widget class="QComboBox" name="comboBox_Station">
+     <property name="geometry">
+      <rect>
+       <x>10</x>
+       <y>50</y>
+       <width>211</width>
+       <height>41</height>
+      </rect>
+     </property>
+    </widget>
+   </widget>
+   <widget class="QGroupBox" name="groupBox_gps">
+    <property name="geometry">
+     <rect>
+      <x>280</x>
+      <y>470</y>
+      <width>361</width>
+      <height>151</height>
+     </rect>
+    </property>
+    <property name="title">
+     <string>GPS</string>
+    </property>
+    <widget class="QLineEdit" name="lineEdit_gpsins">
+     <property name="geometry">
+      <rect>
+       <x>80</x>
+       <y>30</y>
+       <width>81</width>
+       <height>25</height>
+      </rect>
+     </property>
+    </widget>
+    <widget class="QLabel" name="label_gpsins">
+     <property name="geometry">
+      <rect>
+       <x>10</x>
+       <y>30</y>
+       <width>67</width>
+       <height>17</height>
+      </rect>
+     </property>
+     <property name="text">
+      <string>Ins</string>
+     </property>
+    </widget>
+    <widget class="QLabel" name="label_gpsrtk">
+     <property name="geometry">
+      <rect>
+       <x>190</x>
+       <y>30</y>
+       <width>67</width>
+       <height>17</height>
+      </rect>
+     </property>
+     <property name="text">
+      <string>RTK</string>
+     </property>
+    </widget>
+    <widget class="QLineEdit" name="lineEdit_gpsrtk">
+     <property name="geometry">
+      <rect>
+       <x>250</x>
+       <y>30</y>
+       <width>81</width>
+       <height>25</height>
+      </rect>
+     </property>
+    </widget>
+    <widget class="QLineEdit" name="lineEdit_gpslon">
+     <property name="geometry">
+      <rect>
+       <x>80</x>
+       <y>60</y>
+       <width>81</width>
+       <height>25</height>
+      </rect>
+     </property>
+    </widget>
+    <widget class="QLineEdit" name="lineEdit_gpslat">
+     <property name="geometry">
+      <rect>
+       <x>250</x>
+       <y>60</y>
+       <width>81</width>
+       <height>25</height>
+      </rect>
+     </property>
+    </widget>
+    <widget class="QLabel" name="label_gpslon">
+     <property name="geometry">
+      <rect>
+       <x>10</x>
+       <y>60</y>
+       <width>67</width>
+       <height>17</height>
+      </rect>
+     </property>
+     <property name="text">
+      <string>Lon</string>
+     </property>
+    </widget>
+    <widget class="QLabel" name="label_gpslat">
+     <property name="geometry">
+      <rect>
+       <x>190</x>
+       <y>60</y>
+       <width>67</width>
+       <height>17</height>
+      </rect>
+     </property>
+     <property name="text">
+      <string>Lat</string>
+     </property>
+    </widget>
+    <widget class="QLabel" name="label_gpsheading">
+     <property name="geometry">
+      <rect>
+       <x>10</x>
+       <y>90</y>
+       <width>67</width>
+       <height>17</height>
+      </rect>
+     </property>
+     <property name="text">
+      <string>Heading</string>
+     </property>
+    </widget>
+    <widget class="QLineEdit" name="lineEdit_gpsheading">
+     <property name="geometry">
+      <rect>
+       <x>80</x>
+       <y>90</y>
+       <width>81</width>
+       <height>25</height>
+      </rect>
+     </property>
+    </widget>
+    <widget class="QLineEdit" name="lineEdit_gpsheight">
+     <property name="geometry">
+      <rect>
+       <x>250</x>
+       <y>90</y>
+       <width>81</width>
+       <height>25</height>
+      </rect>
+     </property>
+    </widget>
+    <widget class="QLabel" name="label_gpsheight">
+     <property name="geometry">
+      <rect>
+       <x>190</x>
+       <y>90</y>
+       <width>67</width>
+       <height>17</height>
+      </rect>
+     </property>
+     <property name="text">
+      <string>Height</string>
+     </property>
+    </widget>
+    <widget class="QLineEdit" name="lineEdit_gpsspeed">
+     <property name="geometry">
+      <rect>
+       <x>80</x>
+       <y>120</y>
+       <width>81</width>
+       <height>25</height>
+      </rect>
+     </property>
+    </widget>
+    <widget class="QLineEdit" name="lineEdit_gpssat">
+     <property name="geometry">
+      <rect>
+       <x>250</x>
+       <y>120</y>
+       <width>81</width>
+       <height>25</height>
+      </rect>
+     </property>
+    </widget>
+    <widget class="QLabel" name="label_gpsspeed">
+     <property name="geometry">
+      <rect>
+       <x>10</x>
+       <y>120</y>
+       <width>67</width>
+       <height>17</height>
+      </rect>
+     </property>
+     <property name="text">
+      <string>Speed</string>
+     </property>
+    </widget>
+    <widget class="QLabel" name="label_gpssat">
+     <property name="geometry">
+      <rect>
+       <x>190</x>
+       <y>120</y>
+       <width>67</width>
+       <height>17</height>
+      </rect>
+     </property>
+     <property name="text">
+      <string>Sat</string>
+     </property>
+    </widget>
+   </widget>
+   <widget class="QGroupBox" name="groupBox_picsel">
+    <property name="geometry">
+     <rect>
+      <x>280</x>
+      <y>210</y>
+      <width>551</width>
+      <height>91</height>
+     </rect>
+    </property>
+    <property name="title">
+     <string>图像</string>
+    </property>
+    <widget class="QRadioButton" name="radioButton_picfront">
+     <property name="geometry">
+      <rect>
+       <x>10</x>
+       <y>40</y>
+       <width>51</width>
+       <height>23</height>
+      </rect>
+     </property>
+     <property name="text">
+      <string>前</string>
+     </property>
+    </widget>
+    <widget class="QRadioButton" name="radioButton_picrear">
+     <property name="geometry">
+      <rect>
+       <x>70</x>
+       <y>40</y>
+       <width>51</width>
+       <height>21</height>
+      </rect>
+     </property>
+     <property name="text">
+      <string>后</string>
+     </property>
+    </widget>
+    <widget class="QRadioButton" name="radioButton_picleft">
+     <property name="geometry">
+      <rect>
+       <x>140</x>
+       <y>40</y>
+       <width>41</width>
+       <height>21</height>
+      </rect>
+     </property>
+     <property name="text">
+      <string>左</string>
+     </property>
+    </widget>
+    <widget class="QRadioButton" name="radioButton_picright">
+     <property name="geometry">
+      <rect>
+       <x>220</x>
+       <y>40</y>
+       <width>41</width>
+       <height>23</height>
+      </rect>
+     </property>
+     <property name="text">
+      <string>右</string>
+     </property>
+    </widget>
+    <widget class="QPushButton" name="pushButton_AllPic">
+     <property name="geometry">
+      <rect>
+       <x>300</x>
+       <y>40</y>
+       <width>71</width>
+       <height>25</height>
+      </rect>
+     </property>
+     <property name="text">
+      <string>All</string>
+     </property>
+    </widget>
+    <widget class="QCheckBox" name="checkBox">
+     <property name="geometry">
+      <rect>
+       <x>390</x>
+       <y>40</y>
+       <width>71</width>
+       <height>23</height>
+      </rect>
+     </property>
+     <property name="text">
+      <string>Save</string>
+     </property>
+    </widget>
+    <widget class="QPushButton" name="pushButton_big">
+     <property name="geometry">
+      <rect>
+       <x>460</x>
+       <y>40</y>
+       <width>51</width>
+       <height>25</height>
+      </rect>
+     </property>
+     <property name="text">
+      <string>Big</string>
+     </property>
+    </widget>
+   </widget>
+  </widget>
+  <widget class="QMenuBar" name="menubar">
+   <property name="geometry">
+    <rect>
+     <x>0</x>
+     <y>0</y>
+     <width>1183</width>
+     <height>28</height>
+    </rect>
+   </property>
+  </widget>
+  <widget class="QStatusBar" name="statusbar"/>
+ </widget>
+ <resources>
+  <include location="remotectrl.qrc"/>
+ </resources>
+ <connections/>
+</ui>

+ 120 - 0
src/tool/RemoteCtrl_Thread/myview.cpp

@@ -0,0 +1,120 @@
+#include "myview.h"
+#include <QScrollBar>
+#include <iostream>
+#define VIEW_CENTER viewport()->rect().center()
+const double PI = 3.1415926535898;
+
+MyView::MyView(QWidget *parent) :
+     QGraphicsView(parent),
+    beishu(1.00000)
+{
+    setDragMode(QGraphicsView::ScrollHandDrag);
+}
+
+void MyView::mousePressEvent(QMouseEvent *event)
+{
+//    qDebug("x is %d",event->pos().x());
+    bottonstatus = true;
+    QGraphicsView::mousePressEvent(event);
+}
+void MyView::mouseMoveEvent(QMouseEvent *event)
+{
+    QGraphicsView::mouseMoveEvent(event);
+//    QScrollBar * ps = verticalScrollBar();
+//    std::cout<<" size is "<<ps->size().height()<<" v = "<<ps->value()<<std::endl;
+//    QScrollBar * ps2= horizontalScrollBar();
+//     std::cout<<" size is "<<ps2->size().width()<<" h = "<<ps2->value()<<std::endl;
+}
+void MyView::mouseReleaseEvent(QMouseEvent *event)
+{
+    bottonstatus = false;
+    QGraphicsView::mouseReleaseEvent(event);
+}
+
+// 放大/缩小
+void MyView::wheelEvent(QWheelEvent *event)
+{
+    // 滚轮的滚动量
+    QPoint scrollAmount = event->angleDelta();
+    // 正值表示滚轮远离使用者(放大),负值表示朝向使用者(缩小)
+    scrollAmount.y() > 0 ? zoomIn() : zoomOut();
+}
+
+
+// 放大
+void MyView::zoomIn()
+{
+
+    int width,hgt;
+    width = sceneRect().width();
+    hgt = sceneRect().height();
+    QScrollBar * psV = verticalScrollBar();
+    QScrollBar * psH = horizontalScrollBar();
+
+    int centery = (psV->value() + psV->size().height()/2)/beishu;
+    int centerx = (psH->value() + psH->size().width()/2)/beishu;
+
+    scale(1.1, 1.1);
+    beishu *= 1.1;
+ //   centerOn(450, 700 - (200 / beishu));
+
+
+
+
+
+    centerOn(centerx,centery);
+
+//    QPoint x = viewport()->rect().center();
+
+
+//    std::cout<<" x is"<<sceneRect().bottom()<<" y is "<<sceneRect().y()<<std::endl;
+//    QScrollBar * ps = verticalScrollBar();
+//    std::cout<<" size is "<<ps->size().height()<<" v = "<<ps->value()<<std::endl;
+
+}
+
+// 缩小
+void MyView::zoomOut()
+{
+
+    int width,hgt;
+    width = sceneRect().width();
+    hgt = sceneRect().height();
+    QScrollBar * psV = verticalScrollBar();
+    QScrollBar * psH = horizontalScrollBar();
+
+    int centery = (psV->value() + psV->size().height()/2)/beishu;
+    int centerx = (psH->value() + psH->size().width()/2)/beishu;
+
+    scale(1 / 1.1, 1 / 1.1);
+    beishu /= 1.1;
+//    centerOn(450, 700 - (200 / beishu));
+
+    centerOn(centerx,centery);
+}
+
+void MyView::mouseDoubleClickEvent(QMouseEvent *event)
+{
+
+    QScrollBar * psV = verticalScrollBar();
+    QScrollBar * psH = horizontalScrollBar();
+
+    int centery = (psV->value() + psV->size().height()/2)/beishu;
+    int centerx = (psH->value() + psH->size().width()/2)/beishu;
+
+
+//    qDebug("x is %d y is %d view center x is %d  centerx is %d",event->pos().x(),
+//           event->pos().y(),
+//           viewport()->rect().center().x(),centerx);
+
+    int viewx,viewy;
+    if(beishu == 0)return;
+    viewx = centerx +(event->pos().x() - viewport()->rect().center().x())/beishu;
+    viewy = centery +(event->pos().y() - viewport()->rect().center().y())/beishu;
+
+    QPoint viewpoint;
+    viewpoint.setX(viewx);
+    viewpoint.setY(viewy);
+
+//    qDebug("view x is %d view y is %d ",viewx,viewy);
+}

+ 35 - 0
src/tool/RemoteCtrl_Thread/myview.h

@@ -0,0 +1,35 @@
+#ifndef MYVIEW_H
+#define MYVIEW_H
+
+#include <qtimer.h>
+#include <qpainter.h>
+#include <QGraphicsView>
+#include <QWheelEvent>
+#include <QKeyEvent>
+#include <QPoint>
+#include <QPointF>
+#include <QGraphicsItem>
+#include <QKeyEvent>
+
+class MyView : public QGraphicsView
+{
+    Q_OBJECT
+
+public:
+    explicit MyView(QWidget *parent =0);
+    qreal x, y, beishu;
+protected:
+    void wheelEvent(QWheelEvent *event) Q_DECL_OVERRIDE;
+    void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
+    void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
+    void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
+    void mouseDoubleClickEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
+public Q_SLOTS:
+    void zoomIn();  // 放大
+    void zoomOut();  // 缩小
+private:
+    bool bottonstatus = false;
+    QPoint myview_lastMousePos;
+};
+
+#endif // MYVIEW_H

+ 2 - 0
src/tool/RemoteCtrl_Thread/pos.txt

@@ -0,0 +1,2 @@
+站点1	117.02730168	39.12070791
+站点2	117.02730387	39.12051011

+ 16 - 0
src/tool/RemoteCtrl_Thread/pos_def.h

@@ -0,0 +1,16 @@
+#ifndef POS_DEF_H
+#define POS_DEF_H
+
+#include <string>
+
+namespace  iv {
+struct pos_def
+{
+    double mflon;
+    double mflat;
+    std::string mstrstationname;
+};
+
+}
+
+#endif // POS_DEF_H

BIN
src/tool/RemoteCtrl_Thread/remotectrl.png


+ 5 - 0
src/tool/RemoteCtrl_Thread/remotectrl.qrc

@@ -0,0 +1,5 @@
+<RCC>
+    <qresource prefix="/">
+        <file>remotectrl.png</file>
+    </qresource>
+</RCC>

+ 199 - 0
src/tool/RemoteCtrl_Thread/speed.cpp

@@ -0,0 +1,199 @@
+#include "speed.h"
+
+
+#include <QPainter>
+
+#include <math.h>
+
+Speed::Speed(QWidget *parent) : QWidget(parent)
+{
+    m_background = Qt::black;
+    m_foreground = Qt::green;
+
+    m_startAngle = 60;
+    m_endAngle = 60;
+    m_scaleMajor = 10;
+    m_minValue = 100;
+    m_maxValue = -100;
+    m_scaleMajor = 10;//分度
+    m_scaleMinor = 10;
+    m_units = "";
+    m_title = "Wheel";
+    m_precision = 0;
+    m_value = 0;
+}
+
+void Speed::drawCrown(QPainter *painter) //绘制表冠
+{
+    painter->save();
+    int radius = 100;
+    QLinearGradient lg1(0, -radius, 0, radius);
+
+    lg1.setColorAt(0, Qt::white); //设置渐变的颜色和路径比例
+    lg1.setColorAt(1, Qt::gray); //只是粗略的颜色,具体的可以参考RGB颜色查询对照表
+
+    painter->setBrush(lg1); // 创建QBrush对象,把这个渐变对象传递进去:
+    painter->setPen(Qt::NoPen); //边框线无色
+    painter->drawEllipse(-radius, -radius, radius << 1, radius << 1);
+    painter->setBrush(m_background = Qt::black);
+    painter->drawEllipse(-92, -92, 184, 184);
+    painter->restore();
+}
+
+void Speed::drawScaleNum(QPainter *painter) //绘制刻度数字
+{
+    painter->save();
+    painter->setPen(m_foreground);
+    //m_startAngle是起始角度,m_endAngle是结束角度,m_scaleMajor在一个量程中分成的刻度数
+    double startRad = ( 270-m_startAngle) * (3.14 / 180);
+    double deltaRad = (360 - m_startAngle - m_endAngle) * (3.14 / 180) / m_scaleMajor;
+    double sina,cosa;
+    int x, y;
+    QFontMetricsF fm(this->font());
+    double w, h, tmpVal;
+    QString str;
+
+    for (int i = 0; i <= m_scaleMajor; i++)
+    {
+        sina = sin(startRad - i * deltaRad);
+        cosa = cos(startRad - i * deltaRad);
+
+        tmpVal = 1.0 * i *((m_maxValue - m_minValue) / m_scaleMajor) + m_minValue;
+        // tmpVal = 50;
+        str = QString( "%1" ).arg(tmpVal);  //%1作为占位符   arg()函数比起 sprintf()来是类型安全的
+        w = fm.size(Qt::TextSingleLine,str).width();
+        h = fm.size(Qt::TextSingleLine,str).height();
+        x = 82 * cosa - w / 2;
+        y = -82 * sina + h / 4;
+        painter->drawText(x, y, str); //函数的前两个参数是显示的坐标位置,后一个是显示的内容,是字符类型""
+
+    }
+    painter->restore();
+}
+
+void Speed::drawScale(QPainter *painter) //绘制刻度线
+{
+    painter->save();
+    painter->rotate(m_startAngle);
+    int steps = (m_scaleMajor * m_scaleMinor); //相乘后的值是分的份数
+    double angleStep = (360.0 - m_startAngle - m_endAngle) / steps; //每一个份数的角度
+
+    // painter->setPen(m_foreground); //m_foreground是颜色的设置
+    // QPen pen = painter->pen(); //第一种方法
+    QPen pen ;
+    pen.setColor(Qt::green); //推荐使用第二种方式
+    for (int i = 0; i <= steps; i++)
+    {
+        if (i % m_scaleMinor == 0)//整数刻度显示加粗
+        {
+            pen.setWidth(1); //设置线宽
+            painter->setPen(pen); //使用面向对象的思想,把画笔关联上画家。通过画家画出来
+
+            painter->drawLine(0, 62, 0, 72); //两个参数应该是两个坐标值
+        }
+        else
+        {
+            pen.setWidth(0);
+            painter->setPen(pen);
+            painter->drawLine(0, 67, 0, 72);
+        }
+        painter->rotate(angleStep);
+    }
+    painter->restore();
+
+}
+
+void Speed::drawTitle(QPainter *painter)
+{
+    painter->save();
+    painter->setPen(m_foreground);
+    //painter->setBrush(m_foreground);
+    QString str(m_title); //显示仪表的功能
+    QFontMetricsF fm(this->font());
+    double w = fm.size(Qt::TextSingleLine,str).width();
+    painter->drawText(-w / 2, -30, str);
+    painter->restore();
+}
+
+void Speed::drawNumericValue(QPainter *painter)
+{
+    QString str = QString("%1 %2").arg(m_value, 0, 'f', m_precision).arg(m_units);
+    QFontMetricsF fm(font());
+    double w = fm.size(Qt::TextSingleLine,str).width();
+    painter->setPen(m_foreground);
+    painter->drawText(-w / 2, 42, str);
+}
+
+void Speed::drawIndicator(QPainter *painter)
+{
+    painter->save();
+    QPolygon pts;
+    pts.setPoints(3, -2, 0, 2, 0, 0, 60);	/* (-2,0)/(2,0)/(0,60) *///第一个参数是 ,坐标的个数。后边的是坐标
+
+    painter->rotate(m_startAngle);
+    double degRotate = (360.0 - m_startAngle - m_endAngle) / (m_maxValue - m_minValue)*(m_value - m_minValue);
+
+    //画指针
+    painter->rotate(degRotate);  //顺时针旋转坐标系统
+    QRadialGradient haloGradient(0, 0, 60, 0, 0);  //辐射渐变
+    haloGradient.setColorAt(0, QColor(60, 60, 60));
+    haloGradient.setColorAt(1, QColor(160, 160, 160)); //灰
+    painter->setPen(Qt::white); //定义线条文本颜色  设置线条的颜色
+    painter->setBrush(haloGradient);//刷子定义形状如何填满 填充后的颜色
+    painter->drawConvexPolygon(pts); //这是个重载函数,绘制多边形。
+    painter->restore();
+
+    //画中心点
+    QColor niceBlue(150, 150, 200);
+    QConicalGradient coneGradient(0, 0, -90.0);  //角度渐变
+    coneGradient.setColorAt(0.0, Qt::darkGray);
+    coneGradient.setColorAt(0.2, niceBlue);
+    coneGradient.setColorAt(0.5, Qt::white);
+    coneGradient.setColorAt(1.0, Qt::darkGray);
+    painter->setPen(Qt::NoPen);  //没有线,填满没有边界
+    painter->setBrush(coneGradient);
+    painter->drawEllipse(-5, -5, 10, 10);
+}
+
+void Speed ::paintEvent(QPaintEvent *)
+{
+    QPainter painter(this);//一个类中的this表示一个指向该类自己的指针
+    painter.setRenderHint(QPainter::Antialiasing);  /* 使用反锯齿(如果可用) */
+    painter.translate(width() / 2, height() / 2);   /* 坐标变换为窗体中心 */
+    int side = qMin(width(), height());
+    painter.scale(side / 200.0, side / 200.0);      /* 比例缩放 */
+
+   drawCrown(&painter);                                 /* 画表盘边框 */
+   drawScaleNum(&painter);                          /* 画刻度数值值 */
+   drawScale(&painter);                                 /* 画刻度线 */
+   drawTitle(&painter);                                     /* 画单位 */
+   drawNumericValue(&painter);                      /* 画数字显示 */
+   drawIndicator(&painter);                             /* 画表针 */
+
+}
+
+void Speed::setminvalue(int value)
+{
+    m_minValue = value;
+}
+
+void Speed::setmaxvalue(int value)
+{
+    m_maxValue = value;
+}
+
+void Speed::updatevalue(int value)
+{
+    m_value = value;
+    update();
+}
+
+void Speed::setunits(QString strunits)
+{
+    m_units = strunits;
+}
+
+void Speed::settitle(QString strtitle)
+{
+    m_title = strtitle;
+}

+ 51 - 0
src/tool/RemoteCtrl_Thread/speed.h

@@ -0,0 +1,51 @@
+#ifndef SPEED_H
+#define SPEED_H
+
+#include <QWidget>
+
+class Speed : public QWidget
+{
+    Q_OBJECT
+public:
+    explicit Speed(QWidget *parent = nullptr);
+
+protected:
+    void paintEvent(QPaintEvent *);
+
+    void drawCrown(QPainter *painter);
+    void drawBackground(QPainter *painter);
+    void drawScale(QPainter *painter);
+    void drawScaleNum(QPainter *painter);
+    void drawTitle(QPainter *painter);
+    void drawIndicator(QPainter *painter);
+    void drawNumericValue(QPainter *painter);
+
+private:
+    QColor m_background;
+    QColor m_foreground;
+
+
+    int m_maxValue;
+    int m_minValue;
+    int m_startAngle;
+    int m_endAngle;
+
+    int m_scaleMajor;
+    int m_scaleMinor;
+    double m_value;
+    int m_precision;
+    QTimer *m_updateTimer;
+    QString m_units;
+    QString m_title;
+    public Q_SLOTS:
+//	void UpdateAngle();
+
+public:
+    void setminvalue(int value);
+    void setmaxvalue(int value);
+    void updatevalue(int value);
+    void setunits(QString strunits);
+    void settitle(QString strtitle);
+};
+
+#endif // SPEED_H