Skip to content

Commit a3c6eea

Browse files
perchessManos-G
authored andcommitted
Implement Critic for Velocity Deadband Hardware Constraints (ros-navigation#4256)
* Adding new velocity deadband critic. - add some tests - cast double to float - add new features from "main" branch - fix formating - add cost test - fix linting issue - add README Signed-off-by: Denis Sokolov <[email protected]> * Remove velocity deadband critic from defaults Signed-off-by: Denis Sokolov <[email protected]> * remove old weight Signed-off-by: Denis Sokolov <[email protected]> * fix velocity deadband critic tests Signed-off-by: Denis Sokolov <[email protected]> --------- Signed-off-by: Denis Sokolov <[email protected]>
1 parent 119b816 commit a3c6eea

File tree

6 files changed

+227
-0
lines changed

6 files changed

+227
-0
lines changed

nav2_mppi_controller/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ add_library(mppi_critics SHARED
8888
src/critics/prefer_forward_critic.cpp
8989
src/critics/twirling_critic.cpp
9090
src/critics/constraint_critic.cpp
91+
src/critics/velocity_deadband_critic.cpp
9192
)
9293

9394
set(libraries mppi_controller mppi_critics)

nav2_mppi_controller/README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,15 @@ Uses inflated costmap cost directly to avoid obstacles
171171
| cost_weight | double | Default 10.0. Weight to apply to critic term. |
172172
| cost_power | int | Default 1. Power order to apply to term. |
173173

174+
175+
#### Velocity Deadband Critic
176+
| Parameter | Type | Definition |
177+
| --------------- | ------ | ----------------------------------------------------------------------------------------------------------- |
178+
| cost_weight | double | Default 35.0. Weight to apply to critic term. |
179+
| cost_power | int | Default 1. Power order to apply to term. |
180+
| deadband_velocities | double[] | Default [0.0, 0.0, 0.0]. The array of deadband velocities [vx, vz, wz]. A zero array indicates that the critic will take no action. |
181+
182+
174183
### XML configuration example
175184
```
176185
controller_server:
@@ -262,6 +271,11 @@ controller_server:
262271
threshold_to_consider: 0.5
263272
max_angle_to_furthest: 1.0
264273
forward_preference: true
274+
# VelocityDeadbandCritic:
275+
# enabled: true
276+
# cost_power: 1
277+
# cost_weight: 35.0
278+
# deadband_velocities: [0.05, 0.05, 0.05]
265279
# TwirlingCritic:
266280
# enabled: true
267281
# twirling_cost_power: 1

nav2_mppi_controller/critics.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,5 +41,9 @@
4141
<description>mppi critic for incentivizing moving within kinematic and dynamic bounds</description>
4242
</class>
4343

44+
<class type="mppi::critics::VelocityDeadbandCritic" base_class_type="mppi::critics::CriticFunction">
45+
<description>mppi critic for restricting command velocities in deadband range</description>
46+
</class>
47+
4448
</library>
4549
</class_libraries>
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// Copyright (c) 2022 Samsung Research America, @artofnothingness Alexey Budyakov
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#ifndef NAV2_MPPI_CONTROLLER__CRITICS__VELOCITY_DEADBAND_CRITIC_HPP_
16+
#define NAV2_MPPI_CONTROLLER__CRITICS__VELOCITY_DEADBAND_CRITIC_HPP_
17+
18+
#include <vector>
19+
20+
#include "nav2_mppi_controller/critic_function.hpp"
21+
#include "nav2_mppi_controller/models/state.hpp"
22+
#include "nav2_mppi_controller/tools/utils.hpp"
23+
24+
namespace mppi::critics
25+
{
26+
27+
/**
28+
* @class mppi::critics::VelocityDeadbandCritic
29+
* @brief Critic objective function for enforcing feasible constraints
30+
*/
31+
class VelocityDeadbandCritic : public CriticFunction
32+
{
33+
public:
34+
/**
35+
* @brief Initialize critic
36+
*/
37+
void initialize() override;
38+
39+
/**
40+
* @brief Evaluate cost related to goal following
41+
*
42+
* @param costs [out] add reference cost values to this tensor
43+
*/
44+
void score(CriticData & data) override;
45+
46+
protected:
47+
unsigned int power_{0};
48+
float weight_{0};
49+
std::vector<float> deadband_velocities_{0.0f, 0.0f, 0.0f};
50+
};
51+
52+
} // namespace mppi::critics
53+
54+
#endif // NAV2_MPPI_CONTROLLER__CRITICS__VELOCITY_DEADBAND_CRITIC_HPP_
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
// Copyright (c) 2022 Samsung Research America, @artofnothingness Alexey Budyakov
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include "nav2_mppi_controller/critics/velocity_deadband_critic.hpp"
16+
17+
namespace mppi::critics
18+
{
19+
20+
void VelocityDeadbandCritic::initialize()
21+
{
22+
auto getParam = parameters_handler_->getParamGetter(name_);
23+
24+
getParam(power_, "cost_power", 1);
25+
getParam(weight_, "cost_weight", 35.0);
26+
27+
// Recast double to float
28+
std::vector<double> deadband_velocities{0.0, 0.0, 0.0};
29+
getParam(deadband_velocities, "deadband_velocities", std::vector<double>{0.0, 0.0, 0.0});
30+
std::transform(
31+
deadband_velocities.begin(), deadband_velocities.end(), deadband_velocities_.begin(),
32+
[](double d) {return static_cast<float>(d);});
33+
34+
RCLCPP_INFO_STREAM(
35+
logger_, "VelocityDeadbandCritic instantiated with "
36+
<< power_ << " power, " << weight_ << " weight, deadband_velocity ["
37+
<< deadband_velocities_.at(0) << "," << deadband_velocities_.at(1) << ","
38+
<< deadband_velocities_.at(2) << "]");
39+
}
40+
41+
void VelocityDeadbandCritic::score(CriticData & data)
42+
{
43+
using xt::evaluation_strategy::immediate;
44+
45+
if (!enabled_) {
46+
return;
47+
}
48+
49+
auto & vx = data.state.vx;
50+
auto & wz = data.state.wz;
51+
52+
if (data.motion_model->isHolonomic()) {
53+
auto & vy = data.state.vy;
54+
if (power_ > 1u) {
55+
data.costs += xt::pow(
56+
xt::sum(
57+
std::move(
58+
xt::maximum(fabs(deadband_velocities_.at(0)) - xt::fabs(vx), 0) +
59+
xt::maximum(fabs(deadband_velocities_.at(1)) - xt::fabs(vy), 0) +
60+
xt::maximum(fabs(deadband_velocities_.at(2)) - xt::fabs(wz), 0)) *
61+
data.model_dt,
62+
{1}, immediate) *
63+
weight_,
64+
power_);
65+
} else {
66+
data.costs += xt::sum(
67+
(std::move(
68+
xt::maximum(fabs(deadband_velocities_.at(0)) - xt::fabs(vx), 0) +
69+
xt::maximum(fabs(deadband_velocities_.at(1)) - xt::fabs(vy), 0) +
70+
xt::maximum(fabs(deadband_velocities_.at(2)) - xt::fabs(wz), 0))) *
71+
data.model_dt,
72+
{1}, immediate) *
73+
weight_;
74+
}
75+
return;
76+
}
77+
78+
if (power_ > 1u) {
79+
data.costs += xt::pow(
80+
xt::sum(
81+
std::move(
82+
xt::maximum(fabs(deadband_velocities_.at(0)) - xt::fabs(vx), 0) +
83+
xt::maximum(fabs(deadband_velocities_.at(2)) - xt::fabs(wz), 0)) *
84+
data.model_dt,
85+
{1}, immediate) *
86+
weight_,
87+
power_);
88+
} else {
89+
data.costs += xt::sum(
90+
(std::move(
91+
xt::maximum(fabs(deadband_velocities_.at(0)) - xt::fabs(vx), 0) +
92+
xt::maximum(fabs(deadband_velocities_.at(2)) - xt::fabs(wz), 0))) *
93+
data.model_dt,
94+
{1}, immediate) *
95+
weight_;
96+
}
97+
return;
98+
}
99+
100+
} // namespace mppi::critics
101+
102+
#include <pluginlib/class_list_macros.hpp>
103+
104+
PLUGINLIB_EXPORT_CLASS(mppi::critics::VelocityDeadbandCritic, mppi::critics::CriticFunction)

nav2_mppi_controller/test/critics_tests.cpp

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "nav2_mppi_controller/critics/path_follow_critic.hpp"
3131
#include "nav2_mppi_controller/critics/prefer_forward_critic.hpp"
3232
#include "nav2_mppi_controller/critics/twirling_critic.hpp"
33+
#include "nav2_mppi_controller/critics/velocity_deadband_critic.hpp"
3334
#include "utils_test.cpp" // NOLINT
3435

3536
// Tests the various critic plugin functions
@@ -607,3 +608,52 @@ TEST(CriticTests, PathAlignCritic)
607608
critic.score(data);
608609
EXPECT_NEAR(xt::sum(costs, immediate)(), 0.0, 1e-6);
609610
}
611+
612+
TEST(CriticTests, VelocityDeadbandCritic)
613+
{
614+
// Standard preamble
615+
auto node = std::make_shared<rclcpp_lifecycle::LifecycleNode>("my_node");
616+
auto costmap_ros = std::make_shared<nav2_costmap_2d::Costmap2DROS>(
617+
"dummy_costmap", "", "dummy_costmap", true);
618+
ParametersHandler param_handler(node);
619+
auto getParam = param_handler.getParamGetter("critic");
620+
std::vector<double> deadband_velocities_;
621+
getParam(deadband_velocities_, "deadband_velocities", std::vector<double>{0.08, 0.08, 0.08});
622+
rclcpp_lifecycle::State lstate;
623+
costmap_ros->on_configure(lstate);
624+
625+
models::State state;
626+
models::ControlSequence control_sequence;
627+
models::Trajectories generated_trajectories;
628+
models::Path path;
629+
xt::xtensor<float, 1> costs = xt::zeros<float>({1000});
630+
float model_dt = 0.1;
631+
CriticData data =
632+
{state, generated_trajectories, path, costs, model_dt, false, nullptr, nullptr, std::nullopt,
633+
std::nullopt};
634+
data.motion_model = std::make_shared<OmniMotionModel>();
635+
636+
// Initialization testing
637+
638+
// Make sure initializes correctly and that defaults are reasonable
639+
VelocityDeadbandCritic critic;
640+
critic.on_configure(node, "mppi", "critic", costmap_ros, &param_handler);
641+
EXPECT_EQ(critic.getName(), "critic");
642+
643+
// Scoring testing
644+
645+
// provide velocities out of deadband bounds, should not have any costs
646+
state.vx = 0.80 * xt::ones<float>({1000, 30});
647+
state.vy = 0.60 * xt::ones<float>({1000, 30});
648+
state.wz = 0.80 * xt::ones<float>({1000, 30});
649+
critic.score(data);
650+
EXPECT_NEAR(xt::sum(costs, immediate)(), 0, 1e-6);
651+
652+
// Test cost value
653+
state.vx = 0.01 * xt::ones<float>({1000, 30});
654+
state.vy = 0.02 * xt::ones<float>({1000, 30});
655+
state.wz = 0.021 * xt::ones<float>({1000, 30});
656+
critic.score(data);
657+
// 35.0 weight * 0.1 model_dt * (0.07 + 0.06 + 0.059) * 30 timesteps = 56.7
658+
EXPECT_NEAR(costs(1), 19.845, 0.01);
659+
}

0 commit comments

Comments
 (0)