Delivery optimization service creates multiple visits to identical pickup address

I’m working with a delivery optimization service for my logistics company. The system handles collections from vendors and drop-offs to customers, plus some return shipments going back from customers to vendors.

The main problem is that the optimizer schedules multiple trips to the same vendor location to collect some items during the first visit and remaining items later. This happens even when there are no return packages for that vendor. Our parcels are tiny and lightweight, so vehicle capacity is never a concern. We can easily collect everything in one stop.

These extra trips to vendors waste time because they require detours off the main route and cost extra fuel. I can’t figure out how to configure the service to visit each pickup location only once.

I think the system assumes we have space limitations, but that’s not our situation. We also only have one delivery driver handling everything right now, not multiple teams that could split the work.

Here’s my current implementation:

var optimizationModel = new ShipmentModel();
var deliveryTruck = new Vehicle()
{
    StartWaypoint = new Waypoint()
    {
        Location = new Location()
        {
            LatLng = new LatLng()
            {
                Latitude = driver.StartLat.Value,
                Longitude = driver.StartLng.Value
            }
        },
    },
    EndWaypoint = new Waypoint()
    {
        Location = new Location()
        {
            LatLng = new LatLng()
            {
                Latitude = driver.EndLat.Value,
                Longitude = driver.EndLng.Value
            }
        },
    },
    RouteModifiers = new RouteModifiers()
    {
        AvoidTolls = true,
    },
    CostPerKilometer = 1.2,
    CostPerHour = 25,
    FixedCost = 3,
    CostPerTraveledHour = 2.8
};

optimizationModel.Vehicles.Add(deliveryTruck);

foreach (var order in OrderList)
{
    foreach (var item in order.Items)
    {
        Shipment transport = new Shipment();
        transport.Label = item.ItemId.ToString();

        transport.Pickups.Add(new Shipment.Types.VisitRequest()
        {
            ArrivalLocation = new LatLng()
            {
                Latitude = item.OriginPoint.Lat.Value,
                Longitude = item.OriginPoint.Lng.Value
            }
        });

        transport.Deliveries.Add(new Shipment.Types.VisitRequest()
        {
            ArrivalLocation = new LatLng()
            {
                Latitude = item.DestinationPoint.Lat.Value,
                Longitude = item.DestinationPoint.Lng.Value
            }
        });
        
        optimizationModel.Shipments.Add(transport);
    }
}

var optimizationRequest = new OptimizeToursRequest()
{
    Parent = "projects/my-project",
    PopulatePolylines = true,
    PopulateTransitionPolylines = true,
    Model = optimizationModel,
    SearchMode = OptimizeToursRequest.Types.SearchMode.ConsumeAllAvailableTime,
    Timeout = new Google.Protobuf.WellKnownTypes.Duration()
    {
        Seconds = 8
    }
};

var optimizationClient = RouteOptimizationClient.Create();
var apiResponse = optimizationClient.OptimizeTours(optimizationRequest);

Any suggestions on how to prevent duplicate visits to the same pickup location?

I hit the same problem with delivery routing for my e-commerce site. Your loop creates separate shipment objects for each item, so the optimizer treats them as independent tasks - that’s why you’re getting multiple visits to the same address. Here’s what fixed it for me: preprocess your data first. I built a dictionary that groups items by pickup coordinates, then created one shipment per pickup location with all the delivery requests bundled together. The optimizer now sees one pickup task with multiple deliveries instead of separate jobs. Also worth trying - add explicit constraints to your vehicle config. Even if capacity isn’t an issue, the optimizer often works better with clear parameters rather than assuming unlimited resources.

Found your problem - you’re creating separate shipments for each item instead of grouping them by pickup location. The optimizer sees each shipment as its own task, so it’s scheduling multiple trips to the same vendor. I hit this same issue when setting up route optimization for our distribution network. Here’s the fix: group your items by pickup location first, then create one shipment per vendor with multiple delivery points. Don’t loop through items individually - collect everything from the same vendor location into a single shipment object. This way the optimizer knows to grab all items from one vendor in a single visit. The API docs don’t explain this well, but that’s how most optimization engines handle pickup consolidation. Also, set explicit vehicle capacity constraints even if they’re generous. The optimizer often makes better consolidation choices when it has defined parameters instead of assuming unlimited capacity.

Your problem is creating separate shipments for each item. The optimizer thinks they’re different locations, so it schedules multiple visits.

Group all items from the same vendor into one shipment with multiple deliveries. This way the optimizer collects everything from that vendor in one trip.

But honestly? These optimization APIs are a pain. I’ve dealt with the same routing headaches, and switching to automation saved my sanity.

I built a workflow that handles all my delivery data automatically - groups pickups by location, handles optimization logic, runs on autopilot. No more wrestling with API configs.

It pulls orders, clusters items by pickup spot, creates optimized routes, and handles exceptions like capacity limits or time windows. No more debugging weird optimizer decisions.

Saved me weeks of dev time and killed these routing issues completely. Way cleaner than configuring every edge case in the API.

Everyone’s right about the item grouping issue - that’s your main problem. But there’s something else that’ll bite you later.

That SearchMode.ConsumeAllAvailableTime setting? It’s working against you. I’ve seen this with delivery fleets where the optimizer creates terrible routes just to fill time windows.

Switch to ReturnToStart or ConsumeAllAvailableTimeOrReturnToStart. The optimizer makes way better consolidation choices when it’s not trying to burn through every available hour.

That 8-second timeout is crazy aggressive for route optimization. Bump it to 30+ seconds. I’ve seen weird routing decisions that were obviously the algorithm giving up too early.

For the grouping fix - add a small radius buffer (50-100 meters) when clustering pickup locations instead of exact coordinate matching. GPS isn’t perfect, and you’ll miss obvious groups when coordinates are slightly off.

I’ve seen the same warehouse show up as multiple locations because of tiny coordinate differences way too many times.