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

actuator: add support for MAV_CMD_DO_SET_ACTUATOR #16758

Merged
merged 1 commit into from
Mar 2, 2021

Conversation

coderkalyan
Copy link
Contributor

Adds support for using the MAVLink command MAV_CMD_DO_SET_ACTUATOR to
update the actuator values on control group 3 aux{1, 2, 3}. A simple
deconfliction with rc_update is implemented: when a MAVLink command is
sent, RC is disabled for that channel until a major stick movement is
detected.

Closes what was attempted in #10320 and #15281.

The following MAVSDK script can be used to test (minor modification might be necessary based on your setup):

#include <mavsdk/mavsdk.h>
#include <mavsdk/plugins/mavlink_passthrough/mavlink_passthrough.h>
#include <mavsdk/plugins/info/info.h>
#include <chrono>
#include <cstdint>
#include <iostream>
#include <future>
#include <memory>

using namespace mavsdk;

void send_actuator(MavlinkPassthrough& mavlink_passthrough,
        float value1, float value2, float value3);

int main(int argc, char **argv)
{
    Mavsdk mavsdk;
    std::string connection_url;
    ConnectionResult connection_result;
    float value1, value2, value3;

    if (argc == 5) {
        connection_url = argv[1];
        connection_result = mavsdk.add_any_connection(connection_url);
        value1 = std::stof(argv[2]);
        value2 = std::stof(argv[3]);
        value3 = std::stof(argv[4]);
    } 

    if (connection_result != ConnectionResult::Success) {
        std::cout << "Connection failed: " << connection_result << std::endl;
        return 1;
    }

	bool discovered_system = false;
    mavsdk.subscribe_on_new_system([&mavsdk, &discovered_system]() {
		const auto system = mavsdk.systems().at(0);

		if (system->is_connected()) {
			std::cout << "Discovered system" << std::endl;
			discovered_system = true;
		}
	});

	std::this_thread::sleep_for(std::chrono::seconds(2));

	if (!discovered_system) {
        std::cout << "No device found, exiting." << std::endl;
        return 1;
    }

	std::shared_ptr<System> system = mavsdk.systems().at(0);
	for (auto& tsystem : mavsdk.systems()) {
		auto info = Info{tsystem};
		std::cout << info.get_identification().second.hardware_uid << std::endl;
		if (info.get_identification().second.hardware_uid == "3762846593019032885") {
			system = tsystem;
		}
	}

	auto mavlink_passthrough = MavlinkPassthrough{system};

	send_actuator(mavlink_passthrough, value1, value2, value3);

    return 0;
}

void send_actuator(MavlinkPassthrough& mavlink_passthrough,
		float value1, float value2, float value3)
{
	std::cout << "Sending message" << std::endl;
	mavlink_message_t message;
	mavlink_msg_command_long_pack(
			mavlink_passthrough.get_our_sysid(),
			mavlink_passthrough.get_our_compid(),
			&message,
			1, 1,
			MAV_CMD_DO_SET_ACTUATOR,
			0,
			value1, value2, value3,
			NAN, NAN, NAN, 0);
	mavlink_passthrough.send_message(message);
	std::cout << "Sent message" << std::endl;
}

@coderkalyan
Copy link
Contributor Author

FYI @jinger26 @bkueng @hamishwillee

@dagar
Copy link
Member

dagar commented Feb 4, 2021

Hold tight, we're very close to finally having a good solution to this problem.

FYI @JacobCrabill

actuator_controls_s actuator_group_3{};
// copy in previous actuator control setpoint in case aux{1, 2, 3} isn't changed
_actuator_controls_3_sub.update(&actuator_group_3);
Copy link
Member

Choose a reason for hiding this comment

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

It's almost always a bad idea to publish the same topic from multiple sources simultaneously.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hmm ok. I implemented the deconfliction logic that Beat recommended but I see how it could cause problems.

Copy link
Member

Choose a reason for hiding this comment

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

And then you copy control group 6 here if published and changing and overwrite group 3? That would allow you to default the output of group 3 to the last active from either manual or external control. And someone just interested in external can map the mixer straight to group 6 and never have manual intervention.

@coderkalyan
Copy link
Contributor Author

coderkalyan commented Feb 4, 2021

Hold tight, we're very close to finally having a good solution to this problem.

@dagar Ok 😄 Do you mean a good solution that will solve the deconfliction or something that circumvents my PR completely?

@coderkalyan
Copy link
Contributor Author

I fixed the format issues but CI seems to be overflowing flash space on fmuv2. Is this something I need to account for, and how?

@coderkalyan
Copy link
Contributor Author

Note before any merging can take place: I haven't checked how mission mode handles this command yet, if its different.

Adds support for using the MAVLink command MAV_CMD_DO_SET_ACTUATOR to
update the actuator values on control group 3 aux{1, 2, 3}. A simple
deconfliction with rc_update is implemented: when a MAVLink command is
sent, RC is disabled for that channel until a major stick movement is
detected.
// if there is a major stick movement to re-activate RC mode
bool major_movement[3] = {false, false, false};

// detect a big stick movement
Copy link
Member

Choose a reason for hiding this comment

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

This will not detect a big, but a fast stick movement.

}

if (updated) {
_actuator_controls_pubs[3].publish(actuator_controls);
Copy link
Member

Choose a reason for hiding this comment

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

How about you publish control group 6 (might need to be defined) here, so it's conflict-free? https://docs.px4.io/master/en/concept/mixing.html#control-group-6-first-payload

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@LorenzMeier I think the rationale @bkueng had with using control group 3 was that it would work OOTB (mixers would not have to be modified by the user) and RC override is also possible. If group 6 is still preferable I can update

Copy link
Member

Choose a reason for hiding this comment

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

@coderkalyan I was suggesting to handle the vehicle_command MAV_CMD_DO_SET_ACTUATOR directly in rc_update.cpp to avoid conflicts and then it would also just work for navigator.

actuator_controls_s actuator_group_3{};
// copy in previous actuator control setpoint in case aux{1, 2, 3} isn't changed
_actuator_controls_3_sub.update(&actuator_group_3);
Copy link
Member

Choose a reason for hiding this comment

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

And then you copy control group 6 here if published and changing and overwrite group 3? That would allow you to default the output of group 3 to the last active from either manual or external control. And someone just interested in external can map the mixer straight to group 6 and never have manual intervention.

@@ -489,8 +489,39 @@ void MavlinkReceiver::handle_message_command_both(mavlink_message_t *msg, const
send_ack = true;
}

} else {
} else if (cmd_mavlink.command == MAV_CMD_DO_SET_ACTUATOR) {
// since we're only paying attention to 3 AUX outputs, the
Copy link
Member

Choose a reason for hiding this comment

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

This also needs to be added to navigator.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yep, will do.

Copy link
Contributor

Choose a reason for hiding this comment

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

To avoid code duplication, you could move it to the commander. This handles commands in a mission as well as MAVLink commands. Compare with the code and successful tests in #14809

Copy link
Member

Choose a reason for hiding this comment

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

since we're only paying attention to 3 AUX outputs What is the rational behind this? This is very confusing, and is not obvious unless you dig into the code

@JacobCrabill
Copy link
Member

I actually am working on a more general solution with @dagar that should solve this problem as a subset of the much broader control allocation / output mapping topic... will share more details once it's a little more complete, but as of right now I can arbitrarily map a DO_SET_SERVO command to any output you'd like, simply by setting a parameter on that output. More details to come soon!

@coderkalyan
Copy link
Contributor Author

@JacobCrabill sounds cool! Keep me updated as soon as you have details/a PR 😄

@JacobCrabill
Copy link
Member

@JacobCrabill sounds cool! Keep me updated as soon as you have details/a PR

It's still very much a WIP, but see here for how to control up to 8 arbitrary actuators via DO_SET_SERVO: #16808

@LorenzMeier
Copy link
Member

@coderkalyan I expect the more general approach to take more time, so I would like to get this here in for 1.12. Please disregard my earlier comments regarding the control groups, I would keep this as-is at it seems like a good solution for 1.12. But could you please take note of the comment from @dayjaby regarding the command handling? His PR is indeed pretty good and should be included:
#14809

@mrpollo
Copy link
Contributor

mrpollo commented Feb 24, 2021

Closing in favor of #16808

@mrpollo mrpollo closed this Feb 24, 2021
@LorenzMeier
Copy link
Member

@mrpollo This should not have been closed without the alternative being actually merged. I'm merging this now. @dagar @JacobCrabill we need to make sure to not impair the usage of PX4 by trying to do the right thing. This has been going on as a pattern, effectively pushing away users because it leads to six-month long delays where people can't use the project.

@LorenzMeier LorenzMeier reopened this Mar 2, 2021
@LorenzMeier LorenzMeier merged commit b257f9d into PX4:master Mar 2, 2021
@mrpollo
Copy link
Contributor

mrpollo commented Mar 2, 2021

@LorenzMeier thanks for merge, over the last developer call we decided to close it in favor of #16808, at the time it seemed ready to be merged.

@DronecodeBot
Copy link

This pull request has been mentioned on Discussion Forum for PX4, Pixhawk, QGroundControl, MAVSDK, MAVLink. There might be relevant details there:

https://discuss.px4.io/t/using-do-set-actuator-to-releasing-the-payload/28686/5

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants