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

Follow Me mode Second order filter & improvements #19260

Merged

Conversation

junwoo091400
Copy link
Contributor

@junwoo091400 junwoo091400 commented Feb 25, 2022

Describe problem solved by this pull request
Refer to the document : https://docs.google.com/document/d/1E04Rn6sxYNqKve4-KZYdC2-9LExKmHKuYjWZlwf61rA/edit

Describe your solution

Describe possible alternatives
A clear and concise description of alternative solutions or features you've considered.

Test data / coverage
This change log : https://logs.px4.io/plot_app?log=6561ce69-e2e3-46c3-9e13-e29f2dbc11c7
Alessandro PR log : https://logs.px4.io/plot_app?log=fa76985d-87c6-4c4f-9164-fa2f2c15338b

Additional context

Discussions

  1. Should we just change the 'follow perspective' into a single number parameter (0 ~ 360 degrees), instead of using an enum / selection of : "Front, Back, Right, Left, etc."?
  2. Google Astyle for the member variables : Do we need to add the _ suffix?

TODOS

@Jaeyoung-Lim
Copy link
Member

@junwoo091400 Probably the flightgear bridge submodule has been updated unintentionally. I don't think this should be part of this PR

Copy link

@tstastny tstastny left a comment

Choose a reason for hiding this comment

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

@junwoo091400 - some great progress on this. lots of nice features and improvements. main points i noticed during the review - try to const when possible, let's avoid adding more internal states when we don't need to, and we should be careful not to disable old functionality while putting in new (unless it is intentional), e.g. seems that the manual stick inputs are the only way to change the follow height angle or distance now. please let me know if you need any clarification on any of the review comments. cheers.

msg/follow_target_status.msg Outdated Show resolved Hide resolved
Comment on lines 252 to 256
(ParamFloat<px4::params::NAV_FT_HT>) _param_nav_ft_ht,
(ParamFloat<px4::params::NAV_FT_DST>) _param_nav_ft_dst,
(ParamInt<px4::params::NAV_FT_FS>) _param_nav_ft_fs,
(ParamInt<px4::params::NAV_FT_ALT_M>) _param_nav_ft_alt_m,
(ParamInt<px4::params::NAV_FT_GMB_M>) _param_nav_ft_gmb_m,
(ParamInt<px4::params::NAV_FT_DELC>) _param_nav_ft_delc
(ParamFloat<px4::params::NAV_FT_YAW_T>) _param_ft_yaw_t

Choose a reason for hiding this comment

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

since these are all defined locally.. would be great to give the local states more verbose names so that we can actually understand what they are within this flight task. e.g. _param_follow_target_height (only with param prefix if the idea is that we want it to be clear this was from the params.. and we have other sources that could change the actually used follow target height)

Copy link
Contributor

Choose a reason for hiding this comment

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

Fair point. I was always torn between having them named exactly as the corresponding parameter, and having them named with more details.
Never thought about combining both approaches with prefix + meaning as you mentioned 👍
So you would suggest something like _param_ft_yaw_t_filter_time_constant ?

Choose a reason for hiding this comment

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

i would get rid of all acronyms, so that the variable is readable in the code without needing to go check the para.c file -- the param import here already tells where the value comes from, now in the flight task we just need something we can understand in the lines of the code. the only reason i would put the prefix param is to distinguish between "param" set value and the actual follow height that we are commanding (which can be adjusted from sticks as well). so there would in principle be two variables of the same name, unless we distinguish between the two.

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 was this discussion 3 years ago exactly about this issue. And it removed all these 'readable' parameter variable names in the code, and reset them to match exactly the parameter name. Could you review this as well for the final decision? thinking @tstastny @potaito

#11686

Copy link

@tstastny tstastny Mar 22, 2022

Choose a reason for hiding this comment

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

honestly i totally disagree with that PR. i understand the want to be able to grep for something, but if it is defined all in one place in the header anyway.. this shouldnt be so hard to find the value you want. and the param names are very limited on characters, so is very hard to read. having the _param prefix in front could be a way to identify, but keeping the name totally the same seems like not worth it to me at expense of readability in the code itself.

but anyway - my opinion is not the only one that matters. we could also chat with @MaEtUgR and @bresch about it (maybe offline is easier).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Right I agree that using the direct parameter name in the code decreases code readability 😋

Copy link
Contributor

Choose a reason for hiding this comment

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

I have to admit I'm siding with #11686 because it's weird to sometimes be able to CTRL+F certain parameters, and other times not, because the handle is not re-using the parameter name 😅

But your argument is valid.

Copy link
Member

@MaEtUgR MaEtUgR Mar 23, 2022

Choose a reason for hiding this comment

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

@tstastny Thanks for asking. I totally understand your point all information is there and the verbose internal variable names were used for a very long time before the naming was enforced. But for years I was wasting minutes every day looking up which parameter is used where and what exact parameter contributes to the code I'm reading. I have to say it was such a big improvement when the names were streamlined and finally grepable, I never looked back once. As you can see in the pr this relief was shared by a lot of if not all the core contributors that cared. Correct me if I'm wrong. So I would disadvise reverting this naming strategy.

That said I don't like abbreviations in variable names and I encourage to use descriptive unshortened names. Also, I suggest thinking twice when defining or reviewing parameter names to make them as descriptive as possible given the limitations. Ideally parameter names would not be limited to 16 characters only.

Choose a reason for hiding this comment

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

thanks for the extra insight @MaEtUgR and @potaito - i can understand the reasoning. i guess then as we discussed in the dev call we should attack the *heart of the issue .. 16 char limits on param names. I'll follow up with @bkueng offline. @junwoo091400 for now you should then stick with the convention from #11686

Copy link
Contributor

@potaito potaito left a comment

Choose a reason for hiding this comment

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

Also, these submodules were updated, but probably not on purpose, right?

  • src/drivers/gps/devices
  • Tools/flightgear_bridge
  • src/modules/mavlink/mavlink

I'll take another look at the PR once TJ's remarks were addressed. Otherwise it will become too much for everyone involved 😂

SecondOrderReferenceModel<matrix::Vector3f> _target_pose_filter;

// Internally tracked Follow Target characteristics, to allow RC control input adjustments
float _follow_target_distance{0.0f};
Copy link
Contributor

Choose a reason for hiding this comment

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

No 🙈
Especially not with height being initialized to 0.0 as well. That's a homing missile right there 😅

I would initialize to the default values of the corresponding parameters. Or initialize to NaN if there is a possibility, that the values have not been initialized when follow-me is running.

Comment on lines 252 to 256
(ParamFloat<px4::params::NAV_FT_HT>) _param_nav_ft_ht,
(ParamFloat<px4::params::NAV_FT_DST>) _param_nav_ft_dst,
(ParamInt<px4::params::NAV_FT_FS>) _param_nav_ft_fs,
(ParamInt<px4::params::NAV_FT_ALT_M>) _param_nav_ft_alt_m,
(ParamInt<px4::params::NAV_FT_GMB_M>) _param_nav_ft_gmb_m,
(ParamInt<px4::params::NAV_FT_DELC>) _param_nav_ft_delc
(ParamFloat<px4::params::NAV_FT_YAW_T>) _param_ft_yaw_t
Copy link
Contributor

Choose a reason for hiding this comment

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

Fair point. I was always torn between having them named exactly as the corresponding parameter, and having them named with more details.
Never thought about combining both approaches with prefix + meaning as you mentioned 👍
So you would suggest something like _param_ft_yaw_t_filter_time_constant ?

Copy link
Contributor

@potaito potaito left a comment

Choose a reason for hiding this comment

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

git submodule updates still need to be reverted :)

msg/follow_target_status.msg Outdated Show resolved Hide resolved
// The drone will move into position as soon as the target starts moving and its heading becomes known.
Vector2f current_drone_heading_2d{cosf(_yaw), -sinf(_yaw)};
// We don't command the yawspeed, since only the yaw can be calculated off of the target
_yawspeed_setpoint = NAN;
Copy link
Contributor

Choose a reason for hiding this comment

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

Is yaw (not yawspeed) correctly initialized somewhere? I.e. where does the drone point at when follow-me is initiated while the target is not moving?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Current behaviour is to not set yaw at all, until drone & target's distance is bigger than minimum distance for yaw control, then sets as the raw heading from drone to target as the yaw.

Copy link
Contributor

Choose a reason for hiding this comment

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

But is it initialized correctly? If it's not set at all, what value does _yaw_setpoint have?
We could initialize it to the current yaw angle, just to maintain whatever the current setpoint is.

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 don't believe so 🤔. But also I thought that the sudden 360 degrees yaw spin that happens when I activate the follow me mode is from this hard setpoint, which is why I believe I want to not set it at all.

Since we don't know where the target is 🤔

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So the FlightTask (the parent class) initializes (resets) it to NAN, so it won't be commanding at all. I guess then it makes sense to command the current yaw since commanding NAN is unpredictible? 🤔

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, I would also command the current yaw 👍

Copy link
Member

Choose a reason for hiding this comment

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

No need to do it now, but don't forget that you're getting last_setpoint as a parameter, meaning that you could initialize with it (if finite) to avoid glitches (see

_yaw_sp_prev = PX4_ISFINITE(last_setpoint.yaw) ? last_setpoint.yaw : _yaw;
)

src/modules/logger/logged_topics.cpp Outdated Show resolved Hide resolved
src/modules/mavlink/mavlink_receiver.cpp Outdated Show resolved Hide resolved
src/modules/mavlink/streams/HIL_ACTUATOR_CONTROLS.hpp Outdated Show resolved Hide resolved
@junwoo091400 junwoo091400 changed the title [Draft] Follow Me mode Second order filter refactor PR Follow Me mode Second order filter refactor PR Apr 26, 2022
@junwoo091400 junwoo091400 marked this pull request as ready for review April 26, 2022 13:52
@junwoo091400
Copy link
Contributor Author

Some related videos I wanted to share:

  1. Upstream Follow-Me behavior
    https://www.youtube.com/watch?time_continue=42

  2. Current PR's Follow-Me behavior
    From March 26th:
    https://www.youtube.com/watch?time_continue=107
    From March 11th:
    https://www.youtube.com/watch?v=myPFVJJkm04&t=19s

@junwoo091400
Copy link
Contributor Author

junwoo091400 commented Apr 26, 2022

Few Notes on the current development progress:

  1. Right now, this version is ready to go & to be reviewed for merge. It fixed all the major tiny problems that was arising from algorithmical details of Follow Target.
  2. The last challenge was the 'Overshoot' of the 2nd order reference model problem, which was causing the drone to thinking that target was moving backwards, when in fact target is moving still. By including unfiltered velocity into consideration (which, stays at 0 when we have the overshoot phenomenon) this was fixed.

Images related to this overshoot problem (from 4 days ago) :

image
image

@junwoo091400
Copy link
Contributor Author

Squashed so there are 8 PR-specific commits + 12 cherry-picked commits! Ready for review :)

@junwoo091400 junwoo091400 force-pushed the followme_refactor branch 4 times, most recently from 68a9a00 to 0ef4156 Compare May 5, 2022 12:28
To return Exponential Values, which is helpful for reducing the
sensitivity of the stick around the centered value (0), since it's
exponential curve.

Useful for user adjustment implementations, where accidentally touching the stick
wouldn't have so much effect when using the Exponential value, compared
to using the raw position value.
@junwoo091400
Copy link
Contributor Author

I cherry-picked #19591 into the PR and applied the usage of Expo() values for User RC adjustments.

Also, addressed all the comments! Is it ready to merge?

Copy link

@tstastny tstastny left a comment

Choose a reason for hiding this comment

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

@junwoo091400 almost!

A few comments below -- also the style comment was also still not addressed. The method name styles are inconsistent. Should switch them all to lowerCamelCase like the flight task base class and your newly implemented function shown here:
https://github.com/PX4/PX4-Autopilot/blob/20355e8c18515a7b53f52ad6407b742ee042a73e/src/modules/flight_mode_manager/tasks/AutoFollowTarget/FlightTaskAutoFollowTarget.hpp#L257-L267

@junwoo091400
Copy link
Contributor Author

Addressed all the comments! @tstastny

@junwoo091400
Copy link
Contributor Author

Force pushed to confine FollowPerspective enum to uint8_t type to avoid followperspective being casted to negative value.
https://en.wikipedia.org/wiki/C%2B%2B11#Strongly_typed_enumerations

Copy link
Contributor

@potaito potaito left a comment

Choose a reason for hiding this comment

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

LGTM 👏

Copy link
Member

@bresch bresch left a comment

Choose a reason for hiding this comment

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

It's mostly good to me, just a small mistake on the param update.
There are still way too many comments IMO, but it's not a big problem.

// The drone will move into position as soon as the target starts moving and its heading becomes known.
Vector2f current_drone_heading_2d{cosf(_yaw), -sinf(_yaw)};
// We don't command the yawspeed, since only the yaw can be calculated off of the target
_yawspeed_setpoint = NAN;
Copy link
Member

Choose a reason for hiding this comment

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

No need to do it now, but don't forget that you're getting last_setpoint as a parameter, meaning that you could initialize with it (if finite) to avoid glitches (see

_yaw_sp_prev = PX4_ISFINITE(last_setpoint.yaw) ? last_setpoint.yaw : _yaw;
)

Use RC Sticks' Expo() function for user adjustments to decrease sensitivity around the center (0 value)

Update Function styles to lowerCamelCase

And make functions const & return the params, rather than modifying them
internally via pointer / reference

Specify kFollowPerspective enum as uint8_t, so that it can't be set to negative value when converted from the parameter 'FLW_TGT_FP'

Fix bug in updateParams() to reset internally tracked params if they actually changed.

Remove unnecessary comments
@junwoo091400
Copy link
Contributor Author

I will test the yaw setpoint mode you commented about with this branch : https://github.com/junwoo091400/PX4-Autopilot/tree/followme_refactor_yaw_tracking_test

With a Mantis Edu!

@junwoo091400
Copy link
Contributor Author

junwoo091400 commented May 10, 2022

image
Left : With yaw setpoint as (Position Setpoint -> Target) | Right : With yaw setpoint as (Actual Position -> Target)

@bresch I didn't find significant difference in the yaw / yaw rate command difference in between two different yaw setpoint calculation methods.

However, I did find that basing the yaw calculation off of position setpoint can introduce a yaw tracking lag when there's a difference between the setpoint & actual position:

Yaw_delay_demonstration

Here, it is visible that the PS (Position Setpoint) is leading the AP (Actual Position), and target is moving in upwards-right direction. The yaw setpoint (PS -> Tgt) is calculated as to point lower-right direction, but the correct yaw setpoint (AP -> Tgt) should point right direction. Therefore, the camera ends up pointing on the trailing side of the target. Which is why in the video I am almost out of frame.

I think keeping the yaw setpoint based on Actual Position makes sense in this regards. What do you think? @bresch

@junwoo091400
Copy link
Contributor Author

https://youtu.be/C1Jy3ln028M?t=143

This is the video link to where the yaw legging behavior can be observed (timestamp included)!

@junwoo091400
Copy link
Contributor Author

Oh and yesterday I also tested RC adjustments & Whether changing the Parameter resets the Follow distance, angle and height, it all worked 👍

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.

6 participants