Error: undefined reference to `main'

I was following the instructions in UNIT 4 for Cartesian paths [Ex 4.1]

Starting >>> moveit2_scripts
--- stderr: moveit2_scripts
/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/Scrt1.o: in function `_start':
(.text+0x1b): undefined reference to `main'
collect2: error: ld returned 1 exit status
gmake[2]: *** [CMakeFiles/test_trajectory.dir/build.make:351: test_trajectory] Error 1
gmake[1]: *** [CMakeFiles/Makefile2:143: CMakeFiles/test_trajectory.dir/all] Error 2
gmake: *** [Makefile:146: all] Error 2
---
Failed   <<< moveit2_scripts [22.4s, exited with code 2]

Summary: 0 packages finished [24.6s]
  1 package failed: moveit2_scripts
  1 package had stderr output: moveit2_scripts

I have even copy pasted the the source code from the instructions but the problem still remains.

@neilthomas110
Let’s take this step by step.

First thing, this error message is from the C++ compiler, indicating that the main function is missing from the C++ source code. It is usually helpful to try to understand the error message. Is this error coming from your source code or ours?

Second, it appears you are trying to solve an exercise. To help us to help you, you should include some information about what the exercise entails, and what you did (the package(s) and source code). Also, which specific source code did you copy-paste?

Finally, after making corrections to the source code, you need to clear the build and install folders for the change to reflect. This is especially true for C+±based packages.

cd ~/ros2_ws
rm -rf build/ install/ log/
colcon build

Please review the steps above and provide more context.

Below is the source code “cartesian_path.cpp”

#include <moveit/move_group_interface/move_group_interface.h>
#include <moveit/planning_scene_interface/planning_scene_interface.h>

#include <moveit_msgs/msg/display_robot_state.hpp>
#include <moveit_msgs/msg/display_trajectory.hpp>

static const rclcpp::Logger LOGGER = rclcpp::get_logger("move_group_demo");

int main(int argc, char **argv) {
  rclcpp::init(argc, argv);
  rclcpp::NodeOptions node_options;
  node_options.automatically_declare_parameters_from_overrides(true);
  auto move_group_node =
      rclcpp::Node::make_shared("move_group_interface_tutorial", node_options);

  rclcpp::executors::SingleThreadedExecutor executor;
  executor.add_node(move_group_node);
  std::thread([&executor]() { executor.spin(); }).detach();

  static const std::string PLANNING_GROUP_ARM = "ur_manipulator";

  moveit::planning_interface::MoveGroupInterface move_group_arm(
      move_group_node, PLANNING_GROUP_ARM);

  const moveit::core::JointModelGroup *joint_model_group_arm =
      move_group_arm.getCurrentState()->getJointModelGroup(PLANNING_GROUP_ARM);

  // Get Current State
  moveit::core::RobotStatePtr current_state_arm =
      move_group_arm.getCurrentState(10);

  std::vector<double> joint_group_positions_arm;
  current_state_arm->copyJointGroupPositions(joint_model_group_arm,
                                             joint_group_positions_arm);

  move_group_arm.setStartStateToCurrentState();

  // Go Home
  RCLCPP_INFO(LOGGER, "Going Home");

  // joint_group_positions_arm[0] = 0.00;  // Shoulder Pan
  joint_group_positions_arm[1] = -2.50; // Shoulder Lift
  joint_group_positions_arm[2] = 1.50;  // Elbow
  joint_group_positions_arm[3] = -1.50; // Wrist 1
  joint_group_positions_arm[4] = -1.55; // Wrist 2
  // joint_group_positions_arm[5] = 0.00;  // Wrist 3

  move_group_arm.setJointValueTarget(joint_group_positions_arm);

  moveit::planning_interface::MoveGroupInterface::Plan my_plan_arm;
  bool success_arm = (move_group_arm.plan(my_plan_arm) ==
                      moveit::core::MoveItErrorCode::SUCCESS);

  move_group_arm.execute(my_plan_arm);

  // Pregrasp
  RCLCPP_INFO(LOGGER, "Pregrasp Position");

  geometry_msgs::msg::Pose target_pose1;
  target_pose1.orientation.x = -1.0;
  target_pose1.orientation.y = 0.00;
  target_pose1.orientation.z = 0.00;
  target_pose1.orientation.w = 0.00;
  target_pose1.position.x = 0.343;
  target_pose1.position.y = 0.132;
  target_pose1.position.z = 0.264;
  move_group_arm.setPoseTarget(target_pose1);

  success_arm = (move_group_arm.plan(my_plan_arm) ==
                 moveit::core::MoveItErrorCode::SUCCESS);

  move_group_arm.execute(my_plan_arm);

  // Approach
  RCLCPP_INFO(LOGGER, "Approach to object!");

  std::vector<geometry_msgs::msg::Pose> approach_waypoints;
  target_pose1.position.z -= 0.03;
  approach_waypoints.push_back(target_pose1);

  target_pose1.position.z -= 0.03;
  approach_waypoints.push_back(target_pose1);

  moveit_msgs::msg::RobotTrajectory trajectory_approach;
  const double jump_threshold = 0.0;
  const double eef_step = 0.01;

  double fraction = move_group_arm.computeCartesianPath(
      approach_waypoints, eef_step, jump_threshold, trajectory_approach);

  move_group_arm.execute(trajectory_approach);

  // Retreat

  RCLCPP_INFO(LOGGER, "Retreat from object!");

  std::vector<geometry_msgs::msg::Pose> retreat_waypoints;
  target_pose1.position.z += 0.03;
  retreat_waypoints.push_back(target_pose1);

  target_pose1.position.z += 0.03;
  retreat_waypoints.push_back(target_pose1);

  moveit_msgs::msg::RobotTrajectory trajectory_retreat;

  fraction = move_group_arm.computeCartesianPath(
      retreat_waypoints, eef_step, jump_threshold, trajectory_retreat);

  move_group_arm.execute(trajectory_retreat);

  rclcpp::shutdown();
  return 0;
}

My Cmakelists is below

cmake_minimum_required(VERSION 3.8)
project(moveit2_scripts)

if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
  add_compile_options(-Wall -Wextra -Wpedantic)
endif()

# Find dependencies
find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)
find_package(rclcpp_action REQUIRED)
find_package(moveit_core REQUIRED)
find_package(moveit_ros_planning REQUIRED)
find_package(moveit_ros_planning_interface REQUIRED)
find_package(interactive_markers REQUIRED)
find_package(geometric_shapes REQUIRED)
find_package(control_msgs REQUIRED)
find_package(moveit_msgs REQUIRED)

if(BUILD_TESTING)
  find_package(ament_lint_auto REQUIRED)
  # The following line skips the linter which checks for copyrights
  # Comment the line when a copyright and license is added to all source files
  set(ament_cmake_copyright_FOUND TRUE)
  # The following line skips cpplint (only works in a git repo)
  # Comment the line when this package is in a git repo and when
  # a copyright and license is added to all source files
  set(ament_cmake_cpplint_FOUND TRUE)
  ament_lint_auto_find_test_dependencies()
endif()

# Generate the executables
add_executable(test_trajectory src/test_trajectory.cpp)
target_include_directories(test_trajectory PUBLIC include)
ament_target_dependencies(test_trajectory
  ament_cmake
  rclcpp
  rclcpp_action
  moveit_core
  moveit_ros_planning_interface
  interactive_markers
  moveit_ros_planning
  control_msgs
)

add_executable(test_trajectory2 src/test_trajectory2.cpp)
target_include_directories(test_trajectory2 PUBLIC include)
ament_target_dependencies(test_trajectory2
  ament_cmake
  rclcpp
  rclcpp_action
  moveit_core
  moveit_ros_planning_interface
  interactive_markers
  moveit_ros_planning
  control_msgs
)

add_executable(test_trajectory3 src/test_trajectory3.cpp)
target_include_directories(test_trajectory3 PUBLIC include)
ament_target_dependencies(test_trajectory3
  ament_cmake
  rclcpp
  rclcpp_action
  moveit_core
  moveit_ros_planning_interface
  interactive_markers
  moveit_ros_planning
  control_msgs
)

add_executable(cartesian_path src/cartesian_path.cpp)
target_include_directories(cartesian_path PUBLIC include)
ament_target_dependencies(cartesian_path
  ament_cmake
  rclcpp
  rclcpp_action
  moveit_core
  moveit_ros_planning_interface
  interactive_markers
  moveit_ros_planning
  control_msgs
)

# Install the executables
install(TARGETS 
  test_trajectory
  test_trajectory2
  test_trajectory3
  cartesian_path
  DESTINATION lib/${PROJECT_NAME}
)

# Install the launch files
install(DIRECTORY launch DESTINATION share/${PROJECT_NAME})

ament_package()

I tried a clean colcon build but it didn’t solve the problem

Hi @neilthomas110,

Your logs say that in compiling moveit2_scripts, there is a main function missing.

You showed the content of cartesian_path.cpp that has a main function, and that is correct.

But let’s look at the error more carefully, especially the following line:

gmake[2]: *** [CMakeFiles/test_trajectory.dir/build.make:351: test_trajectory] Error 1

As you can see, the error mentions test_trajectory.

In your CMakeLists.txt you have 4 calls to add_executable:

  1. add_executable(test_trajectory src/test_trajectory.cpp)
  2. add_executable(test_trajectory2 src/test_trajectory2.cpp)
  3. add_executable(test_trajectory3 src/test_trajectory3.cpp)
  4. add_executable(cartesian_path src/cartesian_path.cpp)

We can see that the test_trajectory in the CMakeLists.txt refers to test_trajectory.cpp, not the file that you think the error is, since the name of the executable for cartesian_path.cpp is cartesian_path, not test_trajectory as stated in the error.

So, the problem is on test_trajectory.cpp, not on cartesian_path.cpp.

I suppose this file does not have a main function.

You can also find the compiled executables using the following command, to make sure the error is not building the cartesian_path executable:

ls ~/ros2_ws/build/moveit2_scripts/

with the command above you should see that the 3 other executables compiled fine:

  • cartesian_path, test_trajectory2, test_trajectory3

The easy ways of getting rid of this error are two:

  1. Add a main function to the test_trajectory.cpp file
  2. Comment out the lines that refer to that file on the CMakeLists.txt.

If we choose the second option, the CMakeLists.txt would be like below:

cmake_minimum_required(VERSION 3.8)
project(moveit2_scripts)

if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
  add_compile_options(-Wall -Wextra -Wpedantic)
endif()

# Find dependencies
find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)
find_package(rclcpp_action REQUIRED)
find_package(moveit_core REQUIRED)
find_package(moveit_ros_planning REQUIRED)
find_package(moveit_ros_planning_interface REQUIRED)
find_package(interactive_markers REQUIRED)
find_package(geometric_shapes REQUIRED)
find_package(control_msgs REQUIRED)
find_package(moveit_msgs REQUIRED)

if(BUILD_TESTING)
  find_package(ament_lint_auto REQUIRED)
  # The following line skips the linter which checks for copyrights
  # Comment the line when a copyright and license is added to all source files
  set(ament_cmake_copyright_FOUND TRUE)
  # The following line skips cpplint (only works in a git repo)
  # Comment the line when this package is in a git repo and when
  # a copyright and license is added to all source files
  set(ament_cmake_cpplint_FOUND TRUE)
  ament_lint_auto_find_test_dependencies()
endif()

# Generate the executables
#add_executable(test_trajectory src/test_trajectory.cpp)
#target_include_directories(test_trajectory PUBLIC include)
#ament_target_dependencies(test_trajectory
#  ament_cmake
#  rclcpp
#  rclcpp_action
#  moveit_core
#  moveit_ros_planning_interface
#  interactive_markers
#  moveit_ros_planning
#  control_msgs
#)

add_executable(test_trajectory2 src/test_trajectory2.cpp)
target_include_directories(test_trajectory2 PUBLIC include)
ament_target_dependencies(test_trajectory2
  ament_cmake
  rclcpp
  rclcpp_action
  moveit_core
  moveit_ros_planning_interface
  interactive_markers
  moveit_ros_planning
  control_msgs
)

add_executable(test_trajectory3 src/test_trajectory3.cpp)
target_include_directories(test_trajectory3 PUBLIC include)
ament_target_dependencies(test_trajectory3
  ament_cmake
  rclcpp
  rclcpp_action
  moveit_core
  moveit_ros_planning_interface
  interactive_markers
  moveit_ros_planning
  control_msgs
)

add_executable(cartesian_path src/cartesian_path.cpp)
target_include_directories(cartesian_path PUBLIC include)
ament_target_dependencies(cartesian_path
  ament_cmake
  rclcpp
  rclcpp_action
  moveit_core
  moveit_ros_planning_interface
  interactive_markers
  moveit_ros_planning
  control_msgs
)

# Install the executables
install(TARGETS 
  # test_trajectory
  test_trajectory2
  test_trajectory3
  cartesian_path
  DESTINATION lib/${PROJECT_NAME}
)

# Install the launch files
install(DIRECTORY launch DESTINATION share/${PROJECT_NAME})

ament_package()

We basically commented out references to test_trajectory.

Using this modified CMakeLists.txt, you should have no errors compiling your workspace.

Please let us know when you successfully compile your workspace with no errors.

Yes that was exactly the issue. My test_trajectory was surprisingly empty

1 Like

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.