ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question
0

Compilation errors when trying to link custom class

asked 2018-03-07 13:20:34 -0600

rayvburn gravatar image

updated 2018-03-07 16:04:18 -0600

Hello everyone, I've started messing with ROS not long ago so forgive me if my question is silly.

I'm facing problems when trying to link custom class to node. The class is for measuring distance with ultrasonic sensor. I'm using external library for Raspberry Pi - wiringPi (already managed to get it working properly). WiringPi's functions are utilised in the Sonar class. Eclipse doesn't throw any errors when rebuilding project but I get errors when trying to catkin build so I guess it's something with CMakeLists.txt. After reading similar posts thought the solution will be simply in add_library() and target_link_libraries() but still get error described below.

catkin build error:

/home/rayvburn/catkin_ws/devel/.private/beginner_tutorials/lib/libsonar_lib.so: undefined reference to `Sonar::echoPin'
/home/rayvburn/catkin_ws/devel/.private/beginner_tutorials/lib/libsonar_lib.so: undefined reference to `Sonar::maxDistance'
/home/rayvburn/catkin_ws/devel/.private/beginner_tutorials/lib/libsonar_lib.so: undefined reference to `Sonar::trigPin'
collect2: error: ld returned 1 exit status
make[2]: *** [/home/rayvburn/catkin_ws/devel/.private/beginner_tutorials/lib/beginner_tutorials/measurer] Error 1
make[1]: *** [CMakeFiles/measurer.dir/all] Error 2
make: *** [all] Error 2

CMakeLists.txt

cmake_minimum_required(VERSION 2.8.3)
project(beginner_tutorials)

FIND_LIBRARY(WIRINGPI_LIBRARY wiringPi /home/rayvburn/git/wiringPi)

find_package(catkin REQUIRED COMPONENTS
  roscpp
  rospy
  std_msgs
)

catkin_package(
#  INCLUDE_DIRS include
#  LIBRARIES beginner_tutorials
#  CATKIN_DEPENDS roscpp rospy std_msgs
#  DEPENDS system_lib
)

include_directories(
  ${catkin_INCLUDE_DIRS}
  include
  src
)

add_library(sonar_lib 
 src/Sonar.h
 src/Sonar.cpp
)

add_executable(talker src/talker.cpp)
target_link_libraries(talker ${catkin_LIBRARIES} ${WIRINGPI_LIBRARY})
add_dependencies(talker ${WIRINGPI_LIBRARY})

add_executable(listener src/listener.cpp)
target_link_libraries(listener ${catkin_LIBRARIES} ${WIRINGPI_LIBRARY})
add_dependencies(listener ${WIRINGPI_LIBRARY})

add_executable(measurer src/measurer.cpp)
target_link_libraries(measurer 
    sonar_lib
    ${catkin_LIBRARIES} 
    ${WIRINGPI_LIBRARY}
)
add_dependencies(measurer ${WIRINGPI_LIBRARY})

As can be seen above I’ve been messing with

  • include_directories(),

  • add_library(),

  • target_link_libraries()

but with no luck. Please note that echoPin, maxDistance, trigPin are private elements of class declared in header file (the one I seem to include in CMakeLists). Do I really need to include .h file separately? Sonar.cpp and Sonar.h are placed in /src directory along with talker.cpp, listener.cpp and measurer.cpp. Objects of Sonar class are used only in the measurer node. I'm using Ubuntu 16.04 with ROS Kinetic, compiling project on my laptop for later use with Raspberry Pi (also Ubuntu 16.04 and ROS Kinetic). Thanks in advance!

EDIT:

Sonar.h

#ifndef SRC_SONAR_H_
#define SRC_SONAR_H_
#include <stdint.h>

class Sonar {
 public:
  Sonar(uint8_t trigPin, uint8_t echoPin, uint8_t maxDistance);
  uint8_t getDistance();
  virtual ~Sonar();
 private:
  static int trigPin;
  static int echoPin;
  static uint8_t maxDistance;
};

#endif

Sonar.cpp

#include "Sonar.h"
#include <wiringPi.h>

Sonar::Sonar(uint8_t trigPin, uint8_t echoPin, uint8_t maxDist) {
  Sonar::maxDistance = maxDist;
  Sonar::trigPin = trigPin;
  Sonar::echoPin = echoPin;
  pinMode(Sonar::trigPin, OUTPUT);
  pinMode(Sonar::echoPin, INPUT);
}
uint8_t Sonar::getDistance() {

  uint32_t startTime;
  uint32_t time;
  uint8_t distance;

  digitalWrite(Sonar::trigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(Sonar::trigPin, HIGH);
  delayMicroseconds(12);
  digitalWrite(Sonar::trigPin, LOW);

  startTime = micros();
  while ( digitalRead(Sonar::echoPin) == 0 ) {    // wait until rising edge
    if ( micros() - startTime > 1000000L ) {      // 1 sec timeout
      break;
    }
  }

  startTime = micros();
  while ( digitalRead(Sonar::echoPin) == 1 ...
(more)
edit retag flag offensive close merge delete

Comments

This linker error is telling you that something in sonar_lib is calling Sonar::echoPin and the other functions listed, but that there is no implementation for those functions. In order to help debug further it would be good to see the contents of Sonar.h and Sonar.cpp

ahendrix gravatar image ahendrix  ( 2018-03-07 14:43:38 -0600 )edit

In general it looks like your build rules are OK, and that this is a problem with your code.

ahendrix gravatar image ahendrix  ( 2018-03-07 14:44:00 -0600 )edit

Thanks for having a look, I updated the post with class files.

rayvburn gravatar image rayvburn  ( 2018-03-07 16:06:26 -0600 )edit

1 Answer

Sort by » oldest newest most voted
0

answered 2018-03-07 16:57:33 -0600

rayvburn gravatar image

Seems like removing static keyword from private class members solved the problem, now compiles without errors. @ahendrix thank you for pointing me the right path.

edit flag offensive delete link more

Comments

That makes sense. static variables in C++ are similar to globals (there is only one copy in your entire program), and like a global you need to declare them in your cpp file to actually allocate storage for them. Removing the static keyword is definitely the right thing to do here.

ahendrix gravatar image ahendrix  ( 2018-03-07 22:57:24 -0600 )edit

Question Tools

2 followers

Stats

Asked: 2018-03-07 13:20:00 -0600

Seen: 766 times

Last updated: Mar 07 '18