Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve voice instructions #4696

Closed
wants to merge 23 commits into from

Conversation

Trietes
Copy link
Contributor

@Trietes Trietes commented Apr 19, 2024

Issue

Trying to do more work on #4640.

Tasklist

  • Add tests
  • Do some more real-world testing
  • Update the changelog

Requirements / Relations

Also contains the changes made in #4644. So we can either skip #4644 and wait for this one or quickly merge as soon as we know that it works with Maplibre and later on merge this one.

Copy link
Contributor Author

@Trietes Trietes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It just a draft right now. Even if it works fine in my case it should be tested by somebody else to verify if it works in reality on the road.

@@ -12,6 +12,8 @@
#include "midgard/util.h"
#include "odin/enhancedtrippath.h"
#include "odin/util.h"
#include "odin/narrative_builder_factory.h"
#include "odin/narrativebuilder.h"
Copy link
Contributor Author

@Trietes Trietes Apr 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having these here is ofc debatable. We have following problem here: Currently we only build instructions during building the maneuver. But we decide the distance when a maneuver is played in the osrm_serializer and the instructions do depend on the distance (e.g. In 200 meter do XY). So the two options in my mind are:

  • Calculate the distances here and add the 'IN 200 meters' information here. This needs the dependency and that's how I did it.
  • Inject the distance information during maneuver building. So we later on just call here e.g. verbal_transition_alert_instruction() and we also get the distance when to play it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah i think the long term way we should do it is the second way primarily because it is odins main function, deciding where maneuvers are. deciding when to warn about them is very closely related in my opinion.

having said that, you already did all the work and there has been slow progress on this effort in the past so i think it could stay this way until someone has time for a larger refactor. i would wager that others would agree especially because there are other odin deps mixed in here as well (which was already not great and was for the same reason).

as an aside.. maybe we should have had the actor stuff that tyr provides be part of the valhalla namespace exposed in the main valhalla header and then just have odin subsume all the serialization stuff (essentially dividing up tyrs parts and then removing tyr completely). i think it would be reasonably appropriate for odin to generate maneuvers narrative and do serialization. its essentially serializing the path into maneuvers and then serializing maneuvers into narrative. may as well do the final serialization into json or pbf bytes. this of course ignores that there are some endpoints that have no directions or narrative and maybe those would seem strange calling into odin.. meh just some thoughts 😄

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for having a look! I completely agree. The second way feels more correct, but would need some more time. Would also be better so the normal valhalla json answer could be enhanced by the same distance information which might be helpful.

But then let me clean up this one and write some test. I'll also open a cleanup issue for doing it the second way. Maybe I'll have some time in the future to clean it up.

const constexpr double SECONDS_BEFORE_VERBAL_TRANSITION_ALERT_INSTRUCTION = 15.0;
const constexpr double SECONDS_BEFORE_VERBAL_PRE_TRANSITION_INSTRUCTION = 5.0;
const constexpr double SECONDS_BEFORE_VERBAL_TRANSITION_ALERT_INSTRUCTION = 35.0;
const constexpr double SECONDS_BEFORE_VERBAL_PRE_TRANSITION_INSTRUCTION = 10.0;
Copy link
Contributor Author

@Trietes Trietes Apr 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just increased those values. 5 and 15 seconds sound nice in theory but on the road I experienced that this is way too late. Would be cool to get some feedback of somebody else on this

Also 35 seconds is the way better option for alert instructions when enhancing it by the 'IN 200 meters ...' information.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, these are much better values.

I think that longer term (maybe not this PR), these values be tunable at request time. We can set sensible defaults, but different people / use cases may have different preferences.

const constexpr double SECONDS_BEFORE_VERBAL_PRE_TRANSITION_INSTRUCTION = 5.0;
const constexpr double SECONDS_BEFORE_VERBAL_TRANSITION_ALERT_INSTRUCTION = 35.0;
const constexpr double SECONDS_BEFORE_VERBAL_PRE_TRANSITION_INSTRUCTION = 10.0;
const constexpr double MIN_DISTANCE_VERBAL_PRE_TRANSITION_INSTRUCTION = 40;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding a minimum distance for the pre transition alert here. I experienced that on low speed roads we will just announce right before the turn due to the low speed. That also often feels way too late. On such low speed roads its even fine to announce 30 seconds before the transition if you can already can see it.
One thing to take into account here is that a routing graph only reflects (ideally) the center of the road and doesn't represent the width of a road.
I'm not sure if I 100% like this concept, but it helped in my case

const valhalla::Options& options) {
// narrative builder for custom pre alert instructions
MarkupFormatter nullFormatter;
std::unique_ptr<NarrativeBuilder> narrative_builder = NarrativeBuilderFactory::Create(options, etp, nullFormatter);
Copy link
Contributor Author

@Trietes Trietes Apr 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also not 100% happy with this. The functions which we need don't use the markup formatter, so I'm just passing a null formatter.

@@ -1494,65 +1503,94 @@ json::ArrayPtr voice_instructions(const valhalla::DirectionsLeg::Maneuver* prev_
// shortly (10 meters at the given speed) after the maneuver has started.
// The voice_instruction_beginning starts shortly after the beginning of the step.
// The voice_instruction_end starts shortly before the end of the step.
float distance_before_verbal_transition_alert_instruction = -1;
float distance_before_verbal_pre_transition_instruction = -1;
if (prev_maneuver) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just moved this if(prev_maneuver) out of the function. We should always have it.

// TODO: don't add alert instruction if there was already a pre/post transition aleart which is close by
if (!maneuver.verbal_transition_alert_instruction().empty()
&& distance_before_verbal_transition_alert_instruction > -1.0
&& prev_maneuver->time() > SECONDS_BEFORE_VERBAL_TRANSITION_ALERT_INSTRUCTION + APPROXIMATE_VERBAL_PRERANSITION_SECONDS) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is one of the most important changes. We will not have the alert instructions for short maneuvers. Doesn't make sense in my mind to alert something on a 50 meter road. Just play the transition instruction in that case is fine enough. Two instructions on that small maneuver are way too much.
Actually we should even go further and collapse multiple maneuver into a single one if the maneuver itself is too short

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, this is the exact approach I took in a hacked up previous implementation.

voice_instruction_end->emplace("announcement", maneuver.verbal_transition_alert_instruction());
//building voice instructions for the alert
float distance_km = (float) distance_along_geometry / 1000.0f;
std::string instruction = narrative_builder->FormVerbalAlertApproachInstruction(distance_km, maneuver.verbal_transition_alert_instruction());
Copy link
Contributor Author

@Trietes Trietes Apr 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is the part where I'm enhancing the alert instruction by the distance information. This needs the narrative_builder. In english language it will add some prefix like 'In x meters ...'

@@ -1832,29 +1871,28 @@ json::ArrayPtr serialize_legs(const google::protobuf::RepeatedPtrField<valhalla:

// Add banner instructions if the user requested them
if (options.banner_instructions()) {
if (prev_step) {
if (prev_step && prev_maneuver) {
Copy link
Contributor Author

@Trietes Trietes Apr 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just ensuring here that we have the prev_maneuver, since I moved it out of the build voice instruction function. Actually it should always be present

kevinkreiser and others added 15 commits April 19, 2024 09:39
…la#4698)

Co-authored-by: Michael Kirk <michael.code@endoftheworl.de>
Co-authored-by: Christian <58629404+chrstnbwnkl@users.noreply.github.com>
…alhalla#4710)

Co-authored-by: Christian <58629404+chrstnbwnkl@users.noreply.github.com>
Co-authored-by: Christian <58629404+chrstnbwnkl@users.noreply.github.com>
Co-authored-by: Martin Schlossarek <martin.schlossarek@gmail.com>
Copy link
Contributor

@ianthetechie ianthetechie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll need a review from one of the core maintainers to comment on the parts that you flagged as needing a design review, but throwing in my 2 cents, this 1) does appear to work (running it on some servers now after some local testing), and 2) is a significant improvement.

I'd suggest marking this ready for review @Trietes unless you're still waiting on something I missed.

const constexpr double SECONDS_BEFORE_VERBAL_TRANSITION_ALERT_INSTRUCTION = 15.0;
const constexpr double SECONDS_BEFORE_VERBAL_PRE_TRANSITION_INSTRUCTION = 5.0;
const constexpr double SECONDS_BEFORE_VERBAL_TRANSITION_ALERT_INSTRUCTION = 35.0;
const constexpr double SECONDS_BEFORE_VERBAL_PRE_TRANSITION_INSTRUCTION = 10.0;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, these are much better values.

I think that longer term (maybe not this PR), these values be tunable at request time. We can set sensible defaults, but different people / use cases may have different preferences.

// TODO: don't add alert instruction if there was already a pre/post transition aleart which is close by
if (!maneuver.verbal_transition_alert_instruction().empty()
&& distance_before_verbal_transition_alert_instruction > -1.0
&& prev_maneuver->time() > SECONDS_BEFORE_VERBAL_TRANSITION_ALERT_INSTRUCTION + APPROXIMATE_VERBAL_PRERANSITION_SECONDS) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, this is the exact approach I took in a hacked up previous implementation.

@Trietes
Copy link
Contributor Author

Trietes commented May 16, 2024

Thanks for checking it out and giving it a test. I've been waiting for somebody to test it out and saying it is at least better than before :D
I'm only concerned of including the narrative builder here. Works fine, but I don't know if it is good practice. If the maintainers are fine with it, I can add some tests and make the PR ready.

…uncements (valhalla#4644)

Co-authored-by: Christian <58629404+chrstnbwnkl@users.noreply.github.com>
@Trietes
Copy link
Contributor Author

Trietes commented Jun 9, 2024

Seems like GitHub doesn't like my rebase. I'm just done with adapting the tests and cleaning the stuff up. I'll open a clean new pull request now

@Trietes Trietes closed this Jun 9, 2024
@Trietes Trietes mentioned this pull request Jun 9, 2024
3 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

10 participants