How to manage set_rate_xxx

I’m starting to learn MAVSDK … I would like to transmit attitude and position data using subscription method.
I wrote this on the GCS part:

	result = telemetry.set_rate_position(0.5);

	switch (result)
	{
		case Telemetry::Result::Success:
			cout << "set_rate_position : Success" << endl;
			break;
		case Telemetry::Result::Unknown: /**< @brief Unknown result. */
			cout << "set_rate_position : Unknown" << endl;
			break;
		case Telemetry::Result::NoSystem: /**< @brief No system connected. */
			cout << "set_rate_position : NoSystem" << endl;
			break;
		case Telemetry::Result::ConnectionError: /**< @brief Connection error. */
			cout << "set_rate_position : ConnectionError" << endl;
			break;
		case Telemetry::Result::Busy: /**< @brief Vehicle is busy. */
			cout << "set_rate_position : Busy" << endl;
			break;
		case Telemetry::Result::CommandDenied: /**< @brief Command refused by vehicle. */
			cout << "set_rate_position : CommandDenied" << endl;
			break;
		case Telemetry::Result::Timeout: /**< @brief Request timed out. */
			cout << "set_rate_position : Timeout" << endl;
			break;
		case Telemetry::Result::Unsupported: /**< @brief Request not supported. */
			cout << "set_rate_position : Unsupported" << endl;
			break;
	}

	telemetry.subscribe_position([] (Telemetry::Position position) {
		cout 	<< "lat: " << position.latitude_deg
				<< ", lon: " << position.longitude_deg
				<< ", abs alt: " << position.absolute_altitude_m << endl;
	});

        while (true) {
	    this_thread::sleep_for(chrono::seconds(1));
	}

and tried with this on the autopilot part:

	TelemetryServer::Position position{55.953251, -3.188267, 0, 0};
	telemServer.publish_position(position, velocity, heading);

	while (true) {
		this_thread::sleep_for(std::chrono::seconds(1));
	}

I got a Telemetry::Result::Timeout as set_rate_position() result, and of course the position message is received only once.
I tried with other type of messages (attitude) with the same result.
Where did I fail?

Best regards,
Mike

It means that MAVSDK did not get an answer from the autopilot before the timeout.

Do other MAVSDK functions work? E.g. can you receive telemetry or send actions like arm() or takeoff()? Just to confirm that your connection works properly.

As I wrote I correctly receive the position telemetry message sent from autopilot the first time it calls publish_position . If I move the publish call inside the while loop it send position once per second.

Well that makes sense, right? If you call publish_position exactly once and then wait, then it will be published exactly once:

    TelemetryServer::Position position{55.953251, -3.188267, 0, 0};
	telemServer.publish_position(position, velocity, heading);

	while (true) {
		this_thread::sleep_for(std::chrono::seconds(1));
	}

If you call publish_position once per second, then it will publish the position once per second:

    TelemetryServer::Position position{55.953251, -3.188267, 0, 0};

	while (true) {
        this_thread::sleep_for(std::chrono::seconds(1));
        telemServer.publish_position(position, velocity, heading);
	}

What else would do you expect? Or did I misunderstand your question? :thinking:

Also how do you handle set_rate_position() on your server side?

I don’t know if you have misunderstood the question or I misunderstood MAVLink at this point.
To cut it short AFAIK MAVSDK implements in TelemetryServer what MAVLink protocol defines as telemetry microservice. When a Telemetry object calls upon .set_rate_xxx() the bound TelemetryServer activate a timer that publish a message of the specified telemetry with the rate you request. This code is embedded in default TelemetryServer code thre’s no need to handle it .

My problem was given by a lack of syncrhonism between GCS and Autopilot initialization.
Recalling .set_rate_xxx() command until a result different from TIMEOUT is received fixed everything.

I don’t think that the TelemetryServer will handle set_rate_xxx() for you. It just gives you access to the messages. So from your client you call set_rate_xxx(), and from your server you need to handle that message, and adapt the corresponding stream.

It does. Just read the code in telemetry_server_impl.cpp TelemetryServerImpl::init() method.
And, incidentally, .set_rate_xxx() is called trough Telemetry object (from GCS side).

Oh right, I had not realized/forgotten it was implemented like this :+1:. My mistake, sorry :see_no_evil:.

don’t worry we are all here to learn … :slight_smile:

I see. So your problem was that you were running your client while the server was down, which was timing out. Is that it?

The server was still waiting for other clients to get discoverd while the (only) GCS client was already asking for telemetry subscriptions… my fault of course. :sweat_smile:

1 Like