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

[RSDK-8574][RSDK-8184]: return an error if user tries to move a sensor controlled base without copy/pasting tuned PID values to the config #4291

Merged
merged 22 commits into from
Sep 12, 2024

Conversation

martha-johnston
Copy link
Contributor

@martha-johnston martha-johnston commented Aug 16, 2024

This isn't 100% ready but I want some early feedback on the setup. Things that still need to be done:

  • stress test every combination of configs with tuned and untuned values and make sure we are always using the correct values, only tested this briefly so far
  • clean up all the new variables I added, there's def a more streamlined way to keep track of the tuned values so if anyone has suggestions lmk

Update:

  • stored tuned PID values in sensor base and controlled motor
  • if tuning is in progress, return an error that says tuning in progress
  • if tuning is completed and a user hasn't copied over the values to the config, return an error with those values and don't move
  • if only one pid is tuned (for sensor base) error with only those tuned values
  • add a DoCommand that returns pid values when "get_tuned_pid" is true

@viambot viambot added the safe to test This pull request is marked safe to test from a trusted zone label Aug 16, 2024
Copy link
Member

@JohnN193 JohnN193 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 what you have makes sense. Didn't realize we weren't saving the gains in the struct already(outside of within the loop/config).

would honestly be fine with having the gains be linGains and angGains instead of the array of gains, just to match the config card. would make some of the tuning/reconfig logic easier to parse.

only other thought is making sure the sensorbase can close the wait for tuning loop thread

components/base/sensorcontrolled/velocities.go Outdated Show resolved Hide resolved
components/base/sensorcontrolled/velocities.go Outdated Show resolved Hide resolved
control/setup_control.go Outdated Show resolved Hide resolved
components/base/sensorcontrolled/velocities.go Outdated Show resolved Hide resolved
components/base/sensorcontrolled/sensorcontrolled.go Outdated Show resolved Hide resolved
@martha-johnston
Copy link
Contributor Author

have implemented some of your feedback @JohnN193, but pausing on this to finish up the rover canary so might not update for a bit

@viambot viambot added safe to test This pull request is marked safe to test from a trusted zone and removed safe to test This pull request is marked safe to test from a trusted zone labels Sep 4, 2024
@viambot viambot added safe to test This pull request is marked safe to test from a trusted zone and removed safe to test This pull request is marked safe to test from a trusted zone labels Sep 4, 2024
@viambot viambot added safe to test This pull request is marked safe to test from a trusted zone and removed safe to test This pull request is marked safe to test from a trusted zone labels Sep 4, 2024
@viambot viambot added safe to test This pull request is marked safe to test from a trusted zone and removed safe to test This pull request is marked safe to test from a trusted zone labels Sep 5, 2024
@martha-johnston
Copy link
Contributor Author

martha-johnston commented Sep 5, 2024

lots of changes here, but I did some basic starter hardware testing and everything seems to work as expected, but I need to do some more searching for edge cases. also need to update software tests still but feel free to review changes because I think the issues are in the test files.

@viambot viambot added safe to test This pull request is marked safe to test from a trusted zone and removed safe to test This pull request is marked safe to test from a trusted zone labels Sep 5, 2024
@martha-johnston
Copy link
Contributor Author

update: software tests fixed

@martha-johnston
Copy link
Contributor Author

@randhid tagging you if you're interested in taking a look

Copy link
Member

@JohnN193 JohnN193 left a comment

Choose a reason for hiding this comment

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

Want to confirm the plan for controlled motor before approving. otherwise looks good and lmk if I can help test

components/motor/gpio/controlled.go Show resolved Hide resolved
components/base/sensorcontrolled/movestraight.go Outdated Show resolved Hide resolved
components/base/sensorcontrolled/sensorcontrolled.go Outdated Show resolved Hide resolved
control/control_loop.go Show resolved Hide resolved
components/base/sensorcontrolled/spin.go Outdated Show resolved Hide resolved
components/base/sensorcontrolled/sensorcontrolled.go Outdated Show resolved Hide resolved
@viambot viambot added the safe to test This pull request is marked safe to test from a trusted zone label Sep 10, 2024
@martha-johnston
Copy link
Contributor Author

okay should be way more simple now, and added everything to motor. have tested tuning in progress and the tunedPIDError on every sensor base and motor api. all that should be left is to add do command get pid values to motor which I'll do in the next commit

control/setup_control.go Show resolved Hide resolved
}
}

// unlock the mutex before setting up the control loop so that the motors
// are not locked, and can run if any auto-tuning is necessary
sb.mu.Unlock()
if err := sb.setupControlLoop(linear, angular); err != nil {
if err := sb.setupControlLoop(sb.configPIDVals[0], sb.configPIDVals[1]); err != nil {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

there is an error a couple lines above when we are assigning the values, is that sufficient? or do you want this logic moved to the validate function? to me it seems like we should only loop through the control parameters once but I'm open to moving it

control/setup_control.go Outdated Show resolved Hide resolved
Comment on lines 60 to 64
if (sb.configPIDVals[0].NeedsAutoTuning() && !(*sb.tunedVals)[0].NeedsAutoTuning()) ||
(sb.configPIDVals[1].NeedsAutoTuning() && !(*sb.tunedVals)[1].NeedsAutoTuning()) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

yes

@@ -100,15 +102,16 @@ func SetupPIDControlConfig(
pidLoop := &PIDLoop{
Controllable: c,
PIDVals: pidVals,
TunedVals: &[]PIDConfig{},
Copy link
Contributor Author

Choose a reason for hiding this comment

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

true let me add some more checks for indexing

control/setup_control.go Outdated Show resolved Hide resolved
control/setup_control.go Outdated Show resolved Hide resolved
@viambot viambot added safe to test This pull request is marked safe to test from a trusted zone and removed safe to test This pull request is marked safe to test from a trusted zone labels Sep 10, 2024
Copy link
Member

@randhid randhid left a comment

Choose a reason for hiding this comment

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

Some minor nits, but please address them.

Please add description of cases tested manually and a better explanation of what was changed in this ticket.

Comment on lines 59 to 67
// if loop is tuning, return an error
// if loop has been tuned but the values haven't been added to the config, error with tuned values
if sb.loop != nil && sb.loop.GetTuning(ctx) {
return control.TuningInProgressErr(sb.Name().ShortName())
} else if (sb.configPIDVals[0].NeedsAutoTuning() && !(*sb.tunedVals)[0].NeedsAutoTuning()) ||
(sb.configPIDVals[1].NeedsAutoTuning() && !(*sb.tunedVals)[1].NeedsAutoTuning()) {
return control.TunedPIDErr(sb.Name().ShortName(), *sb.tunedVals)
}

Copy link
Member

Choose a reason for hiding this comment

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

let's make this a bit more readable. You can:
1 - use a case structure.
2—Write an in-line, anonymous function that checks if the PID values need Autotuning and passes in the four PID values for your second case.

Copy link
Member

Choose a reason for hiding this comment

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

tbh i think these should just be two separate if statements with their own comments. Don't see a reason for them to be grouped together and I personally find it weird when switch statements have a bunch of logic for cases(fine if peeps disagree tho). Agree with the helper function, its something I wanted to add as part of the refactors

}
}

// unlock the mutex before setting up the control loop so that the motors
// are not locked, and can run if any auto-tuning is necessary
sb.mu.Unlock()
if err := sb.setupControlLoop(linear, angular); err != nil {
if err := sb.setupControlLoop(sb.configPIDVals[0], sb.configPIDVals[1]); err != nil {
Copy link
Member

Choose a reason for hiding this comment

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

Is there a test (manual or software) that shows you what the experience looks like for a user right now, if they try to configure with 1) one badly named "type" 2) two badly named types? Are we hitting the tuning loops, and what happens if one loop is tuned but not the other in your current logic? What errors are returned?

Comment on lines 37 to 45
// if loop is tuning, return an error
// if loop has been tuned but the values haven't been added to the config, error with tuned values
if sb.loop != nil && sb.loop.GetTuning(ctx) {
return control.TuningInProgressErr(sb.Name().ShortName())
} else if (sb.configPIDVals[0].NeedsAutoTuning() && !(*sb.tunedVals)[0].NeedsAutoTuning()) ||
(sb.configPIDVals[1].NeedsAutoTuning() && !(*sb.tunedVals)[1].NeedsAutoTuning()) {
return control.TunedPIDErr(sb.Name().ShortName(), *sb.tunedVals)
}

Copy link
Member

Choose a reason for hiding this comment

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

Ah, is this the same case structure? Then scratch what I said in the above comment. Let's make it a private helper method for the sensor-controlled base.

components/motor/gpio/controlled.go Show resolved Hide resolved
Comment on lines 291 to 298
// if loop is tuning, return an error
// if loop has been tuned but the values haven't been added to the config, error with tuned values
if cm.loop != nil && cm.loop.GetTuning(ctx) {
return control.TuningInProgressErr(cm.Name().ShortName())
} else if cm.configPIDVals[0].NeedsAutoTuning() && !(*cm.tunedVals)[0].NeedsAutoTuning() {
return control.TunedPIDErr(cm.Name().ShortName(), *cm.tunedVals)
}

Copy link
Member

Choose a reason for hiding this comment

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

Since this is another package and this logic is only used once, I'd keep it as is, we may want to look out for this pattern to consider a shared method in the control package if we need this logic across more controlled components.

components/motor/gpio/controlled.go Show resolved Hide resolved
Comment on lines 342 to 349
// if loop is tuning, return an error
// if loop has been tuned but the values haven't been added to the config, error with tuned values
if cm.loop != nil && cm.loop.GetTuning(ctx) {
return control.TuningInProgressErr(cm.Name().ShortName())
} else if cm.configPIDVals[0].NeedsAutoTuning() && !(*cm.tunedVals)[0].NeedsAutoTuning() {
return control.TunedPIDErr(cm.Name().ShortName(), *cm.tunedVals)
}

Copy link
Member

Choose a reason for hiding this comment

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

Ah maybe I spoke too soon, but still, a private method in this package as well, if they're exactly the same for GoFor and SetRPM and have no reason to ever be different, let's make them the same check.

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'll try and add a control helper

Copy link
Member

@randhid randhid Sep 11, 2024

Choose a reason for hiding this comment

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

FWIW I think these should be helper in the scope of this package, not the control package. They care about things passed into the driver code at the driver level; it just makes it a little bit less repeated, so if you ever need to change its check in this package, you don't end up with a mismatch within the driver code itself.f

Copy link
Member

Choose a reason for hiding this comment

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

I think the controls package could own the helper, since the controls package kinda owns the tunedVals in the first place. That was something I wanted to setup when proposing the refactors. fine with leaving it in the driver for this pr

Copy link
Member

Choose a reason for hiding this comment

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

we can incrementally add to the scope to the eventual PR, don't want to go too DRY in case we limit ourselves while addressing a driver functionality request, which is this ticket.

@viambot viambot added safe to test This pull request is marked safe to test from a trusted zone and removed safe to test This pull request is marked safe to test from a trusted zone labels Sep 11, 2024
@martha-johnston
Copy link
Contributor Author

Okay I think I should have covered everything we discussed but let me know if I misunderstood anything and there's more changes you'd like

@martha-johnston
Copy link
Contributor Author

going to do a hardware test one more time to make sure everything still works as expected

components/motor/gpio/controlled_test.go Show resolved Hide resolved
}
}

// unlock the mutex before setting up the control loop so that the motors
// are not locked, and can run if any auto-tuning is necessary
sb.mu.Unlock()
if err := sb.setupControlLoop(linear, angular); err != nil {
if err := sb.setupControlLoop(sb.configPIDVals[0], sb.configPIDVals[1]); err != nil {
Copy link
Member

Choose a reason for hiding this comment

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

^ If the config is not nil, and there are incorrect types, and I copy over my PID values to those incorrect types, that's not great for a user, I'm assuming it'll just keep re-tuning even if I populate the fields of the malformed types?

Let's error in Validate for that case, tell people they've misspelt the types if the control part of the config is populated.

}
}

// unlock the mutex before setting up the control loop so that the motors
// are not locked, and can run if any auto-tuning is necessary
sb.mu.Unlock()
if err := sb.setupControlLoop(linear, angular); err != nil {
if err := sb.setupControlLoop(sb.configPIDVals[0], sb.configPIDVals[1]); err != nil {
Copy link
Member

Choose a reason for hiding this comment

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

Also, for Validation, add a test for all the Valid and erroring cases.

@viambot viambot added safe to test This pull request is marked safe to test from a trusted zone and removed safe to test This pull request is marked safe to test from a trusted zone labels Sep 11, 2024
@viambot viambot added safe to test This pull request is marked safe to test from a trusted zone and removed safe to test This pull request is marked safe to test from a trusted zone labels Sep 11, 2024
@viambot viambot added safe to test This pull request is marked safe to test from a trusted zone and removed safe to test This pull request is marked safe to test from a trusted zone labels Sep 11, 2024
@martha-johnston martha-johnston changed the title RSDK-8574: return an error if user tries to move a sensor controlled base without copy/pasting tuned PID values to the config [RSDK-8574][RSDK-8184]: return an error if user tries to move a sensor controlled base without copy/pasting tuned PID values to the config Sep 12, 2024
Copy link
Member

@randhid randhid left a comment

Choose a reason for hiding this comment

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

Yay, LGTM.

@martha-johnston martha-johnston merged commit d82e93c into viamrobotics:main Sep 12, 2024
20 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
safe to test This pull request is marked safe to test from a trusted zone
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants