Skip to content

Commit f8aad77

Browse files
Merge pull request fzi-forschungszentrum-informatik#196 from MarcoMagriDev/fix-ik-solver-params
Allow to set IKSolver parameters
2 parents 2a0268a + 504d9d4 commit f8aad77

8 files changed

Lines changed: 92 additions & 13 deletions

File tree

.pre-commit-config.yaml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,20 @@ repos:
1919

2020
# Python
2121
- repo: https://github.com/pycqa/flake8
22-
rev: 6.0.0
22+
rev: '88a4f9b2f48fc44b025a48fa6a8ac7cc89ef70e0' # 7.0.0
2323
hooks:
2424
- id: flake8
2525

2626
- repo: https://github.com/psf/black.git
27-
rev: 23.7.0
27+
rev: '6fdf8a4af28071ed1d079c01122b34c5d587207a' # 24.2.0
2828
hooks:
2929
- id: black
3030

31+
- repo: https://github.com/pre-commit/mirrors-mypy
32+
rev: '9db9854e3041219b1eb619872a2dfaf58adfb20b' # v1.9.0
33+
hooks:
34+
- id: mypy
35+
3136
# C++
3237
- repo: local
3338
hooks:

cartesian_controller_base/include/cartesian_controller_base/DampedLeastSquaresSolver.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,7 @@ class DampedLeastSquaresSolver : public IKSolver
103103
KDL::Jacobian m_jnt_jacobian;
104104

105105
// Dynamic parameters
106-
std::shared_ptr<rclcpp::Node> m_handle; ///< handle for dynamic parameter interaction
107-
const std::string m_params = "solver/damped_least_squares"; ///< namespace for parameter access
106+
const std::string m_params = "solver.damped_least_squares"; ///< namespace for parameter access
108107
double m_alpha; ///< damping coefficient
109108
};
110109

cartesian_controller_base/include/cartesian_controller_base/ForwardDynamicsSolver.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,7 @@ class ForwardDynamicsSolver : public IKSolver
119119
KDL::JntSpaceInertiaMatrix m_jnt_space_inertia;
120120

121121
// Dynamic parameters
122-
std::shared_ptr<rclcpp::Node> m_handle; ///< handle for dynamic parameter interaction
123-
const std::string m_params = "solver/forward_dynamics"; ///< namespace for parameter access
122+
const std::string m_params = "solver.forward_dynamics"; ///< namespace for parameter access
124123

125124
/**
126125
* Virtual link mass

cartesian_controller_base/include/cartesian_controller_base/IKSolver.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,21 @@ class IKSolver
170170
*/
171171
void applyJointLimits();
172172

173+
template <typename ParameterT>
174+
auto auto_declare(const std::string & name, const ParameterT & default_value)
175+
{
176+
if (!m_handle->has_parameter(name))
177+
{
178+
return m_handle->declare_parameter<ParameterT>(name, default_value);
179+
}
180+
else
181+
{
182+
return m_handle->get_parameter(name).get_value<ParameterT>();
183+
}
184+
}
185+
186+
std::shared_ptr<rclcpp_lifecycle::LifecycleNode> m_handle;
187+
173188
//! The underlying physical system
174189
KDL::Chain m_chain;
175190

cartesian_controller_base/src/DampedLeastSquaresSolver.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ trajectory_msgs::msg::JointTrajectoryPoint DampedLeastSquaresSolver::getJointCon
7979
// \f$ \dot{q} = ( J^T J + \alpha^2 I )^{-1} J^T f \f$
8080
ctrl::MatrixND identity;
8181
identity.setIdentity(m_number_joints, m_number_joints);
82-
m_handle->get_parameter(m_params + "/alpha", m_alpha);
82+
m_handle->get_parameter(m_params + ".alpha", m_alpha);
8383

8484
m_current_velocities.data =
8585
(m_jnt_jacobian.data.transpose() * m_jnt_jacobian.data + m_alpha * m_alpha * identity)
@@ -122,7 +122,7 @@ bool DampedLeastSquaresSolver::init(std::shared_ptr<rclcpp_lifecycle::LifecycleN
122122
m_jnt_jacobian_solver.reset(new KDL::ChainJntToJacSolver(m_chain));
123123
m_jnt_jacobian.resize(m_number_joints);
124124

125-
nh->declare_parameter<double>(m_params + "/alpha", 1.0);
125+
auto_declare(m_params + ".alpha", 1.0);
126126

127127
return true;
128128
}

cartesian_controller_base/src/ForwardDynamicsSolver.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ bool ForwardDynamicsSolver::init(std::shared_ptr<rclcpp_lifecycle::LifecycleNode
136136
m_jnt_space_inertia.resize(m_number_joints);
137137

138138
// Set the initial value if provided at runtime, else use default value.
139-
m_min = nh->declare_parameter<double>(m_params + "/link_mass", 0.1);
139+
m_min = auto_declare(m_params + ".link_mass", 0.1);
140140

141141
RCLCPP_INFO(nh->get_logger(), "Forward dynamics solver initialized");
142142
RCLCPP_INFO(nh->get_logger(), "Forward dynamics solver has control over %i joints",

cartesian_controller_base/src/IKSolver.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -102,11 +102,11 @@ void IKSolver::synchronizeJointPositions(
102102
}
103103
}
104104

105-
bool IKSolver::init(std::shared_ptr<rclcpp_lifecycle::LifecycleNode> /*nh*/,
106-
const KDL::Chain & chain, const KDL::JntArray & upper_pos_limits,
107-
const KDL::JntArray & lower_pos_limits)
105+
bool IKSolver::init(std::shared_ptr<rclcpp_lifecycle::LifecycleNode> nh, const KDL::Chain & chain,
106+
const KDL::JntArray & upper_pos_limits, const KDL::JntArray & lower_pos_limits)
108107
{
109108
// Initialize
109+
m_handle = nh;
110110
m_chain = chain;
111111
m_number_joints = m_chain.getNrOfJoints();
112112
m_current_positions.data = ctrl::VectorND::Zero(m_number_joints);

cartesian_controller_tests/integration_tests/integration_tests.py

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,14 @@
1010
import time
1111
import rclpy
1212
from rclpy.node import Node
13+
from rclpy.client import Client
14+
from rcl_interfaces.msg import Parameter, ParameterType, ParameterValue
1315
from controller_manager_msgs.srv import ListControllers
1416
from controller_manager_msgs.srv import SwitchController
1517
from geometry_msgs.msg import PoseStamped
1618
from geometry_msgs.msg import WrenchStamped
19+
from rcl_interfaces.srv import GetParameters, SetParameters
20+
from typing import Any
1721

1822

1923
def generate_test_description():
@@ -52,7 +56,6 @@ def __init__(self, *args):
5256
def setUpClass(cls):
5357
rclpy.init()
5458
cls.node = Node("test_startup")
55-
cls.setup_interfaces(cls)
5659

5760
cls.our_controllers = [
5861
"cartesian_motion_controller",
@@ -65,6 +68,8 @@ def setUpClass(cls):
6568
"invalid_cartesian_compliance_controller",
6669
]
6770

71+
cls.setup_interfaces(cls)
72+
6873
@classmethod
6974
def tearDownClass(cls):
7075
cls.node.destroy_node()
@@ -86,6 +91,20 @@ def setup_interfaces(self):
8691
if not self.switch_controller.wait_for_service(timeout.nanoseconds / 1e9):
8792
self.fail("Service switch_controllers not available")
8893

94+
self.get_parameter_clients = {
95+
controller: self.node.create_client(
96+
GetParameters, f"/{controller}/get_parameters"
97+
)
98+
for controller in self.our_controllers[0:3]
99+
}
100+
101+
self.set_parameter_clients = {
102+
controller: self.node.create_client(
103+
SetParameters, f"/{controller}/set_parameters"
104+
)
105+
for controller in self.our_controllers[0:3]
106+
}
107+
89108
self.target_pose_pub = self.node.create_publisher(
90109
PoseStamped, "target_frame", 3
91110
)
@@ -192,6 +211,31 @@ def publish_nan_targets():
192211
)
193212
self.stop_controller(name)
194213

214+
def test_solver_parameters(self):
215+
"""Check whether we can set and get nested solver parameters"""
216+
example_param = "solver.forward_dynamics.link_mass"
217+
default_value = 0.1
218+
new_value = 0.7
219+
220+
for client in self.get_parameter_clients.values():
221+
result = self.get_parameters(client, [example_param])
222+
result = result.values[0].double_value
223+
self.assertTrue(result == default_value)
224+
225+
for client in self.set_parameter_clients.values():
226+
param = Parameter(
227+
name=example_param,
228+
value=ParameterValue(
229+
double_value=new_value, type=ParameterType.PARAMETER_DOUBLE
230+
),
231+
)
232+
self.set_parameters(client, [param])
233+
234+
for client in self.get_parameter_clients.values():
235+
result = self.get_parameters(client, [example_param])
236+
result = result.values[0].double_value
237+
self.assertTrue(result == new_value)
238+
195239
def check_state(self, controller, state):
196240
"""Check the controller's state
197241
@@ -223,3 +267,20 @@ def perform_switch(self, req):
223267
req.strictness = req.BEST_EFFORT
224268
future = self.switch_controller.call_async(req)
225269
rclpy.spin_until_future_complete(self.node, future)
270+
271+
def set_parameters(self, client: Client, params: list[Parameter]) -> None:
272+
req = SetParameters.Request()
273+
req.parameters = params
274+
future = client.call_async(req)
275+
rclpy.spin_until_future_complete(
276+
self.node, future # type: ignore[attr-defined]
277+
)
278+
279+
def get_parameters(self, client: Client, names: list[str]) -> Any:
280+
req = GetParameters.Request()
281+
req.names = names
282+
future = client.call_async(req)
283+
rclpy.spin_until_future_complete(
284+
self.node, future # type: ignore[attr-defined]
285+
)
286+
return future.result()

0 commit comments

Comments
 (0)