Skip to content

Commit

Permalink
Update changelog and add testing
Browse files Browse the repository at this point in the history
  • Loading branch information
alexbeattie42 committed Dec 17, 2024
1 parent f98add8 commit f5635ce
Show file tree
Hide file tree
Showing 3 changed files with 171 additions and 1 deletion.
4 changes: 3 additions & 1 deletion Applications/Analyze/test/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
find_package(Catch2 REQUIRED
HINTS "${OPENSIM_DEPENDENCIES_DIR}/catch2")

file(GLOB TEST_PROGS "test*.cpp")
file(GLOB TEST_FILES *.osim *.xml *.sto *.mot)

OpenSimAddTests(
TESTPROGRAMS ${TEST_PROGS}
DATAFILES ${TEST_FILES}
LINKLIBS osimTools
LINKLIBS osimTools Catch2::Catch2WithMain
)

if(BUILD_TESTING)
Expand Down
167 changes: 167 additions & 0 deletions Applications/Analyze/test/testPointKinematics.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
/* -------------------------------------------------------------------------- *
* OpenSim: testAnalyzeToolCatch.cpp *
* -------------------------------------------------------------------------- *
* The OpenSim API is a toolkit for musculoskeletal modeling and simulation. *
* See http://opensim.stanford.edu and the NOTICE file for more information. *
* OpenSim is developed at Stanford University and supported by the US *
* National Institutes of Health (U54 GM072970, R24 HD065690) and by DARPA *
* through the Warrior Web program. *
* *
* Copyright (c) 2005-2024 Stanford University and the Authors *
* Author(s): Alexander Beattie, Ayman Habib, Ajay Seth *
* *
* Licensed under the Apache License, Version 2.0 (the "License"); you may *
* not use this file except in compliance with the License. You may obtain a *
* copy of the License at http://www.apache.org/licenses/LICENSE-2.0. *
* *
* Unless required by applicable law or agreed to in writing, software *
* distributed under the License is distributed on an "AS IS" BASIS, *
* 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. *
* -------------------------------------------------------------------------- */

// INCLUDE
#include <limits>
#include <iterator> // For std::next

#include <OpenSim/Analyses/PointKinematics.h>
#include <OpenSim/Simulation/Model/Model.h>
#include <OpenSim/Tools/AnalyzeTool.h>

#include <catch2/catch_all.hpp>

using namespace OpenSim;

constexpr double tol = std::numeric_limits<double>::epsilon() * 10;

TEST_CASE("PointKinematics Construction with Blank Model", "[PointKinematics]") {
Model model;
PointKinematics pk(&model);

REQUIRE(pk.getBody() == nullptr);
REQUIRE(pk.getRelativeToBody() == nullptr);
REQUIRE(pk.getPointName() == "NONAME");
}

TEST_CASE("PointKinematics Construction with No Model", "[PointKinematics]") {
PointKinematics pk;

REQUIRE(pk.getBody() == nullptr);
REQUIRE(pk.getRelativeToBody() == nullptr);
REQUIRE(pk.getPointName() == "NONAME");
}

TEST_CASE("PointKinematics Set and Get Body", "[PointKinematics]") {
Model model("SinglePin.osim");
const auto &bodies = model.getComponentList<OpenSim::Body>();
const auto bodyIt = bodies.begin();
const auto body = *bodyIt;

PointKinematics pk(&model);
pk.setBody(&body);

REQUIRE(pk.getBody() == &body);
REQUIRE(pk.getBody()->getName() == body.getName());
}

TEST_CASE("PointKinematics Set and Get RelativeToBody", "[PointKinematics]") {
Model model("subject01.osim");
const auto &bodies = model.getComponentList<OpenSim::Body>();
// Gets the 2nd body (which is at index 1)
const auto bodyIt = std::next(bodies.begin(),1);
const auto body = *bodyIt;

PointKinematics pk(&model);
pk.setRelativeToBody(&body);

REQUIRE(pk.getRelativeToBody() == &body);
REQUIRE(pk.getRelativeToBody()->getName() == body.getName());
}

TEST_CASE("PointKinematics Set and Get Point", "[PointKinematics]") {
Model model;
PointKinematics pk(&model);
SimTK::Vec3 point(1.0, 2.0, 3.0);

pk.setPoint(point);
SimTK::Vec3 retrievedPoint;
pk.getPoint(retrievedPoint);

REQUIRE_THAT(retrievedPoint[0], Catch::Matchers::WithinAbs(1.0,tol));
REQUIRE_THAT(retrievedPoint[1], Catch::Matchers::WithinAbs(2.0,tol));
REQUIRE_THAT(retrievedPoint[2], Catch::Matchers::WithinAbs(3.0,tol));
}

TEST_CASE("PointKinematics Record Kinematics Single Body", "[PointKinematics]") {
std::string model_name = "subject01.osim";
std::string coordinates_file_name = "subject01_walk1_ik.mot";

OpenSim::Model model(model_name);
model.initSystem();

OpenSim::AnalyzeTool analyzeTool;
analyzeTool.setName("test_analysis");
analyzeTool.setModel(model);
analyzeTool.setModelFilename(model_name);
analyzeTool.setCoordinatesFileName(coordinates_file_name);
analyzeTool.setLowpassCutoffFrequency(-1);
analyzeTool.setResultsDir("results");

const auto &bodies = model.getComponentList<OpenSim::Body>();
const auto bodyIt = bodies.begin();
const auto body1 = *bodyIt;
// Gets the 2nd body (which is at index 1)
const auto bodyIt2 = std::next(bodies.begin(),1);
const auto body2 = *bodyIt2;

OpenSim::PointKinematics pk(&model);
pk.setBody(&body1);
pk.setRelativeToBody(&body2);
pk.setPoint(SimTK::Vec3(1.0, 2.0, 3.0));
analyzeTool.updAnalysisSet().cloneAndAppend(pk);

// analyzeTool.run();

std::string output_file_name = "test_analysis_point_kinematics_1.xml";
analyzeTool.print(output_file_name);
OpenSim::AnalyzeTool roundTrip(output_file_name);
roundTrip.run();
}

TEST_CASE("PointKinematics Record Kinematics Whole Body", "[PointKinematics]") {
std::string model_name = "subject01.osim";
std::string coordinates_file_name = "subject01_walk1_ik.mot";

OpenSim::Model model(model_name);
model.initSystem();

OpenSim::AnalyzeTool analyzeTool;
analyzeTool.setName("test_analysis");
analyzeTool.setModel(model);
analyzeTool.setModelFilename(model_name);
analyzeTool.setCoordinatesFileName(coordinates_file_name);
analyzeTool.setLowpassCutoffFrequency(-1);
analyzeTool.setResultsDir("results");

const auto &bodies = model.getComponentList<OpenSim::Body>();
for (auto& root : bodies) {
const std::string& root_name = root.getName();
for (auto& sub_component: bodies) {
const std::string& sub_component_name = sub_component.getName();
// Create point kinematics reporter
OpenSim::PointKinematics pointKin;
pointKin.setPointName(root_name + "-" + sub_component_name);
pointKin.setPoint(SimTK::Vec3(1.0, 2.0, 3.0));
pointKin.setBody(&root);
pointKin.setRelativeToBody(&sub_component);
analyzeTool.updAnalysisSet().cloneAndAppend(pointKin);
}
}

std::string output_file_name = "test_analysis_point_kinematics_2.xml";
analyzeTool.print(output_file_name);
OpenSim::AnalyzeTool roundTrip(output_file_name);
roundTrip.run();

}
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ v4.6
- Make `InverseKinematicsSolver` methods to query for specific marker or orientation-sensor errors more robust to invalid names or names not
in the intersection of names in the model and names in the provided referece/data. Remove methods that are index based from public interface.(#3951)
- Replace usages of `OpenSim::make_unique` with `std::make_unique` and remove wrapper function now that C++14 is used in OpenSim (#3979).
- Fix Point Kinematics Reporter variable and initialization error and add unit tests (#3966)



Expand Down

0 comments on commit f5635ce

Please sign in to comment.