clang-tidy fixes, documentation, refactoring.

This commit is contained in:
Kyle Isom 2023-10-21 02:07:59 -07:00
parent 4e83da345f
commit aee337f2e9
26 changed files with 325 additions and 238 deletions

View File

@ -7,6 +7,7 @@ Checks: >-
performance-*, performance-*,
readability-*, readability-*,
-bugprone-lambda-function-name, -bugprone-lambda-function-name,
-bugprone-easily-swappable-parameters,
-bugprone-reserved-identifier, -bugprone-reserved-identifier,
-cppcoreguidelines-avoid-goto, -cppcoreguidelines-avoid-goto,
-cppcoreguidelines-avoid-magic-numbers, -cppcoreguidelines-avoid-magic-numbers,
@ -21,6 +22,7 @@ Checks: >-
-modernize-use-nodiscard, -modernize-use-nodiscard,
-modernize-use-trailing-return-type, -modernize-use-trailing-return-type,
-performance-unnecessary-value-param, -performance-unnecessary-value-param,
-readability-identifier-length,
-readability-magic-numbers -readability-magic-numbers
CheckOptions: CheckOptions:

View File

@ -41,23 +41,27 @@ set(HEADER_FILES
include/scsl/Buffer.h include/scsl/Buffer.h
include/scsl/Commander.h include/scsl/Commander.h
include/scsl/Dictionary.h include/scsl/Dictionary.h
include/sctest/Exceptions.h
include/scsl/Flags.h include/scsl/Flags.h
include/scsl/StringUtil.h include/scsl/StringUtil.h
include/scsl/TLV.h include/scsl/TLV.h
include/scmp/estimation.h
include/scmp/geom.h include/scmp/geom.h
include/scmp/scmp.h include/scmp/scmp.h
include/scmp/Math.h include/scmp/Math.h
include/scmp/Motion2D.h
include/scmp/geom/Coord2D.h include/scmp/geom/Coord2D.h
include/scmp/geom/Orientation.h include/scmp/geom/Orientation.h
include/scmp/geom/Quaternion.h include/scmp/geom/Quaternion.h
include/scmp/geom/Vector.h include/scmp/geom/Vector.h
include/scmp/filter/Madgwick.h include/scmp/estimation/Madgwick.h
include/sctest/sctest.h
include/sctest/Assert.h include/sctest/Assert.h
include/sctest/Checks.h
include/sctest/Debug.h
include/sctest/Exceptions.h
include/sctest/Report.h include/sctest/Report.h
include/sctest/SimpleSuite.h
) )
include_directories(include) include_directories(include)
@ -74,7 +78,6 @@ set(SOURCE_FILES
src/scmp/Math.cc src/scmp/Math.cc
src/scmp/Coord2D.cc src/scmp/Coord2D.cc
src/scmp/Motion2D.cc
src/scmp/Orientation.cc src/scmp/Orientation.cc
src/scmp/Quaternion.cc src/scmp/Quaternion.cc

View File

@ -22,8 +22,8 @@
/// PERFORMANCE OF THIS SOFTWARE. /// PERFORMANCE OF THIS SOFTWARE.
/// ///
#ifndef SCCCL_MATH_H #ifndef SCSL_SCMP_MATH_H
#define SCCCL_MATH_H #define SCSL_SCMP_MATH_H
#include <cmath> #include <cmath>
#include <vector> #include <vector>
@ -118,4 +118,4 @@ WithinTolerance(T a, T b, T epsilon)
} // namespace scmp } // namespace scmp
#endif //SCCCL_MATH_H #endif //SCSL_SCMP_MATH_H

View File

@ -1,21 +0,0 @@
//
// Created by Kyle Isom on 2/21/20.
//
#ifndef SCCCL_MOTION2D_H
#define SCCCL_MOTION2D_H
#include <scmp/geom/Vector.h>
namespace scmp {
namespace basic {
scmp::geom::Vector2D Acceleration(double speed, double heading);
} // namespace basic
} // namespace phsyics
#endif //SCCCL_MOTION2D_H

39
include/scmp/estimation.h Normal file
View File

@ -0,0 +1,39 @@
///
/// \file include/scmp/estimation.h
/// \author K. Isom <kyle@imap.cc>
/// \date 2023-10-20
/// \brief
///
/// Copyright 2023 K. Isom <kyle@imap.cc>
///
/// Permission to use, copy, modify, and/or distribute this software for
/// any purpose with or without fee is hereby granted, provided that
/// the above copyright notice and this permission notice appear in all /// copies.
///
/// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
/// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
/// WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
/// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
/// DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
/// OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
/// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
/// PERFORMANCE OF THIS SOFTWARE.
///
#include <scmp/estimation/Madgwick.h>
#ifndef SCSL_ESTIMATION_H
#define SCSL_ESTIMATION_H
namespace scmp {
/// \brief Algorithms for estimation position, and system state.
namespace estimation {}
}
#endif // SCSL_ESTIMATION_H

View File

@ -1,8 +1,8 @@
/// ///
/// \file include/scmp/filter/Madgwick.h /// \file include/scmp/estimation/Madgwick.h
/// \author K. Isom <kyle@imap.cc> /// \author K. Isom <kyle@imap.cc>
/// \date 2019-08-06 /// \date 2019-08-06
/// \brief Implementation of a Madgwick filter. /// \brief Implementation of a Madgwick estimation.
/// ///
/// See https://courses.cs.washington.edu/courses/cse466/14au/labs/l4/madgwick_internal_report.pdf. /// See https://courses.cs.washington.edu/courses/cse466/14au/labs/l4/madgwick_internal_report.pdf.
/// ///
@ -33,29 +33,29 @@
/// scmp contains the chimmering clarity math and physics code. /// scmp contains the chimmering clarity math and physics code.
namespace scmp { namespace scmp {
/// filter contains filtering algorithms. namespace estimation {
namespace filter {
/// @brief Madgwick implements an efficient Orientation filter for IMUs. /// \brief Madgwick implements an efficient Orientation estimation for
/// Intertial Measurement Units (IMUs).
/// ///
/// Madgwick is a novel Orientation filter applicable to IMUs /// Madgwick is a novel Orientation estimation applicable to IMUs
/// consisting of tri-Axis gyroscopes and accelerometers, and MARG /// consisting of tri-Axis gyroscopes and accelerometers, and MARG
/// sensor arrays that also include tri-Axis magnetometers. The MARG /// sensor arrays that also include tri-Axis magnetometers. The MARG
/// implementation incorporates magnetic distortionand gyroscope bias /// implementation incorporates magnetic distortionand gyroscope bias
/// drift compensation. /// drift compensation.
/// ///
/// It is described in the paper [An efficient Orientation filter for inertial and inertial/magnetic sensor arrays](http://x-io.co.uk/res/doc/madgwick_internal_report.pdf). /// It is described in the paper [An efficient Orientation estimation for inertial and inertial/magnetic sensor arrays](http://x-io.co.uk/res/doc/madgwick_internal_report.pdf).
/// ///
/// \tparam T A floating point type. /// \tparam T A floating point type.
template <typename T> template <typename T>
class Madgwick { class Madgwick {
public: public:
/// \brief The Madgwick filter is initialised with an identity MakeQuaternion. /// \brief The Madgwick estimation is initialised with an identity MakeQuaternion.
Madgwick() : deltaT(0.0), previousSensorFrame(), sensorFrame() Madgwick() : deltaT(0.0), previousSensorFrame(), sensorFrame()
{}; {};
/// \brief The Madgwick filter is initialised with a sensor frame. /// \brief The Madgwick estimation is initialised with a sensor frame.
/// ///
/// \param sf A sensor frame; if zero, the sensor frame will be /// \param sf A sensor frame; if zero, the sensor frame will be
/// initialised as an identity MakeQuaternion. /// initialised as an identity MakeQuaternion.
@ -66,7 +66,7 @@ public:
} }
} }
/// \brief Initialise the filter with a sensor frame MakeQuaternion. /// \brief Initialise the estimation with a sensor frame MakeQuaternion.
/// ///
/// \param sf A MakeQuaternion representing the current Orientation. /// \param sf A MakeQuaternion representing the current Orientation.
Madgwick(scmp::geom::Quaternion<T> sf) : Madgwick(scmp::geom::Quaternion<T> sf) :
@ -74,7 +74,7 @@ public:
{}; {};
/// \brief Return the current orientation as measured by the /// \brief Return the current orientation as measured by the
/// filter. /// estimation.
/// ///
/// \return The current sensor frame. /// \return The current sensor frame.
scmp::geom::Quaternion<T> scmp::geom::Quaternion<T>
@ -83,15 +83,16 @@ public:
return this->sensorFrame; return this->sensorFrame;
} }
/// \brief Return the filter's rate of angular change from a /// \brief Return the estimation's rate of angular change from a
/// sensor frame. /// sensor frame.
/// ///
/// Return the rate of change of the Orientation of the earth frame /// Return the rate of change of the Orientation of the earth
/// with respect to the sensor frame. /// frame with respect to the sensor frame.
/// ///
/// \param gyro A three-dimensional vector containing gyro readings /// \param gyro A three-dimensional vector containing gyro
/// as w_x, w_y, w_z. /// readings as w_x, w_y, w_z.
/// \return A MakeQuaternion representing the rate of angular change. /// \return A MakeQuaternion representing the rate of angular
/// change.
scmp::geom::Quaternion<T> scmp::geom::Quaternion<T>
AngularRate(const scmp::geom::Vector<T, 3> &gyro) const AngularRate(const scmp::geom::Vector<T, 3> &gyro) const
{ {
@ -112,8 +113,8 @@ public:
/// \brief Update the sensor frame to a new frame. /// \brief Update the sensor frame to a new frame.
/// ///
/// \warning The filter's default Δt must be set before calling /// \warning The estimation's default Δt must be set before
// this. /// calling this.
/// ///
/// \param sf The new sensor frame replacing the previous one. /// \param sf The new sensor frame replacing the previous one.
void void
@ -129,9 +130,10 @@ public:
/// the compile flag NDEBUG, but may be useful to catch /// the compile flag NDEBUG, but may be useful to catch
/// possible errors. /// possible errors.
/// ///
/// \param gyro A three-dimensional vector containing gyro readings /// \param gyro A three-dimensional vector containing gyro
/// as w_x, w_y, w_z. /// readings as w_x, w_y, w_z.
/// \param delta The time step between readings. It must not be zero. /// \param delta The time step between readings. It must not
/// be zero.
void void
UpdateAngularOrientation(const scmp::geom::Vector<T, 3> &gyro, T delta) UpdateAngularOrientation(const scmp::geom::Vector<T, 3> &gyro, T delta)
{ {
@ -147,20 +149,21 @@ public:
/// \brief Update the sensor frame with a gyroscope reading. /// \brief Update the sensor frame with a gyroscope reading.
/// ///
/// If no Δt is provided, the filter's default is used. /// If no Δt is provided, the estimation's default is used.
/// ///
/// \warning The default Δt must be explicitly set using DeltaT /// \warning The default Δt must be explicitly set using DeltaT
/// before calling this. /// before calling this.
/// ///
/// \param gyro A three-dimensional vector containing gyro readings /// \param gyro A three-dimensional vector containing gyro
/// as w_x, w_y, w_z. /// readings as w_x, w_y, w_z.
void void
UpdateAngularOrientation(const scmp::geom::Vector<T, 3> &gyro) UpdateAngularOrientation(const scmp::geom::Vector<T, 3> &gyro)
{ {
this->UpdateAngularOrientation(gyro, this->deltaT); this->UpdateAngularOrientation(gyro, this->deltaT);
} }
/// \brief Retrieve a vector of the Euler angles in ZYX Orientation. /// \brief Retrieve a vector of the Euler angles in ZYX
/// Orientation.
/// ///
/// \return A vector of Euler angles as <ψ, θ, ϕ>. /// \return A vector of Euler angles as <ψ, θ, ϕ>.
scmp::geom::Vector<T, 3> scmp::geom::Vector<T, 3>
@ -172,19 +175,19 @@ public:
/// \brief Set the default Δt. /// \brief Set the default Δt.
/// ///
/// \note This must be explicitly called before calling any /// \note This must be explicitly called before calling any
/// method which uses the filter's internal Δt. /// method which uses the estimation's internal Δt.
/// ///
/// \param newDeltaT The time delta to use when no time delta is /// \param newDeltaT The time delta to use when no time delta
/// provided. /// is provided.
void void
DeltaT(T newDeltaT) DeltaT(T newDeltaT)
{ {
this->deltaT = newDeltaT; this->deltaT = newDeltaT;
} }
/// \brief Retrieve the filter's current ΔT. /// \brief Retrieve the estimation's current ΔT.
/// ///
/// \return The current value the filter will default to using /// \return The current value the estimation will default to using
/// if no time delta is provided. /// if no time delta is provided.
T DeltaT() { return this->deltaT; } T DeltaT() { return this->deltaT; }
@ -202,7 +205,7 @@ using Madgwickd = Madgwick<double>;
using Madgwickf = Madgwick<float>; using Madgwickf = Madgwick<float>;
} // namespace filter } // namespace estimation
} // namespace scmp } // namespace scmp

View File

@ -91,19 +91,19 @@ float Heading2F(Vector2F vec);
/// ///
/// \param vec A vector Orientation. /// \param vec A vector Orientation.
/// \return The compass heading of the vector in radians. /// \return The compass heading of the vector in radians.
double Heading2d(Vector2D vec); double Heading2D(Vector2D vec);
/// \brief Compass heading for a Vector2F. /// \brief Compass heading for a Vector2F.
/// ///
/// \param vec A vector Orientation. /// \param vec A vector Orientation.
/// \return The compass heading of the vector in radians. /// \return The compass heading of the vector in radians.
float Heading3f(Vector3F vec); float Heading3F(Vector3F vec);
/// Heading3d returns a compass heading for a Vector2F. /// Heading3D returns a compass heading for a Vector2F.
/// ///
/// \param vec A vector Orientation. /// \param vec A vector Orientation.
/// \return The compass heading of the vector in radians. /// \return The compass heading of the vector in radians.
double Heading3d(Vector3D vec); double Heading3D(Vector3D vec);
} // namespace geom } // namespace geom

View File

@ -61,7 +61,7 @@ enum class ArenaType
}; };
/// Arena is the class that implements a memory arena. /// \brief Fixed, pre-allocated memory.
/// ///
/// The Arena uses the concept of a cursor to point to memory in the arena. The /// The Arena uses the concept of a cursor to point to memory in the arena. The
/// #Start and #End methods return pointers to the start and end of the /// #Start and #End methods return pointers to the start and end of the

View File

@ -1,5 +1,5 @@
/// ///
/// \file Buffer.h /// \file include/scsl/Buffer.h
/// \author K. Isom <kyle@imap.cc> /// \author K. Isom <kyle@imap.cc>
/// \date 2023-10-09 /// \date 2023-10-09
/// \brief Buffer implements basic line buffers. /// \brief Buffer implements basic line buffers.
@ -33,7 +33,7 @@
namespace scsl { namespace scsl {
/// Buffer is a basic line buffer. /// \brief Basic line buffer.
/// ///
/// The buffer manages its own internal memory, growing and shrinking /// The buffer manages its own internal memory, growing and shrinking
/// as needed. Its capacity is separate from its length; the optimal /// as needed. Its capacity is separate from its length; the optimal

View File

@ -1,5 +1,5 @@
/// ///
/// \file Commander.h /// \file include/scsl/Commander.h
/// \author K. Isom <kyle@imap.cc> /// \author K. Isom <kyle@imap.cc>
/// \date 2023-10-10 /// \date 2023-10-10
/// \brief Subprogram tooling. /// \brief Subprogram tooling.
@ -47,6 +47,8 @@ namespace scsl {
using CommanderFunc = std::function<bool (int, char **)>; using CommanderFunc = std::function<bool (int, char **)>;
/// \brief Subcommands used by Commander.
///
/// Subcommands are the individual commands for the program. A Subcommand /// Subcommands are the individual commands for the program. A Subcommand
/// will check that it has enough arguments before running its function. /// will check that it has enough arguments before running its function.
class Subcommand { class Subcommand {
@ -89,6 +91,8 @@ private:
std::string command; std::string command;
}; };
/// \brief Subcommander manager for programs.
///
/// Commander collects subcommands and can run the apppropriate one. /// Commander collects subcommands and can run the apppropriate one.
/// ///
/// For example: /// For example:

View File

@ -1,5 +1,5 @@
/// ///
/// \file Dictionary.h /// \file include/scsl/Dictionary.h
/// \author kyle (kyle@imap.cc) /// \author kyle (kyle@imap.cc)
/// \date 2023-10-12 /// \date 2023-10-12
/// \brief Key-value store built on top of Arena and TLV. /// \brief Key-value store built on top of Arena and TLV.
@ -39,11 +39,7 @@ static constexpr uint8_t DICTIONARY_TAG_VAL = 2;
namespace scsl { namespace scsl {
/* /// \brief Key-value store on top of Arena and TLV::Record.
* A Dictionary is a collection of key-value pairs, similar to how
* a dictionary is a mapping of names to definitions.
*/
/// Dictionary implements a key-value store on top of Arena and TLV::Record.
/// ///
/// Keys and vales are stored as sequential pairs of TLV records; they are /// Keys and vales are stored as sequential pairs of TLV records; they are
/// expected to contain string values but this isn't necessarily the case. The /// expected to contain string values but this isn't necessarily the case. The

View File

@ -55,7 +55,7 @@ typedef union {
} FlagValue; } FlagValue;
/// Flag describes an individual command-line flag. /// \brief Individual command-line flag
typedef struct { typedef struct {
FlagType Type; ///< The type of the value in the flag. FlagType Type; ///< The type of the value in the flag.
bool WasSet; ///< The flag was set on the command-line. bool WasSet; ///< The flag was set on the command-line.
@ -64,7 +64,7 @@ typedef struct {
FlagValue Value; ///< The flag's value. FlagValue Value; ///< The flag's value.
} Flag; } Flag;
/// NewFlag is a helper function for constructing a new flag. /// \brief NewFlag is a helper function for constructing a new flag.
/// ///
/// \param fName The name of the flag. /// \param fName The name of the flag.
/// \param fType The type of the flag. /// \param fType The type of the flag.
@ -72,7 +72,7 @@ typedef struct {
/// \return A pointer to a flag. /// \return A pointer to a flag.
Flag *NewFlag(std::string fName, FlagType fType, std::string fDescription); Flag *NewFlag(std::string fName, FlagType fType, std::string fDescription);
/// Flags provides a basic facility for processing command line flags. /// \brief Basic facility for processing command line flags.
/// ///
/// Any remaining arguments after the args are added to the parser as /// Any remaining arguments after the args are added to the parser as
/// arguments that can be accessed with NumArgs, Args, and Arg. /// arguments that can be accessed with NumArgs, Args, and Arg.

View File

@ -1,5 +1,5 @@
/// ///
/// \file StringUtil.h /// \file include/scsl/StringUtil.h
/// \author K. Isom <kyle@imap.cc> /// \author K. Isom <kyle@imap.cc>
/// \date 2023-10-14 /// \date 2023-10-14
/// \brief Utilities for working with strings. /// \brief Utilities for working with strings.
@ -32,11 +32,8 @@
namespace scsl { namespace scsl {
/// namespace U contains utilities. /// String-related utility functions.
namespace U { namespace string {
/// namespace S contains string-related functions.
namespace S {
/// Remove any whitespace At the beginning of the string. The string /// Remove any whitespace At the beginning of the string. The string
@ -125,8 +122,7 @@ std::ostream &VectorToString(std::ostream &os, const std::vector<std::string> &s
std::string VectorToString(const std::vector<std::string> &svec); std::string VectorToString(const std::vector<std::string> &svec);
} // namespace S } // namespace string
} // namespace U
} // namespace scsl } // namespace scsl

View File

@ -1,5 +1,5 @@
/// ///
/// \file TLV.h /// \file include/scsl/TLV.h
/// \author K. Isom <kyle@imap.cc> /// \author K. Isom <kyle@imap.cc>
/// \date 2023-10-06 /// \date 2023-10-06
/// \brief TLV.h implements basic tag-length-value records. /// \brief TLV.h implements basic tag-length-value records.
@ -21,6 +21,8 @@
namespace scsl { namespace scsl {
/// \brief Tag-length-value record tooling
namespace TLV { namespace TLV {
@ -31,7 +33,7 @@ static constexpr size_t TLV_MAX_LEN = 253;
static constexpr uint8_t TAG_EMPTY = 0; static constexpr uint8_t TAG_EMPTY = 0;
/// Record describes a tag-length-value record. /// \brief Tag-length-value record with single byte tags and lengths.
/// ///
/// TLV records occupy a fixed size in memory, which can be controlled with the /// TLV records occupy a fixed size in memory, which can be controlled with the
/// TLV_MAX_LEN define. If this isn't defined, it defaults to a size of 253. /// TLV_MAX_LEN define. If this isn't defined, it defaults to a size of 253.

View File

@ -1,5 +1,5 @@
/// ///
/// \file Exceptions.h /// \file include/sctest/Exceptions.h
/// \author K. Isom <kyle@imap.cc> /// \author K. Isom <kyle@imap.cc>
/// \date 2023-10-10 /// \date 2023-10-10
/// \brief Custom exceptions for use in SCSL used in writing test programs. /// \brief Custom exceptions for use in SCSL used in writing test programs.
@ -31,7 +31,7 @@
namespace sctest { namespace sctest {
/// NotImplemented is an exception reserved for unsupported platforms. /// \brief Exception reserved for unsupported platforms.
/// ///
/// It is used to mark functionality included for compatibility, and useful for /// It is used to mark functionality included for compatibility, and useful for
/// debugging. /// debugging.

View File

@ -1,26 +1,25 @@
// ///
// Project: scccl /// \file include/sctest/Report.h
// File: include/test/Report.h /// \author K. Isom <kyle@imap.cc>
// Author: Kyle Isom /// \date 2017-06-05
// Date: 2017-06-05 /// \brief Unit test reporting class.
// Namespace: test ///
// /// Copyright 2017 K. Isom <kyle@imap.cc>
// Report.h defines a Report structure that contains information about ///
// the results of unit tests. /// Permission to use, copy, modify, and/or distribute this software for
// /// any purpose with or without fee is hereby granted, provided that
// Copyright 2017 Kyle Isom <kyle@imap.cc> /// the above copyright notice and this permission notice appear in all /// copies.
// ///
// Licensed under the Apache License, Version 2.0 (the "License"); /// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
// you may not use this file except in compliance with the License. /// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
// You may obtain a copy of the License At /// WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
// /// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
// http://www.apache.org/licenses/LICENSE-2.0 /// DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
// /// OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
// Unless required by applicable law or agreed to in writing, software /// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// distributed under the License is distributed on an "AS IS" BASIS, /// PERFORMANCE OF THIS SOFTWARE.
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ///
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef SCTEST_REPORT_H #ifndef SCTEST_REPORT_H
#define SCTEST_REPORT_H #define SCTEST_REPORT_H
@ -28,9 +27,15 @@
namespace sctest { namespace sctest {
/// \brief A Report holds test run results.
///
/// This is designed to work with SimpleSuite, but might be useful
/// for other things.
class Report { class Report {
public: public:
/// \brief Construct a new Report, zeroed out.
Report();
/// \brief Failing returns the count of failed tests. /// \brief Failing returns the count of failed tests.
/// ///
/// \details If a test is run and expected to pass, but fails, /// \details If a test is run and expected to pass, but fails,
@ -40,24 +45,48 @@ public:
/// \return The number of tests that failed. /// \return The number of tests that failed.
size_t Failing() const; size_t Failing() const;
/// \brief Returns the number of tests that have passed /// \brief The number of tests that have passed successfully.
/// successfully.
size_t Passing() const; size_t Passing() const;
/// \brief Total is the number of tests registered. /// \brief The number of tests registered.
size_t Total() const; size_t Total() const;
/// \brief Report a test as having failed.
void Failed(); void Failed();
/// \brief Report a test as having passed.
void Passed(); void Passed();
/// \brief Register more tests in the report.
///
/// This is used to track the total number of tests in the
/// report.
void AddTest(size_t testCount = 0); void AddTest(size_t testCount = 0);
/// \brief Reset the internal state.
///
/// All fields in the Report will be zeroed out.
///
/// \param testCount
void Reset(size_t testCount = 0); void Reset(size_t testCount = 0);
/// \brief Mark the start of test runs.
///
/// This is used for tracking how long the tests took to complete.
void Start(); void Start();
/// \brief Mark the end of test runs.
///
/// This is used for tracking how long the tests took to complete.
void End(); void End();
/// \brief Retrieve how long the tests took to run.
///
/// This only makes sense to run after called to Start and End.
///
/// \return The number of milliseconds that have elapsed.
std::chrono::duration<double, std::milli> std::chrono::duration<double, std::milli>
Elapsed() const; Elapsed() const;
Report();
private: private:
size_t failing; size_t failing;
size_t passed; size_t passed;

View File

@ -1,5 +1,5 @@
/// ///
/// \file SimpleSuite.h /// \file include/sctest/SimpleSuite.h
/// \author K. Isom <kyle@imap.cc> /// \author K. Isom <kyle@imap.cc>
/// \date 2017-06-05 /// \date 2017-06-05
/// \brief Defines a simple unit testing framework. /// \brief Defines a simple unit testing framework.
@ -33,8 +33,9 @@
namespace sctest { namespace sctest {
/// \brief UnitTest describes a single unit test. It is a predicate: /// \brief UnitTest describes a single unit test.
/// did the test pass? ///
/// It is a predicate: did the test pass?
struct UnitTest { struct UnitTest {
/// What name should be shown when running tests? /// What name should be shown when running tests?
std::string name; std::string name;
@ -99,12 +100,13 @@ public:
/// resetting the suite's internal state. /// resetting the suite's internal state.
void Reset(); void Reset();
/// \brief /// \brief Returns true if Run has been called.
// HasRun returns true if a report is ready.
bool HasRun() const; bool HasRun() const;
// Report returns a Report. /// \brief Retrieve the test run results.
Report GetReport(void); ///
/// The results will only be valid if Run has been called.
Report GetReport();
private: private:
bool quiet; bool quiet;

37
include/sctest/sctest.h Normal file
View File

@ -0,0 +1,37 @@
///
/// \file include/sctest/sctest.h
/// \author K. Isom <kyle@imap.cc>
/// \date 2023-10-20
/// \brief Shimmering Clarity testing code.
///
/// Copyright 2023 K. Isom <kyle@imap.cc>
///
/// Permission to use, copy, modify, and/or distribute this software for
/// any purpose with or without fee is hereby granted, provided that
/// the above copyright notice and this permission notice appear in all /// copies.
///
/// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
/// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
/// WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
/// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
/// DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
/// OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
/// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
/// PERFORMANCE OF THIS SOFTWARE.
///
#include <sctest/Assert.h>
#include <sctest/Checks.h>
#include <sctest/Debug.h>
#include <sctest/Exceptions.h>
#include <sctest/Report.h>
#include <sctest/SimpleSuite.h>
#ifndef SCSL_SCTEST_H
#define SCSL_SCTEST_H
/// \brief Shimmering Clarity testing library.
namespace sctest {}
#endif // SCSL_SCTEST_H

View File

@ -30,11 +30,6 @@
#include <scmp/geom/Vector.h> #include <scmp/geom/Vector.h>
// coord2d.cpp contains 2D geometric functions and data structures, such as
// cartesian and polar coordinates and rotations.
// TODO: deprecate Point2D in favour of Vector
namespace scmp { namespace scmp {
namespace geom { namespace geom {
@ -60,7 +55,7 @@ Point2D::Point2D(const Polar2D &pol)
int int
Point2D::X() const Point2D::X() const
{ {
return this->At(0); return this->At(BasisX);
} }
@ -74,21 +69,21 @@ Point2D::X(int _x)
int int
Point2D::Y() const Point2D::Y() const
{ {
return this->At(1); return this->At(BasisY);
} }
void void
Point2D::Y(int _y) Point2D::Y(int _y)
{ {
this->Set(1, _y); this->Set(BasisY, _y);
} }
std::ostream & std::ostream &
operator<<(std::ostream &outs, const Point2D &pt) operator<<(std::ostream &outs, const Point2D &pt)
{ {
outs << "(" << std::to_string(pt[0]) << ", " << std::to_string(pt[1]) << ")"; outs << "(" << std::to_string(pt.X()) << ", " << std::to_string(pt.Y()) << ")";
return outs; return outs;
} }
@ -192,8 +187,8 @@ Polar2D::Theta(const double _theta)
void void
Polar2D::ToPoint(Point2D &point) Polar2D::ToPoint(Point2D &point)
{ {
point.Y(std::rint(std::sin(this->Theta()) * this->R())); point.Y(static_cast<int>(std::rint(std::sin(this->Theta()) * this->R())));
point.X(std::rint(std::cos(this->Theta()) * this->R())); point.X(static_cast<int>(std::rint(std::cos(this->Theta()) * this->R())));
} }
@ -232,4 +227,4 @@ operator<<(std::ostream &outs, const Polar2D &pol)
} // end namespace geom } // end namespace geom
} // end namespace math } // end namespace scmp

View File

@ -1,19 +0,0 @@
#include <cmath>
#include <scmp/Motion2D.h>
namespace scmp {
namespace basic {
scmp::geom::Vector2D
Acceleration(double speed, double heading)
{
auto dx = std::cos(heading) * speed;
auto dy = std::sin(heading) * speed;
return scmp::geom::Vector2D({dx, dy});
}
} // namespace basic
} // namespace phys

View File

@ -1,3 +1,26 @@
///
/// \file src/scmp/geom/Orientation.cc
/// \author K. Isom <kyle@imap.cc>
/// \date 2017-06-05
/// \brief Orientation of vectors w.r.t. a reference plane, assumed to
/// be the Earth.
///
/// Copyright 2017 K. Isom <kyle@imap.cc>
///
/// Permission to use, copy, modify, and/or distribute this software for
/// any purpose with or without fee is hereby granted, provided that
/// the above copyright notice and this permission notice appear in all /// copies.
///
/// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
/// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
/// WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
/// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
/// DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
/// OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
/// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
/// PERFORMANCE OF THIS SOFTWARE.
///
#include <scmp/geom/Vector.h> #include <scmp/geom/Vector.h>
#include <scmp/geom/Orientation.h> #include <scmp/geom/Orientation.h>
@ -14,25 +37,25 @@ Heading2F(Vector2F vec)
float float
Heading3f(Vector3F vec) Heading3F(Vector3F vec)
{ {
Vector2F vec2f {vec[0], vec[1]}; const Vector2F vec2f {vec.At(BasisX), vec.At(BasisY)};
return Heading2F(vec2f); return Heading2F(vec2f);
} }
double double
Heading2d(Vector2D vec) Heading2D(Vector2D vec)
{ {
return vec.Angle(Basis2D[BasisX]); return vec.Angle(Basis2D[BasisX]);
} }
double double
Heading3d(Vector3D vec) Heading3D(Vector3D vec)
{ {
Vector2D vec2d {vec[0], vec[1]}; const Vector2D vec2d {vec.At(BasisX), vec.At(BasisY)};
return Heading2d(vec2d); return Heading2D(vec2d);
} }

View File

@ -58,7 +58,7 @@ Flags::ParseStatusToString(ParseStatus status)
Flag * Flag *
NewFlag(std::string fName, FlagType fType, std::string fDescription) NewFlag(std::string fName, FlagType fType, std::string fDescription)
{ {
auto flag = new Flag; auto *flag = new Flag;
flag->Type = fType; flag->Type = fType;
flag->WasSet = false; flag->WasSet = false;
@ -71,9 +71,8 @@ NewFlag(std::string fName, FlagType fType, std::string fDescription)
Flags::Flags(std::string fName) Flags::Flags(std::string fName)
: name(std::move(fName)), description("") : name(std::move(fName))
{ {}
}
Flags::Flags(std::string fName, std::string fDescription) Flags::Flags(std::string fName, std::string fDescription)
@ -104,7 +103,7 @@ Flags::Register(std::string fName, FlagType fType, std::string fDescription)
return false; return false;
} }
auto flag = NewFlag(fName, fType, std::move(fDescription)); auto *flag = NewFlag(fName, fType, std::move(fDescription));
assert(flag != nullptr); assert(flag != nullptr);
this->flags[fName] = flag; this->flags[fName] = flag;
return true; return true;
@ -194,7 +193,7 @@ Flags::Lookup(std::string fName)
bool bool
Flags::ValueOf(std::string fName, FlagValue &value) Flags::ValueOf(std::string fName, FlagValue &value)
{ {
if (this->flags.count(fName)) { if (this->flags.count(fName) != 0U) {
return false; return false;
} }
@ -207,7 +206,7 @@ Flags::ParseStatus
Flags::parseArg(int argc, char **argv, int &index) Flags::parseArg(int argc, char **argv, int &index)
{ {
std::string arg(argv[index]); std::string arg(argv[index]);
U::S::TrimWhitespace(arg); string::TrimWhitespace(arg);
index++; index++;
if (!std::regex_search(arg, isFlag)) { if (!std::regex_search(arg, isFlag)) {
@ -221,7 +220,7 @@ Flags::parseArg(int argc, char **argv, int &index)
return ParseStatus::NotRegistered; return ParseStatus::NotRegistered;
} }
auto flag = flags[arg]; auto *flag = flags[arg];
if ((flag->Type != FlagType::Boolean) && index == argc) { if ((flag->Type != FlagType::Boolean) && index == argc) {
return ParseStatus::NotEnoughArgs; return ParseStatus::NotEnoughArgs;
} }
@ -233,11 +232,11 @@ Flags::parseArg(int argc, char **argv, int &index)
return ParseStatus::OK; return ParseStatus::OK;
case FlagType::Integer: case FlagType::Integer:
flag->WasSet = true; flag->WasSet = true;
flag->Value.i = std::stoi(argv[++index], 0, 0); flag->Value.i = std::stoi(argv[++index], nullptr, 0);
return ParseStatus::OK; return ParseStatus::OK;
case FlagType::UnsignedInteger: case FlagType::UnsignedInteger:
flag->WasSet = true; flag->WasSet = true;
flag->Value.u = static_cast<unsigned int>(std::stoi(argv[index++], 0, 0)); flag->Value.u = static_cast<unsigned int>(std::stoi(argv[index++], nullptr, 0));
return ParseStatus::OK; return ParseStatus::OK;
case FlagType::String: case FlagType::String:
flag->WasSet = true; flag->WasSet = true;
@ -275,7 +274,7 @@ Flags::Parse(int argc, char **argv, bool skipFirst)
case ParseStatus::EndOfFlags: case ParseStatus::EndOfFlags:
while (index < argc) { while (index < argc) {
this->args.push_back(std::string(argv[index])); this->args.emplace_back(argv[index]);
index++; index++;
} }
continue; continue;
@ -303,7 +302,7 @@ Flags::Usage(std::ostream &os, int exitCode)
os << this->name << ":\t"; os << this->name << ":\t";
auto indent = this->name.size() + 7; auto indent = this->name.size() + 7;
U::S::WriteTabIndented(os, description, 72 - indent, indent / 8, false); string::WriteTabIndented(os, description, 72 - indent, indent / 8, false);
os << "\n\n"; os << "\n\n";
for (const auto &pair : this->flags) { for (const auto &pair : this->flags) {
@ -337,7 +336,7 @@ Flags::Usage(std::ostream &os, int exitCode)
os << argLine; os << argLine;
indent = argLine.size(); indent = argLine.size();
U::S::WriteTabIndented(os, pair.second->Description, string::WriteTabIndented(os, pair.second->Description,
72-indent, (indent/8)+2, false); 72-indent, (indent/8)+2, false);
} }
@ -374,11 +373,11 @@ Flags::Arg(size_t i)
Flag * Flag *
Flags::checkGetArg(std::string& fName, FlagType eType) Flags::checkGetArg(std::string& fName, FlagType eType)
{ {
if (this->flags[fName] == 0) { if (this->flags[fName] == nullptr) {
return nullptr; return nullptr;
} }
auto flag = this->flags[fName]; auto *flag = this->flags[fName];
if (flag == nullptr) { if (flag == nullptr) {
return nullptr; return nullptr;
} }
@ -394,7 +393,7 @@ Flags::checkGetArg(std::string& fName, FlagType eType)
bool bool
Flags::GetBool(std::string fName, bool &flagValue) Flags::GetBool(std::string fName, bool &flagValue)
{ {
auto flag = this->checkGetArg(fName, FlagType::Boolean); auto *flag = this->checkGetArg(fName, FlagType::Boolean);
flagValue = flag->Value.b; flagValue = flag->Value.b;
return flag->WasSet; return flag->WasSet;
@ -404,7 +403,7 @@ Flags::GetBool(std::string fName, bool &flagValue)
bool bool
Flags::GetInteger(std::string fName, int &flagValue) Flags::GetInteger(std::string fName, int &flagValue)
{ {
auto flag = this->checkGetArg(fName, FlagType::Integer); auto *flag = this->checkGetArg(fName, FlagType::Integer);
flagValue = flag->Value.i; flagValue = flag->Value.i;
return flag->WasSet; return flag->WasSet;
@ -414,7 +413,7 @@ Flags::GetInteger(std::string fName, int &flagValue)
bool bool
Flags::GetUnsignedInteger(std::string fName, unsigned int &flagValue) Flags::GetUnsignedInteger(std::string fName, unsigned int &flagValue)
{ {
auto flag = this->checkGetArg(fName, FlagType::UnsignedInteger); auto *flag = this->checkGetArg(fName, FlagType::UnsignedInteger);
flagValue = flag->Value.u; flagValue = flag->Value.u;
return flag->WasSet; return flag->WasSet;
@ -424,7 +423,7 @@ Flags::GetUnsignedInteger(std::string fName, unsigned int &flagValue)
bool bool
Flags::GetSizeT(std::string fName, std::size_t &flagValue) Flags::GetSizeT(std::string fName, std::size_t &flagValue)
{ {
auto flag = this->checkGetArg(fName, FlagType::SizeT); auto *flag = this->checkGetArg(fName, FlagType::SizeT);
flagValue = flag->Value.size; flagValue = flag->Value.size;
return flag->WasSet; return flag->WasSet;
@ -434,7 +433,7 @@ Flags::GetSizeT(std::string fName, std::size_t &flagValue)
bool bool
Flags::GetString(std::string fName, std::string &flagValue) Flags::GetString(std::string fName, std::string &flagValue)
{ {
auto flag = this->checkGetArg(fName, FlagType::String); auto *flag = this->checkGetArg(fName, FlagType::String);
if (flag->Value.s == nullptr) { if (flag->Value.s == nullptr) {
return false; return false;

View File

@ -28,11 +28,7 @@
namespace scsl { namespace scsl {
/// namespace U contains utilities. namespace string {
namespace U {
/// namespace S contains string-related functions.
namespace S {
std::vector<std::string> std::vector<std::string>
@ -40,9 +36,11 @@ SplitKeyValuePair(std::string line, std::string delimiter)
{ {
auto pair = SplitN(std::move(line), std::move(delimiter), 2); auto pair = SplitN(std::move(line), std::move(delimiter), 2);
if (pair.size() == 0) { if (pair.empty()) {
return {"", ""}; return {"", ""};
} else if (pair.size() == 1) { }
if (pair.size() == 1) {
return {pair[0], ""}; return {pair[0], ""};
} }
@ -61,7 +59,7 @@ SplitKeyValuePair(std::string line, char delimiter)
{ {
std::string sDelim; std::string sDelim;
sDelim.push_back(std::move(delimiter)); sDelim.push_back(delimiter);
return SplitKeyValuePair(std::move(line), sDelim); return SplitKeyValuePair(std::move(line), sDelim);
} }
@ -72,7 +70,7 @@ TrimLeadingWhitespace(std::string &s)
s.erase(s.begin(), s.erase(s.begin(),
std::find_if(s.begin(), s.end(), std::find_if(s.begin(), s.end(),
[](unsigned char ch) { [](unsigned char ch) {
return !std::isspace(ch); return std::isspace(ch) == 0;
})); }));
} }
@ -81,7 +79,7 @@ void
TrimTrailingWhitespace(std::string &s) TrimTrailingWhitespace(std::string &s)
{ {
s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) { s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) {
return !std::isspace(ch); return std::isspace(ch) == 0;
}).base(), s.end()); }).base(), s.end());
} }
@ -125,9 +123,9 @@ SplitN(std::string s, std::string delim, size_t maxCount)
size_t ss = 0; size_t ss = 0;
size_t se = 0; size_t se = 0;
for (ss = 0; s.size() != 0 && ss < s.size(); ss++) { for (ss = 0; !s.empty() && ss < s.size(); ss++) {
se = s.find(delim, ss); se = s.find(delim, ss);
if ((maxCount > 0) && (parts.size() == maxCount - 1)) { if ((maxCount > 0) && (parts.size() == (maxCount - 1))) {
se = s.size(); se = s.size();
} else if (se == std::string::npos) { } else if (se == std::string::npos) {
se = s.size(); se = s.size();
@ -155,7 +153,7 @@ WrapText(std::string& line, size_t lineLength)
std::string wLine; std::string wLine;
for (auto &word: parts) { for (auto &word: parts) {
if (word.size() == 0) { if (word.empty()) {
continue; continue;
} }
@ -164,13 +162,13 @@ WrapText(std::string& line, size_t lineLength)
wLine.clear(); wLine.clear();
} }
if (wLine.size() > 0) { if (!wLine.empty()) {
wLine += " "; wLine += " ";
} }
wLine += word; wLine += word;
} }
if (wLine.size() > 0) { if (!wLine.empty()) {
wrapped.push_back(wLine); wrapped.push_back(wLine);
} }
@ -182,7 +180,7 @@ void
WriteTabIndented(std::ostream &os, std::vector<std::string> lines, WriteTabIndented(std::ostream &os, std::vector<std::string> lines,
int tabStop, bool indentFirst) int tabStop, bool indentFirst)
{ {
std::string indent(tabStop, '\t'); std::string const indent(tabStop, '\t');
for (size_t i = 0; i < lines.size(); i++) { for (size_t i = 0; i < lines.size(); i++) {
if (i > 0 || indentFirst) { if (i > 0 || indentFirst) {
@ -230,6 +228,5 @@ VectorToString(const std::vector<std::string> &svec)
} }
} // namespace S } // namespace string
} // namespace U
} // namespace scsl } // namespace scsl

View File

@ -7,7 +7,7 @@
#include <scmp/geom/Quaternion.h> #include <scmp/geom/Quaternion.h>
#include <scmp/Math.h> #include <scmp/Math.h>
#include <scmp/filter/Madgwick.h> #include <scmp/estimation/Madgwick.h>
#include <sctest/Assert.h> #include <sctest/Assert.h>
#include <sctest/Checks.h> #include <sctest/Checks.h>
#include <sctest/SimpleSuite.h> #include <sctest/SimpleSuite.h>
@ -20,22 +20,22 @@ using namespace scmp;
bool bool
SimpleAngularOrientationFloat() SimpleAngularOrientationFloat()
{ {
filter::Madgwickf mflt; estimation::Madgwickf estimation;
const geom::Vector3F gyro{0.174533, 0.0, 0.0}; // 10° X rotation. const geom::Vector3F gyro{0.174533, 0.0, 0.0}; // 10° X rotation.
const geom::Quaternionf frame20Deg{0.984808, 0.173648, 0, 0}; // 20° final Orientation. const geom::Quaternionf frame20Deg{0.984808, 0.173648, 0, 0}; // 20° final Orientation.
const float delta = 0.00917; // assume 109 updates per second, as per the paper. const float delta = 0.00917; // assume 109 updates per second, as per the paper.
const float twentyDegrees = scmp::DegreesToRadiansF(20.0); const float twentyDegrees = scmp::DegreesToRadiansF(20.0);
// The paper specifies a minimum of 109 IMU readings to stabilize; for // The paper specifies a minimum of 109 IMU readings to stabilize; for
// two seconds, that means 218 updates. // two seconds, that means 218 updates.
for (int i = 0; i < 218; i++) { for (int i = 0; i < 218; i++) {
mflt.UpdateAngularOrientation(gyro, delta); estimation.UpdateAngularOrientation(gyro, delta);
} }
SCTEST_CHECK_EQ(mflt.Orientation(), frame20Deg); SCTEST_CHECK_EQ(estimation.Orientation(), frame20Deg);
auto euler = mflt.Euler(); auto euler = estimation.Euler();
SCTEST_CHECK_FEQ_EPS(euler[0], twentyDegrees, 0.01); SCTEST_CHECK_FEQ_EPS(euler[0], twentyDegrees, 0.01);
SCTEST_CHECK_FEQ_EPS(euler[1], 0.0, 0.01); SCTEST_CHECK_FEQ_EPS(euler[1], 0.0, 0.01);
SCTEST_CHECK_FEQ_EPS(euler[2], 0.0, 0.01); SCTEST_CHECK_FEQ_EPS(euler[2], 0.0, 0.01);
@ -47,7 +47,7 @@ SimpleAngularOrientationFloat()
bool bool
SimpleAngularOrientationFloatDefaultDT() SimpleAngularOrientationFloatDefaultDT()
{ {
filter::Madgwickf mflt; estimation::Madgwickf mflt;
const geom::Vector3F gyro{0.174533, 0.0, 0.0}; // 10° X rotation. const geom::Vector3F gyro{0.174533, 0.0, 0.0}; // 10° X rotation.
const geom::Quaternionf frame20Deg{0.984808, 0.173648, 0, 0}; // 20° final Orientation. const geom::Quaternionf frame20Deg{0.984808, 0.173648, 0, 0}; // 20° final Orientation.
const float delta = 0.00917; // assume 109 updates per second, as per the paper. const float delta = 0.00917; // assume 109 updates per second, as per the paper.
@ -75,7 +75,7 @@ SimpleAngularOrientationFloatDefaultDT()
bool bool
VerifyUpdateWithZeroDeltaTFails() VerifyUpdateWithZeroDeltaTFails()
{ {
filter::Madgwickf mflt; estimation::Madgwickf mflt;
const geom::Vector3F gyro{0.174533, 0.0, 0.0}; // 10° X rotation. const geom::Vector3F gyro{0.174533, 0.0, 0.0}; // 10° X rotation.
const geom::Quaternionf frame20Deg{0.984808, 0.173648, 0, 0}; // 20° final Orientation. const geom::Quaternionf frame20Deg{0.984808, 0.173648, 0, 0}; // 20° final Orientation.
const float twentyDegrees = scmp::DegreesToRadiansF(20.0); const float twentyDegrees = scmp::DegreesToRadiansF(20.0);
@ -100,7 +100,7 @@ VerifyUpdateWithZeroDeltaTFails()
bool bool
SimpleAngularOrientationDouble() SimpleAngularOrientationDouble()
{ {
filter::Madgwickd mflt; estimation::Madgwickd mflt;
const geom::Vector3D gyro{0.174533, 0.0, 0.0}; // 10° X rotation. const geom::Vector3D gyro{0.174533, 0.0, 0.0}; // 10° X rotation.
const geom::Quaterniond frame20Deg{0.984808, 0.173648, 0, 0}; // 20° final Orientation. const geom::Quaterniond frame20Deg{0.984808, 0.173648, 0, 0}; // 20° final Orientation.
const double delta = 0.00917; // assume 109 updates per second, as per the paper. const double delta = 0.00917; // assume 109 updates per second, as per the paper.
@ -127,7 +127,7 @@ bool
SimpleAngularOrientation2InitialVector3f() SimpleAngularOrientation2InitialVector3f()
{ {
const geom::Vector3F initialFrame{0, 0, 0}; const geom::Vector3F initialFrame{0, 0, 0};
filter::Madgwickf mflt(initialFrame); estimation::Madgwickf mflt(initialFrame);
const geom::Vector3F gyro{0.174533, 0.0, 0.0}; // 10° X rotation. const geom::Vector3F gyro{0.174533, 0.0, 0.0}; // 10° X rotation.
const geom::Quaternionf frame20Deg{0.984808, 0.173648, 0, 0}; // 20° final Orientation. const geom::Quaternionf frame20Deg{0.984808, 0.173648, 0, 0}; // 20° final Orientation.
const float delta = 0.00917; // assume 109 updates per second, as per the paper. const float delta = 0.00917; // assume 109 updates per second, as per the paper.
@ -154,7 +154,7 @@ bool
SimpleAngularOrientation2InitialQuaternionf() SimpleAngularOrientation2InitialQuaternionf()
{ {
const auto initialFrame = geom::FloatQuaternionFromEuler({0, 0, 0}); const auto initialFrame = geom::FloatQuaternionFromEuler({0, 0, 0});
filter::Madgwickf mflt(initialFrame); estimation::Madgwickf mflt(initialFrame);
const geom::Vector3F gyro{0.174533, 0.0, 0.0}; // 10° X rotation. const geom::Vector3F gyro{0.174533, 0.0, 0.0}; // 10° X rotation.
const geom::Quaternionf frame20Deg{0.984808, 0.173648, 0, 0}; // 20° final Orientation. const geom::Quaternionf frame20Deg{0.984808, 0.173648, 0, 0}; // 20° final Orientation.
const float delta = 0.00917; // assume 109 updates per second, as per the paper. const float delta = 0.00917; // assume 109 updates per second, as per the paper.
@ -181,7 +181,7 @@ bool
SimpleAngularOrientation2InitialVector3d() SimpleAngularOrientation2InitialVector3d()
{ {
const geom::Vector3D initialFrame{0, 0, 0}; const geom::Vector3D initialFrame{0, 0, 0};
filter::Madgwickd mflt(initialFrame); estimation::Madgwickd mflt(initialFrame);
const geom::Vector3D gyro{0.174533, 0.0, 0.0}; // 10° X rotation. const geom::Vector3D gyro{0.174533, 0.0, 0.0}; // 10° X rotation.
const geom::Quaterniond frame20Deg{0.984808, 0.173648, 0, 0}; // 20° final Orientation. const geom::Quaterniond frame20Deg{0.984808, 0.173648, 0, 0}; // 20° final Orientation.
const double delta = 0.00917; // assume 109 updates per second, as per the paper. const double delta = 0.00917; // assume 109 updates per second, as per the paper.
@ -208,7 +208,7 @@ bool
SimpleAngularOrientation2InitialQuaterniond() SimpleAngularOrientation2InitialQuaterniond()
{ {
const auto initialFrame = geom::DoubleQuaternionFromEuler({0, 0, 0}); const auto initialFrame = geom::DoubleQuaternionFromEuler({0, 0, 0});
filter::Madgwickd mflt(initialFrame); estimation::Madgwickd mflt(initialFrame);
const geom::Vector3D gyro{0.174533, 0.0, 0.0}; // 10° X rotation. const geom::Vector3D gyro{0.174533, 0.0, 0.0}; // 10° X rotation.
const geom::Quaterniond frame20Deg{0.984808, 0.173648, 0, 0}; // 20° final Orientation. const geom::Quaterniond frame20Deg{0.984808, 0.173648, 0, 0}; // 20° final Orientation.
const double delta = 0.00917; // assume 109 updates per second, as per the paper. const double delta = 0.00917; // assume 109 updates per second, as per the paper.
@ -236,8 +236,8 @@ main(int argc, char **argv)
{ {
auto quiet = false; auto quiet = false;
auto noReport = false; auto noReport = false;
auto flags = new scsl::Flags("test_madgwick", auto *flags = new scsl::Flags("test_madgwick",
"This test validates the Madgwick filter code"); "This test validates the Madgwick estimation code");
flags->Register("-n", false, "don't print the report"); flags->Register("-n", false, "don't print the report");
flags->Register("-q", false, "suppress test output"); flags->Register("-q", false, "suppress test output");

View File

@ -45,7 +45,7 @@ UnitConversions_RadiansToDegreesD()
bool bool
Orientation2f_Heading() Orientation2f_Heading()
{ {
geom::Vector2F a{2.0, 2.0}; geom::Vector2F const a{2.0, 2.0};
SCTEST_CHECK_FEQ(geom::Heading2F(a), scmp::DegreesToRadiansF(45)); SCTEST_CHECK_FEQ(geom::Heading2F(a), scmp::DegreesToRadiansF(45));
@ -56,9 +56,9 @@ Orientation2f_Heading()
bool bool
Orientation3f_Heading() Orientation3f_Heading()
{ {
geom::Vector3F a{2.0, 2.0, 2.0}; geom::Vector3F const a{2.0, 2.0, 2.0};
SCTEST_CHECK_FEQ(geom::Heading3f(a), scmp::DegreesToRadiansF(45)); SCTEST_CHECK_FEQ(geom::Heading3F(a), scmp::DegreesToRadiansF(45));
return true; return true;
} }
@ -67,18 +67,18 @@ Orientation3f_Heading()
bool bool
Orientation2d_Heading() Orientation2d_Heading()
{ {
geom::Vector2D a{2.0, 2.0}; geom::Vector2D const a{2.0, 2.0};
return scmp::WithinTolerance(geom::Heading2d(a), scmp::DegreesToRadiansD(45), 0.000001); return scmp::WithinTolerance(geom::Heading2D(a), scmp::DegreesToRadiansD(45), 0.000001) != 0.0;
} }
bool bool
Orientation3d_Heading() Orientation3d_Heading()
{ {
geom::Vector3D a{2.0, 2.0, 2.0}; geom::Vector3D const a{2.0, 2.0, 2.0};
return scmp::WithinTolerance(geom::Heading3d(a), scmp::DegreesToRadiansD(45), 0.000001); return scmp::WithinTolerance(geom::Heading3D(a), scmp::DegreesToRadiansD(45), 0.000001) != 0.0;
} }
@ -90,7 +90,7 @@ main(int argc, char *argv[])
{ {
auto noReport = false; auto noReport = false;
auto quiet = false; auto quiet = false;
auto flags = new scsl::Flags("test_orientation", auto *flags = new scsl::Flags("test_orientation",
"This test validates various orientation-related components in scmp."); "This test validates various orientation-related components in scmp.");
flags->Register("-n", false, "don't print the report"); flags->Register("-n", false, "don't print the report");
flags->Register("-q", false, "suppress test output"); flags->Register("-q", false, "suppress test output");

View File

@ -42,30 +42,30 @@ TestTrimming(std::string line, std::string lExpected, std::string rExpected, std
std::string result; std::string result;
std::string message; std::string message;
result = U::S::TrimLeadingWhitespaceDup(line); result = string::TrimLeadingWhitespaceDup(line);
message = "TrimLeadingDup(\"" + line + "\"): '" + result + "'"; message = "TrimLeadingDup(\"" + line + "\"): '" + result + "'";
sctest::Assert(result == lExpected, message); sctest::Assert(result == lExpected, message);
result = U::S::TrimTrailingWhitespaceDup(line); result = string::TrimTrailingWhitespaceDup(line);
message = "TrimTrailingDup(\"" + line + "\"): '" + result + "'"; message = "TrimTrailingDup(\"" + line + "\"): '" + result + "'";
sctest::Assert(result == rExpected, message); sctest::Assert(result == rExpected, message);
result = U::S::TrimWhitespaceDup(line); result = string::TrimWhitespaceDup(line);
message = "TrimDup(\"" + line + "\"): '" + result + "'"; message = "TrimDup(\"" + line + "\"): '" + result + "'";
sctest::Assert(result == expected, message); sctest::Assert(result == expected, message);
result = line; result = line;
U::S::TrimLeadingWhitespace(result); string::TrimLeadingWhitespace(result);
message = "TrimLeadingDup(\"" + line + "\"): '" + result + "'"; message = "TrimLeadingDup(\"" + line + "\"): '" + result + "'";
sctest::Assert(result == lExpected, message); sctest::Assert(result == lExpected, message);
result = line; result = line;
U::S::TrimTrailingWhitespace(result); string::TrimTrailingWhitespace(result);
message = "TrimTrailingDup(\"" + line + "\"): '" + result + "'"; message = "TrimTrailingDup(\"" + line + "\"): '" + result + "'";
sctest::Assert(result == rExpected, message); sctest::Assert(result == rExpected, message);
result = line; result = line;
U::S::TrimWhitespace(result); string::TrimWhitespace(result);
message = "TrimDup(\"" + line + "\"): '" + result + "'"; message = "TrimDup(\"" + line + "\"): '" + result + "'";
sctest::Assert(result == expected, message); sctest::Assert(result == expected, message);
} }
@ -75,7 +75,7 @@ std::function<bool()>
TestSplit(std::string line, std::string delim, size_t maxCount, std::vector<std::string> expected) TestSplit(std::string line, std::string delim, size_t maxCount, std::vector<std::string> expected)
{ {
return [line, delim, maxCount, expected]() { return [line, delim, maxCount, expected]() {
return U::S::SplitN(line, delim, maxCount) == expected; return string::SplitN(line, delim, maxCount) == expected;
}; };
} }
@ -86,7 +86,7 @@ TestSplitChar()
{ {
auto expected = std::vector<std::string>{"hello", "world"}; auto expected = std::vector<std::string>{"hello", "world"};
const auto *inputLine = "hello=world\n"; const auto *inputLine = "hello=world\n";
auto actual = U::S::SplitKeyValuePair(inputLine, '='); auto actual = string::SplitKeyValuePair(inputLine, '=');
return actual == expected; return actual == expected;
} }
@ -109,11 +109,11 @@ TestWrapping()
"hope so.", "hope so.",
}; };
auto wrapped = U::S::WrapText(testLine, 16); auto wrapped = string::WrapText(testLine, 16);
if (wrapped.size() != expected.size()) { if (wrapped.size() != expected.size()) {
std::cerr << U::S::VectorToString(wrapped) std::cerr << string::VectorToString(wrapped)
<< " != " << " != "
<< U::S::VectorToString(expected) << string::VectorToString(expected)
<< "\n"; << "\n";
} }
@ -127,7 +127,7 @@ TestWrapping()
return false; return false;
} }
// U::S::WriteTabIndented(std::cout, wrapped, 4, true); // string::WriteTabIndented(std::cout, wrapped, 4, true);
return true; return true;
} }
@ -140,7 +140,7 @@ main(int argc, char *argv[])
{ {
auto noReport = false; auto noReport = false;
auto quiet = false; auto quiet = false;
auto flags = new scsl::Flags("test_orientation", auto *flags = new scsl::Flags("test_orientation",
"This test validates various orientation-related components in scmp."); "This test validates various orientation-related components in scmp.");
flags->Register("-n", false, "don't print the report"); flags->Register("-n", false, "don't print the report");
flags->Register("-q", false, "suppress test output"); flags->Register("-q", false, "suppress test output");