Search code examples
c++boostshared-ptrros

error is boost shared_ptr and class inheritance


I am following this tutorial and writing a ROS nodelet wrapper class for my existing ROS node. But I am getting the following error when I am running the test_nodelet.cpp where every time I am trying to access the base class. How should I be initializing TestNode? Can someone point me in the right direction please -

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.

Following is my header file 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(const std::string& cameraName);
  static TestNode& GetInstance(const std::string& cameraName = "");
  bool init();

 private:
  ros::NodeHandle nh;
  ros::Subscriber imageSub;
  ros::Publisher imagePub;
  void InputImageCallback(const sensor_msgs::Image::ConstPtr& msg);
  const std::string cameraName;
};
}  // namespace test

#endif  // TEST_NODE_H_

My ROS node looks like the following test_node.cpp:

#include <test/test_node.h>

namespace test {
TestNode& TestNode::GetInstance(const std::string& cameraName) {
  static TestNode instance(cameraName);

  return instance;
}

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

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);
  TestNode::GetInstance().SetCurrentImage(cvPtr->image);
  }
 }

Now I am trying to wrap the test class in a nodelet class in the following way (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);

    if (node_->init()) {
      NODELET_INFO_STREAM("Initialised. [" << name << "]");
    } else {
      NODELET_ERROR_STREAM("Couldn't initialise. ["<< name << "]");
    }
  }

 private:
  boost::shared_ptr<test::TestNode> node_;
};
}  // namespace test

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

Solution

  • I suggest that the problem with the code seems to be that the node_ member variable in the TestNodelet class is not being initialized before being accessed in the onInit() function. You need to instantiate an instance of TestNode and assign it to node_. Add node_ = boost::make_shared<test::TestNode>(name); after name = name.substr(pos + 1);