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: External Control enable #28429

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

Conversation

tizianofiorenzani
Copy link
Contributor

@tizianofiorenzani tizianofiorenzani commented Oct 18, 2024

User Story

As an operator, I want to be able to completely cut off any external control from the DDS interface. This functionality is especially helpful during debugging tests, when a quick reaction is of utmost importance.
I would like to be able to assign a switch to Enable/Disable external control, as well as the ability for a script or an external GCS to trigger External Control.

What Changed

  • AP_ExternalControl has now the ability to set and retrieve its status.
  • AP_DDS prevents any Subscription or Service to affect the vehicle: Subscriptions callbacks are simply returned, while service requests reply with false.
  • RC_Channel has been given a new functionality DDS_EXTERNAL_CONTROL = 181 which allows a channel to enable External control when HIGH.

Test

  • Start SITL (plane or copter)
  • Call a mode switch or arm service call and verify that the call is successful.
ros2 service call /ap/mode_switch ardupilot_msgs/srv/ModeSwitch "mode: <mode_num>"
ros2 service call /ap/arm_motors  ardupilot_msgs/srv/ArmMotors "arm: true"
  • Set the RC switch to High ros2 topic pub /ap/joy sensor_msgs/msg/Joy "{axes: [0.0, 0.0, 0.0, 0.0, .nan, 1]}"
  • Assigned RC6_OPTION = 181
  • Notice that the GCS will show Command rejected: External Control Enabled.
  • Call other services and verify they are responded to succesfully.
  • Set the RC switch to Low ros2 topic pub /ap/joy sensor_msgs/msg/Joy "{axes: [0.0, 0.0, .nan, .nan, .nan, -1]}"
  • Try to Arm the vehicle with ros2 service call /ap/arm_motors ardupilot_msgs/srv/ArmMotors "arm: true"
  • Arming command is rejected!

image

@tizianofiorenzani
Copy link
Contributor Author

@Ryanf55 what is the best way to make it testable?

@Ryanf55
Copy link
Collaborator

Ryanf55 commented Oct 19, 2024

@Ryanf55 what is the best way to make it testable?

I'd do something like a mock flyaway recovery.

  1. Take off
  2. Command 100% throttle on AP_DDS joystick topic
  3. Wait till drone reaches 400'
  4. Disable external control using mavlink
  5. Check it never hits 500'

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.

I've replicated your behavior, looks great! I think this is a nice clean way for a GCS to take authority from a companion computer.

Running SITL

ros2 launch ardupilot_sitl sitl_dds_udp.launch.py transport:=udp4 synthetic_clock:=True wipe:=False model:=quad speedup:=1 slave:=0 instance:=0 defaults:=$(ros2 pkg prefix ardupilot_sitl)/share/ardupilot_sitl/config/default_params/copter.parm,$(ros2 pkg prefix ardupilot_sitl)/share/ardupilot_sitl/config/default_params/dds_udp.parm sim_address:=127.0.0.1 master:=tcp:127.0.0.1:5760 sitl:=127.0.0.1:5501

mavproxy

param set RC6_OPTION 181
 reboot

Then use the CLI to test with joystick.

libraries/RC_Channel/RC_Channel.cpp Show resolved Hide resolved
libraries/AP_ExternalControl/AP_ExternalControl.h Outdated Show resolved Hide resolved
libraries/AP_ExternalControl/AP_ExternalControl.h Outdated Show resolved Hide resolved
@IamPete1
Copy link
Member

IamPete1 commented Nov 4, 2024

Could this be done at the top RC_Channels level rather than down in plane and copter? Then it should work for rover too.

ArduCopter/RC_Channel.cpp Outdated Show resolved Hide resolved
libraries/RC_Channel/RC_Channel.cpp Outdated Show resolved Hide resolved
@tizianofiorenzani
Copy link
Contributor Author

Suggestions have been applied, rebased and tested.

@@ -749,8 +757,13 @@ void AP_DDS_Client::on_request(uxrSession* uxr_session, uxrObjectId object_id, u
break;
}

GCS_SEND_TEXT(MAV_SEVERITY_INFO, "%s Request for %sing received", msg_prefix, arm_motors_request.arm ? "arm" : "disarm");
arm_motors_response.result = arm_motors_request.arm ? AP::arming().arm(AP_Arming::Method::DDS) : AP::arming().disarm(AP_Arming::Method::DDS);
if (external_control->is_enabled()) {
Copy link
Collaborator

@Ryanf55 Ryanf55 Nov 5, 2024

Choose a reason for hiding this comment

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

Can we instead put an arm function into the external control library, and check is_enabled there, then call AP::arming().arm there?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

same for the other services though, right?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yep, I think so. For the over services, that could/should be it's own PR. I'll do that now.

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 you would call external_control->arm(), which would fail if either the external control is disabled or arming failed.

Copy link
Collaborator

Choose a reason for hiding this comment

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

yes

Copy link
Collaborator

Choose a reason for hiding this comment

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

Here's the implementation. Once this merges, rebase.
#28609

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

Successfully merging this pull request may close these issues.

5 participants