Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add command queue to servo to account for latency #2594

Merged
merged 58 commits into from Jan 3, 2024

Conversation

pac48
Copy link
Contributor

@pac48 pac48 commented Dec 11, 2023

There is an issue where some robots experience non-smooth and noisy servo performance #2275. Currently, servo sends trajectory messages to the ros2_control JTC one waypoint at a time. However, This causes issues because when the JTC receives a new message, it replaces the old one entirely. My proposal to solve this issue is to send more than one waypoint at a time and make sure everything is time-synchronized. Below is an example diagram.

buffer

When messages are sent from servo to the JTC, there is an inherent noisy delay that should be accounted for. One strategy is to use a buffer that contains all generated servo commands from the current time to the current time plus the maximum expected latency. This range is shown in red. Any commands that are put in the buffer are considered "committed", meaning they will be executed by the JTC. For any time after the red region, there is still an opportunity to change commands. This is illustrated with the green trajectory.

I recorded and plotted the commands received by the JTC with the current servo implementation (left) vs. this PR (right) using the 'demo_pose.cpp' example in the servo package.

image

@pac48 pac48 marked this pull request as draft December 11, 2023 00:21
Copy link

codecov bot commented Dec 11, 2023

Codecov Report

Attention: 25 lines in your changes are missing coverage. Please review.

Comparison is base (74ba730) 50.31% compared to head (3217e03) 50.48%.

❗ Current head 3217e03 differs from pull request most recent head 279925f. Consider uploading reports for the commit 279925f to get more accurate results

Files Patch % Lines
moveit_ros/moveit_servo/src/servo.cpp 48.00% 13 Missing ⚠️
moveit_ros/moveit_servo/src/utils/common.cpp 82.36% 12 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2594      +/-   ##
==========================================
+ Coverage   50.31%   50.48%   +0.18%     
==========================================
  Files         386      386              
  Lines       32151    32228      +77     
==========================================
+ Hits        16172    16266      +94     
+ Misses      15979    15962      -17     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@sea-bass sea-bass self-requested a review December 11, 2023 14:40
Copy link
Member

@AndyZe AndyZe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you could get rid of the complexity of the rolling window and simply always keep 2 waypoints in committed_commands_. I bet the majority of the performance gain comes from the latency parameter and the stop command point.

The latency parameter is identical to #886 but the stop command point is a good idea.

moveit_ros/moveit_servo/src/servo.cpp Outdated Show resolved Hide resolved
@AndyZe
Copy link
Member

AndyZe commented Dec 11, 2023

Adding that halt position waypoint will likely have strange effects if the position/vel/accel JTC interfaces are active, since that increases the spline interpolation order --> potential for large swings during interpolation. It should work well if just the position interface is active, though.

moveit_ros/moveit_servo/config/servo_parameters.yaml Outdated Show resolved Hide resolved
moveit_ros/moveit_servo/config/servo_parameters.yaml Outdated Show resolved Hide resolved
moveit_ros/moveit_servo/src/servo.cpp Outdated Show resolved Hide resolved
moveit_ros/moveit_servo/src/servo.cpp Outdated Show resolved Hide resolved
moveit_ros/moveit_servo/src/servo.cpp Outdated Show resolved Hide resolved
moveit_ros/moveit_servo/include/moveit_servo/servo.hpp Outdated Show resolved Hide resolved
moveit_ros/moveit_servo/src/servo.cpp Outdated Show resolved Hide resolved
moveit_ros/moveit_servo/src/servo.cpp Outdated Show resolved Hide resolved
moveit_ros/moveit_servo/src/utils/common.cpp Outdated Show resolved Hide resolved
Copy link
Member

@AndyZe AndyZe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to rethink the end_state

moveit_ros/moveit_servo/src/servo.cpp Outdated Show resolved Hide resolved
@pac48
Copy link
Contributor Author

pac48 commented Dec 11, 2023

Need to rethink the end_state

The one problem I see with using the haltJoints() function is that it seems like it needs to be called in the servo loop. The only scenario when end_state is even a factor is when the servo loop dies or is severely delayed. So it won't be easy to use.

One option is to actually call haltJoints() multiple times to generate a sequence of gradually slowing points, instead of a single one with zero velocity. The drawback is that it will increase the size of the trajectory message and slow down the servo loop.

Further realizing that this code path should never be executed anyway, unless the latency is extreme.

Another option is to not explicitly account for this case because the low-level controller will likely have a stopping mechanism. But I think it's safer to have it just in case. @AndyZe Do you have a suggestion to handle the edge case of extreme latency?

@AndyZe
Copy link
Member

AndyZe commented Dec 11, 2023

I guess the halt point is fine.

Comment on lines 238 to 239
// keep track of previously generated joint commands for constructing trajectory messages
std::deque<KinematicState> committed_commands_;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// keep track of previously generated joint commands for constructing trajectory messages
std::deque<KinematicState> committed_commands_;
// rolling window of joint commands
std::deque<KinematicState> joint_cmd_rolling_window_;

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a fan of the "committed" terminology. I think people normally think of this as a rolling window.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed all references of "committed" to "joint_cmd_rolling_window"

moveit_ros/moveit_servo/src/servo.cpp Outdated Show resolved Hide resolved
moveit_ros/moveit_servo/src/servo.cpp Outdated Show resolved Hide resolved
@pac48
Copy link
Contributor Author

pac48 commented Dec 14, 2023

Between @sea-bass comments about making the change more functional, e.g. passing the rolling window in, and @AndyZe concerns about performance, I think it is best to factor out the command queueing logic and have the calling code maintain it. I'll move the logic into the servo_node. It's better that way. Also, I'll make the name changes @AndyZe suggested,

@AndyZe
Copy link
Member

AndyZe commented Dec 14, 2023

Well, props for figuring out this long-standing issue!

@pac48
Copy link
Contributor Author

pac48 commented Dec 15, 2023

Well, props for figuring out this long-standing issue!

Here is a result of running the realtime_servo demo in the tutorials. The new implementation is shown in the top plots and the old in the bottom plots. The left and right columns are position and position deltas as a function of time.

image

@pac48 pac48 force-pushed the pr-servo-command-queue branch 6 times, most recently from 12f1039 to 797d8f5 Compare December 15, 2023 23:35
@pac48 pac48 marked this pull request as ready for review December 15, 2023 23:43
pac48 and others added 8 commits December 17, 2023 16:15
Fix wording

Co-authored-by: Sebastian Castro <4603398+sea-bass@users.noreply.github.com>
Co-authored-by: Sebastian Castro <4603398+sea-bass@users.noreply.github.com>
Co-authored-by: Sebastian Castro <4603398+sea-bass@users.noreply.github.com>
Signed-off-by: Paul Gesel <paulgesel@gmail.com>
Copy link
Contributor

@sea-bass sea-bass left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see @AndyZe's point about scaling acceleration doing weird things to the direction being tracked, and left a comment inline asking if there is a way to "time scale" the bundled up trajectory in a way that is more correct.

The other comment about trying velocity filtering with the Butterworth plugin is something we could explore? I tried with these changes and it made my Gazebo simulation do horrible things, but that could have been a combination of Gazebo's physics and some other issues that may have been resolved since (including in this PR). I guess it's worth a shot to try it and get some data.

@@ -284,6 +284,15 @@ bool Servo::validateParams(const servo::Params& servo_params) const
params_valid = false;
}

if (servo_params.max_expected_latency / 3 < servo_params.publish_period)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This 3 in here is a magic number, but I'm assuming this is related to you wanting 3 points in your trajectory, right? Is this the same as MIN_POINTS_FOR_TRAJ_MSG you defined in common.cpp?

If that's not the case, you can probably leave in the literal here (especially since it's also in the error message), but definitely add a comment explaining.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's correct to relate the 3 here to MIN_POINTS_FOR_TRAJ_MSG. Do you think I should move MIN_POINTS_FOR_TRAJ_MSG to moveit_servo/utils/common.hpp so it can be accessed?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think so!

Comment on lines 684 to 688
// apply scaling to target velocity based on robot's limits
Eigen::VectorXd acceleration = -target_state.velocities / servo_params_.publish_period;
const double joint_acceleration_limit_scale = jointLimitAccelerationScalingFactor(acceleration, joint_bounds, 1.0);
target_state.velocities += joint_acceleration_limit_scale * acceleration * servo_params_.publish_period;

Copy link
Contributor

@sea-bass sea-bass Dec 28, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think @AndyZe's comment about direction switching is valid, and I hadn't thought of that since I was thinking about the full trajectory planning case where scaling down acceleration + scaling up time accelerating works equivalently to the unscaled case, as far as the space swept by the robot motion.

Is there any way to do the same within the current servo framework now that we have the rolling window? Like, time scaling https://www2.ece.ohio-state.edu/~zhang/RoboticsClass/docs/LN9_TrajectoryGeneration.pdf -- meaning, taking the existing trajectory's accelerations and scaling up the time_from_start to be higher as needed to meet the limits?

@pac48
Copy link
Contributor Author

pac48 commented Dec 28, 2023

If we filtered velocities instead of positions --> problem solved. There's an issue about that.

@AndyZe If we filter in velocity, won't we run into the same issue of the robot not moving in the direction commanded? That is the main criticism of acceleration limiting.

@AndyZe
Copy link
Member

AndyZe commented Dec 28, 2023

True. Well, it's an optional plugin. Hopefully Ruckig will come along and solve all of our issues. Happy to help make that happen

@pac48 pac48 force-pushed the pr-servo-command-queue branch 2 times, most recently from e72cdb9 to 0544301 Compare December 28, 2023 20:24
…ce the time stamp is set in the updateSlidingWindow function now.

Signed-off-by: Paul Gesel <paulgesel@gmail.com>
Signed-off-by: Paul Gesel <paulgesel@gmail.com>
@pac48
Copy link
Contributor Author

pac48 commented Dec 28, 2023

True. Well, it's an optional plugin. Hopefully Ruckig will come along and solve all of our issues. Happy to help make that happen

@AndyZe Okay great. I removed the acceleration-based limits from this PR. I will follow up with an online_signal_smoothing optional plugin in a future PR if needed.

Signed-off-by: Paul Gesel <paulgesel@gmail.com>
Copy link
Member

@AndyZe AndyZe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yay!

…s current state if no command generated 4) fix smooth hault: stop command was not generated if smoothing disabled 5) call resetSmoothing when there are no commands

Signed-off-by: Paul Gesel <paulgesel@gmail.com>
@sjahr
Copy link
Contributor

sjahr commented Jan 3, 2024

@pac48 Can you address the conflicts? Then we should merge this, nice work!

Copy link

mergify bot commented Jan 3, 2024

This pull request is in conflict. Could you fix it @pac48?

@sea-bass
Copy link
Contributor

sea-bass commented Jan 3, 2024

@pac48 Can you address the conflicts? Then we should merge this, nice work!

I just addressed them, they were simple and from my recent PR, so let's do this!

@sjahr sjahr enabled auto-merge (squash) January 3, 2024 12:22
@sjahr sjahr merged commit 0d2d070 into moveit:main Jan 3, 2024
10 of 11 checks passed
pac48 added a commit to pac48/moveit2 that referenced this pull request Jan 3, 2024
* add command queue to servo to account for latency

* run pre-commit

* fix unsigned compare

* Update moveit_ros/moveit_servo/config/servo_parameters.yaml

Fix wording

Co-authored-by: Sebastian Castro <4603398+sea-bass@users.noreply.github.com>

* Update moveit_ros/moveit_servo/src/servo.cpp

Co-authored-by: Sebastian Castro <4603398+sea-bass@users.noreply.github.com>

* Update moveit_ros/moveit_servo/src/servo.cpp

Co-authored-by: Sebastian Castro <4603398+sea-bass@users.noreply.github.com>

* add comments and change variable names

* add checks to determine what state information should be published

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* change latency parameter name

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* factor command queue out of servo instance

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* update demos

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* needs clean up but working well

* deal with duplicate timestamps for sim

* add acceleration limiting smoothing

* add timeout check in filter

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* factor out robot state from servo call

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* update comments in smoothing pluin

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* fix tests

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* change velocity calculation to make interpolation not overshoot

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* Update moveit_ros/moveit_servo/config/panda_simulated_config.yaml

Co-authored-by: Sebastian Castro <4603398+sea-bass@users.noreply.github.com>

* Update moveit_ros/moveit_servo/config/servo_parameters.yaml

Co-authored-by: Sebastian Castro <4603398+sea-bass@users.noreply.github.com>

* Update moveit_ros/moveit_servo/demos/cpp_interface/demo_joint_jog.cpp

Co-authored-by: Sebastian Castro <4603398+sea-bass@users.noreply.github.com>

* fix time calculation

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* add check to ensure time interval is positive

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* simplify demos

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* wait for first robot state before starting servo loop

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* add comments to acceleration filter

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* fix wait time units

* fix logic bug in smoothHalt and remove stopping point from trajectory message. Still some overshoot.

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* add acceleration limit to servo

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* remove acceleration filter

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* remove other filter files from moveit_core

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* add doc string and basic clean up

* refactor getRobotState to utils and add a test

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* make some things const and fix comments

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* use joint_limts params to get robot acceleration limits

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* update demo config and set velocities in demos

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* fix acceleration calculation

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* apply collision_velocity_scale_ in smooth hault, add comments, and rename variables

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* use bounds on scaling factors in [0... 1]

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* remove joint_acceleration parameter

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* add test for jointLimitAccelerationScaling

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* refactor velocity and acceleration scaling into common function

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* general clean up, add comments, fix parameters, set timestamp in updateSlidingWindow, etc.

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* Update moveit_ros/moveit_servo/config/panda_simulated_config.yaml

Co-authored-by: AndyZe <andyz@utexas.edu>

* Update moveit_ros/moveit_servo/src/servo.cpp

Co-authored-by: AndyZe <andyz@utexas.edu>

* remove override_acceleration_scaling_factor

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* fix variable name

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* enable use_smoothing in demos

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* Update moveit_ros/moveit_servo/config/panda_simulated_config.yaml

Co-authored-by: AndyZe <andyz@utexas.edu>

* add current state to command queue if it is empty. This is needed since the time stamp is set in the updateSlidingWindow function now.

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* remove acceleration smoothing

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* revert jointLimitVelocityScalingFactor refactor

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* 1) fix spelling 2) add comments 3) make sure rolling_window always has current state if no command generated 4) fix smooth hault: stop command was not generated if smoothing disabled 5) call resetSmoothing when there are no commands

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

---------

Signed-off-by: Paul Gesel <paulgesel@gmail.com>
Co-authored-by: Sebastian Castro <4603398+sea-bass@users.noreply.github.com>
Co-authored-by: AndyZe <andyz@utexas.edu>
pac48 added a commit to pac48/moveit2 that referenced this pull request Jan 4, 2024
* add command queue to servo to account for latency

* run pre-commit

* fix unsigned compare

* Update moveit_ros/moveit_servo/config/servo_parameters.yaml

Fix wording

Co-authored-by: Sebastian Castro <4603398+sea-bass@users.noreply.github.com>

* Update moveit_ros/moveit_servo/src/servo.cpp

Co-authored-by: Sebastian Castro <4603398+sea-bass@users.noreply.github.com>

* Update moveit_ros/moveit_servo/src/servo.cpp

Co-authored-by: Sebastian Castro <4603398+sea-bass@users.noreply.github.com>

* add comments and change variable names

* add checks to determine what state information should be published

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* change latency parameter name

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* factor command queue out of servo instance

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* update demos

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* needs clean up but working well

* deal with duplicate timestamps for sim

* add acceleration limiting smoothing

* add timeout check in filter

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* factor out robot state from servo call

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* update comments in smoothing pluin

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* fix tests

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* change velocity calculation to make interpolation not overshoot

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* Update moveit_ros/moveit_servo/config/panda_simulated_config.yaml

Co-authored-by: Sebastian Castro <4603398+sea-bass@users.noreply.github.com>

* Update moveit_ros/moveit_servo/config/servo_parameters.yaml

Co-authored-by: Sebastian Castro <4603398+sea-bass@users.noreply.github.com>

* Update moveit_ros/moveit_servo/demos/cpp_interface/demo_joint_jog.cpp

Co-authored-by: Sebastian Castro <4603398+sea-bass@users.noreply.github.com>

* fix time calculation

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* add check to ensure time interval is positive

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* simplify demos

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* wait for first robot state before starting servo loop

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* add comments to acceleration filter

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* fix wait time units

* fix logic bug in smoothHalt and remove stopping point from trajectory message. Still some overshoot.

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* add acceleration limit to servo

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* remove acceleration filter

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* remove other filter files from moveit_core

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* add doc string and basic clean up

* refactor getRobotState to utils and add a test

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* make some things const and fix comments

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* use joint_limts params to get robot acceleration limits

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* update demo config and set velocities in demos

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* fix acceleration calculation

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* apply collision_velocity_scale_ in smooth hault, add comments, and rename variables

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* use bounds on scaling factors in [0... 1]

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* remove joint_acceleration parameter

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* add test for jointLimitAccelerationScaling

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* refactor velocity and acceleration scaling into common function

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* general clean up, add comments, fix parameters, set timestamp in updateSlidingWindow, etc.

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* Update moveit_ros/moveit_servo/config/panda_simulated_config.yaml

Co-authored-by: AndyZe <andyz@utexas.edu>

* Update moveit_ros/moveit_servo/src/servo.cpp

Co-authored-by: AndyZe <andyz@utexas.edu>

* remove override_acceleration_scaling_factor

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* fix variable name

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* enable use_smoothing in demos

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* Update moveit_ros/moveit_servo/config/panda_simulated_config.yaml

Co-authored-by: AndyZe <andyz@utexas.edu>

* add current state to command queue if it is empty. This is needed since the time stamp is set in the updateSlidingWindow function now.

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* remove acceleration smoothing

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* revert jointLimitVelocityScalingFactor refactor

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

* 1) fix spelling 2) add comments 3) make sure rolling_window always has current state if no command generated 4) fix smooth hault: stop command was not generated if smoothing disabled 5) call resetSmoothing when there are no commands

Signed-off-by: Paul Gesel <paulgesel@gmail.com>

---------

Signed-off-by: Paul Gesel <paulgesel@gmail.com>
Co-authored-by: Sebastian Castro <4603398+sea-bass@users.noreply.github.com>
Co-authored-by: AndyZe <andyz@utexas.edu>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants