-
Notifications
You must be signed in to change notification settings - Fork 2
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
ElectroHydraulicPTO Motor Mode #99
Conversation
Signed-off-by: Michael Anderson <anderson@mbari.org>
Signed-off-by: Michael Anderson <anderson@mbari.org>
Signed-off-by: Michael Anderson <anderson@mbari.org>
Signed-off-by: Michael Anderson <anderson@mbari.org>
Signed-off-by: Michael Anderson <anderson@mbari.org>
Signed-off-by: Michael Anderson <anderson@mbari.org>
Signed-off-by: Michael Anderson <anderson@mbari.org>
Signed-off-by: Michael Anderson <anderson@mbari.org>
Signed-off-by: Michael Anderson <anderson@mbari.org>
Signed-off-by: Michael Anderson <anderson@mbari.org>
Signed-off-by: Michael Anderson <anderson@mbari.org>
|
||
// solver.solve will use functor `df` function to obtain Jacobian instead of | ||
// computing numerically | ||
const int solver_info = solver.solve(this->dataPtr->x); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I set this to solve
rather than solveNumericalDiff
so it would use ElectroHydraulicSoln::df
from our functor
fjac(0, 0) = 1 - J_eff_v[0U] * SecondsPerMinute * this->Q / this->HydMotorDisp; // df0/dx0 | ||
fjac(0, 1) = -J_eff_v[1U] * SecondsPerMinute * this->Q / this->HydMotorDisp; // df0/dx1 | ||
fjac(1, 0) = | ||
(-J_eff_m[0U] * T - eff_m * dTdx0) / (this->HydMotorDisp / (2.0 * M_PI)); // df1/dx0 | ||
fjac(1, 1) = 1 - J_eff_m[1U] * T / (this->HydMotorDisp / (2.0 * M_PI)); // df1/dx1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
check my math?
I didn't put this back in yet just to keep the solver simple for now |
check the comparison to the test machine: |
Very good, thanks for resurrecting this branch, I was looking into how to bring it up to date and you beat me to it (big surprise). One item perhaps to add to the todo list is a battery model improvement, which may or may not get itself tangled up in the solver. Currently the model used uses a constant EMF value, and an improvement would be a coloumb counter that would drive this Vemf up and down as the battery charges and discharges. The internal resistance of the battery may also be dependent upon the state of charge. I think this is orthogonal to the other work so maybe should be done in a second branch after this is done if it's not related to the solver, we will see. In any event, not a required simulation feature, but would be a nice touch. :) |
Signed-off-by: Michael Anderson <anderson@mbari.org>
Signed-off-by: Michael Anderson <anderson@mbari.org>
…o hamilton8415/motormode
…o hamilton8415/motormode
…they are applied, depending now on which motor/pump quadrant the hydraulic motor is operating.
Signed-off-by: Michael Anderson <anderson@mbari.org>
…ckage Signed-off-by: Michael Anderson <anderson@mbari.org>
package. still need to modify code to reference these files.
non-linear equatoin solver.
occasionally not-converging, need to had error handling for this still.
Signed-off-by: Michael Carroll <michael@openrobotics.org>
Signed-off-by: Michael Anderson <anderson@mbari.org>
…ode' into hamilton8415/motormode
@hamilton8415, I just pushed updates to new tests and new launch files for manual vs ci |
@andermi @mjcarroll: I completed the linter work and checked the functionality of motormode in terms of the entire model and simulation, and of course also the tests related to the electro-hydraulic PTO. There are some CI errors, some output below. I'm hoping one of you could look into what's going in there as it's a bit out of my depth. I believe andermi did these originally. Thanks! Looking forward to getting this off the plate and onward with some smaller pull-requests. :) 2022-11-15T03:22:39.4222419Z The following tests FAILED: |
Somehow I guess I did miss your comment here! Looking into it now. |
Signed-off-by: Michael Anderson <anderson@mbari.org>
I think we are good to go after a review |
.gitignore
Outdated
splinter/include | ||
splinter/lib | ||
splinter/splinter | ||
splinter/assets | ||
splinter/CREDITS.md | ||
splinter/docs | ||
splinter/README_SPLINTER.md |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could delete splinter reference here
double x = prismaticJointVelComp->Data().at(0); | ||
this->dataPtr->functor.I_Wind.RamPosition = 40.0; // TODO(hamilton8415) x * 39.4; | ||
double PistonPos = prismaticJointVelComp->Data().at(0); | ||
this->dataPtr->functor.I_Wind.RamPosition = 40; // 2.03 - PistonPos * 39.4; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@hamilton8415, with this like it is, I don't think it's using your ascii art in WindingCurrentTarget like you planned.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, that's right. At the moment I've been leaving that feature disabled as it's a bit second order designed to protect the physical hardware, but it's harder to break metal things in simulation. It complicates the interpretation of how the PTO model is performing so while I do test those features in "WindingCurrentTarget.hpp", I've been thinking to let things settle in a simpler case before they're put into use...
std::cout << "=================================" << std::endl; | ||
std::cout << "Warning: Numericals solver in ElectroHydraulicPTO did not converge" << std::endl; | ||
std::cout << "solver info: [" << solver_info << "]" << std::endl; | ||
std::cout << "=================================" << std::endl; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
perhaps change std::cout
to igndbg
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would use std::stringstream
to append it all together and send it to igndbg
all at once in that case.
std::stringstream ss;
ss << "foo\n";
ss << "bar\n";
igndbg << ss.str();
double tau_c = 0.1; // N-m | ||
double k_v = .06 / 1000; // N-m/RPM | ||
double k_th = 20; | ||
return fabs((tau_c * tanh(2 * M_PI * N / 60 / k_th) + k_v * N / 1000) * N); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I get nervous about integer literals in division
#if 0 | ||
int df(const VectorXd & x, MatrixXd & fjac) | ||
{ | ||
const int n = x.size(); | ||
assert(fjac.rows() == n); | ||
assert(fjac.cols() == n); | ||
for (int k = 0; k < n; k++) { | ||
for (int j = 0; j < n; j++) { | ||
fjac(k, j) = 0.; | ||
} | ||
fjac(k, k) = 3. - 4. * x[k]; | ||
if (k) {fjac(k, k - 1) = -1.;} | ||
if (k != n - 1) {fjac(k, k + 1) = -2.;} | ||
} | ||
return 0; | ||
} | ||
#endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok to remove this section?
0.9400, 0.9390, 0.9380, 0.9370, 0.9360, 0.9370, 0.9360, 0.9350, | ||
0.9320, 0.9300, 0.9200, 0.9100, 0.9000, 0.8400}; | ||
#endif | ||
#if 0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok to remove section?
}; | ||
#if 1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok to make permanent?
struct EffV | ||
{ | ||
EffV() = default; | ||
|
||
std::vector<double> df(const double & rpm, const double & pressure) const | ||
{ | ||
double sech_ = 1.0 / cosh(2e-6 * (rpm + 55.0) * (pressure - 5000.0)); | ||
|
||
// rpm | ||
double dfdx0 = 2.667e-11 * (pressure - 74268.6) * (pressure - 5000.0) * sech_ * sech_; | ||
|
||
// pressure | ||
double dfdx1 = 1.333e-5 * tanh(2e-6 * (rpm + 55.0) * (pressure - 5000.0)) + | ||
2.667e-11 * (rpm + 55.0) * (pressure - 74268.6) * sech_ * sech_; | ||
|
||
return std::vector<double>{dfdx0, dfdx1}; | ||
} | ||
|
||
double operator()(const double & rpm, const double & pressure) const | ||
{ | ||
return std::max( | ||
0.5, | ||
(-1.333e-5 * pressure + 0.99) * tanh((-2e-6 * pressure + 0.01) * (rpm + 55.0))); | ||
} | ||
}; | ||
|
||
|
||
struct EffM | ||
{ | ||
EffM() = default; | ||
|
||
std::vector<double> df(const double & rpm, const double & pressure) const | ||
{ | ||
double sech_ = 1.0 / cosh(8e-8 * (rpm - 37500.0) * (pressure + 34.0)); | ||
|
||
// rpm | ||
double dfdx0 = (4.2664e-13 * rpm - 7.84e-8) * (pressure + 34.0) * sech_ * sech_ - | ||
5.333e-6 * tanh((-8e-8 * rpm + 0.003) * (pressure + 34.0)); | ||
|
||
// pressure | ||
double dfdx1 = 4.2664e-13 * (rpm - 183761.0) * (rpm - 37500.0) * sech_ * sech_; | ||
|
||
return std::vector<double>{dfdx0, dfdx1}; | ||
} | ||
|
||
double operator()(const double & rpm, const double & pressure) const | ||
{ | ||
if (pressure <= 10.0) { | ||
return (2.5871e-14 * rpm + 7.9528e-9) * exp((-3.9e-6 * rpm + 1.25742) * pressure) + 0.1; | ||
} | ||
return std::max( | ||
0.1, | ||
(-5.333e-6 * rpm + 0.98) * tanh((-8e-8 * rpm + 0.003) * (pressure + 34.0))); | ||
} | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's ok to remove these as we aren't doing 2D interpolation anymore
/* | ||
double df(const double & N) const | ||
{ | ||
if (current_override_) { | ||
J_I = 0.0; | ||
} else { | ||
J_I = this->DefaultDamping.evalJacobian(fabs(N)); | ||
J_I *= this->ScaleFactor; | ||
|
||
if (N > 0.0) { | ||
J_I *= -this->RetractFactor; | ||
} | ||
} | ||
|
||
return J_I; | ||
} | ||
*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
delete
def find_proc(ld): | ||
entities = ld.\ | ||
_IncludeLaunchDescription__launch_description_source.\ | ||
_LaunchDescriptionSource__launch_description.\ | ||
_LaunchDescription__entities | ||
for entity in entities: | ||
if type(entity) is Node: | ||
if type(entity._Action__condition) is UnlessCondition: | ||
return entity |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mjcarroll, I wish there was a better way to do this... (used on line 78)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Whoa, what is this trying to do exactly?
|
||
|
||
namespace buoy_gazebo | ||
{ | ||
class ElectroHydraulicPTOPrivate | ||
{ | ||
public: | ||
/// \brief Piston joint entity | ||
static constexpr double RPM_TO_RAD_PER_SEC{2.0 * M_PI / 60.0}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we move all of the constants to a common header?
// ~50GPM/600psi ~= .33472 in^3/psi -> Relief valve flow | ||
// above setpoint, From SUN RPECLAN data sheet | ||
const double ReliefValveFlowPerPSI = 50.0 / 600.0; | ||
const double ReliefValveFlowPerPSI = 30.0 / 600.0; | ||
const double CubicInchesPerGallon = 231.0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
More constants that we can put somewhere common?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks Michael, I can make those adjustments. Not entirely sure how high up to put the constants header file, presumably package wide, i'll look to see what makes sense. Also, I'll leave the "entities" question to andermi
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think Constants.hpp
in the buoy_utils folder would be reasonable and package wide.
buoy_utils/Constanst.hpp
Hi All, I've implemented most of the above suggestions and it's passing CI. For the constants, as discussed I made a header file in buoy_utils but only put physical constants in there that are useful in a variety of places, unit conversions and similar. For the constants specific to the ElectroHydraulicPTO, I left those in the class definitions as static constexpr. There may be some sense in time to pull the constants out that define the exact behavior of this PTO into a header file in ElectroHydraulicPTO, but didn't go for that level of surgery at this time, instead figuring we need to get this merged in. Thanks for all the help and suggestions, have a great weekend... |
LGTM. If @mjcarroll approves, I'll merge. |
WIP
@hamilton8415 I resurrected motor mode and made this draft PR so we could discuss things as we work out of this same branch