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

AP_DDS: Rally Get and Set #28449

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

tizianofiorenzani
Copy link
Contributor

@tizianofiorenzani tizianofiorenzani commented Oct 22, 2024

Issue

#28444

What Changed

  • Service /ap/rally_set appends a Rally Point to the list or clears the list (using the clear flag).
    • point: geolocation
    • altitude_frame mandatory, follows enum of AltFrame.
  • Replies with:
  • success is the action is successful;
  • size is the list's size.
  • Service /ap/rally_get gets the Rally Point at a given index. Returns:
    • success
    • rally the rally point as ardupilot_msgs/Rally type.
  • New ardupilot_msgs/Rally type is defined, that copies the structure definition in AP_Rally.

Test

Auto Test

colcon test --packages-select ardupilot_dds_tests --event-handlers=console_cohesion+ --pytest-args -k test_rally_point

Manual Test

  • run the SITL
  • Call the service to clear the rally list ros2 service call /ap/rally_set ardupilot_msgs/srv/RallySet "{clear: true}"
  • Open up Mavproxy with map and make sure the rally list is clear.
  • Append a new Rally Point: ros2 service call /ap/rally_set ardupilot_msgs/srv/RallySet "{rally: {point: {latitude: -35.36, longitude: 149.17, altitude: 400}}}"
  • In mavproxy, update the rally list and make sure the rally point appears on the map

image

  • use the service call to get the Rally at index 0: ros2 service call /ap/rally_get ardupilot_msgs/srv/RallyGet "index: 0"

Copy link
Collaborator

@Ryanf55 Ryanf55 left a comment

Choose a reason for hiding this comment

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

Nice addition, great to see some more interfaces like this.

Tools/ros2/ardupilot_msgs/msg/Rally.msg Outdated Show resolved Hide resolved
Tools/ros2/ardupilot_msgs/msg/Rally.msg Outdated Show resolved Hide resolved
Tools/ros2/ardupilot_msgs/srv/RallySet.srv Outdated Show resolved Hide resolved
Tools/ros2/ardupilot_msgs/srv/RallySet.srv Outdated Show resolved Hide resolved
libraries/AP_DDS/AP_DDS_Client.cpp Outdated Show resolved Hide resolved
@Ryanf55 Ryanf55 added the ROS label Oct 22, 2024
@timtuxworth
Copy link
Contributor

The altitude needs a frame.

@tizianofiorenzani
Copy link
Contributor Author

tizianofiorenzani commented Oct 22, 2024

@timtuxworth I have set the altitude frame explicitly now.
I don't have a clear answer for what to do with the break_altitude: RallyLocation expects that in Above Home level.

@tizianofiorenzani
Copy link
Contributor Author

As there is no code associated with the Rally flags, the DDS interface has been limited to only the Geopoint and the altitude frame

@tizianofiorenzani
Copy link
Contributor Author

Rebased and pushed again.

Copy link
Collaborator

@Ryanf55 Ryanf55 left a comment

Choose a reason for hiding this comment

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

Functionally, looks good. Just needs code cleanup and removal of potential link-flooding.

Tools/ros2/ardupilot_msgs/CMakeLists.txt Outdated Show resolved Hide resolved
Tools/ros2/ardupilot_msgs/CMakeLists.txt Outdated Show resolved Hide resolved
Tools/ros2/ardupilot_msgs/msg/Rally.msg Show resolved Hide resolved
Tools/ros2/ardupilot_msgs/srv/RallyGet.srv Outdated Show resolved Hide resolved
libraries/AP_DDS/AP_DDS_Client.cpp Outdated Show resolved Hide resolved
libraries/AP_DDS/AP_DDS_Client.cpp Outdated Show resolved Hide resolved
libraries/AP_DDS/AP_DDS_Client.cpp Outdated Show resolved Hide resolved
libraries/AP_DDS/AP_DDS_Client.cpp Outdated Show resolved Hide resolved
libraries/AP_DDS/AP_DDS_Client.cpp Outdated Show resolved Hide resolved
@tizianofiorenzani
Copy link
Contributor Author

@Ryanf55 suggestions applied, rebased and tested.

} else {
rally_location.lat = static_cast<int32_t>(rally_set_request.rally.point.latitude * 1e7);
rally_location.lng = static_cast<int32_t>(rally_set_request.rally.point.longitude * 1e7);
rally_location.alt = static_cast<int16_t>(rally_set_request.rally.point.altitude);
Copy link
Contributor

Choose a reason for hiding this comment

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

We are implicitly losing precision and accuracy here. What should we do if the altitude is > 16 bits? Just silently truncate the value?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Location is set to be integer, I need to pass values like this, the same as you do if it was the GCS to provide it.

rally_location.flags |= (rally_set_request.rally.altitude_frame << 3);

if (rally_location.lat != 0 && rally_location.lng != 0
&& rally_set_request.rally.altitude_frame <= static_cast<uint8_t>(Location::AltFrame::ABOVE_TERRAIN)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't understand this test for altitude_frame being valid. Could you code it in a way that's clearer to understand what you are actually doing?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That means the altitude enum is valid. I can re write it to check for each individual value, but I don't think it makes it more readable.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@timtuxworth check it out now: I have explicitly compared it against every value in the enum.

Append a Rally Point:

```bash
ros2 service call /ap/rally_set ardupilot_msgs/srv/RallySet "{rally: {point: {latitude: -35, longitude: 151, altitude: 400}}}"
Copy link
Contributor

Choose a reason for hiding this comment

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

It would be good to have an example with a frame supplied.


```bash
ros2 service call /ap/rally_get ardupilot_msgs/srv/RallyGet "index: 0"
requester: making request: ardupilot_msgs.srv.RallyGet_Request(index=0)
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe it's something I need to understand about ROS, but how would you know if there is more than one rally point, there doesn't seem to be a request rally count message, do you just keep requesting indexes until you get a fail?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

When you set a rally, it responds with the length of the Rally list. When you request a particular index, it fails if it does not exist. You can also use the service set call with an invalid point to obtain the length of the Rally list without adding any.

Copy link
Contributor

@timtuxworth timtuxworth Dec 2, 2024

Choose a reason for hiding this comment

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

An AP might have previously been configured with zero, one or more rally points. After booting, the only way to find out if there are any rally points would be to start requesting them at the first and then incrementally keep requesting until you get a fail, or to request some really large index number (what the largest valid number +1?) to get the number.

I'm not sure I understand how that's ok.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I agree that we should ensure this API works if there are pre-existing rally points. A sequence diagram could be helpful

ardupilot_msgs.srv.RallySet_Response(success=True, size=0)
```

Append a Rally Point:
Copy link
Contributor

Choose a reason for hiding this comment

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

It would probably be good to show fractional lat/long and be clear that the altitude is meters.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Do we have to show units of measure when in SI?

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 because unfortunately some ArduPilot metrics are not SI (it's a work in progress).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

no problem, I can update the readme.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I think this README needs an update now that you removed some of the flags and optional features.

Regarding units, the DDS interface follows ROS REP-103. Units are SI unless otherwise stated.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@Ryanf55 the Readme has been updated.

geographic_msgs::msg::GeoPoint point;

uint8 altitude_frame;
};
Copy link
Contributor

Choose a reason for hiding this comment

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

Where are break_altitude, land_dir, flag_favorable_winds, flag_do_auto_land?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

They have been removed, as not used. It was agreed in the dev call.

rally_get_response.rally.altitude_frame = (rally_location.flags >> 3) & ((1 << 2) - 1);
} else {
rally_get_response.rally.altitude_frame = static_cast<uint8_t>(Location::AltFrame::ABOVE_HOME);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Where are break_altitude, land_dir, flag_favorable_winds, flag_do_auto_land?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

They are not used anywhere in the code and have been removed. We discussed about that in the dev call.

} else {
rally_set_response.success = false;
}
} else {
Copy link
Contributor

Choose a reason for hiding this comment

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

Where are break_altitude, land_dir, flag_favorable_winds, flag_do_auto_land?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

They are no where to be used in the code and have been removed.

@tizianofiorenzani
Copy link
Contributor Author

Rebased, ready for another round.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: 👀 In review
Development

Successfully merging this pull request may close these issues.

4 participants