【问题标题】:Why won't Gazebo start ROS?为什么 Gazebo 不启动 ROS?
【发布时间】:2016-07-13 18:34:57
【问题描述】:

我正在通过 Gazebo 教程将 Gazebo 传感器连接到 ROS 并传递消息。 http://gazebosim.org/tutorials?cat=guided_i&tut=guided_i6

该程序构建一个 Gazebo ModelPlugin 对象,并从该对象中初始化 ROS。然后,它创建一个 ROS 节点、订阅者、队列和一个标准线程来运行 ROS 队列。该程序使用 Gazebo 的传输对象工作,但是当我尝试添加 ROS 传输对象(如前所述)时,该程序不起作用。我的问题源于 roscore 节点(包括 rosmaster)没有初始化。

我的传感器插件代码如下。 ROS 集成从第 70 行开始:

#ifndef _VELODYNE_PLUGIN_HH_
#define _VELODYNE_PLUGIN_HH_

#include <gazebo/gazebo.hh>
#include <gazebo/msgs/msgs.hh>
#include <gazebo/physics/physics.hh>
#include <gazebo/transport/transport.hh>
#include <ros/ros.h>
#include <ros/callback_queue.h>
#include <ros/subscribe_options.h>
#include <thread>
#include <std_msgs/Float32.h>

namespace gazebo
{
  /// \brief A plugin to control a Velodyne sensor.
  class VelodynePlugin : public ModelPlugin
  {
    /// \brief Constructor
    public: VelodynePlugin() {}

    /// \brief The load function is called by Gazebo when the plugin is
    /// inserted into simulation
    /// \param[in] _model A pointer to the model that this plugin is
    /// attached to.
    /// \param[in] _sdf A pointer to the plugin's SDF element.
    public: virtual void Load(physics::ModelPtr _model, sdf::ElementPtr _sdf) {
            gzwarn << "HERE";
      if (_model->GetJointCount() == 0) {
        std::cerr <<
          "Invalid joint count, Velodyne plugin not loaded\n";
      }

      // Store the model pointer for convenience.
      this->model = _model;

      // Get the first joint. We are making an assumption about the
      // model having one joint that is the rotational joint.
      this->joint = _model->GetJoints()[0];

      // Setup a P-controller with a gain of 0.1.
      this->pid=common::PID(0.1,0,0);

      // Apply the P-controller to the joint.
      this->model->GetJointController()->SetVelocityPID(
          this->joint->GetScopedName(), this->pid);

      // Default to zero velocity
      double velocity=0;

      // Check that the velocity element exists, then read the value
      if (_sdf->HasElement("velocity"))
        velocity=_sdf->Get<double>("velocity");

      this->SetVelocity(velocity);

      // Create the node
      this->node = transport::NodePtr(new transport::Node());
      this->node->Init(this->model->GetWorld()->GetName());

      // Create a topic name
      std::string topicName = "~/" + this->model->GetName() +
        "/vel_cmd";

      // Subscribe to the topic, and register a callback.
      this->sub = this->node->Subscribe(topicName,
          &VelodynePlugin::OnMsg, this);

            // Initialize ros, if it has not already been initialized.
            if (!ros::isInitialized()) {
                std::cout << "initializing ros" << std::endl;
                int argc = 0;
                char **argv=NULL;
                ros::init(argc,argv,"gazebo_client",
                    ros::init_options::NoSigintHandler);
            } else { std::cout << "NOT initializing ros" << std::endl; }

            // Create our ROS node. This acts in a similar manner to the
            // Gazebo node.
            this->rosNode.reset(new ros::NodeHandle("gazebo_client"));

      // Create a named topic, and subscribe to it.
      ros::SubscribeOptions so =
        ros::SubscribeOptions::create<std_msgs::Float32>(
            "/"+this->model->GetName()+"/vel_cmd",
            1,
            boost::bind(&VelodynePlugin::OnRosMsg, this, _1),
            ros::VoidPtr(), &this->rosQueue);

      this->rosSub = this->rosNode->subscribe(so);

      // Spin up the queue helper thread
      this->rosQueueThread = 
        std::thread(std::bind(&VelodynePlugin::QueueThread,this));
    }

    /// \brief Set the velocity of the Velodyne
    /// \param[in] _vel New target velocity
    public: void SetVelocity(const double &_vel) {
      // Set the joint's target velocity.
      this->model->GetJointController()->SetVelocityTarget(
          this->joint->GetScopedName(), _vel);
    }

    /// \brief Handle incoming message
    /// \param[in] _msg Repurpose a vector3 message. This function will
    /// only use the x component.
    private: void OnMsg(ConstVector3dPtr &_msg) {
      this->SetVelocity(_msg->x());
    }

    /// \brief Handle an incoming message from ROS
    /// \param[in] _msg A float value that is used to set the velocity
    /// of the Velodyne.
    public: void OnRosMsg(const std_msgs::Float32ConstPtr &_msg) {
      this->SetVelocity(_msg->data);
    }

    /// \brief ROS helper function that processes messages
    private: void QueueThread() {
      static const double timeout = .01;
      while (this->rosNode->ok()) {
        this->rosQueue.callAvailable(ros::WallDuration(timeout));
      }
    }


    /// \brief Pointer to the model;
    private: physics::ModelPtr model;

    /// \brief Control surfaces joints.
    private: physics::JointPtr joint;

    /// \brief Velocity PID for the propeller.
    private: common::PID pid;

    /// \brief A node used for transport
    private: transport::NodePtr node;

    /// \brief A subscriber to a named topic.
    private: transport::SubscriberPtr sub;

    /// \brief A node used for ROS transport
    private: std::unique_ptr<ros::NodeHandle> rosNode;

    /// \brief A ROS subscriber
    private: ros::Subscriber rosSub;

    /// \brief A ROS callbackqueue that helps process messages
    private: ros::CallbackQueue rosQueue;

    /// \brief A thread that keeps running the rosQueue
    private: std::thread rosQueueThread;

  };

  // Tell Gazebo about this plugin, so that Gazebo can call Load on this plugin.
  GZ_REGISTER_MODEL_PLUGIN(VelodynePlugin)
}
#endif

请告诉我如何才能更具体地回答这个问题。第一个问题肯定是ROS没有初始化。我可以告诉这一点,因为在不同的终端调用rostopic list 输出:

ERROR: Unable to communicate with master

【问题讨论】:

  • “程序不工作”到底是什么意思?您是否收到任何错误消息或订阅者从未收到任何消息?在后一种情况下,您是否通过rostopic echo /topic_name 验证消息确实已发布?
  • 啊,还有一个问题:你究竟是如何启动凉亭的?它是从终端运行的吗?
  • 我从 bash 终端使用 'gazebo ~/.gazebo/worlds/velodyne.world' 启动凉亭,这是我的世界包含我打算与 ros 通信的对象的位置。跨度>
  • “程序不工作”是指rosmaster/roscore 没有初始化/启动。当我尝试运行“rostopic list”时,我收到输出:“错误:无法与主服务器通信”

标签: c++ simulation ros


【解决方案1】:

在我看来,roscore 没有运行。在启动任何 ROS 节点之前,您必须手动运行 roscore

您可以将roscore 想象成一个服务器,所有节点都连接到它并管理这些节点之间的通信。它不会自动启动,因此您必须首先启动roscore,然后才能使用任何 ROS 节点。

如果您使用的是启动文件,则例外。 roslaunch 确实会自动启动 roscore 如果它还没有运行。

【讨论】:

  • 这是一个有趣的观点。我曾假设 ros::init() 会启动 roscore。我实际上尝试过手动启动 roscore,以便可以与 rosmaster 通信。在单独的终端中,“rostopic list”仅显示 /rosout 和 /rosout_agg 作为可用主题。调用“rostopic pub /{my_topic} /{my_msg_type}”会输出“发布和锁定消息。”这让我相信这个过程正在挂起。总之,我认为启动 roscore 不是问题。我会继续研究。谢谢!让我知道你的想法!
  • @errolflynn:我现在无法验证它(没有安装 ROS),但我认为您从 rostopic pub 收到的消息是可以的(所以它按预期工作)。
  • 这条消息很好,但是它应该发布一条消息,然后转换为发送到我的 ROS 兼容对象的命令。当我使用“rostopic pub”发布此消息时,未收到已发布的消息或未对 ROS 兼容对象执行任何操作。
  • @errolflynn 当你在一个终端运行rostopic echo /topic_name,然后在另一个终端用rostopic pub 发布消息时,回显命令会收到消息吗?
  • 是的,echo 命令接收数据。调用“rostopic list”会显示我正在发布的命令。
【解决方案2】:

在启动 Gazebo 服务器之前运行roscore 可以解决问题。我必须接受本教程确实遵循 Gazebo-first 管道。尽管如此,我相信在 ROS 和 Gazebo 之间架起桥梁是一种不推荐使用的方法。您应该检查gazebo-ros-pkgs 中的代码以获得更简单的方法。

Gazebo 插件是一个运行时组件 - 技术术语中的共享库 - 它附加到特定对象或通过 SDF/URDF 文件直接附加到 World 实例。可以通过命令gzserver &lt;world_file&gt; 模拟世界实例。如果您将 Gazebo 与 ROS 结合使用(如果您打算在某个时候使用 ROS,我强烈建议您这样做),您需要的是 gazebo-ros 节点。同样在上面的链接中,有几个例子说明了它是如何完成的。

在 ROS Universe 中,所有进程都表示为 ROS 节点,Gazebo 模拟器也不例外。当您使用gazebo_ros 包(使ROS-Gazebo 连接在一行中)时,Gazebo 模拟器被初始化为具有指定世界文件的/gazebo 节点,并且所有附加的Gazebo 插件都作为该节点内的组件运行。第一个问题在这里。你不应该在 Gazebo 插件中调用 ros::init(),因为它已经有一个初始化的节点。第二个问题在于您的假设,例如 ros::init() 调用不会启动 roscore 节点。它仅以可以与同一主控器下的其他 ROS 节点通信的方式初始化您的可执行文件。所以,你只需要一个ros::NodeHandle

我不知道为什么 OSRF 没有更新教程。也许,他们严格地试图在 Gazebo 网站中提供 Gazebo 优先方面,并将 ROS 视为次要组件。但是我发现它相当有问题,尤其是当人们想使用 ROS 作为主要组件时。由于roslaunch只启动ROS节点,导致gzserver &lt;world_file&gt;命令失效,本教程无效,甚至与主流用法相矛盾。

【讨论】:

    【解决方案3】:

    据我了解,Gazebo 不是 ROS 的一部分,所以如果它不启动 roscore 是有道理的。

    如果您想在该节点启动的同时启动roscore,请尝试使用roslaunch 命令而不是rosrun。

    【讨论】:

      【解决方案4】:

      问题确实是roscore,但之后您可以检查以rosnode info nodename 开头的节点以检查子和发布者状态,或者执行roswtf 以检查一般错误。

      您可以使用 rqt 记录器级别(最简单的方法)检查​​实时调试日志设置 ros 调试级别,以了解您的节点是否正在获取数据

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-06-13
        • 1970-01-01
        • 2017-10-10
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多