add osrm to routing service (#86)

This commit is contained in:
Asim Aslam
2021-04-26 11:42:08 +01:00
committed by GitHub
parent 7ae45b522e
commit d119807d1c
10 changed files with 345 additions and 135 deletions

View File

@@ -4,7 +4,6 @@ import (
"context"
"fmt"
"google.golang.org/protobuf/types/known/wrapperspb"
"googlemaps.github.io/maps"
"github.com/micro/micro/v3/service/errors"
@@ -21,11 +20,11 @@ var (
ErrNoRoutes = errors.BadRequest("NO_ROUTES", "No routes found")
)
type Routing struct {
type Google struct {
Maps *maps.Client
}
func (r *Routing) Route(ctx context.Context, req *pb.RouteRequest, rsp *pb.RouteResponse) error {
func (r *Google) Route(ctx context.Context, req *pb.RouteRequest, rsp *pb.RouteResponse) error {
// validate the request
if req.Origin == nil {
return ErrMissingOrigin
@@ -60,26 +59,28 @@ func (r *Routing) Route(ctx context.Context, req *pb.RouteRequest, rsp *pb.Route
}
// return the result
rsp.Waypoints = make([]*pb.Point, len(points))
rsp.Waypoints = make([]*pb.Waypoint, len(points))
for i, p := range points {
rsp.Waypoints[i] = &pb.Point{
Latitude: &wrapperspb.DoubleValue{Value: p.Lat},
Longitude: &wrapperspb.DoubleValue{Value: p.Lng},
rsp.Waypoints[i] = &pb.Waypoint{
Location: &pb.Point{
Latitude: p.Lat,
Longitude: p.Lng,
},
}
}
return nil
}
func validatePoint(p *pb.Point) error {
if p.Latitude == nil {
if p.Latitude == 0.0 {
return ErrMissingLatitude
}
if p.Longitude == nil {
if p.Longitude == 0.0 {
return ErrMissingLongitude
}
return nil
}
func pointToString(p *pb.Point) string {
return fmt.Sprintf("%v,%v", p.Latitude.Value, p.Longitude.Value)
return fmt.Sprintf("%v,%v", p.Latitude, p.Longitude)
}

View File

@@ -11,7 +11,6 @@ import (
"github.com/micro/services/routing/handler"
pb "github.com/micro/services/routing/proto"
"github.com/stretchr/testify/assert"
"google.golang.org/protobuf/types/known/wrapperspb"
"googlemaps.github.io/maps"
)
@@ -116,13 +115,13 @@ func TestRoute(t *testing.T) {
if err != nil {
t.Fatal(err)
}
h := &handler.Routing{Maps: m}
h := &handler.Google{Maps: m}
originLat := &wrapperspb.DoubleValue{Value: 33.8688}
originLng := &wrapperspb.DoubleValue{Value: 151.2093}
originLat := 33.8688
originLng := 151.2093
destinationLat := &wrapperspb.DoubleValue{Value: 33.8136}
destinationLng := &wrapperspb.DoubleValue{Value: 151.0034}
destinationLat := 33.8136
destinationLng := 151.0034
tt := []struct {
Name string
@@ -159,52 +158,52 @@ func TestRoute(t *testing.T) {
Destination: &pb.Point{Latitude: destinationLat, Longitude: destinationLng},
Result: []*pb.Point{
{
Latitude: &wrapperspb.DoubleValue{Value: -33.867490000000004},
Longitude: &wrapperspb.DoubleValue{Value: 151.20708000000002},
Latitude: -33.867490000000004,
Longitude: 151.20708000000002,
},
{
Latitude: &wrapperspb.DoubleValue{Value: -33.867610000000006},
Longitude: &wrapperspb.DoubleValue{Value: 151.20707000000002},
Latitude: -33.867610000000006,
Longitude: 151.20707000000002,
},
{
Latitude: &wrapperspb.DoubleValue{Value: -33.868080000000006},
Longitude: &wrapperspb.DoubleValue{Value: 151.20702},
Latitude: -33.868080000000006,
Longitude: 151.20702,
},
{
Latitude: &wrapperspb.DoubleValue{Value: -33.868390000000005},
Longitude: &wrapperspb.DoubleValue{Value: 151.20699000000002},
Latitude: -33.868390000000005,
Longitude: 151.20699000000002,
},
{
Latitude: &wrapperspb.DoubleValue{Value: -33.86874},
Longitude: &wrapperspb.DoubleValue{Value: 151.20697},
Latitude: -33.86874,
Longitude: 151.20697,
},
{
Latitude: &wrapperspb.DoubleValue{Value: -33.869400000000006},
Longitude: &wrapperspb.DoubleValue{Value: 151.20696},
Latitude: -33.869400000000006,
Longitude: 151.20696,
},
{
Latitude: &wrapperspb.DoubleValue{Value: -33.86941},
Longitude: &wrapperspb.DoubleValue{Value: 151.20696},
Latitude: -33.86941,
Longitude: 151.20696,
},
{
Latitude: &wrapperspb.DoubleValue{Value: -33.86957},
Longitude: &wrapperspb.DoubleValue{Value: 151.20695},
Latitude: -33.86957,
Longitude: 151.20695,
},
{
Latitude: &wrapperspb.DoubleValue{Value: -33.86965},
Longitude: &wrapperspb.DoubleValue{Value: 151.20695},
Latitude: -33.86965,
Longitude: 151.20695,
},
{
Latitude: &wrapperspb.DoubleValue{Value: -33.87059},
Longitude: &wrapperspb.DoubleValue{Value: 151.20694},
Latitude: -33.87059,
Longitude: 151.20694,
},
{
Latitude: &wrapperspb.DoubleValue{Value: -33.870740000000005},
Longitude: &wrapperspb.DoubleValue{Value: 151.20694},
Latitude: -33.870740000000005,
Longitude: 151.20694,
},
{
Latitude: &wrapperspb.DoubleValue{Value: -33.87078},
Longitude: &wrapperspb.DoubleValue{Value: 151.20693},
Latitude: -33.87078,
Longitude: 151.20693,
},
},
},
@@ -223,17 +222,17 @@ func TestRoute(t *testing.T) {
}
// check the right info was sent to google maps
if tc.Origin != nil && tc.Origin.Latitude != nil {
assert.Equal(t, fmt.Sprintf("%v", tc.Origin.Latitude.Value), oLat)
if tc.Origin != nil && tc.Origin.Latitude != 0.0 {
assert.Equal(t, fmt.Sprintf("%v", tc.Origin.Latitude), oLat)
}
if tc.Origin != nil && tc.Origin.Longitude != nil {
assert.Equal(t, fmt.Sprintf("%v", tc.Origin.Longitude.Value), oLng)
if tc.Origin != nil && tc.Origin.Longitude != 0.0 {
assert.Equal(t, fmt.Sprintf("%v", tc.Origin.Longitude), oLng)
}
if tc.Destination != nil && tc.Destination.Latitude != nil {
assert.Equal(t, fmt.Sprintf("%v", tc.Destination.Latitude.Value), dLat)
if tc.Destination != nil && tc.Destination.Latitude != 0.0 {
assert.Equal(t, fmt.Sprintf("%v", tc.Destination.Latitude), dLat)
}
if tc.Destination != nil && tc.Destination.Longitude != nil {
assert.Equal(t, fmt.Sprintf("%v", tc.Destination.Longitude.Value), dLng)
if tc.Destination != nil && tc.Destination.Longitude != 0.0 {
assert.Equal(t, fmt.Sprintf("%v", tc.Destination.Longitude), dLng)
}
// check the response is correct
@@ -242,8 +241,8 @@ func TestRoute(t *testing.T) {
}
for i, p := range tc.Result {
w := rsp.Waypoints[i]
assert.Equal(t, p.Latitude.Value, w.Latitude.Value)
assert.Equal(t, p.Longitude.Value, w.Longitude.Value)
assert.Equal(t, p.Latitude, w.Location.Latitude)
assert.Equal(t, p.Longitude, w.Location.Longitude)
}
})
}

77
routing/handler/osrm.go Normal file
View File

@@ -0,0 +1,77 @@
package handler
import (
"context"
"net/url"
"time"
"github.com/gojuno/go.osrm"
"github.com/micro/micro/v3/service/errors"
pb "github.com/micro/services/routing/proto"
"github.com/paulmach/go.geo"
)
type OSRM struct {
// api address
Address string
// osrm client
Client *osrm.OSRM
}
func (o *OSRM) Route(ctx context.Context, req *pb.RouteRequest, rsp *pb.RouteResponse) error {
// validate the request
if req.Origin == nil {
return ErrMissingOrigin
}
if req.Destination == nil {
return ErrMissingDestination
}
if err := validatePoint(req.Origin); err != nil {
return err
}
if err := validatePoint(req.Destination); err != nil {
return err
}
if o.Client == nil {
u, _ := url.Parse(o.Address)
if u.Scheme == "" {
u.Scheme = "http"
}
o.Client = osrm.NewFromURL(u.String())
}
ctx, cancelFn := context.WithTimeout(context.Background(), time.Second)
defer cancelFn()
orig := req.Origin
dest := req.Destination
resp, err := o.Client.Route(ctx, osrm.RouteRequest{
Profile: "car",
Coordinates: osrm.NewGeometryFromPointSet(geo.PointSet{
{orig.Longitude, orig.Latitude},
{dest.Longitude, dest.Latitude},
}),
Steps: osrm.StepsTrue,
Annotations: osrm.AnnotationsTrue,
Overview: osrm.OverviewFalse,
Geometries: osrm.GeometriesPolyline6,
})
if err != nil {
return errors.InternalServerError("routing.route", "failed to get route: %v", err.Error())
}
for _, waypoint := range resp.Waypoints {
rsp.Waypoints = append(rsp.Waypoints, &pb.Waypoint{
Name: waypoint.Name,
Distance: float64(waypoint.Distance),
Location: &pb.Point{
Latitude: waypoint.Location.Lat(),
Longitude: waypoint.Location.Lng(),
},
})
}
return nil
}