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

Clearing pending commands - unexpected behavior #1926

Closed
unjambonakap opened this issue Mar 11, 2023 · 9 comments
Closed

Clearing pending commands - unexpected behavior #1926

unjambonakap opened this issue Mar 11, 2023 · 9 comments
Labels
🎵 harmonic Gazebo Harmonic

Comments

@unjambonakap
Copy link

unjambonakap commented Mar 11, 2023

Hi,

Issue summary:

  • Set LinearVelocityCmd to non zero vector (for instance to give the system an initial velocity)
  • This velocity is used on first integration step
  • LinearVelocityCmd gets cleared to zero vector
  • The model stops moving on all subsequent steps (while we don't ecm.RemoveComponent(...))

When specify attaching a command to an entity (such as JointForceCmd, AngularVelocityCmd), these commands get cleared after a physic step (physics.cc)

This clearing has, I'd say, an unexpected behavior for some commands.
Most notably, the velocity commands (angular and linear) get set to the zero vector. This zero vector is then used on later steps to overwrite the velocities.

I suppose the clearing of commands after an integration step means that these commands are considered as impulses - meaning a command should only alter one step and then be no-op.
While clearing a force to the zero vector achieves that, doing the same for the velocity is not correct.

Possibles solutions:

  1. deleting the commands instead of clearing them to zero
  2. modifying the content of the velocity commands to have an optional

I'd favor (1) but I've just started using gazebo so I don't know much :)

Edit: I could do the PR once we've settled on a direction

Thanks

@azeey
Copy link
Contributor

azeey commented Mar 13, 2023

While clearing a force to the zero vector achieves that, doing the same for the velocity is not correct.

Ah, yes, I think clearing to zero only makes sense for force components.

deleting the commands instead of clearing them to zero

I'd favor this too. I think in the past we had performance issues with repeatedly creating and deleting components, but I believe that has been fixed as of #856. The only caveat is I think this would be considered a behavior change since a system that assumes that keeps updating a velocity command now needs to recreate the component in every step, so at best, we'd have to target a PR against main, but we might have to live with the current behavior if too many systems depend on the old behavior.

@azeey azeey self-assigned this Mar 13, 2023
@iche033
Copy link
Contributor

iche033 commented Mar 13, 2023

Looking throughout the codebase, there are a few systems and tests that rely on the current behavior so it might be a good option to go with the approach of creating a new vel cmd component for the different behavior. For the Link API, We can also add an optional arg to indicate whether the vel cmd should persist or not, e.g. SetLinearVelocity(EntityComponentManager &_ecm, const math::Vector3d &_vel, bool _persist = false)

@unjambonakap
Copy link
Author

Could you point to places that rely on this behavior? I'm interested in seeing a situation where the current behavior is useful because I really can't conceive a situation where it makes sense (nor reconcile it semantically to the function's name)

We have 3 behavior:
logical persist: link.SetV(v, persist=true) -> link.v = v, integrate(1), link.v = v, ...
logical dirac: link.SetV(v, persist=false) -> link.v = v, integrate(1) ...
actual behavior: link.SetV(v) -> link.v = v, integrate(1) ,link.v = 0, integrate(1), link.v = 0, ...

I agree that a _persist flag would be a nice feature. A new command for it is fine though the current command's behavior needs to be changed (either through a second new command or through a delete of the component).

@iche033
Copy link
Contributor

iche033 commented Mar 14, 2023

I noticed that most of the systems and tests inside gz-sim had to send the cmd continuously, e.g. velocity_control system and a test helper class. The behavior change here is that if one of our users had code to move a model for a fixed period of time, e.g. by sending vel cmds for 5 seconds then expect the model to stop moving once they stop sending the cmd, the new proposed change would break this behavior.

@unjambonakap
Copy link
Author

Fair point for user code (though I hope they do not do that :) ).
Those systems sending the command continuously wouldn't be affected by this, so that's good.

How do you want to proceed: should I stop bothering you and leave you people to it (I don't know much about the organization, if you're full time on gazebo or not) or we settle on a direction and I write a PR?
That direction could be to introduce a sidekick to LinearVelocityCmd with a persisted and dirac version with the appropriate helpers

@iche033
Copy link
Contributor

iche033 commented Mar 15, 2023

PRs are welcome :) I think we just need to agree on the design and what's to be implemented. @azeey what do you think adding a new component or do you have other ideas?

@azeey
Copy link
Contributor

azeey commented Mar 16, 2023

Those systems sending the command continuously wouldn't be affected by this, so that's good.

I don't think that's quite right because those systems assume the component is there and just update the value. If we remove the component, those systems would have to be updated to recreate the component in every time step.

We could create new components (eg. *VelocityImpulseCmd and *VelocityPersistedCmd) and leave the current components unchanged so we are backward compatible, but how would these new components interact with each other and with the existing *VelocityCmd components. How should the Physics system prioritize the components? And how would multiple systems that each use one of these components coexist? I don't have a good answer for these. It seems a lot cleaner and easier to reason about to have one set of *VelocityCmd components. Systems that need persisted velocities can just create and set the component in each time step. Systems that need the the robot to stop would just set the component to 0.

So my proposal would be to change the current behavior in the main branch and have the Physics system remove *VelocityCmd components. Now that we have EntityComponentManager::SetComponentData, which creates a component if it doesn't exist, it wouldn't be a difficult transition for users to make. For multiple system interactions, perhaps we can create a EntityComponentManager::AddComponentData, so they don't clobber each other's data.

BTW, I also see the same problem with JointVelocityCmd, so the decision we make here should be applied for all *VelocityCmd components.

@azeey azeey removed their assignment May 1, 2023
@azeey azeey added the 🎵 harmonic Gazebo Harmonic label May 1, 2023
@azeey azeey moved this to In progress in Core development Jul 24, 2023
scpeters added a commit that referenced this issue Nov 4, 2023
@scpeters
Copy link
Member

scpeters commented Nov 4, 2023

It seems a lot cleaner and easier to reason about to have one set of *VelocityCmd components. Systems that need persisted velocities can just create and set the component in each time step. Systems that need the the robot to stop would just set the component to 0.

So my proposal would be to change the current behavior in the main branch and have the Physics system remove *VelocityCmd components. Now that we have EntityComponentManager::SetComponentData, which creates a component if it doesn't exist, it wouldn't be a difficult transition for users to make. For multiple system interactions, perhaps we can create a EntityComponentManager::AddComponentData, so they don't clobber each other's data.

BTW, I also see the same problem with JointVelocityCmd, so the decision we make here should be applied for all *VelocityCmd components.

I've started work on this suggestion in #2228

scpeters added a commit that referenced this issue Nov 5, 2023
scpeters added a commit that referenced this issue Apr 9, 2024
This implements a suggestion from #1926 to delete
all `*VelocityCmd` components after each time step.
This also updates the logic for the following two systems
to handle this change:

* MulticopterMotorModel: handle missing component

Since JointVelocityCmd components are deleted after each
timestep, don't skip updating forces and moments if
the component does not exist, and use the
SetComponent API to more cleanly handle the component
creation logic. A syntax error in the the quadcopter test
worlds was fixed as well.

* TrajectoryFollower: don't need to remove commands

Now that the physics system is removing AngularVelocityCmd
components at every timestep, that logic can be removed
from the trajectory follower system.

Signed-off-by: Steve Peters <[email protected]>
@scpeters
Copy link
Member

scpeters commented Apr 9, 2024

all *VelocityCmd components are now removed at each timestep as of #2228, so I will close this issue. Please reopen if there is still something remaining to be done

@scpeters scpeters closed this as completed Apr 9, 2024
@github-project-automation github-project-automation bot moved this from In progress to Done in Core development Apr 9, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🎵 harmonic Gazebo Harmonic
Projects
Archived in project
Development

No branches or pull requests

4 participants