写在前面
最近项目一直用matlab,防止手生整一个回忆工具使用的简单的pid demo,走一边流程,包括配工程debug看结果,复用之前记录的配置见我的bloghttps://blog.csdn.net/weixin_46479223/article/details/135082867?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22135082867%22%2C%22source%22%3A%22weixin_46479223%22%7D。visual studio在这方面感觉比vscode 方便不少
使用说明,不基于内容是什么,主要是配置好基本内容可以快速编译打印验证,或者配置visualstudio,单个文件的话可以使用在线ide页面https://godbolt.org/
结构
cmakelist
bash
cmake_minimum_required(VERSION 3.14.1)
project(project_PIDControllerDemo)
set( CMAKE_CXX_STANDARD 11 )
set( CMAKE_CXX_STANDARD_REQUIRED ON )
set( THREADS_PREFER_PTHREAD_FLAG ON )
function(include_sub_directories_recursively root_dir)
if (IS_DIRECTORY ${root_dir})
include_directories(${root_dir})
file(GLOB children RELATIVE ${root_dir} ${root_dir}/*)
foreach(child ${children})
if (IS_DIRECTORY ${root_dir}/${child})
include_sub_directories_recursively(${root_dir}/${child})
endif()
endforeach()
endif()
endfunction()
function(aux_source_directory_recursively root_dir var_name)
if(IS_DIRECTORY ${root_dir})
aux_source_directory(${root_dir} TMP_SRC_LIST)
set(${var_name} ${${var_name}} ${TMP_SRC_LIST} PARENT_SCOPE)
file(GLOB children RELATIVE ${root_dir} ${root_dir}/*)
foreach(child ${children})
if(IS_DIRECTORY ${root_dir}/${child})
aux_source_directory_recursively(${root_dir}/${child} ${var_name})
endif()
endforeach()
endif()
endfunction()
find_package(glog REQUIRED)
find_package(Eigen3 REQUIRED)
#find_package(osqp REQUIRED )
find_package(OsqpEigen REQUIRED)
find_package(yaml-cpp REQUIRED)
Set(GLOG_INCLUDE_DIRS "/usr/include/glog/")
Set(GLOG_LIBRARIES "/usr/lib/x86_64-linux-gnu/libglog.so")
#Set(GLOG_LIBRARIES "/usr/local/lib/libglog.so")
# message(STATUS "GLOG_INCLUDE_DIRS: ${GLOG_INCLUDE_DIR}")
# message(STATUS "GLOG_LIBRARIES: ${GLOG_LIBRARIES}")
# message(STATUS "EIGEN3_INCLUDE_DIR: ${EIGEN3_INCLUDE_DIR}")
# message(STATUS "EIGEN3_LIBRARIES: ${EIGEN3_LIBRARIES}")
# message(STATUS "osqp_INCLUDE_DIR: ${osqp_INCLUDE_DIR}")
# message(STATUS "osqp_LIBRARIES: ${osqp_LIBRARIES}")
set(CMAKE_BUILD_TYPE "Debug")
set(CMAKE_INCLUDE_CURRENT_DIR ON)
# aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR} SRC_LIST)
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/src/. SRC_LIST)
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/commen/. SRC_LIST)
#aux_source_directory_recursively(${CMAKE_CURRENT_SOURCE_DIR}/src SRC_LIST)
include_sub_directories_recursively(${CMAKE_CURRENT_SOURCE_DIR}/include)
include_sub_directories_recursively(${CMAKE_CURRENT_SOURCE_DIR}/libs)
include_sub_directories_recursively(${CMAKE_CURRENT_SOURCE_DIR}/src)
include_sub_directories_recursively(${CMAKE_CURRENT_SOURCE_DIR}/inc)
##############################debug start##############################
get_property(include_dirs DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY INCLUDE_DIRECTORIES)
foreach(dir ${include_dirs})
message("Include directory: ${dir}")
endforeach()
message("Source files:")
foreach(file IN LISTS SRC_LIST)
message(" ${file}")
endforeach()
#################################debug end####################################
include_directories(${GLOG_INCLUDE_DIRS})
include_directories(${EIGEN3_INCLUDE_DIR})
add_executable(${PROJECT_NAME} ${SRC_LIST})
#add_library(${PROJECT_NAME} STATIC ${SRC_LIST}) # temp use
target_include_directories(${PROJECT_NAME} PRIVATE ${GLOG_INCLUDE_DIRS})
#target_include_directories(${PROJECT_NAME} PRIVATE ${OSQP_INCLUDE_DIRS})
#target_link_libraries(${PROJECT_NAME} OsqpEigen::OsqpEigen)
target_link_libraries(${PROJECT_NAME} PRIVATE ${GLOG_LIBRARIES})
target_link_libraries(${PROJECT_NAME} PRIVATE ${EIGEN3_LIBRARIES})
target_link_libraries(${PROJECT_NAME} PRIVATE yaml-cpp)
# link_directories(${CMAKE_CURRENT_SOURCE_DIR}/libs/yaml-cpp/)# for all
# target_link_libraries(${PROJECT_NAME} PRIVATE libyaml-cpp.a)
#target_link_libraries(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/libs/yaml-cD/libyaml-cD.a)
#target_link_libraries(${PROJECT_NAME} PRIVATE osqp::osqp)
#####################################unit test ###################################
# add_executable(unit_test_pathFW ${SRC_LIST})
# target_link_libraries( unit_test_pathFW
# ${GLOG_LIBRARIES}
# # ${CMAKE_CURRENT_SOURCE_DIR}/libs/yaml-cD/libyaml-cD.a
# ${CMAKE_CURRENT_SOURCE_DIR}/libs/yaml-cD/libyaml-cD.a
# # yaml-cD
# )
#####################################unit test end#################################
c_cpp_properties.json
c
{
"configurations": [
{
"name": "Linux",
"includePath": [
"${workspaceFolder}/**",
"${workspaceFolder}/inc",
"/usr/include/**"
],
"defines": [],
"compilerPath": "/usr/bin/gcc",
"cStandard": "c17",
"cppStandard": "gnu++14",
"intelliSenseMode": "linux-gcc-x64"
}
],
"version": 4
}
launch.json
bash
{
// 使用 IntelliSense 了解相关属性。
// 悬停以查看现有属性的描述。
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) 启动",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build/project_PIDControllerDemo",
"args": [],
"stopAtEntry": false,
"cwd": "${fileDirname}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "为 gdb 启用整齐打印",
"text": "-enable-pretty-printing",
"ignoreFailures": true
},
{
"description": "将反汇编风格设置为 Intel",
"text": "-gdb-set disassembly-flavor intel",
"ignoreFailures": true
}
]
}
]
}
pid.h
cpp
# ifndef _PID_H_
# define _PID_H_
#include <cmath>
#include <algorithm>
# define RUNCYCLE 0.02
class PID{
public:
PID(): ki_(0), kp_(0), kd_(0){}
PID(const float& KI,const float& KP,const float& KD): ki_( KI), kp_( KP)
, kd_(KD){}
PID(const PID& pid)=delete;
~PID()
{}
void updatePos();
void calError(const float & targetPos);
float getRes();
private:
float ki_ ;
float kp_;
float kd_;
float error_ {0.f};
float pos_ {0.f};
float res_ {0.f};
};
# endif
pid.cc
cpp
#include "pid.h"
using namespace std;
void PID:: calError( const float & targetPos )
{
float error_i=0.f,error_d=0.f,error_p=0.f;
static float error_last=0;
error_p=targetPos-pos_;
error_i=RUNCYCLE*error_p;
error_d=(error_p-error_last)/RUNCYCLE;
if (error_p*error_p<0)
{
error_i=0;
}
error_i=min(error_i,3.f);
error_i=max(error_i,-3.f);
error_last=error_p;
res_= ki_*error_i+kp_*error_p+kd_*error_d;
}
void PID:: updatePos()
{
pos_+=res_*RUNCYCLE;
}
float PID:: getRes()
{
return pos_;
}
main.cc
cpp
# include "pid.h"
#include <glog/logging.h>
int main(int argc, char* argv[])
{
google::InitGoogleLogging(argv[0]);
google::SetStderrLogging(google::GLOG_ERROR);
FLAGS_colorlogtostderr = true;
FLAGS_logtostderr = true;
FLAGS_minloglevel = 0;
PID pidUser (0.3f,1.f,0.5f); // user defined parameters
int Target=10; // user defined
int count=0; // counter
LOG(INFO) << "Hello,myPID";
while (fabs(Target-pidUser.getRes())>0.1&&count<1000)
{
pidUser.calError(Target);
pidUser.updatePos();
count++;
LOG(INFO) << "Target: "<<Target<< "Current pos: "<< pidUser.getRes();
}
LOG(INFO) << "End at "<< count<< "Times";
google::ShutdownGoogleLogging();
}
结果
用重定向 放入excel中画图展示如下
如果练习使用的电脑 只有gcc 没有cmake的话,临时练习方案
对于我的项目在项目主文件夹下
使用gcc ./src/main.cc ./src/pid.cc -I./inc -o Test
以下扩展来自于gpt:
Q:如果想使用eigen库 和osqp库 用cpp14标准 编译模式为debug 编译结果为动态库或者静态库 该怎么设置,比如在gcc ./src/main.cc ./src/pid.cc -I./inc -o Test 扩展该怎么做 而不是使用cmakelist
A:如下
bash
# 编译并生成可执行文件
gcc ./src/main.cc ./src/pid.cc -I./inc -o Test -std=c++14 -g -lYourOSQPLibrary -lYourEigenLibrary
# 或者编译并生成动态库
gcc -shared -fPIC ./src/main.cc ./src/pid.cc -I./inc -o libYourLibraryName.so -std=c++14 -g -lYourOSQPLibrary -lYourEigenLibrary
或者编译并生成静态库
bash
gcc -c ./src/main.cc ./src/pid.cc -I./inc -o YourObjectFile.o -std=c++14 -g
ar rcs libYourLibraryName.a YourObjectFile.o
等效于cmakelist如下:
bash
cmake_minimum_required(VERSION 3.10)
project(YourProjectName)
# 设置 C++ 标准
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
# 查找 Eigen 库
find_package(Eigen3 REQUIRED)
include_directories(${EIGEN3_INCLUDE_DIR})
# 查找 OSQP 库
find_package(osqp REQUIRED)
include_directories(${OSQP_INCLUDE_DIRS})
# 设置编译模式为 Debug
set(CMAKE_BUILD_TYPE Debug)
# 生成动态库
add_library(YourLibraryName SHARED
src/your_source_file1.cpp
src/your_source_file2.cpp
# 添加其他源文件
)
# 或者生成静态库
# add_library(YourLibraryName STATIC
# src/your_source_file1.cpp
# src/your_source_file2.cpp
# # 添加其他源文件
# )
# 链接 OSQP 和其他可能的库,例如 Eigen
target_link_libraries(YourLibraryName ${OSQP_LIBRARIES} Eigen3::Eigen)
# 可执行文件示例
add_executable(YourExecutableName
src/main.cpp
# 添加其他源文件
)
# 链接生成的库
target_link_libraries(YourExecutableName YourLibraryName)