Use the Ceres nonlinear optimization library in the windows system: (1) Install the Ceres library

(1) Install the Ceres library

        1. Install the Ceres library with vcpkg

                1.1. Install vcpkg

                1.2. Install Ceres

                1.3. Configure Ceres

        2. Install the Ceres library with Virtual Studio

                2.1. Download ceres-windows

                2.2. Open or upgrade a solution

                2.3. Compile the project libglog_static

                2.4. Compile the project ceres_static and ceres

                2.5. Compile routine

                2.6. In-depth understanding of the compilation and linking process

        3. Install the Ceres library with CMake

(2) Call the Ceres library

(3) Release the application

Ceres, translated as Ceres, is a dwarf planet in the solar system. It was first observed by Italian priest Piazzi in 1801, but then Piazzi lost its orbit because of illness. A few months later, the German mathematician Gauss successfully predicted the trajectory of Ceres by using the least square method and only relying on the 12 data observed by Piazzi before.

More than two hundred years later, in order to solve some complex optimization problems (such as: nonlinear least squares with boundary constraints, general unconstrained optimization, etc.), Google developed a C++ library Ceres Solver. The reason why it is named Ceres Solver is to commemorate Gauss's use of the least square method to successfully predict the trajectory of Ceres, which is an event of great significance in the history of optimization, statistics, and astronomy.

Within Google, Ceres has been used in multiple products, such as: pose estimation of cars and aircraft in Google Street View; establishment of 3D models in PhotoTours; SLAM algorithm Cartographer, etc. In addition, some companies and research institutes are also using Ceres, such as Southwest Research Institute's robot vision system calibration, OpenMVG's beam adjustment (BA) problem, Willow Garage's SLAM problem, etc.

I am a SLAM professional, and I have always installed and used the Ceres library on the Linux system. Whether I apt install or download the source code and compile it with CMake, it is quite simple. However, there is a recent project that needs to install and use the Ceres library on the windows system. It is found that installing and using the Ceres library on windows is much more complicated than on Linux. Writing this blog is to record the various pits I have stepped on, hoping to help others later.

 (1) Install the Ceres library

To install the Ceres library, I recommend looking directly at the official tutorial ( Installation — Ceres Solver ), which is very detailed. The official gives 3 ways to install the Ceres library on the windows system:

  • Install the Ceres library with vcpkg.
  • Install the Ceres library with Virtual Studio.
  • Install the Ceres library with CMake.

Installing the Ceres library with vcpkg is very simple, almost a one-click installation, but the disadvantage is that you cannot manually select the version of Ceres and its dependencies, and some other compilation options cannot be modified. In the later application, the editing options need to be modified, obviously the vcpkg method cannot meet the requirements. To install the Ceres library with Virtual Studio is to create a new C++ project in Virtual Studio, then put the Ceres and its dependent source code downloaded from the Internet into the corresponding location of the newly created C++ project, and then compile these C++ projects to generate the Lib static library we need And Dll dynamic library. In this way, you can manually select the version of Ceres and its dependencies, and you can also modify the compilation options. Using CMake to install the Ceres library, compared to using Virtual Studio to install the Ceres library, has the advantage that it can be compiled based on the CMake project, which is very lightweight and has good portability, but the disadvantage is that the configuration process is very complicated. Therefore, I recommend installing the Ceres library with Virtual Studio.

1. Install the Ceres library with vcpkg

vcpkg is a cross-platform open source package manager for C and C++ libraries developed by the Microsoft C++ team. It greatly simplifies the download and configuration operations related to third-party libraries on Windows, Linux and macOS. There are currently more than 1,600 third-party libraries Libraries can be installed via vcpkg. vcpkg is actually something similar to Linux's apt package manager and Python's pip package manager.

1.1. Install vcpkg

Regarding the installation and use of vcpkg, the official tutorial ( vcpkg/README_zh_CN.md at master · microsoft/vcpkg · GitHub ) for installing vcpkg on the Windows system is already very detailed, so I will briefly talk about it here. The first is to download the vcpkg installation package to our windows computer, and then just run the installation package. First install the Git client on your windows computer, and then use Git to download the vcpkg installation package; it doesn’t matter if you don’t have Git installed, just go directly to vcpkg’s github to download the installation package and then install it.

Here it is assumed that Git already exists, directly open the CMD command terminal of your windows computer as an administrator, and enter the following command to install vcpkg:

> git clone https://github.com/microsoft/vcpkg
> .\vcpkg\bootstrap-vcpkg.bat

1.2. Install Ceres

Continue to use the following command to install the C/C++ library you need in the CMD command terminal. For the specific usage of vcpkg, you can use the help command vcpkg help to view the tutorial. Here, first use the vcpkg search command to query the situation of the ceres package we want to install:

> CD vcpkg\vcpkg
> vcpkg search ceres

 From the above query results, the ceres version in the vcpkg warehouse is 2.1.0, and there are other versions of ceres (such as ceres[cuda], ceres[cxsparse], etc.). In addition, the packages in vcpkg are divided into 32-bit and 64-bit, and the default is to install 32-bit. If you want to use this package in both 32-bit and 64-bit applications, you need to install both:

#安装ceres 32位版本的命令
> vcpkg install ceres
#安装ceres 64位版本的命令
> vcpkg install ceres:x64-windows

The ceres version installed directly above is the DENSE_QR solution method used when performing optimization iterations. The ceres[cxsparse], ceres[suitesparse], ceres[eigensparse] and other versions are not required. If these versions are installed, the SPARSE_NORMAL_CHOLESKY solution method of SuiteSparse or CXSparse or Eigen's sparse Cholesky decomposition option is used when performing optimization iterations. . When the problem matrix to be solved is relatively sparse, the solution efficiency of the latter is obviously higher than that of the former. Therefore, you can choose whether to install these non-essential versions according to your needs. The installation method is as follows:

#安装ceres 32位版本的命令
> vcpkg install ceres[cxsparse] --recurse
> vcpkg install ceres[suitesparse] --recurse
> vcpkg install ceres[eigensparse] --recurse
#安装ceres 64位版本的命令
> vcpkg install ceres[cxsparse]:x64-windows --recurse
> vcpkg install ceres[suitesparse]:x64-windows --recurse
> vcpkg install ceres[eigensparse]:x64-windows --recurse

Finally, after the installation is complete, we use the vcpkg list command to view the installed packages. We can find that the ceres package is installed and its corresponding dependencies (such as Eigen, glog, gflags, etc.) are also automatically installed.

 1.3. Configure Ceres

Although the Ceres library has been installed above, when we write a C++ program to call the Ceres library, we need to configure the include and lib directories involved in the Ceres library and specify some link attributes in our program, which is very inconvenient. The following discusses how to configure Ceres in several cases. I am using the environment of win10+VS2022 here, and the environment of other versions is similar.

(1) Non-CMake projects in Visual Studio use the configuration of the Ceres library

The newly created C++ project in Visual Studio is a non-CMake project by default. We can configure all the libraries installed in vcpkg to the global scope of Visual Studio, so that the installed libraries in vcpkg are like the C/C++ system standard library. We can call it directly by #include <xxx> in any new C++ project in Visual Studio without additional configuration. The method of configuring the library in vcpkg to the global scope of Visual Studio, as shown in the following command:

#将vcpkg安装到Visual Studio全局范围
> vcpkg integrate install
#将vcpkg从Visual Studio全局范围卸载
> vcpkg integrate remove

Sometimes you may want to use different versions of some libraries in different projects, so you cannot configure vcpkg to the global scope of Visual Studio. At this time, you can package vcpkg into nuget, and then load the library in vcpkg through nuget in a specific project of Visual Studio, so the flexibility is very high. If the version of the corresponding library of vcpkg is not what our project wants, the project can install and configure the library manually without loading vcpkg. The method of configuring the library in vcpkg to the local scope of Visual Studio, as shown in the following command:

> vcpkg integrate project

Then open Visual Studio, click in the menu bar: Tools->NuGet Package Manager->Package Manager Settings, find "Package Source" in the settings interface, and add vcpkg to it. Fill in the name column casually, I filled in vcpkg here, so it is easy to find when you use it later. In the source column, fill in the path of the file generated after the above command is executed, such as C:\<replace with your actual path>\vcpkg\vcpkg\scripts\buildsystems. Finally, click OK.

  If you want to use the package in vcpkg in a project of the Visual Studio solution, you only need to install vcpkg with nuget in the project, such as the following. If you don't need it later, just click Uninstall.

 (2) The CMake project in Visual Studio uses the configuration of the Ceres library

The newly created C++ project in Visual Studio is a non-CMake project by default, which means that this C++ project depends on *.sln or *.vcxproj project files, which means it cannot be separated from the Visual Studio development environment. The new CMake C++ project in Visual Studio is a cross-platform C++ project that does not depend on *.sln or *.vcxproj project files. If you want to use the Ceres library in the CMake C++ project in Visual Studio, open the CMake setting option of the project, and add the vcpkg toolchain file path to the CMake toolchain file, as follows:

[vcpkg root]/scripts/buildsystems/vcpkg.cmake

(3) The CMake project in non- Visual Studio uses the configuration of the Ceres library

If you want to use the Ceres library in a CMake C++ project in a non-Visual Studio development environment, you need to use the following toolchain file for command configuration when compiling the project with the CMake command:

> cmake -B [build directory] -S . "-DCMAKE_TOOLCHAIN_FILE=[path to vcpkg]/scripts/buildsystems/vcpkg.cmake"
> cmake --build [build directory]

In addition, in CMake, you still need to use find_package to use the installed library in vcpkg.

2. Install the Ceres library with Virtual Studio

Although it is simple to install the Ceres library with vcpkg, it is very inflexible. Therefore, I choose a more flexible method here. Install the Ceres library with Virtual Studio, that is, create a new C++ project in Virtual Studio, and then put the Ceres and its dependent source code downloaded from the Internet into the corresponding location of the newly created C++ project. Then compile these C++ projects to generate the Lib static library and Dll dynamic library we need. In this way, you can manually select the version of Ceres and its dependencies, and you can also modify the compilation options.

2.1. Download ceres-windows

If you don’t know how to create a new C++ project in Virtual Studio and then configure and compile the Ceres source code, you can go to the official tutorial to download the ready-made Virtual Studio project. The download address is as follows:

 We can find that the ceres-windows folder just downloaded above is actually a template, and the ceres-solver, Eigen, and glog folders in it are all empty. Therefore, we have to download the source codes of ceres-solver, Eigen, and glog separately, and then decompress them into the corresponding folders in ceres-windows. The source code version I downloaded here is as follows:

2.2. Open or upgrade a solution

It can be found that there are 3 solution files in the ceres-windows folder: ceres-2010.sln, ceres-2012.sln, ceres-2015.sln. Select the solution corresponding to the version of Virtual Studio on your computer and open it. If your version of Virtual Studio is higher than version 2015 (for example, I use Virtual Studio 2022), then directly open the ceres-2015.sln solution and press Accept The next prompt operation steps to complete the automatic upgrade of the solution version.

In addition, remember to go to the solution properties and set the configuration (Debug/Release) and platform (x64/Win32) of the solution and each project to a unified mode. If they are not unified, an error will be reported later when compiling. I have uniformly set the modes of Release and Win32 here, as shown below.

 Before officially starting to compile, you can go to the solution properties to see the dependencies between the various projects.

 You can find the dependencies between the various projects under our solution. The project libglog_static does not depend on other projects. The project libglog_static is the project used to create the static C++ library Lib. Both the project ceres_static and ceres depend on the project libglog_static, the project ceres_static is used to create the static C++ library Lib, and the project ceres is used to create the dynamic C++ library Dll. Other projects (curve_fitting, curve_fitting_c, ellipse_approximation, helloworld, helloworld_analytic_diff, helloworld_numeric_diff, helloworld_static, robust_curve_fitting, simple_bundle_adjuster) are routines that depend on ceres_static or ceres. The specific dependencies are as follows:

 According to the dependencies between projects, we need to compile the project libglog_static first, then compile the projects ceres_static and ceres, and finally compile the routine projects (curve_fitting, curve_fitting_c, ellipse_approximation, helloworld, helloworld_analytic_diff, helloworld_numeric_diff, helloworld_static, robust_curve_fitting, sim ple_bundle_adjuster).

2.3. Compile the project libglog_static

Directly select the project libglog_static, then right-click, and select "Generate" in the pop-up menu list to start compiling. After the compilation is completed, according to the output path configured in the project properties, the compiled static library file libglog_static.lib is stored in the path "<your solution folder>\Win32\Release\".

2.4. Compile the project ceres _static and ceres

As above, directly select the project, then right-click, and select "Generate" in the pop-up menu list to start compiling. After the compilation is completed, according to the output path configured in the project properties, the static library file ceres_static.lib and the dynamic library file ceres.dll generated by the project ceres_static and ceres are still stored in the path "<your solution folder>\Win32\Release \". At this point, the library files libglog_static.lib, ceres_static.lib, and ceres.dll that will be used in the routine will be ready.

2.5. Compile routine

Other projects in the solution (curve_fitting, curve_fitting_c, ellipse_approximation, helloworld, helloworld_analytic_diff, helloworld_numeric_diff, helloworld_static, robust_curve_fitting, simple_bundle_adjuster) are all routines, that is, for you to test the ceres library, see the ceres library compilation and installation Is it correct.

(1) Compile the routine helloworld

Select the project directly, then right-click, and select "Generate" in the pop-up menu list to start compiling. However, the compilation will encounter the "C4996" error, as follows:

 The solution is to add macros in the project property settings, configuration properties > C/C++ > preprocessor > preprocessor definitions, and then add the following macros in it:

_CRT_NONSTDC_NO_DEPRECATE

Then "regenerate" is enough. After the compilation is successful, the executable file helloworld.exe will be generated. According to the output path configured in the project properties, the compiled executable file helloworld.exe is stored in the path "<your solution folder>\Win32\Release\". Just double-click helloworld.exe to execute this routine and see the output of the operation. But the console will flash by, because the program exits immediately after running. You can run this routine in Virtual Studio without crashing. That is, select the project helloworld in Virtual Studio, then right-click > debug > start a new instance, and the running results are as follows:

 (2) Compile the routine helloworld_static

As above, the compilation will encounter the "C4996" error. The solution is to add a macro in the project property settings, as follows:

_CRT_NONSTDC_NO_DEPRECATE

Then "regenerate" is enough. After the compilation is successful, the executable file helloworld_static.exe will be generated. According to the output path configured in the project properties, the compiled executable file helloworld_static.exe is stored in the path "<your solution folder>\Win32\Release\". Just double-click helloworld_static.exe to execute this routine and see the output of the operation. But the console will flash by, because the program exits immediately after running. You can run this routine in Virtual Studio without crashing. That is, select the project helloworld in Virtual Studio, then right-click > debug > start a new instance, and the running result is the same as above.

Let me talk about the difference between the two projects helloworld and helloworld_static,

2.6. In-depth understanding of the compilation and linking process

In order to ensure that the programs developed by ourselves can have better compatibility when they are sent to users, there are many setting items that need to be paid attention to during the program development process. Here, we will combine the above two items of helloworld and helloworld_static to discuss in depth about the process of compiling the program. and link for the full process.

(1) The unity of configuration and platform selection

Remember to go to the solution properties and set the configuration (Debug/Release) and platform (x64/Win32) of the solution and each project to a unified mode. If they are not unified, an error will be reported later when compiling. I have set it to the Release and Win32 modes uniformly here.

In fact, the *.exe executable files compiled by Debug and Release can run normally. The program compiled by Debug will be added with some debugging-related things, so the program file of the Debug version will be larger. Of course, the program of the Debug version The operating efficiency is also lower than that of Release. Therefore, it is generally the Release version when the software program is officially released.

However, x64 and Win32 are related to the hardware platform on which the program is running. We know that there are two types of computer CPUs: 32-bit and 64-bit, and the corresponding operating systems also have 32-bit operating systems and 64-bit operating systems. Win32 corresponds to a 32-bit operating system, and x64 corresponds to a 64-bit operating system. Generally speaking, a 32-bit operating system can only run Win32 programs, and a 64-bit operating system can run both x64 programs and Win32 programs. For users, using a 64-bit operating system is more compatible. For program developers, there are more machines that are compatible with Win32 programs.

(2) The unity of the runtime mode

The file size compiled by multi-threaded MT is larger than that compiled by multi-threaded MD, because MT puts the corresponding runtime library directly into the compiled PE file, while MD gets it from a third-party dll when running The runtime library itself is not included. The files compiled by multi-threaded MT do not need to load third-party dlls when running, so the running efficiency is slightly higher than that of multi-threaded MD. Of course, as a user, you can't feel it at all.

At present, most of the software on the market use the multi-threaded MD method, the compiled file is small, all runtime libraries are unified, and memory management is also simplified, eliminating various bugs caused by cross-module memory access . At present, most of the software on the market use the multi-threaded MD method, the compiled file is small, all runtime libraries are unified, and memory management is also simplified, eliminating various bugs caused by cross-module memory access .

Select configuration properties in the project properties window, the code generation multi-threaded debugging DLL (/MDd) and multi-threaded debugging DLL (/MTd) of the C++ option are the Debug version, and those without d behind are the Release version. The multithreaded MT loads the static runtime library, which belongs to the C language version. The multi-threaded MD version loads a dynamic runtime library, which belongs to the Microsoft version. No matter which runtime mode you choose, the mode of your project and its dependent library projects should be unified. For example, if the mode of your project helloworld is MD, then the modes of its dependent libraries ceres and libglog_static should also be MD. There is no special case, just use the default mode MD uniformly.

(3) Dynamic library and static library

For static libraries, functions and data are compiled into a binary file (usually with a .lib extension). In the case of static libraries, when the executable is compiled and linked, the linker copies these functions and data from the library and combines them with other modules of the application to create the final executable (.exe file). When distributing a product, only the executable needs to be distributed, not the static libraries that are used.

When using a dynamic library, two files are often provided after compilation: an import library (. lib) file (also called "import library file") and a DLL (. dll) file. Of course, I will tell you later that if only one DLL file is provided, it can also be called by using the display connection method, but it is just a little troublesome. Although the suffix name of the imported library is also "lib", there is an essential difference between the imported library file of the dynamic library and the static library file. For a DLL file, its import library file (.lib) contains the symbolic names of the functions and variables exported by the DLL, and the .dll file contains the actual functions and data of the DLL. In the case of using a dynamic library, when compiling and linking an executable file, only the import library file of the DLL needs to be linked, and the function code and data in the DLL cannot be copied to the executable file until the executable program is running. To load the required DLL, map that DLL into the address space of the process, and then access the exported functions in the DLL. At this time, when releasing the product, in addition to releasing the executable file, it is also necessary to release the dynamic link library to be called by the program.

Both the static link library and the dynamic link library share code. If the static link library is used, all the instructions in the lib static library are directly included in the final generated exe file. However, if a DLL dynamic library is used, the DLL does not have to be included in the final exe file, and the DLL file independent of the exe can be "dynamically" referenced and uninstalled when the exe file is executed. Another difference between a static link library and a dynamic link library is that the static link library cannot contain other dynamic link libraries or static libraries, and the dynamic link library can also contain other dynamic or static link libraries.

The previous routine projects helloworld and helloworld_static are used to illustrate the linking process of the dynamic library and the static library. First, the static library libglog_static.lib is statically linked to the static library ceres_static.lib and the dynamic library ceres.dll respectively. That is to say, both ceres_static.lib and ceres.dll have included all the content of libglog_static.lib, and libglog_static.lib is no longer required when releasing ceres_static.lib and ceres.dll libraries. The static library ceres_static.lib is statically linked to the application program helloworld_static.exe, which means that helloworld_static.exe has already included all the contents of ceres_static.lib. We only need to copy helloworld_static.exe to the customer when releasing the program. . The dynamic library ceres.dll is dynamically linked to the application program helloworld.exe, that is to say, when helloworld.exe is running, it will dynamically link to ceres.dll, so when we release the program, we must link helloworld.exe and ceres.dll together Copy it to the client. If you only copy helloworld.exe to the client, then the program will report an error that ceres.dll cannot be found when the program is running.

(4) System-level runtime support

In the situation discussed above, the static library lib, dynamic library dll, and application program exe actually all depend on system-level runtime (RunTime) support. For any C++ program running on a Windows system, it depends on the system's C++ runtime library (Microsoft Virtual C++). And for any .NET-based program (such as WPF, Winform, etc.) running on the Windows system, it must depend on the system's .NET runtime library (.NET Framework).

Because the programs we discussed above are all C++ programs, here we mainly discuss the C++ runtime library of the Windows system. I personally tested it, whether it is win7 or win10, after the system is installed or the system is automatically updated, the C++ runtime library (Microsoft Virtual C++) will be automatically installed, as shown below.

First of all, we need to know that there are many versions of Virtual C++, and the higher version is not necessarily backward compatible (for example, if a program depends on Virtual C++ 2010, your computer may not be able to run if only Virtual C++ 2012 is installed). Therefore, all currently supported versions of Virtual C++ are generally installed on the computer, including 2005/2008/2010/2012/2013/2015-2022, and the 2015-2022 version includes 2015 and later versions . In addition, the Virtual C++ version is divided into 32-bit (x86) and (x64). In the 64-bit Windows system, both the x86 and x64 versions of Virtual C++ will be installed, while in the 32-bit Windows system, only the x86 version of Virtual C++ will be installed.

In some special cases, some computers may not have Virtual C++ installed, or the version of Virtual C++ may not be complete. Then the program we send to the customer (such as helloworld_static.exe, or helloworld.exe+ceres.dll) may report an error saying that MSVCP140.dll is missing, such as:

The most direct solution is to download the corresponding version of Virtual C++ and install it on your computer. Generally, which version of the Virtual Studio development environment do we use to develop this C++ program, then this C++ program is based on the Virtual C++ integrated by this version of Virtual Studio. You can go to the property page of the project to view the specific version of the platform toolset. The version numbers of the toolset corresponding to each version of Virtual Studio are as follows:

-Visual Studio 2022: V143

-Visual Studio 2019: V142

-Visual Studio 2017: V141

-Visual Studio 2015: V140

-Visual Studio 2013: V120

-Visual Studio 2012: V110

-Visual Studio 2010: V100

-Visual Studio 2008: V90

-Visual Studio 2005: V80

-Visual Studio 2003: V71

-Visual Studio 2002: V70

-Visual Studio 6: V60

 If you don't know which version of Virtual C++ is missing, just install all Virtual C++ versions. The Virtual C++ installation package can be downloaded from Microsoft’s official website ( Latest supported Visual C++ Redistributable downloads | Microsoft Learn ). The installation package is a VC_redist executable file. After running, the corresponding version of Virtual C++ will be installed online. If it is troublesome to manually download each version of Virtual C++ one by one, you can go here ( Download Microsoft Visual C++ Redistributable (All Versions) ) to package and download all versions of Virtual C++.

But for ordinary users who do not understand technology, manually installing Virtual C++ is too complicated, and sometimes our C++ programs may depend on additional libraries such as MFC or ATL, because it is unrealistic for users to manually install these dependencies . In fact, when we compile our project, we can set "Copy C++ runtime to output directory" in the property page to "Yes".

  Then after compiling the project, in addition to generating exe and dll files written by ourselves, a large number of system-level dll files are also generated in the compilation output directory. We only need to copy all these system-level dlls and our own exe and dll files to the customer, and the computer on the customer's side can use the program normally no matter whether the system-level runtime environment is installed or not.

 3. Install the Ceres library with CMake

If you don't use the Virtual Studio development environment for development, then you have to use CMake to manually configure and compile Ceres and its dependent source code step by step. The specific steps are relatively cumbersome, let’s go directly to the official tutorial of Ceres:

Installation — Ceres Solver

references

[1] Zhang Hu, Robot SLAM Navigation Core Technology and Practice [M]. Machinery Industry Press, 2022.

Guess you like

Origin blog.csdn.net/m0_68732180/article/details/130233901