OSRM:为什么路线A的行驶时间-> B偏离路线的行进时间为2倍B->一种? [英] OSRM: Why is the traveltime of route A -> B a factor 2 off route's traveltime B -> A?

查看:89
本文介绍了OSRM:为什么路线A的行驶时间-> B偏离路线的行进时间为2倍B->一种?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如上所述:它甚至相差2倍!那怎么可能? 我发现了此问题,但看来它仍然在那里?

事实证明,高速公路仅沿方向行驶(请参见map_route 的传单地图.我会错过任何内容吗?

这是一个可复制的示例:

wd <- getwd()
setwd("C:/OSRM_API5")
shell(paste0("osrm-routed ", "switzerland-latest.osrm", " >nul 2>nul"), wait = F)
Sys.sleep(3) # OSRM needs time
setwd(wd)

k1 <- 46.99917
k2 <- 8.610048
k3 <- 47.05398
k4 <- 8.530232
r1 <- viaroute5_2(k1, k2, k3, k4)
r1$routes[[1]]$duration
# [1] 598.2
geometry <- decode_geom(r1$routes[[1]]$geometry, 5)
map_route(geometry)

r2 <- viaroute5_2(k3, k4,k1, k2)
r2$routes[[1]]$duration
# [1] 1302
geometry <- decode_geom(r2$routes[[1]]$geometry, 5)
map_route(geometry)
shell("TaskKill /F /IM osrm-routed.exe >nul 2>nul")

以下是您需要的功能:

viaroute5_2 <- function(lat1, lng1, lat2, lng2) {
  # address <- "http://localhost:5000" # this should work without a  local server
  address <- "http://localhost:5000"
  request <- paste(address, "/route/v1/driving/",
                   lng1, ",", lat1, ";", lng2, ",", lat2,
                   "?overview=full", sep = "", NULL)

  R.utils::withTimeout({
    repeat {
      res <- try(
        route <- rjson::fromJSON(
          file = request))
      if (class(res) != "try-error") {
        if (!is.null(res)) {
          break
        } else {
          stop("???")
        }
      }
    }
  }, timeout = 1, onTimeout = "warning")

  if (res$code == "Ok") {
    return(res)
  } else {
    t_guess <- 16*60
    warning("Route not found: ", paste(lat1, lng1, lat2, lng2, collapse = ", "),
            ". Time set to ", t_guess/60 , " min.")
  }
}

decode_geom <- function(encoded, precision = stop("a numeric, either 5 or 6")) {
  if (precision == 5) {
    scale <- 1e-5
  } else if (precision == 6) {
    scale <- 1e-6
  } else {
    stop("precision not set to 5 or 6")
  }
  len = stringr::str_length(encoded)
  encoded <- strsplit(encoded, NULL)[[1]]
  index = 1
  N <- 100000
  df.index <- 1
  array = matrix(nrow = N, ncol = 2)
  lat <- dlat <- lng <- dlnt <- b <- shift <- result <- 0

  while (index <= len) {
    shift <- result <- 0
    repeat {
      b = as.integer(charToRaw(encoded[index])) - 63
      index <- index + 1
      result = bitops::bitOr(result, bitops::bitShiftL(bitops::bitAnd(b, 0x1f), shift))
      shift = shift + 5
      if (b < 0x20) break
    }
    dlat = ifelse(bitops::bitAnd(result, 1),
                  -(result - (bitops::bitShiftR(result, 1))),
                  bitops::bitShiftR(result, 1))
    lat = lat + dlat;

    shift <- result <- b <- 0
    repeat {
      b = as.integer(charToRaw(encoded[index])) - 63
      index <- index + 1
      result = bitops::bitOr(result, bitops::bitShiftL(bitops::bitAnd(b, 0x1f), shift))
      shift = shift + 5
      if (b < 0x20) break
    }
    dlng = ifelse(bitops::bitAnd(result, 1),
                  -(result - (bitops::bitShiftR(result, 1))),
                  bitops::bitShiftR(result, 1))
    lng = lng + dlng

    array[df.index,] <- c(lat = lat * scale, lng = lng * scale)
    df.index <- df.index + 1
  }

  geometry <- data.frame(array[1:df.index - 1,])
  names(geometry) <- c("lat", "lng")
  return(geometry)
}

map <- function() {
  library(leaflet)
  m <- leaflet() %>%
    addTiles() %>%
    addProviderTiles(providers$OpenStreetMap, group = "OSM") %>%
    addProviderTiles(providers$Stamen.TonerLite, group = "Toner Lite") %>%
    addLayersControl(baseGroups = c("OSM", "Toner Lite"))
  return(m)
}

map_route <- function(geometry) { # Which parameters make sence? osrm inside or outside?
  m <- map()
  m <- addCircleMarkers(map = m,
                        lat = geometry$lat[1],
                        lng = geometry$lng[1],
                        color = imsbasics::fhs(),
                        popup = paste("Source"),
                        stroke = FALSE,
                        radius = 6,
                        fillOpacity = 0.8) %>%
    addCircleMarkers(lat = geometry$lat[nrow(geometry)],
                     lng = geometry$lng[nrow(geometry)],
                     color = imsbasics::fhs(),
                     popup = paste("Destination"),
                     stroke = FALSE,
                     radius = 6,
                     fillOpacity = 0.8) %>%
    addPolylines(lat = geometry$lat, lng = geometry$lng, color = "red", weight = 4) %>%
    addLayersControl(baseGroups = c("OSM", "Stamen.TonerLite"))
  return(m)
}

解决方案

答案是:因为OSRM默认情况下会搜索最近的点并从该点搜索一条路线.如果您的坐标位于高速公路的稍微北边,那么OSRM只会向西行驶(考虑到您在欧洲的右侧行驶,因此我们会在欧洲行驶.).

因此,在您的示例中,左上角点位于高速公路以北一点,因此,从该点进行搜索时,OSRM会走很多弯路.

以下示例显示了这一点:

osrmr::run_server("switzerland-latest", "C:/OSRM_API5")

lat1 <- 46.99917
lng1 <- 8.610048
lat2 <- 47.05398
lng2 <- 8.530232

res1 <- osrmr::viaroute(lat1, lng1, lat2, lng2, instructions = TRUE, api_version = 5, localhost = TRUE)
res2 <- osrmr::viaroute(lat2, lng2, lat1, lng1, instructions = TRUE, api_version = 5, localhost = TRUE)
res1$routes[[1]]$duration
# [1] 598.2
res2$routes[[1]]$duration
# [1] 1302
map_route(decode_geom(res1$routes[[1]]$geometry, 5))
map_route(decode_geom(res2$routes[[1]]$geometry, 5))


lat1 <- 46.99917
lng1 <- 8.610048
lat2 <- 47.051 # setting that point a bit more south changes the results to the opposite..
lng2 <- 8.530232

res1 <- osrmr::viaroute(lat1, lng1, lat2, lng2, instructions = TRUE, api_version = 5, localhost = TRUE)
res2 <- osrmr::viaroute(lat2, lng2, lat1, lng1, instructions = TRUE, api_version = 5, localhost = TRUE)
res1$routes[[1]]$duration
# [1] 1307.5
res2$routes[[1]]$duration
# [1] 592.7
map_route(decode_geom(res1$routes[[1]]$geometry, 5))
map_route(decode_geom(res2$routes[[1]]$geometry, 5))

osrmr::quit_server()

如您所见,将第二点设置在更南的位置会反转结果.现在,另一种方法花费的时间要长得多.

例如在此处中讨论的 radiuses选项可能提供解决该问题的方法.但是,我不知道该如何将其用于您的示例.

或者也许(更简单..)您想计算两个方向并采用较短的duration?

什么才是最好的取决于您的算法问题.

As said: it even differs by a factor of 2 in time! How is that possible? I found this issue but it seems it is still there?

It turns out that the highway is only taken in on direction (See leaflet map from map_route. Do I miss anything?

Here is a reproducible example:

wd <- getwd()
setwd("C:/OSRM_API5")
shell(paste0("osrm-routed ", "switzerland-latest.osrm", " >nul 2>nul"), wait = F)
Sys.sleep(3) # OSRM needs time
setwd(wd)

k1 <- 46.99917
k2 <- 8.610048
k3 <- 47.05398
k4 <- 8.530232
r1 <- viaroute5_2(k1, k2, k3, k4)
r1$routes[[1]]$duration
# [1] 598.2
geometry <- decode_geom(r1$routes[[1]]$geometry, 5)
map_route(geometry)

r2 <- viaroute5_2(k3, k4,k1, k2)
r2$routes[[1]]$duration
# [1] 1302
geometry <- decode_geom(r2$routes[[1]]$geometry, 5)
map_route(geometry)
shell("TaskKill /F /IM osrm-routed.exe >nul 2>nul")

Here are the functions you need:

viaroute5_2 <- function(lat1, lng1, lat2, lng2) {
  # address <- "http://localhost:5000" # this should work without a  local server
  address <- "http://localhost:5000"
  request <- paste(address, "/route/v1/driving/",
                   lng1, ",", lat1, ";", lng2, ",", lat2,
                   "?overview=full", sep = "", NULL)

  R.utils::withTimeout({
    repeat {
      res <- try(
        route <- rjson::fromJSON(
          file = request))
      if (class(res) != "try-error") {
        if (!is.null(res)) {
          break
        } else {
          stop("???")
        }
      }
    }
  }, timeout = 1, onTimeout = "warning")

  if (res$code == "Ok") {
    return(res)
  } else {
    t_guess <- 16*60
    warning("Route not found: ", paste(lat1, lng1, lat2, lng2, collapse = ", "),
            ". Time set to ", t_guess/60 , " min.")
  }
}

decode_geom <- function(encoded, precision = stop("a numeric, either 5 or 6")) {
  if (precision == 5) {
    scale <- 1e-5
  } else if (precision == 6) {
    scale <- 1e-6
  } else {
    stop("precision not set to 5 or 6")
  }
  len = stringr::str_length(encoded)
  encoded <- strsplit(encoded, NULL)[[1]]
  index = 1
  N <- 100000
  df.index <- 1
  array = matrix(nrow = N, ncol = 2)
  lat <- dlat <- lng <- dlnt <- b <- shift <- result <- 0

  while (index <= len) {
    shift <- result <- 0
    repeat {
      b = as.integer(charToRaw(encoded[index])) - 63
      index <- index + 1
      result = bitops::bitOr(result, bitops::bitShiftL(bitops::bitAnd(b, 0x1f), shift))
      shift = shift + 5
      if (b < 0x20) break
    }
    dlat = ifelse(bitops::bitAnd(result, 1),
                  -(result - (bitops::bitShiftR(result, 1))),
                  bitops::bitShiftR(result, 1))
    lat = lat + dlat;

    shift <- result <- b <- 0
    repeat {
      b = as.integer(charToRaw(encoded[index])) - 63
      index <- index + 1
      result = bitops::bitOr(result, bitops::bitShiftL(bitops::bitAnd(b, 0x1f), shift))
      shift = shift + 5
      if (b < 0x20) break
    }
    dlng = ifelse(bitops::bitAnd(result, 1),
                  -(result - (bitops::bitShiftR(result, 1))),
                  bitops::bitShiftR(result, 1))
    lng = lng + dlng

    array[df.index,] <- c(lat = lat * scale, lng = lng * scale)
    df.index <- df.index + 1
  }

  geometry <- data.frame(array[1:df.index - 1,])
  names(geometry) <- c("lat", "lng")
  return(geometry)
}

map <- function() {
  library(leaflet)
  m <- leaflet() %>%
    addTiles() %>%
    addProviderTiles(providers$OpenStreetMap, group = "OSM") %>%
    addProviderTiles(providers$Stamen.TonerLite, group = "Toner Lite") %>%
    addLayersControl(baseGroups = c("OSM", "Toner Lite"))
  return(m)
}

map_route <- function(geometry) { # Which parameters make sence? osrm inside or outside?
  m <- map()
  m <- addCircleMarkers(map = m,
                        lat = geometry$lat[1],
                        lng = geometry$lng[1],
                        color = imsbasics::fhs(),
                        popup = paste("Source"),
                        stroke = FALSE,
                        radius = 6,
                        fillOpacity = 0.8) %>%
    addCircleMarkers(lat = geometry$lat[nrow(geometry)],
                     lng = geometry$lng[nrow(geometry)],
                     color = imsbasics::fhs(),
                     popup = paste("Destination"),
                     stroke = FALSE,
                     radius = 6,
                     fillOpacity = 0.8) %>%
    addPolylines(lat = geometry$lat, lng = geometry$lng, color = "red", weight = 4) %>%
    addLayersControl(baseGroups = c("OSM", "Stamen.TonerLite"))
  return(m)
}

解决方案

The answer is: Because OSRM searches by default a nearest point and searches one route from that point. If your coordinates are slightly north a highway, OSRM will only drive westbound (considering you're drive on the right side as we do in Europe..).

So in your example the point upleft is just a bit north of the highway and therefore when searching from that point OSRM takes quite a bit of a detour.

The following example shows this:

osrmr::run_server("switzerland-latest", "C:/OSRM_API5")

lat1 <- 46.99917
lng1 <- 8.610048
lat2 <- 47.05398
lng2 <- 8.530232

res1 <- osrmr::viaroute(lat1, lng1, lat2, lng2, instructions = TRUE, api_version = 5, localhost = TRUE)
res2 <- osrmr::viaroute(lat2, lng2, lat1, lng1, instructions = TRUE, api_version = 5, localhost = TRUE)
res1$routes[[1]]$duration
# [1] 598.2
res2$routes[[1]]$duration
# [1] 1302
map_route(decode_geom(res1$routes[[1]]$geometry, 5))
map_route(decode_geom(res2$routes[[1]]$geometry, 5))


lat1 <- 46.99917
lng1 <- 8.610048
lat2 <- 47.051 # setting that point a bit more south changes the results to the opposite..
lng2 <- 8.530232

res1 <- osrmr::viaroute(lat1, lng1, lat2, lng2, instructions = TRUE, api_version = 5, localhost = TRUE)
res2 <- osrmr::viaroute(lat2, lng2, lat1, lng1, instructions = TRUE, api_version = 5, localhost = TRUE)
res1$routes[[1]]$duration
# [1] 1307.5
res2$routes[[1]]$duration
# [1] 592.7
map_route(decode_geom(res1$routes[[1]]$geometry, 5))
map_route(decode_geom(res2$routes[[1]]$geometry, 5))

osrmr::quit_server()

As you can see, setting the second point a bit more south inverts the results. Now the other way takes quite a bit longer.

As discussed for example here the radiuses option might provide a solution to that problem. I couldn't however figure out to get that to work on your example..

Or maybe (simpler..) you want to calculate both directions and take the shorter duration?

What's best really depends on your algorithmic problem..

这篇关于OSRM:为什么路线A的行驶时间-> B偏离路线的行进时间为2倍B->一种?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆