You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ROS Nodelet封装TestNode时boost shared_ptr空指针错误求助

问题分析与解决

错误原因

你遇到的断言错误是因为test_nodelet.cpp中的boost::shared_ptr<test::TestNode> node_未初始化,直接调用node_->init()时触发了boost空指针检查。同时你的TestNode采用单例模式设计,和nodelet的实例化逻辑存在冲突,需要调整两者的结合方式。

错误信息

nodelet: /usr/include/boost/smart_ptr/shared_ptr.hpp:734: typename boost::detail::sp_member_access::type boost::shared_ptr::operator->() const [with T = test::TestNode; typename boost::detail::sp_member_access::type = test::TestNode*]: Assertion `px != 0' failed.

修复步骤

1. 调整TestNode的设计,适配nodelet节点句柄

原TestNode使用默认构造的全局节点句柄,nodelet需要使用自身的私有节点句柄来保证命名空间和资源隔离,因此修改TestNode的构造函数和单例方法:

修改后的test.h

#ifndef TEST_NODE_H_
#define TEST_NODE_H_

#include <test/TuningConfig.h>
#include <cv_bridge/cv_bridge.h>
#include <dynamic_reconfigure/server.h>
#include <ros/ros.h>
#include <sensor_msgs/Image.h>
#include <sensor_msgs/RegionOfInterest.h>
#include <sensor_msgs/image_encodings.h>
#include <opencv2/opencv.hpp>

namespace test {
class TestNode {
 public:
  TestNode(ros::NodeHandle& nh, const std::string& cameraName);
  static TestNode& GetInstance(ros::NodeHandle& nh, const std::string& cameraName = "");
  bool init();
  void SetCurrentImage(const cv::Mat& img); // 补充之前缺失的函数

 private:
  ros::NodeHandle nh;
  ros::Subscriber imageSub;
  ros::Publisher imagePub;
  cv::Mat currentImage; // 补充存储图像的成员变量
  void InputImageCallback(const sensor_msgs::Image::ConstPtr& msg);
  const std::string cameraName;
};
}  // namespace test

#endif  // TEST_NODE_H_

修改后的test_node.cpp

#include <test/test_node.h>

namespace test {
TestNode& TestNode::GetInstance(ros::NodeHandle& nh, const std::string& cameraName) {
  static TestNode instance(nh, cameraName);
  return instance;
}

TestNode::TestNode(ros::NodeHandle& nh, const std::string& cameraName)
    : nh(nh), cameraName(cameraName){};

bool TestNode::init() {
  imageSub = nh.subscribe(cameraName + "/image_raw", 10, &TestNode::InputImageCallback, this);
  imagePub = nh.advertise<sensor_msgs::Image>(cameraName + "/final_image", 100);
  return true;
}

void TestNode::InputImageCallback(const sensor_msgs::Image::ConstPtr& msg) {
  cv_bridge::CvImageConstPtr cvPtr = cv_bridge::toCvShare(msg, sensor_msgs::image_encodings::BGR8);
  SetCurrentImage(cvPtr->image);
}

void TestNode::SetCurrentImage(const cv::Mat& img) {
  currentImage = img;
}
}

2. 修复nodelet的初始化逻辑

去掉未初始化的shared_ptr,直接通过单例方法获取TestNode实例,并传入nodelet的私有节点句柄:

修改后的test_nodelet.cpp

#include "test/test_node.h"
#include "nodelet/nodelet.h"
#include "pluginlib/class_list_macros.h"

namespace test {

class TestNodelet : public nodelet::Nodelet {
 public:
  TestNodelet(){};
  ~TestNodelet(){}

  virtual void onInit() {
    ros::NodeHandle& nh = this->getPrivateNodeHandle();

    std::string name = nh.getUnresolvedNamespace();
    int pos = name.find_last_of('/');
    name = name.substr(pos + 1);

    // 获取TestNode单例实例并初始化
    test::TestNode& node = test::TestNode::GetInstance(nh, name);
    if (node.init()) {
      NODELET_INFO_STREAM("Initialised. [" << name << "]");
    } else {
      NODELET_ERROR_STREAM("Couldn't initialise. ["<< name << "]");
    }
  }
};
}  // namespace test

PLUGINLIB_EXPORT_CLASS(test::TestNodelet, nodelet::Nodelet);

关键说明

  • 单例模式下,TestNode的全局实例只会被创建一次,后续调用GetInstance会返回同一个实例,确保资源不重复创建。
  • 使用nodelet提供的getPrivateNodeHandle()保证节点在正确的命名空间下运行,避免和其他节点或nodelet的资源冲突。
  • 补充了原代码中缺失的SetCurrentImage函数和对应的成员变量,修复回调函数中的错误调用。

内容的提问来源于stack exchange,提问作者waka_linux

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 11:24:59