def queryClusterResult(): res = ResMsg() try: logger.info("begin queryClusterResult!") aiBusModel = AiBusModel() userInfo = session.get("userInfo") data = request.get_json() fileId = data["fileId"] clusterOutPoints = [] clusterCorePoints = [] clusterAroundPoints = [] #1)先查询聚类参数 clusterParams = aiBusModel.selectClusterParams((fileId)) if not clusterParams: clusterParams = aiBusModel.selectClusterParamsBySiteFileId( (fileId)) if not clusterParams: res.update(code=ResponseCode.Success) return res.data fileId = clusterParams["id"] #2)查询聚类结果 clusterResut = aiBusModel.selectClusterResult((1, fileId)) for item in clusterResut: if item["relativeProperty"] == 1: siteProperty = "固定" elif item["relativeProperty"] == 0: siteProperty = "临时" else: siteProperty = "自定义" #根据site id查询网点信息 clientNames = [] users = [] if item["siteSet"] != '': users = item["siteSet"].split(",") siteInfo = aiBusModel.selectClientNameByIds(users) for site in siteInfo: clientNames.append(site["clientName"]) row={"id":item["id"],"siteName":item["clusterName"],"siteProperty":siteProperty,\ "longitude":item["longitude"],"latitude":item["latitude"],"number":item["number"],\ "users":users,"userNames":clientNames} if item["clusterProperty"] == 1: clusterCorePoints.append(row) elif item["clusterProperty"] == 2: clusterAroundPoints.append(row) else: clusterOutPoints.append(row) res.update(code=ResponseCode.Success, data={ "epsRadius": clusterParams["clusterRadius"], "minSamples": clusterParams["clusterMinSamples"], "clusterCorePoints": clusterCorePoints, "clusterAroundPoints": clusterAroundPoints, "clusterOutPoints": clusterOutPoints }) return res.data except Exception as e: logger.error("generateClusterPoints exception:{}".format(str(e))) res.update(code=ResponseCode.Fail, msg="查询聚类结果报错!") return res.data
def generateClusterPoints(): """ 根据网点文件id生成聚类点 """ res = ResMsg() try: logger.info("begin generateClusterPoints!") aiBusModel = AiBusModel() userInfo = session.get("userInfo") data = request.get_json() fileId = data["fileId"] epsRadius = float(data["epsRadius"]) minSamples = data["minSamples"] #先判断网点文件是否有效 fileProperty = aiBusModel.selectSiteFileStatus(fileId) if fileProperty["fileStatus"] == 0: res.update(code=ResponseCode.Fail, msg="该文件已经失效!") return res.data #根据网点文件查询网点list #先判断是该文件是聚类文件还是网点文件 if fileProperty["clusterStatus"] == 1: siteFileId = fileProperty["siteFileId"] else: siteFileId = fileId #对网点文件的临时聚类结果进行失效 aiBusModel.updateClusterResultByFileId( (0, userInfo["userName"], fileId), [2]) siteGeoList = aiBusModel.selectSiteGeoListByFileId(siteFileId) if not siteGeoList: res.update(code=ResponseCode.Fail, msg="网点为空!") return res.data #{"noiseList":[ids],"aroundList":[ids],"clusterDict":{"id":[ids],"id":[ids]}} clusterInfo = clusterByAdaptiveDbscan(siteGeoList, epsRadius, minSamples) #将聚类结果保存至表中 insertVals = [] siteGeoDict = {} for site in siteGeoList: siteGeoDict[str(site["id"])] = site clusterOutPoints = [] clusterCorePoints = [] clusterAroundPoints = [] #1)处理异常点fileId,siteId,clusterName,clusterProperty,clusterStatus,longitude,latitude,number,siteSet for id in clusterInfo["noiseList"]: relativeId = "site_" + str(id) site = siteGeoDict[str(id)] insertVals.append( (fileId, relativeId, site["siteName"], site["siteProperty"], 0, 2, site["lng"], site["lat"], site["number"], str(id), userInfo["userName"], userInfo["userName"])) #clusterOutPoints.append({"id":relativeId,"siteName":site["siteName"],"siteProperty":site["siteProperty"],"number":site["number"],"longitude":site["lng"],"latitude":site["lat"]}) #2)处理聚类点 for key in clusterInfo["clusterDict"].keys(): clusterSet = clusterInfo["clusterDict"][key] #处理聚类核心点 clusterNumber = 0 site = siteGeoDict[str(key)] for id in clusterSet: sitePoint = siteGeoDict[str(id)] clusterNumber += int(sitePoint["number"]) clusterIdStr = ",".join(map(str, clusterSet)) insertVals.append((fileId, "site_" + str(key), site["siteName"], site["siteProperty"], 1, 2, site["lng"], site["lat"], clusterNumber, clusterIdStr, userInfo["userName"], userInfo["userName"])) #处理边界点 for id in clusterInfo["aroundList"]: relativeId = "site_" + str(id) aroundSite = siteGeoDict[str(id)] insertVals.append( (fileId, relativeId, aroundSite["siteName"], aroundSite["siteProperty"], 2, 2, aroundSite["lng"], aroundSite["lat"], aroundSite["number"], str(id), userInfo["userName"], userInfo["userName"])) #3)插入聚类点并返回 aiBusModel.batchClusterSites(insertVals) #4)返回聚类结果 clusterResut = aiBusModel.selectClusterResult((2, fileId)) for item in clusterResut: if item["relativeProperty"] == 1: siteProperty = "固定" elif item["relativeProperty"] == 0: siteProperty = "临时" else: siteProperty = "自定义" #根据site id查询网点信息 siteInfo = aiBusModel.selectClientNameByIds( item["siteSet"].split(",")) clientNames = [] for site in siteInfo: clientNames.append(site["clientName"]) row={"id":item["id"],"siteName":item["clusterName"],"siteProperty":siteProperty,\ "longitude":item["longitude"],"latitude":item["latitude"],"number":item["number"],\ "users":item["siteSet"].split(","),"userNames":clientNames} if item["clusterProperty"] == 1: clusterCorePoints.append(row) elif item["clusterProperty"] == 2: clusterAroundPoints.append(row) else: clusterOutPoints.append(row) res.update(code=ResponseCode.Success, data={ "clusterCorePoints": clusterCorePoints, "clusterAroundPoints": clusterAroundPoints, "clusterOutPoints": clusterOutPoints }) return res.data except Exception as e: logger.error("generateClusterPoints exception:{}".format(str(e))) res.update(code=ResponseCode.Fail, msg=str(e)) return res.data
def generateClusterPointsOld(): """ 根据网点文件id生成聚类点 """ res = ResMsg() try: aiBusModel = AiBusModel() userInfo = session.get("userInfo") data = request.get_json() fileId = data["fileId"] epsRadius = float(data["epsRadius"]) minSamples = data["minSamples"] #先判断网点文件是否有效 fileStatus = aiBusModel.selectSiteFileStatus(fileId) #if fileStatus["fileProperty"]==0: # res.update(code=ResponseCode.Fail,data="该网点文件还未确认导入!") # return res.data if fileStatus["fileStatus"] == 0: res.update(code=ResponseCode.Fail, msg="该网点文件已经失效!") return res.data #对聚类过的临时结果进行失效 aiBusModel.updateClusterResultByFileId( (0, userInfo["userName"], fileId), [2]) #根据网点文件查询网点list siteGeoList = aiBusModel.selectSiteGeoListByFileId(fileId) clusterInfo = clusterByDbscan(siteGeoList, epsRadius / 1000, minSamples) #将聚类结果保存至表中 insertVals = [] siteGeoDict = {} for site in siteGeoList: siteGeoDict[str(site["id"])] = site clusterOutPoints = [] clusterCorePoints = [] clusterAroundPoints = [] #1)处理异常点fileId,siteId,clusterName,clusterProperty,clusterStatus,longitude,latitude,number,siteSet for id in clusterInfo["noiseIds"]: relativeId = "site_" + str(id) site = siteGeoDict[str(id)] insertVals.append( (fileId, relativeId, site["siteName"], site["siteProperty"], 0, 2, site["lng"], site["lat"], site["number"], "", userInfo["userName"], userInfo["userName"])) #clusterOutPoints.append({"id":relativeId,"siteName":site["siteName"],"siteProperty":site["siteProperty"],"number":site["number"],"longitude":site["lng"],"latitude":site["lat"]}) #2)处理聚类点 for cluster in clusterInfo["clusterSet"]: #处理聚类核心点 clusterNumber = 0 clusterId = int(cluster["clusterCenterId"]) site = siteGeoDict[str(clusterId)] for id in cluster["clusterCoreIds"]: clusterNumber += siteGeoDict[str(id)]["number"] insertVals.append( (fileId, "site_" + str(clusterId), site["siteName"], site["siteProperty"], 1, 2, site["lng"], site["lat"], clusterNumber, ",".join(map(str, cluster["clusterCoreIds"])), userInfo["userName"], userInfo["userName"])) #clusterCorePoints.append({"id":"site_"+str(clusterId),"siteName":site["siteName"],"siteProperty":site["siteProperty"],"number":clusterNumber,"longitude":site["lng"],"latitude":site["lat"]}) #处理边界点 for id in cluster["clusterAroundIds"]: relativeId = "site_" + str(id) aroundSite = siteGeoDict[str(id)] insertVals.append( (fileId, relativeId, aroundSite["siteName"], aroundSite["siteProperty"], 2, 2, aroundSite["lng"], aroundSite["lat"], aroundSite["number"], "", userInfo["userName"], userInfo["userName"])) #clusterAroundPoints.append({"id":relativeId,"siteName":aroundSite["siteName"],"siteProperty":site["siteProperty"],"number":aroundSite["number"],"longitude":aroundSite["lng"],"latitude":aroundSite["lat"]}) #3)插入聚类点并返回 aiBusModel.batchClusterSites(insertVals) #4)返回聚类结果 clusterResut = aiBusModel.selectClusterResult((2, fileId)) for item in clusterResut: if item["relativeProperty"] == 1: siteProperty = "固定" elif item["relativeProperty"] == 0: siteProperty = "临时" else: siteProperty = "自定义" row={"id":item["id"],"siteName":item["clusterName"],"siteProperty":siteProperty,\ "longitude":item["longitude"],"latitude":item["latitude"],"number":item["number"]} if item["clusterProperty"] == 1: clusterCorePoints.append(row) elif item["clusterProperty"] == 2: clusterAroundPoints.append(row) else: clusterAroundPoints.append(row) res.update(code=ResponseCode.Success, data={ "clusterCorePoints": clusterCorePoints, "clusterAroundPoints": clusterAroundPoints, "clusterOutPoints": clusterOutPoints }) return res.data except Exception as e: res.update(code=ResponseCode.Fail, msg="生成聚类点报错!") return res.data
def planSingleRoute(): """ 单路线规划 """ res = ResMsg() try: logger.info("begin planSingleRoute!") data = request.get_json() aiBusModel = AiBusModel() fileId = data["fileId"] destination = data["destination"] waypoints = data["waypoints"] passengers = data["passengers"] #座位上限 occupancyRate = int(data["occupancyRate"]) #改为上座下限 #初始化相关系数 odometerFactor = 100.0 maxDistance = 1000.0 * 1000 #m maxDuration = 24 * 3600 #分钟 if "odometerFactor" in data and data["odometerFactor"] != "": odometerFactor = float(data["odometerFactor"]) #非直线系数(非必选) if "maxDistance" in data and data["maxDistance"] != "": maxDistance = float( data["maxDistance"]) * 1000 #最大行程距离,data["maxDistance"](km) if "maxDuration" in data and data["maxDuration"] != "": maxDuration = float(data["maxDuration"]) * 60 #最大行程耗时 roundTrip = data["roundTrip"] #是否往返0, routeFactor = data["routeFactor"] #路线方案,0时间最短,1距离最短 vehicleType = int(data["vehicleType"]) #车辆类型0为小车方案,1为货车方案 MAXNODE = 20 MINNODE = 2 if not destination: res.update(code=ResponseCode.Fail, data=[], msg="目的地不能为空!") return res.data #1)先判断fileid是否为空 routeNode = [] indexList = [] index = 0 orderNumber = -1 #订单总数 if fileId is not None and fileId != '': #根据fileId查询文件信息,判断是聚类文件还网点文件 fileInfo = aiBusModel.selectSiteFileStatus(fileId) if fileInfo and fileInfo["clusterStatus"] == 1: clusterPoints = aiBusModel.selectClusterResult((1, fileId)) siteInfo = aiBusModel.selectSiteFileStatus( fileInfo["siteFileId"]) orderNumber = siteInfo["siteCount"] for point in clusterPoints: indexList.append(str(index)) routeNode.append({ "index": index, "nodeName": point["clusterName"], "lng": format(point["longitude"], '.6f'), "lat": format(point["latitude"], '.6f'), "number": point["number"] }) index += 1 else: orderNumber = fileInfo["siteCount"] sitePoints = aiBusModel.selectSiteInfoByFileId(fileId) for point in sitePoints: indexList.append(str(index)) routeNode.append({ "index": index, "nodeName": point["siteName"], "lng": format(point["longitude"], '.6f'), "lat": format(point["latitude"], '.6f'), "number": point["clientNumber"] }) index += 1 if orderNumber is None or orderNumber <= 0: orderNumber = passengers else: fileId = -1 orderNumber = passengers #添加途经点 for point in waypoints: indexList.append(str(index)) routeNode.append({ "index": index, "nodeName": point["siteName"], "lng": format(point["lng"], '.6f'), "lat": format(point["lat"], '.6f'), "number": point["number"] }) index += 1 #判断结点数量是否超过限制len(routeNode)>MAXNODE or if len(routeNode) < MINNODE: res.update(code=ResponseCode.Fail, data=[], msg="路线规划结点数量超过最大限制{}或者小于最小限度{}!".format( MAXNODE, MINNODE)) return res.data #判断参数是否冲突 if occupancyRate > passengers: res.update(code=ResponseCode.Fail, data=[], msg="路线规划上座下限必须小于座位上限!") return res.data """ if occupancyRate<=0 or occupancyRate>100: res.update(code=ResponseCode.Fail,data=[],msg="路线规划上座率下限必须大于{}或者小于{}!".format(0,100)) return res.data if passengers<int(orderNumber*occupancyRate/100): res.update(code=ResponseCode.Fail,data=[],msg="最低上座率人数超过座位上限!") return res.data """ #将目标点一起添加至末尾 routeNode.append({ "index": "dest", "nodeName": destination["siteName"], "lng": format(destination["lng"], '.6f'), "lat": format(destination["lat"], '.6f'), "number": 0 }) indexList.append("dest") #2)构建结点对,用于获取高德数据 nodePairDict = {} nodePairList = [] #用于多线程获取高德数据 pointNum = len(indexList) nodeCostDF = pd.DataFrame(np.zeros([pointNum, pointNum]), columns=indexList, index=indexList) routeNodePair = list(itertools.permutations(routeNode, 2)) paramIds = [] for nodePair in routeNodePair: fromNode = str(round(float(nodePair[0]["lng"]), 6)) + "," + str( round(float(nodePair[0]["lat"]), 6)) toNode = str(round(float(nodePair[1]["lng"]), 6)) + "," + str( round(float(nodePair[1]["lat"]), 6)) #手动生成id,批量查询 paramId = generate_md5_key(fromNode + "," + toNode) paramIds.append(paramId) #根据paramIds查询缓存的距离nodePairDistList nodePairParamsList = aiBusModel.selectRouteParams( vehicleType, paramIds) nodePairParamsDict = {} if nodePairParamsList: for item in nodePairParamsList: nodePairParamsDict[item["id"]] = item #获取nodePair的距离 for nodePair in routeNodePair: key = str(nodePair[0]["index"]) + "-" + str(nodePair[1]["index"]) fromNode = str(round(float(nodePair[0]["lng"]), 6)) + "," + str( round(float(nodePair[0]["lat"]), 6)) toNode = str(round(float(nodePair[1]["lng"]), 6)) + "," + str( round(float(nodePair[1]["lat"]), 6)) paramId = generate_md5_key(fromNode + "," + toNode) #先判断是否已经存在库中 if paramId in nodePairParamsDict.keys(): item = nodePairParamsDict[paramId] directDist = getGPSDistance(float(nodePair[0]["lng"]), float(nodePair[0]["lat"]), float(nodePair[1]["lng"]), float(nodePair[1]["lat"])) nodePairDict[key] = { "dist": float(item["dist"]), "time": item["time"], "directDist": directDist } #对df进行赋值 if routeFactor == 0: nodeCostDF.loc[str(nodePair[0]["index"]), str(nodePair[1]["index"])] = int( item["time"]) else: nodeCostDF.loc[str(nodePair[0]["index"]), str(nodePair[1]["index"])] = float( item["dist"]) else: nodePairList.append({ "key": key, "origin": fromNode, "destination": toNode, "routeType": vehicleType, "fromNode": nodePair[0], "toNode": nodePair[1], "paramId": paramId }) #从高德获取路径数据 if len(nodePairList) > 0: nodePairResult = build_process(nodePairList) for item in nodePairList: key = item["key"] nodeItem = nodePairResult[key] directDist = getGPSDistance(float(item["fromNode"]["lng"]), float(item["fromNode"]["lat"]), float(item["toNode"]["lng"]), float(item["toNode"]["lat"])) nodePairDict[key] = { "dist": nodeItem["dist"], "time": nodeItem["time"], "directDist": directDist } #对df进行赋值 if routeFactor == 0: nodeCostDF.loc[ str(item["fromNode"]["index"]), str(item["toNode"]["index"])] = nodeItem["time"] else: nodeCostDF.loc[ str(item["fromNode"]["index"]), str(item["toNode"]["index"])] = nodeItem["dist"] #存储获取的数据 if item["paramId"] not in nodePairParamsDict.keys(): #startGeo = '{ "type": "Point", "coordinates": [%s, %s]}'%(float(item["fromNode"]["lng"]),float(item["fromNode"]["lat"])) #endGeo = '{ "type": "Point", "coordinates": [%s, %s]}'%(float(item["toNode"]["lng"]),float(item["toNode"]["lat"])) aiBusModel.inserRouteParams((item["paramId"],float(item["fromNode"]["lng"]),float(item["fromNode"]["lat"]),\ float(item["toNode"]["lng"]),float(item["toNode"]["lat"]),nodeItem["dist"],nodeItem["time"],directDist,0.0)) else: aiBusModel.updateRouteParams( (nodeItem["dist"], nodeItem["time"], directDist, item["paramId"])) #3)进行路线规划 logger.info("start single route plan!") solution = singleRoutePlanByGreedyAlgorithm(routeNode, nodePairDict, nodeCostDF, passengers, occupancyRate, orderNumber, odometerFactor, maxDistance, maxDuration) if solution["routeNode"] is None: res.update(code=ResponseCode.Fail, data=[], msg="未找到满足条件的路线!") return res.data else: #用sa算法进行优化 routeInfo = { "nodePair": nodePairDict, "routeNode": solution["routeNode"], "routeFactor": routeFactor } reSolution = singleRoutePlanSolution(routeInfo) #print("re bestCost:",reSolution["bestRouteCost"]) if solution["bestRouteCost"] > reSolution["bestRouteCost"]: solution["routeNode"] = reSolution["routeNode"] #找出最后一段顺路点 if len(solution["routeNode"]) > 1: lastNode = solution["routeNode"][len(solution["routeNode"]) - 2] fromNode = str(round(float(lastNode["lng"]), 6)) + "," + str( round(float(lastNode["lat"]), 6)) toNode = str(round(float(destination["lng"]), 6)) + "," + str( round(float(destination["lat"]), 6)) polyline = get_driving_polyline(fromNode, toNode) solution = findOnwayRouteNode(solution, polyline) if solution["routeNumber"] < occupancyRate: res.update(code=ResponseCode.Fail, data=[], msg="未找到满足条件的路线!") return res.data logger.info("end single route plan!") #4)保存路线规划结果,获取最优路径的行程距离、行程时间、直线距离 routeList = [] ############往程################ nodeIndex = 0 routeDist = 0 routeTime = 0 routeNumber = 0 directDist = 0 routeNodeList = [] for i in range(len(solution["routeNode"]) - 1): fromNode = solution["routeNode"][i] toNode = solution["routeNode"][i + 1] key = str(fromNode["index"]) + "-" + str(toNode["index"]) routeDist += nodePairDict[key]["dist"] routeTime += nodePairDict[key]["time"] directDist += getGPSDistance(float(fromNode["lng"]), float(fromNode["lat"]), float(toNode["lng"]), float(toNode["lat"])) routeNumber += fromNode["number"] routeNodeList.append({"nodeIndex":nodeIndex,"nodeName":fromNode["nodeName"],\ "lng":float(fromNode["lng"]),"lat":float(fromNode["lat"]),"number":fromNode["number"],\ "nextDist":nodePairDict[key]["dist"],"nextTime":nodePairDict[key]["time"]}) nodeIndex += 1 #添加终点 routeNodeList.append({"nodeIndex":nodeIndex,"nodeName":destination["siteName"],\ "lng":float(destination["lng"]),"lat":float(destination["lat"]),"number":0,"nextDist":0,"nextTime":0}) #存储路线结点 routeUuid = uuid.uuid1().int aiBusModel.insertRouteInfo((fileId,routeUuid,destination["siteName"],\ destination["lng"],destination["lat"],passengers,occupancyRate,odometerFactor,\ routeFactor,roundTrip,json.dumps(waypoints),maxDistance,maxDuration,vehicleType,2)) for node in routeNodeList: aiBusModel.insertRouteDetail((fileId,routeUuid,0,node["nodeIndex"],node["nodeName"],2,\ node["lng"],node["lat"],node["number"],node["nextDist"],node["nextTime"],1,1)) for i, node in enumerate(solution["invalidRouteNode"]): aiBusModel.insertRouteDetail((fileId,routeUuid,0,i,node["nodeName"],2,\ node["lng"],node["lat"],node["number"],0,0,0,1)) #查询路线结点及未规划的结点 routeOccupancyRate = int(routeNumber / orderNumber * 100) routeNodeResult1 = aiBusModel.selectRouteDetail((routeUuid, 2, 0, 1)) invalidRouteNodeResult = aiBusModel.selectRouteDetail( (routeUuid, 2, 0, 0)) invalidNodeList = [] for routeNode in invalidRouteNodeResult: invalidNodeList.append({ "id": routeNode["id"], "lat": routeNode["lat"], "lng": routeNode["lng"], "nodeIndex": routeNode["nodeIndex"], "nodeName": routeNode["nodeName"], "number": routeNode["number"] }) routeList.append({"routeId":routeUuid,"routeDist":int(routeDist),\ "routeTime":routeTime,"routeNumber":routeNumber,"orderNumber":orderNumber,\ "routeOccupancyRate":routeOccupancyRate,"roundStatus":0,\ "routeNodeList":routeNodeResult1,"invalidNodeList":invalidNodeList}) #############返程################ if roundTrip == 1: roundRouteDist = 0 roundRouteTime = 0 roundDirectDist = 0 roundRouteNodeList = [] nodeIndex = 0 for i in range(len(solution["routeNode"]) - 1, 0, -1): fromNode = solution["routeNode"][i] toNode = solution["routeNode"][i - 1] key = str(fromNode["index"]) + "-" + str(toNode["index"]) roundRouteDist += nodePairDict[key]["dist"] roundRouteTime += nodePairDict[key]["time"] roundDirectDist += getGPSDistance(float(fromNode["lng"]), float(fromNode["lat"]), float(toNode["lng"]), float(toNode["lat"])) roundRouteNodeList.append({"nodeIndex":nodeIndex,"nodeName":fromNode["nodeName"],\ "lng":float(fromNode["lng"]),"lat":float(fromNode["lat"]),"number":fromNode["number"],\ "nextDist":nodePairDict[key]["dist"],"nextTime":nodePairDict[key]["time"]}) nodeIndex += 1 if i == 1: roundRouteNodeList.append({"nodeIndex":nodeIndex,"nodeName":toNode["nodeName"],\ "lng":float(toNode["lng"]),"lat":float(toNode["lat"]),"number":toNode["number"],\ "nextDist":0,"nextTime":0}) #存储结点 for node in roundRouteNodeList: aiBusModel.insertRouteDetail((fileId,routeUuid,1,node["nodeIndex"],node["nodeName"],2,\ node["lng"],node["lat"],node["number"],node["nextDist"],node["nextTime"],1,1)) for i, node in enumerate(solution["invalidRouteNode"]): aiBusModel.insertRouteDetail((fileId,routeUuid,1,i,node["nodeName"],2,\ node["lng"],node["lat"],node["number"],0,0,0,1)) #查询路线结点及未规划的结点 routeNodeResult2 = aiBusModel.selectRouteDetail( (routeUuid, 2, 1, 1)) invalidRouteNodeResult = aiBusModel.selectRouteDetail( (routeUuid, 2, 1, 0)) invalidNodeList = [] for routeNode in invalidRouteNodeResult: invalidNodeList.append({ "id": routeNode["id"], "lat": routeNode["lat"], "lng": routeNode["lng"], "nodeIndex": routeNode["nodeIndex"], "nodeName": routeNode["nodeName"], "number": routeNode["number"] }) routeList.append({"routeId":routeUuid,"routeDist":int(roundRouteDist),\ "routeTime":roundRouteTime,"routeNumber":routeNumber,"orderNumber":orderNumber,\ "routeOccupancyRate":routeOccupancyRate,"roundStatus":1,\ "routeNodeList":routeNodeResult2,"invalidNodeList":invalidNodeList}) res.update(code=ResponseCode.Success, data={ "destination": destination, "routeList": routeList }) return res.data except Exception as e: logger.error("planSingleRoute exception:{}".format(str(e))) res.update(code=ResponseCode.Fail, msg=str(e)) return res.data