blob: 15bad8a959a4ac4fb78949c19378f8a584a2681e [file] [log] [blame]
// Copyright 2022 Google LLC
//
// 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 "ink_stroke_modeler/params.h"
#include <limits>
#include "gtest/gtest.h"
#include "absl/status/status.h"
namespace ink {
namespace stroke_model {
namespace {
const KalmanPredictorParams kGoodKalmanParams{
.process_noise = .01,
.measurement_noise = .1,
.min_stable_iteration = 2,
.max_time_samples = 10,
.min_catchup_velocity = 1,
.acceleration_weight = -1,
.jerk_weight = 200,
.prediction_interval{Duration(1)},
.confidence_params{.desired_number_of_samples = 10,
.max_estimation_distance = 1,
.min_travel_speed = 6,
.max_travel_speed = 50,
.max_linear_deviation = 2,
.baseline_linearity_confidence = .5}};
const StrokeModelParams kGoodStrokeModelParams{
.wobble_smoother_params{
.timeout = Duration(.5), .speed_floor = 1, .speed_ceiling = 20},
.position_modeler_params{.spring_mass_constant = .2, .drag_constant = 4},
.sampling_params{.min_output_rate = 3,
.end_of_stroke_stopping_distance = 1e-6,
.end_of_stroke_max_iterations = 1},
.stylus_state_modeler_params{.max_input_samples = 7},
.prediction_params = StrokeEndPredictorParams{}};
TEST(ParamsTest, ValidatePositionModelerParams) {
EXPECT_TRUE(ValidatePositionModelerParams(
{.spring_mass_constant = 1, .drag_constant = 3})
.ok());
EXPECT_EQ(ValidatePositionModelerParams(
{.spring_mass_constant = 0, .drag_constant = 1})
.code(),
absl::StatusCode::kInvalidArgument);
EXPECT_EQ(ValidatePositionModelerParams(
{.spring_mass_constant = 1, .drag_constant = 0})
.code(),
absl::StatusCode::kInvalidArgument);
}
TEST(ParamsTest, ValidateSamplingParams) {
EXPECT_TRUE(ValidateSamplingParams({.min_output_rate = 10,
.end_of_stroke_stopping_distance = .1,
.end_of_stroke_max_iterations = 3})
.ok());
EXPECT_EQ(ValidateSamplingParams({.min_output_rate = 0,
.end_of_stroke_stopping_distance = .1,
.end_of_stroke_max_iterations = 3})
.code(),
absl::StatusCode::kInvalidArgument);
EXPECT_EQ(ValidateSamplingParams({.min_output_rate = 1,
.end_of_stroke_stopping_distance = 0,
.end_of_stroke_max_iterations = 3})
.code(),
absl::StatusCode::kInvalidArgument);
EXPECT_EQ(ValidateSamplingParams({.min_output_rate = 1,
.end_of_stroke_stopping_distance = 5,
.end_of_stroke_max_iterations = 0})
.code(),
absl::StatusCode::kInvalidArgument);
}
TEST(ParamsTest, ValidateStylusStateModelerParams) {
EXPECT_TRUE(ValidateStylusStateModelerParams({.max_input_samples = 1}).ok());
EXPECT_EQ(ValidateStylusStateModelerParams({.max_input_samples = 0}).code(),
absl::StatusCode::kInvalidArgument);
}
TEST(ParamsTest, ValidateWobbleSmootherParams) {
EXPECT_TRUE(
ValidateWobbleSmootherParams(
{.timeout = Duration(1), .speed_floor = 2, .speed_ceiling = 3})
.ok());
EXPECT_TRUE(
ValidateWobbleSmootherParams(
{.timeout = Duration(0), .speed_floor = 0, .speed_ceiling = 0})
.ok());
EXPECT_EQ(ValidateWobbleSmootherParams(
{.timeout = Duration(-1), .speed_floor = 2, .speed_ceiling = 5})
.code(),
absl::StatusCode::kInvalidArgument);
EXPECT_EQ(ValidateWobbleSmootherParams(
{.timeout = Duration(1), .speed_floor = -2, .speed_ceiling = 1})
.code(),
absl::StatusCode::kInvalidArgument);
EXPECT_EQ(ValidateWobbleSmootherParams(
{.timeout = Duration(1), .speed_floor = 7, .speed_ceiling = 4})
.code(),
absl::StatusCode::kInvalidArgument);
}
TEST(ParamsTest, ValidateStrokeEndPredictorParams) {
EXPECT_TRUE(ValidatePredictionParams(StrokeEndPredictorParams()).ok());
}
TEST(ParamsTest, ValidateKalmanPredictorParams) {
EXPECT_TRUE(ValidatePredictionParams(kGoodKalmanParams).ok());
{
auto bad_params = kGoodKalmanParams;
bad_params.process_noise = 0;
EXPECT_EQ(ValidatePredictionParams(bad_params).code(),
absl::StatusCode::kInvalidArgument);
}
{
auto bad_params = kGoodKalmanParams;
bad_params.measurement_noise = 0;
EXPECT_EQ(ValidatePredictionParams(bad_params).code(),
absl::StatusCode::kInvalidArgument);
}
{
auto bad_params = kGoodKalmanParams;
bad_params.min_stable_iteration = 0;
EXPECT_EQ(ValidatePredictionParams(bad_params).code(),
absl::StatusCode::kInvalidArgument);
}
{
auto bad_params = kGoodKalmanParams;
bad_params.max_time_samples = 0;
EXPECT_EQ(ValidatePredictionParams(bad_params).code(),
absl::StatusCode::kInvalidArgument);
}
{
auto bad_params = kGoodKalmanParams;
bad_params.prediction_interval = Duration(0);
EXPECT_EQ(ValidatePredictionParams(bad_params).code(),
absl::StatusCode::kInvalidArgument);
}
}
TEST(ParamsTest, ValidateKalmanPredictorConfidenceParams) {
EXPECT_TRUE(ValidatePredictionParams(kGoodKalmanParams).ok());
{
auto bad_params = kGoodKalmanParams;
bad_params.confidence_params.desired_number_of_samples = 0;
EXPECT_EQ(ValidatePredictionParams(bad_params).code(),
absl::StatusCode::kInvalidArgument);
}
{
auto bad_params = kGoodKalmanParams;
bad_params.confidence_params.max_estimation_distance = 0;
EXPECT_EQ(ValidatePredictionParams(bad_params).code(),
absl::StatusCode::kInvalidArgument);
}
{
auto bad_params = kGoodKalmanParams;
bad_params.confidence_params.min_travel_speed = -1;
EXPECT_EQ(ValidatePredictionParams(bad_params).code(),
absl::StatusCode::kInvalidArgument);
}
{
auto bad_params = kGoodKalmanParams;
bad_params.confidence_params.min_travel_speed = 10;
bad_params.confidence_params.max_travel_speed = 1;
EXPECT_EQ(ValidatePredictionParams(bad_params).code(),
absl::StatusCode::kInvalidArgument);
}
{
auto bad_params = kGoodKalmanParams;
bad_params.confidence_params.max_linear_deviation = 0;
EXPECT_EQ(ValidatePredictionParams(bad_params).code(),
absl::StatusCode::kInvalidArgument);
}
{
auto bad_params = kGoodKalmanParams;
bad_params.confidence_params.baseline_linearity_confidence = -.3;
EXPECT_EQ(ValidatePredictionParams(bad_params).code(),
absl::StatusCode::kInvalidArgument);
}
{
auto bad_params = kGoodKalmanParams;
bad_params.confidence_params.baseline_linearity_confidence = 1.01;
EXPECT_EQ(ValidatePredictionParams(bad_params).code(),
absl::StatusCode::kInvalidArgument);
}
}
TEST(ParamsTest, ValidateStrokeModelParams) {
EXPECT_TRUE(ValidateStrokeModelParams(kGoodStrokeModelParams).ok());
{
auto bad_params = kGoodStrokeModelParams;
bad_params.wobble_smoother_params.timeout = Duration(-10);
EXPECT_EQ(ValidateStrokeModelParams(bad_params).code(),
absl::StatusCode::kInvalidArgument);
}
{
auto bad_params = kGoodStrokeModelParams;
bad_params.position_modeler_params.spring_mass_constant = -1;
EXPECT_EQ(ValidateStrokeModelParams(bad_params).code(),
absl::StatusCode::kInvalidArgument);
}
{
auto bad_params = kGoodStrokeModelParams;
bad_params.stylus_state_modeler_params.max_input_samples = 0;
EXPECT_EQ(ValidateStrokeModelParams(bad_params).code(),
absl::StatusCode::kInvalidArgument);
}
{
auto bad_params = kGoodStrokeModelParams;
bad_params.sampling_params.end_of_stroke_max_iterations = -3;
EXPECT_EQ(ValidateStrokeModelParams(bad_params).code(),
absl::StatusCode::kInvalidArgument);
}
{
auto bad_params = kGoodStrokeModelParams;
bad_params.prediction_params =
KalmanPredictorParams{.prediction_interval = Duration(-1)};
EXPECT_EQ(ValidateStrokeModelParams(bad_params).code(),
absl::StatusCode::kInvalidArgument);
}
}
TEST(ParamsTest, NaNIsNotAValidValue) {
auto bad_params = kGoodStrokeModelParams;
bad_params.position_modeler_params.spring_mass_constant =
std::numeric_limits<float>::quiet_NaN();
EXPECT_EQ(ValidateStrokeModelParams(bad_params).code(),
absl::StatusCode::kInvalidArgument);
}
TEST(ParamsTest, InfinityIsNotAValidValue) {
auto bad_params = kGoodStrokeModelParams;
bad_params.position_modeler_params.spring_mass_constant =
std::numeric_limits<float>::infinity();
EXPECT_EQ(ValidateStrokeModelParams(bad_params).code(),
absl::StatusCode::kInvalidArgument);
}
} // namespace
} // namespace stroke_model
} // namespace ink