Skip to content

Commit 08e058d

Browse files
Reduce mutex scope in Servo thread (#3259)
Fixes occasional main thread starvation caused by repeatedly creating a lock_guard in the servo loop. Fairness is improved by removing the thread sleep rate from the lock scope.
1 parent f47ecb5 commit 08e058d

File tree

1 file changed

+59
-57
lines changed

1 file changed

+59
-57
lines changed

moveit_ros/moveit_servo/src/servo_node.cpp

Lines changed: 59 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -326,76 +326,78 @@ void ServoNode::servoLoop()
326326
continue;
327327
}
328328

329-
std::lock_guard<std::mutex> lock_guard(lock_);
330-
const bool use_trajectory = servo_params_.command_out_type == "trajectory_msgs/JointTrajectory";
331-
const auto cur_time = node_->now();
329+
{ // scope for mutex-protected operations
330+
std::lock_guard<std::mutex> lock_guard(lock_);
331+
const bool use_trajectory = servo_params_.command_out_type == "trajectory_msgs/JointTrajectory";
332+
const auto cur_time = node_->now();
332333

333-
if (use_trajectory && !joint_cmd_rolling_window_.empty() && joint_cmd_rolling_window_.back().time_stamp > cur_time)
334-
{
335-
current_state = joint_cmd_rolling_window_.back();
336-
}
337-
else
338-
{
339-
// if all joint_cmd_rolling_window_ is empty or all commands in it are outdated, use current robot state
340-
joint_cmd_rolling_window_.clear();
341-
current_state = servo_->getCurrentRobotState(false /* block for current robot state */);
342-
current_state.velocities *= 0.0;
343-
}
334+
if (use_trajectory && !joint_cmd_rolling_window_.empty() && joint_cmd_rolling_window_.back().time_stamp > cur_time)
335+
{
336+
current_state = joint_cmd_rolling_window_.back();
337+
}
338+
else
339+
{
340+
// if all joint_cmd_rolling_window_ is empty or all commands in it are outdated, use current robot state
341+
joint_cmd_rolling_window_.clear();
342+
current_state = servo_->getCurrentRobotState(false /* block for current robot state */);
343+
current_state.velocities *= 0.0;
344+
}
344345

345-
// update robot state values
346-
robot_state->setJointGroupPositions(joint_model_group, current_state.positions);
347-
robot_state->setJointGroupVelocities(joint_model_group, current_state.velocities);
346+
// update robot state values
347+
robot_state->setJointGroupPositions(joint_model_group, current_state.positions);
348+
robot_state->setJointGroupVelocities(joint_model_group, current_state.velocities);
348349

349-
next_joint_state = std::nullopt;
350-
const CommandType expected_type = servo_->getCommandType();
350+
next_joint_state = std::nullopt;
351+
const CommandType expected_type = servo_->getCommandType();
351352

352-
if (expected_type == CommandType::JOINT_JOG && new_joint_jog_msg_)
353-
{
354-
next_joint_state = processJointJogCommand(robot_state);
355-
}
356-
else if (expected_type == CommandType::TWIST && new_twist_msg_)
357-
{
358-
next_joint_state = processTwistCommand(robot_state);
359-
}
360-
else if (expected_type == CommandType::POSE && new_pose_msg_)
361-
{
362-
next_joint_state = processPoseCommand(robot_state);
363-
}
364-
else if (new_joint_jog_msg_ || new_twist_msg_ || new_pose_msg_)
365-
{
366-
new_joint_jog_msg_ = new_twist_msg_ = new_pose_msg_ = false;
367-
RCLCPP_WARN_STREAM(node_->get_logger(), "Command type has not been set, cannot accept input");
368-
}
353+
if (expected_type == CommandType::JOINT_JOG && new_joint_jog_msg_)
354+
{
355+
next_joint_state = processJointJogCommand(robot_state);
356+
}
357+
else if (expected_type == CommandType::TWIST && new_twist_msg_)
358+
{
359+
next_joint_state = processTwistCommand(robot_state);
360+
}
361+
else if (expected_type == CommandType::POSE && new_pose_msg_)
362+
{
363+
next_joint_state = processPoseCommand(robot_state);
364+
}
365+
else if (new_joint_jog_msg_ || new_twist_msg_ || new_pose_msg_)
366+
{
367+
new_joint_jog_msg_ = new_twist_msg_ = new_pose_msg_ = false;
368+
RCLCPP_WARN_STREAM(node_->get_logger(), "Command type has not been set, cannot accept input");
369+
}
369370

370-
if (next_joint_state && (servo_->getStatus() != StatusCode::INVALID) &&
371-
(servo_->getStatus() != StatusCode::HALT_FOR_COLLISION))
372-
{
373-
if (use_trajectory)
371+
if (next_joint_state && (servo_->getStatus() != StatusCode::INVALID) &&
372+
(servo_->getStatus() != StatusCode::HALT_FOR_COLLISION))
374373
{
375-
auto& next_joint_state_value = next_joint_state.value();
376-
updateSlidingWindow(next_joint_state_value, joint_cmd_rolling_window_, servo_params_.max_expected_latency,
377-
cur_time);
378-
if (const auto msg = composeTrajectoryMessage(servo_params_, joint_cmd_rolling_window_))
374+
if (use_trajectory)
375+
{
376+
auto& next_joint_state_value = next_joint_state.value();
377+
updateSlidingWindow(next_joint_state_value, joint_cmd_rolling_window_, servo_params_.max_expected_latency,
378+
cur_time);
379+
if (const auto msg = composeTrajectoryMessage(servo_params_, joint_cmd_rolling_window_))
380+
{
381+
trajectory_publisher_->publish(msg.value());
382+
}
383+
}
384+
else
379385
{
380-
trajectory_publisher_->publish(msg.value());
386+
multi_array_publisher_->publish(composeMultiArrayMessage(servo_->getParams(), next_joint_state.value()));
381387
}
388+
last_commanded_state_ = next_joint_state.value();
382389
}
383390
else
384391
{
385-
multi_array_publisher_->publish(composeMultiArrayMessage(servo_->getParams(), next_joint_state.value()));
392+
// if no new command was created, use current robot state
393+
updateSlidingWindow(current_state, joint_cmd_rolling_window_, servo_params_.max_expected_latency, cur_time);
394+
servo_->resetSmoothing(current_state);
386395
}
387-
last_commanded_state_ = next_joint_state.value();
388-
}
389-
else
390-
{
391-
// if no new command was created, use current robot state
392-
updateSlidingWindow(current_state, joint_cmd_rolling_window_, servo_params_.max_expected_latency, cur_time);
393-
servo_->resetSmoothing(current_state);
394-
}
395396

396-
status_msg.code = static_cast<int8_t>(servo_->getStatus());
397-
status_msg.message = servo_->getStatusMessage();
398-
status_publisher_->publish(status_msg);
397+
status_msg.code = static_cast<int8_t>(servo_->getStatus());
398+
status_msg.message = servo_->getStatusMessage();
399+
status_publisher_->publish(status_msg);
400+
}
399401

400402
servo_frequency.sleep();
401403
}

0 commit comments

Comments
 (0)