GoPi5Go-Dave Has Something To Say!

Repurposing the ROS 2 “Say Node” from Create3-Wali, GoPi5Go-Dave now has a voice:

pi@GoPi5Go:DOCKER:~/GoPi5Go/ros2ws $  ros2 run gopi5go_dave say_node &

which offers a /say service to speak the content of the SayStr message:

ros2 service call /say dave_interfaces/srv/Say "Hello from Go Pi Five Go Dave using Piper TTS arctic-medium voice"

requester: making request: dave_interfaces.srv.Say_Request(saystring='Hello from Go Pi Five Go Dave using Piper TTS arctic-medium voice')

[INFO] [1716495377.975366780] [say]: Say request:"Hello from Go Pi Five Go Dave using Piper TTS arctic-medium voice"
response:
dave_interfaces.srv.Say_Response(spoken=True)

and indeed the say_node logs anything spoken (or asked to be spoken during “Quiet Time”):

2024-05-23 05:57|Battery at 10.0 volts.  Docking now. - quiet time
2024-05-23 05:57|Docking success after 3.4 hours playtime - quiet time
2024-05-23 05:57|Reset Encoders To Zero - quiet time
2024-05-23 08:16|Full Charge.  Undocking now. - quiet time
...
2024-05-23 16:16|Hello from Go Pi Five Go Dave using Piper TTS arctic-medium voice - spoken: True

A current problem Dave is facing: Volume can only be set from outside the Docker container. Takes human assistance when he wants to shout!

2 Likes

And a clear one at that.
Very cool - congrats on the progress.
/K

2 Likes

Thanks - yes the piper-tts voices are created from real humans - hundreds of “voice talents” in almost any language desired, male and female, young and adult which makes them more understandable than the default espeak-ng Text-To-Speech engine for the GoPiGo3 robots.

As with everything I attempt to integrate, there are issues to be solved. In this case, I don’t know how to stream from piper-tts, so I have to write the audio to file, then play it back. It works but there is a delay equal to the time it takes to generate the audio for the entire phrase before Dave can be heard speaking.

At some point in the future, I’ll have to tackle that one.

2 Likes

Wow, months since Dave learned to speak with Piper-TTS, and I have a confession: Dave has still been using espeak-ng all this time.

I just integrated Piper-TTS so that every program that uses speak.py will use Piper-TTS. Dave can speak, shout, and whisper with Piper-TTS. (A terrible mashup of Python launching CLI commands to set the volume, run a bash script that streams the output from Piper-TTS to aplay, but Dave can do it.)

2 Likes

Cool beanies!

Though it was hard to hear (on my telephone) unless the volume was turned way up.

Sounds better than
“that. . . . voice. . . . used. . . . by. . . . e. . . speaking. . .”
(sound bite: an announcement in Penn Station, Manhattan. “Garble, garble, muffle, garble”)
Translation:  You just missed your train and the next one isn’t for another 12 hours!

It sounds like it might be worth putting on my list of things to try.  Eventually.

Any chance of a voice that isn’t from jolly-old England?

2 Likes

Sure - How about a “non-jolly” Russian Irina?

But if you insist on English try Norman

(There are over 100 different en_US voices to choose from. Some of them sound like Indian, some British, some Scot, and some American.)

2 Likes

Very cool! Dave just keeps getting more talented.
/K

2 Likes

GoPi5Go-Dave loses his voice…

Didn’t test enough. My ROS 2 say_node works once or twice and then explodes in PiperTTS:

  File "/home/pi/GoPi5Go/ros2ws/build/gopi5go_dave/gopi5go_dave/say_node.py", line 85, in say_cb
    audio = voice.synthesize(text,wav_file)
  File "/usr/local/lib/python3.10/dist-packages/piper/voice.py", line 95, in synthesize
    for audio_bytes in self.synthesize_stream_raw(
  File "/usr/local/lib/python3.10/dist-packages/piper/voice.py", line 123, in synthesize_stream_raw
    yield self.synthesize_ids_to_raw(
  File "/usr/local/lib/python3.10/dist-packages/piper/voice.py", line 166, in synthesize_ids_to_raw
    audio = self.session.run(
  File "/usr/local/lib/python3.10/dist-packages/onnxruntime/capi/onnxruntime_inference_collection.py", line 220, in run
    return self._sess.run(output_names, input_feed, run_options)
onnxruntime.capi.onnxruntime_pybind11_state.RuntimeException: [ONNXRuntimeError] : 6 : RUNTIME_EXCEPTION : Non-zero status code returned while running GatherElements node. Name:'/dp/flows.7/GatherElements_3' Status Message: /onnxruntime_src/onnxruntime/core/providers/cpu/tensor/gather_elements.cc:154 void onnxruntime::core_impl(const Tensor*, const Tensor*, Tensor*, int64_t, concurrency::ThreadPool*) [with Tin = long int; int64_t = long int] GatherElements op: Out of range value in index tensor

[ros2run]: Process exited with failure 1

Just another simple without ROS, not simple with ROS.

Saw a guy asking a question on the ROS subreddit this morning, and told:

There is nothing, ABSOLUTELY NOTHING, solvable in ROS in “literally 5 minutes”. Excuuuussssseeee Meeee, I seem to have wandered into the big heads community.

1 Like

 

And this is my answer to that person’s comment:
 

:man_facepalming:
:rofl:

1 Like