Skip to content

Commit 1235f2e

Browse files
committed
Merge branch 'fix/pywalk' into feature/mujoco
2 parents 8cebf64 + 5345887 commit 1235f2e

File tree

5 files changed

+60
-43
lines changed

5 files changed

+60
-43
lines changed

bitbots_motion/bitbots_quintic_walk/bitbots_quintic_walk_py/py_walk.py

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from typing import Optional
2+
13
from biped_interfaces.msg import Phase
24
from bitbots_quintic_walk_py.libpy_quintic_walk import PyWalkWrapper
35
from bitbots_utils.utils import parse_parameter_dict
@@ -11,17 +13,24 @@
1113

1214

1315
class PyWalk:
14-
def __init__(self, namespace="", parameters: list[Parameter] | None = None, set_force_smooth_step_transition=False):
15-
serialized_parameters = []
16-
if parameters is not None:
17-
for parameter in parameters:
18-
serialized_parameters.append(serialize_message(parameter))
19-
if parameter.value.type == 2:
20-
print(
21-
f"Gave parameter {parameter.name} of integer type. If the code crashes it is maybe because this "
22-
f"should be a float. You may need to add an .0 in some yaml file."
23-
)
24-
self.py_walk_wrapper = PyWalkWrapper(namespace, serialized_parameters, set_force_smooth_step_transition)
16+
def __init__(
17+
self,
18+
namespace="",
19+
walk_parameters: Optional[list[Parameter]] = None,
20+
moveit_parameters: Optional[list[Parameter]] = None,
21+
set_force_smooth_step_transition=False,
22+
):
23+
def serialize_parameters(parameters):
24+
if parameters is None:
25+
return []
26+
return list(map(serialize_message, parameters))
27+
28+
self.py_walk_wrapper = PyWalkWrapper(
29+
namespace,
30+
serialize_parameters(walk_parameters),
31+
serialize_parameters(moveit_parameters),
32+
set_force_smooth_step_transition,
33+
)
2534

2635
def spin_ros(self):
2736
self.py_walk_wrapper.spin_some()

bitbots_motion/bitbots_quintic_walk/include/bitbots_quintic_walk/walk_node.hpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ namespace bitbots_quintic_walk {
5454
class WalkNode {
5555
public:
5656
explicit WalkNode(rclcpp::Node::SharedPtr node, const std::string &ns = "",
57-
std::vector<rclcpp::Parameter> parameters = {});
57+
std::vector<rclcpp::Parameter> moveit_parameters = {});
5858
bitbots_msgs::msg::JointCommand step(double dt);
5959
bitbots_msgs::msg::JointCommand step(double dt, geometry_msgs::msg::Twist::SharedPtr cmdvel_msg,
6060
sensor_msgs::msg::Imu::SharedPtr imu_msg,
@@ -112,8 +112,6 @@ class WalkNode {
112112

113113
nav_msgs::msg::Odometry getOdometry();
114114

115-
rcl_interfaces::msg::SetParametersResult onSetParameters(const std::vector<rclcpp::Parameter> &parameters);
116-
117115
void publish_debug();
118116
rclcpp::TimerBase::SharedPtr startTimer();
119117
double getTimerFreq();

bitbots_motion/bitbots_quintic_walk/include/bitbots_quintic_walk/walk_pywrapper.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ using namespace ros2_python_extension;
2323

2424
class PyWalkWrapper {
2525
public:
26-
explicit PyWalkWrapper(std::string ns, std::vector<py::bytes> parameter_msgs = {},
27-
bool force_smooth_step_transition = false);
26+
explicit PyWalkWrapper(std::string ns, std::vector<py::bytes> walk_parameter_msgs = {},
27+
std::vector<py::bytes> moveit_parameter_msgs = {}, bool force_smooth_step_transition = false);
2828
py::bytes step(double dt, py::bytes &cmdvel_msg, py::bytes &imu_msg, py::bytes &jointstate_msg,
2929
py::bytes &pressure_left, py::bytes &pressure_right);
3030
py::bytes step_relative(double dt, py::bytes &step_msg, py::bytes &imu_msg, py::bytes &jointstate_msg,

bitbots_motion/bitbots_quintic_walk/src/walk_node.cpp

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,29 +9,23 @@ using namespace std::chrono_literals;
99

1010
namespace bitbots_quintic_walk {
1111

12-
WalkNode::WalkNode(rclcpp::Node::SharedPtr node, const std::string& ns, std::vector<rclcpp::Parameter> parameters)
12+
WalkNode::WalkNode(rclcpp::Node::SharedPtr node, const std::string& ns,
13+
std::vector<rclcpp::Parameter> moveit_parameters)
1314
: node_(node),
1415
param_listener_(node_),
1516
config_(param_listener_.get_params()),
1617
walk_engine_(node_, config_.engine),
1718
stabilizer_(node_),
1819
ik_(node_, config_.node.ik),
1920
visualizer_(node_, config_.node.tf) {
20-
// Create dummy node for moveit
21-
auto moveit_node = std::make_shared<rclcpp::Node>(ns + "walking_moveit_node");
22-
23-
// when called from python, parameters are given to the constructor
24-
for (auto parameter : parameters) {
25-
if (node_->has_parameter(parameter.get_name())) {
26-
// this is the case for walk engine params set via python
27-
node_->set_parameter(parameter);
28-
} else {
29-
// parameter is not for the walking, set on moveit node
30-
moveit_node->declare_parameter(parameter.get_name(), parameter.get_type());
31-
moveit_node->set_parameter(parameter);
32-
}
33-
}
34-
21+
// Create dummy node for moveit. This is necessary for dynamic reconfigure to work (moveit does some bullshit with
22+
// parameter declarations, so we need to isolate the walking parameters from the moveit parameters).
23+
// If the walking is instantiated using the python wrapper, moveit parameters are passed because no moveit config
24+
// is loaded in the conventional way. Normally the moveit config is loaded via launch file and the passed vector is
25+
// empty.
26+
auto moveit_node = std::make_shared<rclcpp::Node>(
27+
"walking_moveit_node", ns,
28+
rclcpp::NodeOptions().automatically_declare_parameters_from_overrides(true).parameter_overrides(moveit_parameters));
3529
// get all kinematics parameters from the move_group node if they are not set manually via constructor
3630
std::string check_kinematic_parameters;
3731
if (!moveit_node->get_parameter("robot_description_kinematics.LeftLeg.kinematics_solver",

bitbots_motion/bitbots_quintic_walk/src/walk_pywrapper.cpp

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,37 @@
22

33
void PyWalkWrapper::spin_some() { rclcpp::spin_some(node_); }
44

5-
PyWalkWrapper::PyWalkWrapper(std::string ns, std::vector<py::bytes> parameter_msgs, bool force_smooth_step_transition) {
5+
PyWalkWrapper::PyWalkWrapper(std::string ns, std::vector<py::bytes> walk_parameter_msgs,
6+
std::vector<py::bytes> moveit_parameter_msgs, bool force_smooth_step_transition) {
67
// initialize rclcpp if not already done
78
if (!rclcpp::contexts::get_global_default_context()->is_valid()) {
89
rclcpp::init(0, nullptr);
910
}
1011

11-
// create parameters from serialized messages
12-
std::vector<rclcpp::Parameter> cpp_parameters = {};
13-
for (auto &parameter_msg : parameter_msgs) {
14-
cpp_parameters.push_back(
15-
rclcpp::Parameter::from_parameter_msg(fromPython<rcl_interfaces::msg::Parameter>(parameter_msg)));
16-
}
17-
18-
node_ = rclcpp::Node::make_shared(ns + "walking");
19-
walk_node_ = std::make_shared<bitbots_quintic_walk::WalkNode>(node_, ns, cpp_parameters);
12+
// internal function to deserialize the parameter messages
13+
auto deserialize_parameters = [](std::vector<py::bytes> parameter_msgs) {
14+
std::vector<rclcpp::Parameter> cpp_parameters = {};
15+
for (auto &parameter_msg : parameter_msgs) {
16+
cpp_parameters.push_back(
17+
rclcpp::Parameter::from_parameter_msg(fromPython<rcl_interfaces::msg::Parameter>(parameter_msg)));
18+
}
19+
return cpp_parameters;
20+
};
21+
22+
// Create a node object
23+
// Even tho we use python bindings instead of ros's dds, we still need a node object for logging and parameter
24+
// handling Because the walking is not started using the launch infrastructure and an appropriate parameter file, we
25+
// need to manually set the parameters
26+
node_ = rclcpp::Node::make_shared(
27+
"walking", ns, rclcpp::NodeOptions().parameter_overrides(deserialize_parameters(walk_parameter_msgs)));
28+
29+
// Create the walking object
30+
// We pass it the node we created. But the walking also creates a helper node for moveit (otherwise dynamic
31+
// reconfigure does not work, because moveit does some bullshit with their parameter declarations leading dynamic
32+
// reconfigure not working). This way the walking parameters are isolated from the moveit parameters, allowing dynamic
33+
// reconfigure to work. Therefore we need to pass the moveit parameters to the walking.
34+
walk_node_ =
35+
std::make_shared<bitbots_quintic_walk::WalkNode>(node_, ns, deserialize_parameters(moveit_parameter_msgs));
2036
set_robot_state(0);
2137
walk_node_->initializeEngine();
2238
walk_node_->getEngine()->setForceSmoothStepTransition(force_smooth_step_transition);
@@ -197,7 +213,7 @@ PYBIND11_MODULE(libpy_quintic_walk, m) {
197213
using namespace bitbots_quintic_walk;
198214

199215
py::class_<PyWalkWrapper, std::shared_ptr<PyWalkWrapper>>(m, "PyWalkWrapper")
200-
.def(py::init<std::string, std::vector<py::bytes>, bool>())
216+
.def(py::init<std::string, std::vector<py::bytes>, std::vector<py::bytes>, bool>())
201217
.def("step", &PyWalkWrapper::step)
202218
.def("step_relative", &PyWalkWrapper::step_relative)
203219
.def("step_open_loop", &PyWalkWrapper::step_open_loop)

0 commit comments

Comments
 (0)