Ticket #660: trac660_r5917.patch

File trac660_r5917.patch, 13.3 KB (added by mvglasow (2), 5 years ago)

Refine criteria for ambiguous maneuvers (fix for Emeryville test case), third try

  • navit/navit/navigation.c

    diff --git a/navit/navit/navigation.c b/navit/navit/navigation.c
    index 713bc4b..7979963 100644
    a b struct navigation_itm { 
    283283        int angle_end;
    284284        struct coord start,end;
    285285        int time;
    286         int length;
     286        int length;                         /**< Length of {@code way} */
    287287        int speed;
    288288        int dest_time;
    289289        int dest_length;
    static int maneuver_category(enum item_type type) 
    11471147       
    11481148}
    11491149
     1150/**
     1151 * @brief Checks whether a way is allowed
     1152 *
     1153 * This function checks whether a given vehicle is permitted to enter a given way by comparing the
     1154 * access and one-way restrictions of the way against the settings in {@code nav->vehicleprofile}.
     1155 * Turn restrictions are not taken into account.
     1156 *
     1157 * @return True if entry is permitted, false otherwise. If {@code nav->vehicleprofile} is null, true is returned.
     1158 */
    11501159static int
    11511160is_way_allowed(struct navigation *nav, struct navigation_way *way, int mode)
    11521161{
    is_motorway_like(struct navigation_way *way) 
    11941203static int
    11951204maneuver_required2(struct navigation *nav, struct navigation_itm *old, struct navigation_itm *new, int *delta, char **reason)
    11961205{
    1197         int ret=0,d,dw,dlim;
     1206        int ret=0,d,dw,dlim,dc;
    11981207        char *r=NULL;
    11991208        struct navigation_way *w;
    1200         int cat,ncat,wcat,maxcat,left=-180,right=180,is_unambigous=0,is_same_street;
    1201         int curve_limit=25;
     1209        int cat,ncat,wcat,maxcat,left=-180,right=180,is_unambiguous=0,is_same_street;
     1210        int curve_limit=25; /* any angle less than this is considered straight */
     1211        int junction_limit = 100; /* maximum distance between two carriageways at a junction */
     1212        int num_similar = 0; /* number of ways in a category similar to current one */
     1213        int num_options = 0; /* number of permitted ways */
     1214        int num_new_motorways = 0; /* number of motorway-like ways */
     1215        int num_other = 0; /* number of ways which are neither motorway-like nor ramps */
    12021216
    12031217        dbg(1,"enter %p %p %p\n",old, new, delta);
    12041218        d=angle_delta(old->angle_end, new->way.angle2);
    maneuver_required2(struct navigation *nav, struct navigation_itm *old, struct na 
    12221236                        r="no: staying in roundabout";
    12231237                }
    12241238        }
     1239        cat=maneuver_category(old->way.item.type);
    12251240        if (!r) {
    1226                 if (new->way.item.type == type_ramp) {
    1227                         /* If new is a ramp, ANNOUNCE */
    1228                         r="yes: entering ramp";
    1229                         ret=1;
    1230                 } else if (is_motorway_like(&(old->way))) {
     1241                /* Analyze all options (including new->way).
     1242                 * Anything that iterates over the whole set of options should be done here. This avoids
     1243                 * looping over the entire set of ways multiple times, which aims to improve performance
     1244                 * and predictability (because the same filter is applied to the ways being analyzed).
     1245                 */
     1246                struct navigation_way *w = &(new->way);
     1247                int through_segments = 0;
     1248                dc=d;
     1249                maxcat=-1;
     1250                /* Check whether the street keeps its name */
     1251                is_same_street=is_same_street2(old->way.name1, old->way.name2, new->way.name1, new->way.name2);
     1252                while (w) {
     1253                        if (is_way_allowed(nav,w,1)) {
     1254                                num_options++;
     1255                                /* ways of similar category */
     1256                                if (maneuver_category(w->item.type) == cat) {
     1257                                        // TODO: decide if a maneuver_category difference of 1 is still similar
     1258                                        num_similar++;
     1259                                }
     1260                                /* motorway-like ways */
     1261                                if (is_motorway_like(w)) {
     1262                                        num_new_motorways++;
     1263                                } else if (w->item.type != type_ramp) {
     1264                                        num_other++;
     1265                                }
     1266                                if (w != &(new->way)) {
     1267                                        dw=angle_delta(old->angle_end, w->angle2);
     1268                                        if (dw < 0) {
     1269                                                if (dw > left)
     1270                                                        left=dw;
     1271                                                if (dw > -curve_limit && d < 0 && d > -curve_limit)
     1272                                                        dc=dw;
     1273                                        } else {
     1274                                                if (dw < right)
     1275                                                        right=dw;
     1276                                                if (dw < curve_limit && d > 0 && d < curve_limit)
     1277                                                        dc=dw;
     1278                                        }
     1279                                        wcat=maneuver_category(w->item.type);
     1280                                        /* If any other street has the same name, we can't use the same name criterion.
     1281                                         * Exceptions apply if we're coming from a motorway-like road and:
     1282                                         * - the other road is motorway-like (a motorway might split up temporarily) or
     1283                                         * - the other road is a ramp (they are sometimes tagged with the name of the motorway)
     1284                                         * The second one is really a workaround for bad tagging practice in OSM. Since entering
     1285                                         * a ramp always creates a maneuver, we don't expect the workaround to have any unwanted
     1286                                         * side effects.
     1287                                         */
     1288                                        if (is_same_street && is_same_street2(old->way.name1, old->way.name2, w->name1, w->name2) && (!is_motorway_like(&(old->way)) || (!is_motorway_like(w) && w->item.type != type_ramp)) && is_way_allowed(nav,w,2))
     1289                                                is_same_street=0;
     1290                                        /* Mark if the street has a higher or the same category */
     1291                                        if (wcat > maxcat)
     1292                                                maxcat=wcat;
     1293                                } /* if w != new->way */
     1294                        } /* if is_way_allowed */
     1295                        //if ((w->flags & AF_ONEWAYMASK) && is_same_street2(new->way.name1, new->way.name2, w->name1, w->name2))
     1296                        if (is_same_street2(new->way.name1, new->way.name2, w->name1, w->name2))
     1297                                // FIXME: for some reason new->way has no flags set (at least in my test case), so we can't test for oneway
     1298                                /* count through_segments (even if they are not allowed) to check if we are at a complex T junction */
     1299                                through_segments++;
     1300                        w = w->next;
     1301                }
     1302                if (num_options <= 1) {
     1303                        if ((abs(d) >= curve_limit) && (through_segments == 2)) {
     1304                                // FIXME: maybe there are cases with more than 2 through_segments...?
     1305                                /* If we have to make a considerable turn (curve_limit or more),
     1306                                 * check whether we are approaching a complex T junction from the "stem"
     1307                                 * (which would need an announcement).
     1308                                 * Complex means that the through road is a dual-carriageway road.
     1309                                 * To find this out, we need to analyze the previous maneuvers.
     1310                                 */
     1311                                int hist_through_segments = 0;
     1312                                int hist_dist = old->length; /* distance between previous and current maneuver */
     1313                                struct navigation_itm *ni = old;
     1314                                while (ni && (hist_through_segments == 0) && (hist_dist <= junction_limit)) {
     1315                                        struct navigation_way *w = ni->way.next;
     1316                                        while (w) {
     1317                                                if ((w->flags & AF_ONEWAYMASK) && (is_same_street2(new->way.name1, new->way.name2, w->name1, w->name2)))
     1318                                                        hist_through_segments++;
     1319                                                w = w->next;
     1320                                        }
     1321                                        ni = ni->prev;
     1322                                        if (ni)
     1323                                                hist_dist += ni->length;
     1324                                }
     1325                                if (hist_through_segments == 2)
     1326                                        // FIXME: see above for number of through_segments
     1327                                        ret=1;
     1328                                        r="yes: turning into dual-carriageway through-road of T junction";
     1329                        }
     1330                        if (!r)
     1331                                r="no: only one option permitted";
     1332                }
     1333        }
     1334        if (!r) {
     1335                if (is_motorway_like(&(old->way)) && (num_other == 0) && (num_new_motorways > 1)) {
    12311336                        /* If we are at a motorway interchange, ANNOUNCE
    12321337                         * We are assuming a motorway interchange when old way and at least
    12331338                         * two possible ways are motorway-like and allowed.
    maneuver_required2(struct navigation *nav, struct navigation_itm *old, struct na 
    12361341                         * at a motorway interchange.
    12371342                         */
    12381343                        // FIXME: motorway junctions could have service roads
    1239                         int num_new_motorways = 0;
    1240                         int num_other = 0;
    1241                         struct navigation_way *cur_itm = &(new->way);
    1242                         while (cur_itm) {
    1243                                 if ((is_motorway_like(cur_itm)) && is_way_allowed(nav,cur_itm,1)) {
    1244                                         num_new_motorways++;
    1245                                 } else if (cur_itm->item.type != type_ramp) {
    1246                                         num_other++;
    1247                                 }
    1248                                 cur_itm = cur_itm->next;
    1249                         }
    1250                         if ((num_other == 0) && (num_new_motorways > 1)) {
    1251                                 r="yes: motorway interchange";
    1252                                 ret=1;
    1253                         }
     1344                        r="yes: motorway interchange";
     1345                        ret=1;
     1346                } else if ((new->way.item.type == type_ramp) && ((num_other == 0) || (abs(d) >= curve_limit))) {
     1347                        /* Motorway ramps can be confusing, therefore announce each maneuver.
     1348                         * We'll assume a motorway ramp when all available ways are either
     1349                         * motorway-like or ramps.
     1350                         * We will also generate a maneuver whenever we have to make a turn
     1351                         * (of curve_limit or more) to enter the ramp.
     1352                         * Going straight on a ramp that crosses non-motorway roads does not
     1353                         * per se create a maneuver. This is to avoid superfluous maneuvers
     1354                         * when the minor road of a complex T junction is a ramp.
     1355                         */
     1356                        r="yes: entering ramp";
     1357                        ret=1;
    12541358                }
    12551359        }
    1256         cat=maneuver_category(old->way.item.type);
    12571360        if (!r && abs(d) > 75) {
    12581361                /* always make an announcement if you have to make a sharp turn */
    12591362                r="yes: delta over 75";
    12601363                ret=1;
    12611364        } else if (!r && abs(d) > 22) {
     1365                //FIXME: use abs(d) >= curve_limit
    12621366                /* When coming from street_2_* or higher category road, check if
    12631367                 * - we have multiple options of the same category and
    12641368                 * - we have to make a considerable turn (more than 22 degrees)
    maneuver_required2(struct navigation *nav, struct navigation_itm *old, struct na 
    12671371                 * closer to 45 than to 0 degrees.
    12681372                 */
    12691373                if (cat >= maneuver_category(type_street_2_city)) {
    1270                         int num_similar = 0;
    1271                         struct navigation_way *cur_itm = &(new->way);
    1272                         while (cur_itm) {
    1273                                 if (maneuver_category(cur_itm->item.type) == cat) {
    1274                                         // TODO: decide if a maneuver_category difference of 1 is still similar
    1275                                         num_similar++;
    1276                                 }
    1277                                 cur_itm = cur_itm->next;
    1278                         }
    12791374                        if (num_similar > 1) {
    12801375                                ret=1;
    12811376                                r="yes: more than one similar road and delta over 22";
    maneuver_required2(struct navigation *nav, struct navigation_itm *old, struct na 
    12841379        }
    12851380        ncat=maneuver_category(new->way.item.type);
    12861381        if (!r) {
    1287                 int dc=d;
    1288                 /* Check whether the street keeps its name */
    1289                 is_same_street=is_same_street2(old->way.name1, old->way.name2, new->way.name1, new->way.name2);
    1290                 w = new->way.next;
    1291                 maxcat=-1;
    1292                 while (w) {
    1293                         dw=angle_delta(old->angle_end, w->angle2);
    1294                         if (dw < 0) {
    1295                                 if (dw > left)
    1296                                         left=dw;
    1297                                 if (dw > -curve_limit && d < 0 && d > -curve_limit)
    1298                                         dc=dw;
    1299                         } else {
    1300                                 if (dw < right)
    1301                                         right=dw;
    1302                                 if (dw < curve_limit && d > 0 && d < curve_limit)
    1303                                         dc=dw;
    1304                         }
    1305                         wcat=maneuver_category(w->item.type);
    1306                         /* If any other street has the same name, we can't use the same name criterion.
    1307                          * Exceptions apply if we're coming from a motorway-like road and:
    1308                          * - the other road is motorway-like (a motorway might split up temporarily) or
    1309                          * - the other road is a ramp (they are sometimes tagged with the name of the motorway)
    1310                          * The second one is really a workaround for bad tagging practice in OSM. Since entering
    1311                          * a ramp always creates a maneuver, we don't expect the workaround to have any unwanted
    1312                          * side effects.
    1313                          */
    1314                         if (is_same_street && is_same_street2(old->way.name1, old->way.name2, w->name1, w->name2) && (!is_motorway_like(&(old->way)) || (!is_motorway_like(w) && w->item.type != type_ramp)) && is_way_allowed(nav,w,2))
    1315                                 is_same_street=0;
    1316                         /* Mark if the street has a higher or the same category */
    1317                         if (wcat > maxcat)
    1318                                 maxcat=wcat;
    1319                         w = w->next;
    1320                 }
    13211382                /* get the delta limit for checking for other streets. It is lower if the street has no other
    13221383                   streets of the same or higher category */
    13231384                if (ncat < cat)
    maneuver_required2(struct navigation *nav, struct navigation_itm *old, struct na 
    13271388                /* if the street is really straight, the others might be closer to straight */
    13281389                if (abs(d) < 20)
    13291390                        dlim/=2;
     1391                /* if both old and new way have a category of 0, or if both ways and at least one other way are
     1392                 * in the same category and no other ways are higher,
     1393                 * dlim is 620/256 (roughly 2.5) times the delta of the maneuver */
    13301394                if ((maxcat == ncat && maxcat == cat) || (ncat == 0 && cat == 0))
    13311395                        dlim=abs(d)*620/256;
     1396                /* if both old, new and highest other category differ by no more than 1,
     1397                 * dlim is just higher than the delta (so another way with a delta of exactly -d will be treated as ambiguous) */
     1398                else if (max(max(cat, ncat), maxcat) - min(min(cat, ncat), maxcat) <= 1)
     1399                        dlim = abs(d) + 1;
     1400                /* if both old and new way are in higher than highest encountered category,
     1401                 * dlim is 128/256 times (i.e. one half) the delta of the maneuver */
    13321402                else if (maxcat < ncat && maxcat < cat)
    13331403                        dlim=abs(d)*128/256;
     1404                /* if no other ways are within +/-dlim, the maneuver is unambiguous */
    13341405                if (left < -dlim && right > dlim)
    1335                         is_unambigous=1;
     1406                        is_unambiguous=1;
    13361407                if (dc != d) {
    13371408                        dbg(1,"d %d vs dc %d\n",d,dc);
    13381409                        d-=(dc+d+1)/2;
    13391410                        dbg(1,"result %d\n",d);
    1340                         is_unambigous=0;
     1411                        is_unambiguous=0;
    13411412                }
    1342                 if (!is_same_street && is_unambigous < 1) {
     1413                if (!is_same_street && is_unambiguous < 1) {
    13431414                        ret=1;
    1344                         r="yes: not same street or ambigous";
     1415                        r="yes: different street and ambiguous";
    13451416                } else
    1346                         r="no: same street and unambigous";
     1417                        r="no: same street or unambiguous";
    13471418#ifdef DEBUG
    1348                 r=g_strdup_printf("yes: d %d left %d right %d dlim=%d cat old:%d new:%d max:%d unambigous=%d same_street=%d", d, left, right, dlim, cat, ncat, maxcat, is_unambigous, is_same_street);
     1419                r=g_strdup_printf("%s: d %d left %d right %d dlim=%d cat old:%d new:%d max:%d unambiguous=%d same_street=%d", ret==1?"yes":"no", d, left, right, dlim, cat, ncat, maxcat, is_unambiguous, is_same_street);
    13491420#endif
    13501421        }
    13511422        *delta=d;
    13521423        if (reason)
    13531424                *reason=r;
     1425        if (r)
     1426                dbg(1, "%s %s -> %s %s: %s\n", old->way.name2, old->way.name1, new->way.name2, new->way.name1, r);
    13541427        return ret;
    13551428       
    13561429
  • navit/navit/util.h

    diff --git a/navit/navit/util.h b/navit/navit/util.h
    index b7b60b5..5beceb7 100644
    a b  
    2323#include <ctype.h>
    2424#include "config.h"
    2525
     26#define max(a,b) ((a) > (b) ? (a) : (b))
     27#define min(a,b) ((a) < (b) ? (a) : (b))
     28
    2629void strtoupper(char *dest, const char *src);
    2730void strtolower(char *dest, const char *src);
    2831int navit_utf8_strcasecmp(const char *s1, const char *s2);