C++ main entry point

From Rsewiki
(Difference between revisions)
Jump to: navigation, search
(Include files)
(Compile using CMake)
Line 104: Line 104:
  
 
== Compile using CMake ==
 
== Compile using CMake ==
 +
 +
To compile, the compiler uses a lot of parameters to specify what to compile, where the system libraries are placed and other compile options.
 +
A Makefile is often used to specify these options, to check for dependencies and not to compile more than needed.
 +
 +
A Makefile can be complicated too, and a number of apps exist to simplify the generation of the Makefile.
 +
One of the most widely used is CMake
 +
 +
=== CMake ===
 +
 +
CMake has a specification file called ''CMakeLists.txt'', for our project, it looks like this:
 +
 +
cmake_minimum_required(VERSION 3.8)
 +
project('''raubase''')
 +
 +
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
 +
  add_compile_options(-Wall -Wextra -Wpedantic)
 +
endif()
 +
 +
find_package(OpenCV REQUIRED )
 +
find_package(Threads REQUIRED)
 +
#find_package(libgpiodcxx REQUIRED)
 +
 +
include_directories(${OpenCV_INCLUDE_DIRS} ${rclcpp_INCLUDE_DIRS} ${dlib_INCLUDE_DIR})
 +
execute_process(COMMAND uname -m RESULT_VARIABLE IS_OK OUTPUT_VARIABLE CPU1)
 +
string(STRIP ${CPU1} CPU)
 +
# works for Raspberry 3 and 4
 +
if (${CPU} MATCHES "armv7l" OR ${CPU} MATCHES "aarch64")
 +
    message("# Is a RASPBERRY; CPU=${CPU} (Pi3=armv7l, pi4=aarch64)")
 +
    #    set(EXTRA_CC_FLAGS " -mfpu=vfp -mfloat-abi=hard -march=armv6zk -mtune=arm1176jzf-s -DRASPBERRY_PI -D${CPU}")
 +
    set(EXTRA_CC_FLAGS "-D${CPU} -O2 -g0 -DRASPBERRY_PI -I/home/local/git/CLI11/include")
 +
    #set(EXTRA_CC_FLAGS "-D${CPU} -O0 -g2 -DRASPBERRY_PI")
 +
  else()
 +
    message("# Not a RASPBERRY; CPU=${CPU}")
 +
    set(EXTRA_CC_FLAGS "-D${CPU} -O0 -g2")
 +
endif()
 +
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -pedantic \
 +
    -Wno-format-truncation -Wno-return-type \
 +
    -std=c++20 ${EXTRA_CC_FLAGS}")
 +
set(CMAKE_C_FLAGS ${CMAKE_C_FLAGS} "-pthread")
 +
 +
add_executable('''raubase'''
 +
      '''src/bplan20.cpp'''
 +
      src/bplan21.cpp
 +
      src/bplan40.cpp
 +
      src/cedge.cpp
 +
      src/cheading.cpp
 +
      src/cmixer.cpp
 +
      src/cmotor.cpp
 +
      src/cservo.cpp
 +
      src/main.cpp
 +
      src/medge.cpp
 +
      src/mpose.cpp
 +
      src/sedge.cpp
 +
      src/sencoder.cpp
 +
      src/sgpiod.cpp
 +
      src/simu.cpp
 +
      src/sdist.cpp
 +
      src/sjoylogitech.cpp
 +
      src/spyvision.cpp
 +
      src/sstate.cpp
 +
      src/steensy.cpp
 +
      src/upid.cpp
 +
      src/uservice.cpp
 +
      src/usocket.cpp
 +
      src/utime.cpp
 +
      )
 +
 +
if (${CPU} MATCHES "armv7l" OR ${CPU} MATCHES "aarch64")
 +
  target_link_libraries('''raubase''' ${CMAKE_THREAD_LIBS_INIT} readline gpiod rt)
 +
else()
 +
  target_link_libraries('''raubase''' ${CMAKE_THREAD_LIBS_INIT} readline gpiod)
 +
endif()

Revision as of 10:03, 31 December 2023

Back to Robobot B. Back to Robobot software description

Contents

Main

C++ starts executing a function called main(int argc, char ** argv)

In Robobot, this is rather simple and the intention is explained here.

The main.cpp file looks like this (slightly reduced):

/*
#***************************************************************************
#*   Copyright (C) 2023 by DTU
#*   jcan@dtu.dk
#*
#* The MIT License (MIT)  https://mit-license.org/
#***************************************************************************/
// System libraries
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <string>
//
// include local files for data values and functions
#include "uservice.h"
#include "cmixer.h"
#include "sgpiod.h"
#include "bplan20.h"
#include "bplan40.h"

int main (int argc, char **argv)
{ // prepare all modules and start data flow
  bool setupOK = service.setup(argc, argv);
  if (setupOK)
  { // turn on LED on port 16
    gpio.setPin(16, 1);
    // run the planned missions
    if (ini["plan20"]["run"] == "true")
    { // example odometry drive using distance and turned angle
      plan20.run();
    }
    if (ini["plan40"]["run"] == "true")
    { // example odometry drive using distance and turned angle
      plan40.run();
    }
    mixer.setVelocity(0.0);
    mixer.setTurnrate(0.0);
    sleep(1); // to allow robot to stop while logging is running
    // turn off led 16
    gpio.setPin(16, 0);
  }
  // close all logfiles
  service.terminate();
}

The main() function

The main function handles:

  • setup of all modules by calling setup(...) in the service module.
  • run the mission (or missions) needed.
  • stop and terminate in a proper way; the service module handles the termination details.

Run mission

The entire mission can be divided into smaller parts that can be tested individually.

One example could be plan20.

    if (ini["plan20"]["run"] == "true")
    { // example odometry drive using distance and turned angle
      plan20.run();
    }

It can be activated by setting the run flag in the robot.ini configuration file.

; part of robot.ini file
[plan20]
log = true
run = true
print = true

The sequence of the entire mission is handled here. In this case, the entire mission consists of plan20 and plan40.

You are, of course, allowed to change whatever you like, especially if you find more innovative ways to do it. The main objective has been to make it readable, understandable and then functional.

Copyright

All software, specific for Robobot, is free to use and change, according to the MIT License. One of the least restrictive copyright types.

Include files

To call functions, the compiler needs to know where these functions are defined. C++ handles this by including the needed files prior to compiling.

Where to look for these files is indicated by the brackets, like

#include <string>
#include "bplan20.h"

The first file included is string in <..> brackets, indicating that this is a system library, and the path for such libraries is part of the compile parameters.

The second file bplan20.h is in ".." bracket, indicating that the file is in the same directory as the file that includes the file.

Compile using CMake

To compile, the compiler uses a lot of parameters to specify what to compile, where the system libraries are placed and other compile options. A Makefile is often used to specify these options, to check for dependencies and not to compile more than needed.

A Makefile can be complicated too, and a number of apps exist to simplify the generation of the Makefile. One of the most widely used is CMake

CMake

CMake has a specification file called CMakeLists.txt, for our project, it looks like this:

cmake_minimum_required(VERSION 3.8)
project(raubase)

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

find_package(OpenCV REQUIRED )
find_package(Threads REQUIRED)
#find_package(libgpiodcxx REQUIRED) 
include_directories(${OpenCV_INCLUDE_DIRS} ${rclcpp_INCLUDE_DIRS} ${dlib_INCLUDE_DIR})
execute_process(COMMAND uname -m RESULT_VARIABLE IS_OK OUTPUT_VARIABLE CPU1)
string(STRIP ${CPU1} CPU)
# works for Raspberry 3 and 4
if (${CPU} MATCHES "armv7l" OR ${CPU} MATCHES "aarch64")
   message("# Is a RASPBERRY; CPU=${CPU} (Pi3=armv7l, pi4=aarch64)")
    #    set(EXTRA_CC_FLAGS " -mfpu=vfp -mfloat-abi=hard -march=armv6zk -mtune=arm1176jzf-s -DRASPBERRY_PI -D${CPU}")
    set(EXTRA_CC_FLAGS "-D${CPU} -O2 -g0 -DRASPBERRY_PI -I/home/local/git/CLI11/include")
    #set(EXTRA_CC_FLAGS "-D${CPU} -O0 -g2 -DRASPBERRY_PI")
 else()
    message("# Not a RASPBERRY; CPU=${CPU}")
    set(EXTRA_CC_FLAGS "-D${CPU} -O0 -g2")
endif()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -pedantic \
    -Wno-format-truncation -Wno-return-type \
    -std=c++20 ${EXTRA_CC_FLAGS}")
set(CMAKE_C_FLAGS ${CMAKE_C_FLAGS} "-pthread") 

add_executable(raubase
     src/bplan20.cpp
     src/bplan21.cpp
     src/bplan40.cpp
     src/cedge.cpp
     src/cheading.cpp
     src/cmixer.cpp
     src/cmotor.cpp
     src/cservo.cpp
     src/main.cpp
     src/medge.cpp
     src/mpose.cpp
     src/sedge.cpp
     src/sencoder.cpp
     src/sgpiod.cpp
     src/simu.cpp
     src/sdist.cpp
     src/sjoylogitech.cpp
     src/spyvision.cpp
     src/sstate.cpp
     src/steensy.cpp
     src/upid.cpp
     src/uservice.cpp
     src/usocket.cpp
     src/utime.cpp
     )

if (${CPU} MATCHES "armv7l" OR ${CPU} MATCHES "aarch64")
  target_link_libraries(raubase ${CMAKE_THREAD_LIBS_INIT} readline gpiod rt)
else()
  target_link_libraries(raubase ${CMAKE_THREAD_LIBS_INIT} readline gpiod)
endif()
Personal tools
Namespaces

Variants
Actions
Navigation
Toolbox