автоматическое воспроизведение музыки на C++ в Ubuntu 22.04.5 с ROS2

Вопрос или проблема

Я пишу код ROS, чтобы автоматически воспроизводить музыку в зависимости от ситуации в Ubuntu 22.04. Подробно, цель кода заключается в том, чтобы сообщать о статусе робота через динамик. Робот разработан, чтобы следовать за целью, поэтому, если цель нейтральная, звук не воспроизводится, если цель обнаружена — воспроизводится музыка1, а если цель потеряна — воспроизводится музыка2.


int g_target_detecting_state = 0; // глобальная переменная для хранения статуса

void clusteringNode::timer_callback()
{
   // Определение статуса, код ROS 
}

void followingSoundPlay(void) // (const char* filename)
{
    sf::SoundBuffer go_buffer, stop_buffer;

    if (!go_buffer.loadFromFile("audio/music1.wav") || !stop_buffer.loadFromFile("audio/music2.wav"))
    {
        std::cerr << "загрузка не удалась!";
    }

    sf::Sound go_sound, stop_sound;

    go_sound.setBuffer(go_buffer);
    stop_sound.setBuffer(stop_buffer);

    while(1)
    {
        if(g_target_detecting_state == 0)
        {
            go_sound.stop();
            stop_sound.stop();
        }
        else if(g_target_detecting_state == 1)
        {
            stop_sound.stop();
            go_sound.play();
        }
        else if(g_target_detecting_state == 2)
        {
            go_sound.stop();
            stop_sound.play();
        }

        std::this_thread::sleep_for(std::chrono::milliseconds(1000));
    }
}

int main(int nArgc,const char* pszArgv[])
{
    rclcpp::init(nArgc, pszArgv);

    auto node = std::make_shared<clusteringNode>();

    std::thread ros_thread([&](){
        rclcpp::spin(node);
    });
    std::thread play_thread(followingSoundPlay);

    if(ros_thread.joinable())
        ros_thread.join();
    if(play_thread.joinable())
        play_thread.join();

    rclcpp::shutdown();

    return 0;
}

Это мой код в кратком виде. Если вам нужно больше объяснений, пожалуйста, дайте знать.

Я пробовал crontab -e, чтобы запустить мой код автоматически при загрузке (я слышал, что systemd довольно критичен, так что пока не пробовал). Конечно, я создал скрипт и дал разрешение 755, и crontab -e — это пользовательский crontab.

Я запускал код вручную — он работает с музыкой, и crontab -e также работает, но только часть с музыкой не сработала. Есть ли что-то, что я пропустил? Если вы это найдете, пожалуйста, дайте мне знать.

PS. Спасибо, что прочитали мой вопрос, несмотря на мой плохой английский.

Одно странное — я пробовал на 2 ПК, но один работает, а другой — нет. Есть ли вероятность, что я неправильно установил Ubuntu?

<div class="s-prose js-post-body" itemprop="text">
    <p>Спасибо всем, кто дал совет. Проблема была в переменной DISPLAY cron. Библиотеки, такие как SFML, должны взаимодействовать с GUI дисплеем, но cron не создает его по умолчанию. Поэтому я изменил свой cron на</p>
    <pre><code>

DISPLAY=:0
XDG_RUNTIME_DIR=/run/user/(номер из id -u)
***** /path/of/script

Ответ или решение

Для автоматического воспроизведения музыки на Ubuntu 22.04.5 с использованием ROS2 и языка C++ необходимо учесть несколько важных аспектов, таких как правильное использование библиотек, работа с графическим интерфейсом и конфигурация системы для запуска скрипта при загрузке. В данном ответе мы рассмотрим, как правильно организовать воспроизведение музыки в зависимости от состояния робота, а также прокомментируем проблемы, с которыми вы столкнулись.

1. Код для воспроизведения музыки

Ваш код выглядит в целом корректно, но есть некоторые моменты, на которые стоит обратить внимание. Ваша основная функция для воспроизведения звуков (followingSoundPlay) на основе глобального состояния g_target_detecting_state реализована хорошо, однако стоит хорошенько протестировать загрузку и воспроизведение звуков.

Вот как выглядит ваша функция с небольшими улучшениями. Убедитесь, что файлы music1.wav и music2.wav находятся в указанной директории:

#include <SFML/Audio.hpp>
#include <rclcpp/rclcpp.hpp>
#include <thread>
#include <iostream>
#include <chrono>

int g_target_detecting_state = 0; // Глобальная переменная для хранения состояния

void followingSoundPlay() {
    sf::SoundBuffer music1_buffer, music2_buffer;

    if (!music1_buffer.loadFromFile("audio/music1.wav") || !music2_buffer.loadFromFile("audio/music2.wav")) {
        std::cerr << "Не удалось загрузить аудиофайлы!" << std::endl;
        return; // Выход из функции, если не удалось загрузить
    }

    sf::Sound music1_sound, music2_sound;
    music1_sound.setBuffer(music1_buffer);
    music2_sound.setBuffer(music2_buffer);

    while (true) {
        switch (g_target_detecting_state) {
            case 0: // Цель не обнаружена
                music1_sound.stop();
                music2_sound.stop();
                break;
            case 1: // Цель обнаружена
                music2_sound.stop();
                music1_sound.play();
                break;
            case 2: // Цель потеряна
                music1_sound.stop();
                music2_sound.play();
                break;
        }
        std::this_thread::sleep_for(std::chrono::milliseconds(1000)); // Задержка 1 секунда
    }
}

2. Настройка автоматического запуска

Для автоматического запуска приложения при загрузке вы используете cron. Действительно, при запуске из пользовательского cron могут возникнуть проблемы с доступом к графическому интерфейсу, так как переменные окружения, такие как DISPLAY, не устанавливаются автоматически. Чтобы решить эту проблему, вы уже нашли правильное решение, добавив соответствующие переменные окружения. Вот правильный формат вашего cron-job:

DISPLAY=:0
XDG_RUNTIME_DIR=/run/user/$(id -u)
@reboot /path/to/your/script

Убедитесь, что в path/to/your/script указан абсолютный путь к вашему скрипту, и предоставлены права на выполнение (755). Также убедитесь, что скрипт правильно инициализирует ROS и создает необходимые ноды.

3. Отладка

Если на одном компьютере ваш код работает, а на другом – нет, стоит проверить несколько моментов:

  • Установлены ли все необходимые зависимости? Убедитесь, что на всех компьютерах установлены все необходимые пакеты (включая SFML и ROS2).
  • Права на доступ к аудиоустройству. Убедитесь, что пользователь, под которым запускается cron, имеет права на доступ к аудиоустройствам.
  • Проблемы с окружением. Возможные различия в конфигурации и окружении. Выполните env в терминале и в cron для сопоставления окружения.

Заключение

Следуя вышеуказанным рекомендациям, вы сможете улучшить свой код и настроить его для автоматического запуска. Вопросы с переменными окружения в cron не редкость, но их можно успешно решить с помощью установки соответствующих настроек. Если будут еще вопросы или потребуются дополнительные уточнения, не стесняйтесь их задавать.

Оцените материал
Добавить комментарий

Капча загружается...