How to change VTOL Flight Mode from Multi-Rotor to Fixed Wing in OFFBOARD mode by using ROS (MAVROS) in Gazebo too without using QgroundControl? thank you

I had followed the example sample here MAVROS Offboard control example PX4

In that example code, it defines the custom flight mode with the following lines before executing the main loop:
mavros_msgs::SetMode offb_set_mode;
offb_set_mode.request.custom_mode = “OFFBOARD”;

At the end of the example, the drone (I had used the VTOL model) is rising up to the desired altitude and stay there.

My question is “How can I change the flight mode to “VTOL:Fixed Wing” and then change it back to "VTOL:Multi-Rotor” in ROS?

In the terminal of “pxh>” if you type (after VTOL is takeoff) “commander transition” you can change the VTOL:Multi-Rotor to VTOL:Fixed Wing and if you type “commander transition” again then it returns back to VTOL:Multi-Rotor mode again.

Thus, I have added this “offb_set_mode.request.custom_mode = "OFFBOARD;” line of code once the VTOL reaches to takeoff altitude in the while loop of the “MAVROS Offboard control example of PX4”. However, I still couldn’t find a way to change the VTOL flight mode with using ROS.

I don’t want to use QgroundControl to do these; but I want to do the same concept in ROS myself while writing my custom code in “Offboard” mode to fly my drone in Gazebo by using ROS.

I will be very glad if you would guide me to solve this problem about changing VTOL flight modes in OFFBOARD, thank you very much.

1 Like

If you are using mavros, you can do it through a service called vtol_transition

2 Likes

In the while loop of “offboard” while “offboard” is active to execute our custom code, I wrote this line on condition which is working (when I said “land()” it lands, so I added the offb_set_mode.request.custom_mode = “vtol_transition”; there to activate VTOL:Fixed Wing ).

If you reached to “4 meters takeoff destination then activate the VTOL:Fixed Wing”.

if( (z_takeoff >= (takeoff_altitude - 0.1) && z_takeoff <= (takeoff_altitude + 0.009999)) && (current_pos_drone.z >= (takeoff_altitude - 0.1) && current_pos_drone.z <= (takeoff_altitude + 0.009999)) ){
                      //land();
                     //offb_set_mode.request.custom_mode = "vtol_transition";
                     offb_set_mode.request.custom_mode = "VTOL_TRANSITION";
                }

I have tried these offb_set_mode.request.custom_mode = "VTOL_TRANSITION"; and offb_set_mode.request.custom_mode = "vtol_transition"; and even offb_set_mode.request.custom_mode = "TRANSITION";
However, non of them are worked at all.

@Jaeyoung-Lim friend or anyone who knows, how to fix / solve this issue? thank you.

1 Like

Transition is not a mode. There is a service called vtol_transition

Your using a different service to set mode in your code

2 Likes

Thank you for the reply @Jaeyoung-Lim.

I have never tried a service call like that for vtol_transition which I don’t know how to do it or where to start to write it. Therefore, would you tell me please “how can we apply “vtol_transition” in ROS code, or somewhere/someone would guide me how to do it”? thank you.

If you know how to do it, if it is possible would you give me a very small example that will help me to understand how to write it? thank you very much.

1 Like

Do you have a small example about how to use mavros VTOL plugin to control drone via ROS C++ code (you had written) in Gazebo environment ? I have found one of your videos about VTOL plugin mavros but there is no explanation how have you done it / how did you use that VTOL plugin in mavros
MAVROS VTOL plugin transition demo by Jaeyoung Lim

I have checked the official MAVROS github to find where is this VTOL plugin you have mentioned, but I couldn’t find it.

mavros/mavros/src/plugins/

mavros/mavros_extras/src/plugins/

Note:

The only information I was able to find are these:

MAVSDK/src/plugins/action/action_impl.cpp

Add vtol plugin for vtol transitions #1323

mavros/mavros_msgs/srv/ (/CommandVtolTransition.srv)

1 Like

Here is a good example on how you can implement your own service client: http://wiki.ros.org/ROS/Tutorials/WritingServiceClient(c%2B%2B)

2 Likes

Is it possible to write some code like this below to activate VTOL:Fixed Wing and VTOL:Quad-Rotor?
I wrote it but I didn’t test it yet that I am not so sure if it is correct way or not. Thus, I will be very glad if you would guide me please? thank you.

// **Parameter**
mavros_msgs::CommandVtolTransition change_VTOL_flight;
ros::ServiceClient arming_client_VTOL;

/*
This function changes the mode of the VTOL drone to change the way of the flight type (VTOL:Quad-Rotor or VTOL:Fixed Wing)
@returns 1 - mode change successful
@returns 0 - mode change not successful
*/
int vtol_transition_cb()
{
  mavros_msgs::CommandVtolTransition srv_VTOL_change;
  if(arming_client_VTOL.call(srv_VTOL_change) && srv_VTOL_change.response.success)
  {
    ROS_INFO("VTOL transition is successful %d", srv_VTOL_change.response.success);
    return 0;
  }else{
    ROS_ERROR("VTOL transition failed");
    return -1;
  }
}

Then

// int main section to add these line of codes
arming_client_VTOL = controlnode.serviceClient<mavros_msgs::CommandVtolTransition>("/mavros/cmd/command");

// So if it FALSE then it is on “VTOL:Quad-Rotor” and if it is TRUE then it is “VTOL:Fixed Wing” right?
mavros_msgs::CommandVtolTransition arm_cmd_vtol;
arm_cmd_vtol.request.state = true;

// In an example code
while (!current_state_g.armed && !arm_cmd_vtol.response.success && ros::ok())
{
ros::Duration(.1).sleep();
arming_client_VTOL.call(arm_cmd_vtol);
local_pos_pub.publish(waypoint_g);
}
if(arm_cmd_vtol.response.success)
{
ROS_INFO(“VTOL:Fixed Wing Arming Successful”);
}else{
ROS_INFO(“VTOL:Fixed Wing Arming failed with %d”, arm_cmd_vtol.response.success);
ROS_INFO(“VTOL:Quad-Rotor Arming Successful with %d”, arm_cmd_vtol.response.success);
return -1;
}

If any logic and the way of writing, would you help me to fix it please? thank you very much.
or
How can we write it with the correct way? thank you very much.

Note:
I was not so sure how to do and apply these with /catkin_ws/src/mavros/mavros_msgs/srv/CommandVtolTransition.srv with other srv files CommandTriggerInterval.srv and CommandTriggerControl.srv that I need to make changes in package.xml and CMakeLists.txt which I was not sure what code lines should I need to add there too.

I hope that a knowledgeable person would make a clear with good explanation tutorial for VTOL PX4 ROS MAVROS usage video. After a long research in the internet, most of the people encounters with the same problems but there is no exact solution or some good examples with visual tutorial to show and explain these one by one that this problem exist for ROS control px4 drone (directly from ROS - instead of using QgroundControl that actually is doing everything you want; but personally I try to learn the ROS side version to do these features from ROS side). Let’s hope that some good people will come and guide the newbie PX4 learners to teach in more detail, thank you.

1 Like

Your using the service /mavros/cmd/command this is not correct. It would be something like /mavros/cmd/command/vtol_transition but you would need to browse the service list to figure out exactly what the topic name is.

Unfortunately, I cannot write an example code for you. Please go through the ROS service client tutorial and MAVROS to understand how to get it working.

2 Likes

Dear @Jaeyoung-Lim friend,

I just try to understand the way of how to apply such feature in ROS, therefore I had written some sample code to ask if the way of code is going to correct direction or not; because I am not so sure which I am newbie myself with PX4 in ROS already. However, when I go back to home - I will check your giving link in more detail to do more testing and I will inform you in this thread if it is worked or not. Shortly, I don’t ask you to write a code for me, but I wanted to get your opinion about if my given example code above is going to correct direction or not. Otherwise, I don’t know whom to ask already, except in this discuss px4 forum.

At least this thread I had opened might help the other newbies to give some idea too. I will make a tutorial about my other thread about custom vtol model and how to apply it too that you had mentioned before here: “https://discuss.px4.io/t/how-to-change-the-appearance-of-standard-vtol-drone-model-with-custom-vtol-drone-model/19669/3

I really enjoy(ed) to learn and use the PX4 a lot, so I try to do new things which it improves myself too. I am sorry if I ask many questions (I hope that I don’t bother you with my specific questions), but I am glad to meet you that at least there is a person I would talk about PX4 to understand PX4 better.

2 Likes

@Jaeyoung-Lim, I checked the ROS link you had given me above and then according to the “command.cpp” in mavros below, I had written the necessary codes firstly.

Website:
https://github.com/mavlink/mavros/blob/master/mavros/src/plugins/command.cpp

bool vtol_transition_cb(mavros_msgs::CommandVtolTransition::Request &req,
			mavros_msgs::CommandVtolTransition::Response &res)
	{
		using mavlink::common::MAV_CMD;
		return send_command_long_and_wait(false,
			enum_value(MAV_CMD::DO_VTOL_TRANSITION), false,
			req.state,
			0, 0, 0, 0, 0, 0,
			res.success, res.result);
	}

After that, I have defined my extra variables and libraries as like these in my .cpp file:

#include <mavros_msgs/CommandTriggerControl.h>
#include <mavros_msgs/CommandTriggerInterval.h>
#include <mavros_msgs/CommandVtolTransition.h>


mavros_msgs::CommandVtolTransition change_VTOL_flight;
ros::ServiceClient arming_client_VTOL;

arming_client_VTOL = controlnode.serviceClient<mavros_msgs::CommandVtolTransition>("/mavros/cmd/command/vtol_transition");

After that, I have defined a function to see if everything works or not (to communicate with CommandVtolTransition or not). Thus, I have written “ROS_INFO” to see the results first.

int vtol_arming(){
  mavros_msgs::CommandVtolTransition arm_cmd_vtol;
  arm_cmd_vtol.request.state = true;

  while(ros::ok()){
    if(arming_client_VTOL.call(arm_cmd_vtol)){
      ROS_INFO("VTOL Request - State: %d", arm_cmd_vtol.request.state);
    }

    if(arming_client_VTOL.call(arm_cmd_vtol)){
      ROS_INFO("VTOL Response - Success: %d", arm_cmd_vtol.response.success);
    }else{
      //ROS_ERROR("Failed to call service CommandVtolTransition");
      ROS_INFO("Failed to call service CommandVtolTransition");
    }

    if(arming_client_VTOL.call(arm_cmd_vtol)){
      ROS_INFO("VTOL Response - Result: %d", arm_cmd_vtol.response.result);
    }

    if(arm_cmd_vtol.response.success){
        ROS_INFO("VTOL:Fixed Wing Arming Successful");
        //arm_cmd_vtol.request.state = 4;
      }else{
        //ROS_INFO("VTOL:Fixed Wing Arming failed with %d", arm_cmd_vtol.response.success);
        ROS_INFO("VTOL:Quad-Rotor is still ON and VTOL:Fixed Wing is failed: %d", arm_cmd_vtol.response.success);
      }

    //@returns 1 - mode change successful
    //@returns 0 - mode change not successful
    if(arming_client_VTOL.call(arm_cmd_vtol) && arm_cmd_vtol.response.success){
      ROS_INFO("VTOL:Fixed Wing is Activated: %d", arm_cmd_vtol.response.success);
      return 0;
    }else{
      //ROS_ERROR("VTOL:Fixed Wing Activation is failed!!!");
      ROS_INFO("VTOL:Fixed Wing Activation is failed!!!");
      return -1;
    }
  }
}

At the end, I always failed which I couldn’t understand how to activate this “VTOL Transition” with MAVROS in my ROS C++ code which I have confused a lot at the end that I even don’t know where am I doing wrong, or how to do it correctly in coding way.

Apart from the above code, I have tried many ways of writing code but I have failed all the time. Thus, I came here to get you friends’ opinions too.

If it is possible, would you guide me how could we do it? I will be very happy and glad if you would help me to solve this problem, thank you very much.

Note:
@Jaeyoung-Lim friend, I have followed what you said, but I still couldn’t figure out why mu VTOL transition is not working which I still couldn’t understand how to write that “while(condition)” in ROS C++ to activate VTOL transition at will which I have even checked the QgroundControl codes in its github website which they had written their own way of coding which it didn’t help so much (it was in the “vehicle.h and vehicle.cc” files).

qgroundcontrol/src/Vehicle/Vehicle.h
qgroundcontrol/src/Vehicle/Vehicle.cc

The above code that I wrote for testing always give me “It is failed / Failed to call service CommandVtolTransition”. I actually understood better comparing to other day - the way of the code written in mavros and apply it to ROS C++; but I still couldn’t understand the VTOL activation process to write in the while loop process while OFFBOARD mode is active.

@Jaeyoung-Lim friend, if it is possible would you like to give me some hints please? I will be very glad and happy if you would guide me a little more further; because right now I am stuck at this problem and I still couldn’t find any solution so far. I look forward hearing from you, thank you very much.

1 Like

@Aykut_SIRMA_TR First of all, have you checked your service namespace is correct?

You can use rqt to manually trigger service calls and this is useful to make sure what you are doing in code has the expected result.

2 Likes

At ROS official website, it gives these information below (I have shared its links too).

mavros_msgs/CommandVtolTransition Service

http://wiki.ros.org/mavros_msgs
https://github.com/mavlink/mavros/blob/master/mavros_msgs/srv/CommandVtolTransition.srv

bool vtol_transition_cb (mavros_msgs::CommandVtolTransition::Request &req, mavros_msgs::CommandVtolTransition::Response &res)

ros::ServiceServer vtol_transition_srv

mavros::std_plugins::CommandPlugin Class Reference

When I tried to use the CommandVtolTransition from command.cpp, I had written like this according to this website:

https://github.com/mavlink/mavros/blob/master/mavros/src/plugins/command.cpp
Where it writes these:

vtol_transition_srv = cmd_nh.advertiseService(“vtol_transition”, &CommandPlugin::vtol_transition_cb, this);

ros::ServiceServer vtol_transition_srv;

And this for vtol_transition_cb function

bool vtol_transition_cb(mavros_msgs::CommandVtolTransition::Request &req,
			mavros_msgs::CommandVtolTransition::Response &res)
	{
		using mavlink::common::MAV_CMD;
		return send_command_long_and_wait(false,
			enum_value(MAV_CMD::DO_VTOL_TRANSITION), false,
			req.state,
			0, 0, 0, 0, 0, 0,
			res.success, res.result);
	}

Therefore, I had written like this below in my .cpp file:

mavros_msgs::CommandVtolTransition change_VTOL_flight;
ros::ServiceClient arming_client_VTOL;

arming_client_VTOL = controlnode.serviceClient<mavros_msgs::CommandVtolTransition>("/mavros/cmd/command/vtol_transition");

I had written my above code according to the @Jaeyoung-Lim ros website you had given me yesterday ([Writing a Simple Service and Client (C++)](https://Writing a Simple Service and Client (C++))) .

For the namespaces given for the VTOL in mavros is like this while they defined it there:

    vtol_transition_cb()
    bool mavros::std_plugins::CommandPlugin::vtol_transition_cb	(	mavros_msgs::CommandVtolTransition::Request & 	req,
    mavros_msgs::CommandVtolTransition::Response & 	res 
    )

Therefore, I am kind of confused a lot right now about what is the correct way to write this while my above the initial configuration seemed like it was good but it failed still.

I have never used “rqt” before, so is there any nice tutorial about how to control a px4 ros drone in gazebo from there?

According to given technical information I have found above that I shared in the thread, what is the best way to solve this problem or what is the cause of this problem? As I said before, I am really confused right now which there is no solid solution or any working example in the internet to verify where did I do wrong or correct. This, I will be very glad if you (@Jaeyoung-Lim) would give me some small hints to solve this problem please? Because I don’t know whom to ask, thank you very much for replying me with patient always @Jaeyoung-Lim friend, thank you.

1 Like

My question was, given the technical instructions have you verified that /mavros/cmd/command/vtol_transition is the write service name that mavros is consuming. Documents from mavros can be potentially outdated, so it is important you check these service namespaces when something is not working and not only rely on documentation.

How to use rqt is explained in http://wiki.ros.org/rqt

You can start rqt and start a service plugin to send random services, which you can test against the vtol transition

2 Likes

Hey, not sure if your issue is related but if you are having errors switching to OFFBOARD_MODE it might be worth checking that you sent at least 100 commands before switching modes, or else you will have an error and the transition will not work.

I believe this is to protect against an absence of commands that would result in the motors stopping and the drone crashing, or something of the like.

Might be that, might not be ; but it is for sure a behavior that could surprise you. Hope it helps.

2 Likes

I have written a nice piece of code with nice functions based on the original “offboard” px4 example with upgraded version (in addition to that, I have done a nice custom vtol model too).

I think that I don’t have a problem with offboard mode right now; but something is wrong on the vtol transition activation or while defining it in ROS C++ code.

My code is enable to OFFBOARD first then set destination for takeoff then my takeoff function starts and once the assigned altitude is reached (everything is fine until here), then I want to activate the “vtol transition for the fixed wing”. If I manage to solve this problem then I will focus on about how to set destination for vtol fixed wing, like it had been done with QgroundControl.

I had defined like this before
arming_client_VTOL = controlnode.serviceClient<mavros_msgs::CommandVtolTransition>("/mavros/cmd/command/vtol_transition");

After that I checked where is this command/vtol_transition in my installed folder and it was at the location of /mavros/src/plugins/command/vtol_transition . Thus, I have defined my parameter like this:

arming_client_VTOL = controlnode.serviceClient<mavros_msgs::CommandVtolTransition>("/mavros/src/plugins/command/vtol_transition");

But still, it failed. It is so strange why there is no single simple sample example for vtol transition via mavros anywhere. They should think that there are true people who wants to learn these and even there are people who might want to be a developer in the future to contribute.

If someone has ever done this before would give some hints will be very appreciated by everyone. My last resort is RQT so I will start learning it from zero then I will try to do what @Jaeyoung-Lim mentioned at his above comment. Otherwise, I still wish to do and add this feature I mentioned in this thread via ROS C++ with my own .cpp file for PX4 Gazebo to simulate.

1 Like

rosservice list
picture2
I have found out the problem which @Jaeyoung-Lim had mentioned too that “the current mavros info in the internet is outdated”. At the end, I figured out to write the the correct way which I have made testing and it is working.

arming_client_VTOL = controlnode.serviceClient<mavros_msgs::CommandVtolTransition>("/mavros/cmd/vtol_transition");

The code I had shared at my above comments, I modified them a little.

int vtol_arming(){
  //mavros_msgs::CommandVtolTransition arm_cmd_vtol;
  arm_cmd_vtol.request.state = 4;
  // If the parameter is set to 4 then it will change to fixed wing mode
  // If the parameter is set to 3 then the aircraft will change to VTOL mode

  while(current_state_g.armed && !arm_cmd_vtol.response.success && ros::ok()){
    if(arming_client_VTOL.call(arm_cmd_vtol)){
      ROS_INFO("VTOL Request - State: %d", arm_cmd_vtol.request.state);
    }

    if(arming_client_VTOL.call(arm_cmd_vtol)){
      ROS_INFO("VTOL Response - Success: %d", arm_cmd_vtol.response.success);
    }else{
      //ROS_ERROR("Failed to call service CommandVtolTransition");
      ROS_INFO("Failed to call service CommandVtolTransition");
    }

    if(arming_client_VTOL.call(arm_cmd_vtol)){
      ROS_INFO("VTOL Response - Result: %d", arm_cmd_vtol.response.result);
    }

    if(arm_cmd_vtol.response.success){
        ROS_INFO("VTOL:Fixed Wing Arming Successful");
        //arm_cmd_vtol.request.state = 4;
      }else{
        //ROS_INFO("VTOL:Fixed Wing Arming failed with %d", arm_cmd_vtol.response.success);
        ROS_INFO("VTOL:Quad-Rotor is still ON and VTOL:Fixed Wing is failed: %d", arm_cmd_vtol.response.success);
      }

    //@returns 1 - mode change successful
    //@returns 0 - mode change not successful
    if(arming_client_VTOL.call(arm_cmd_vtol) && arm_cmd_vtol.response.success){
      ROS_INFO("VTOL:Fixed Wing is Activated: %d", arm_cmd_vtol.response.success);
      return 0;
    }else{
      //ROS_ERROR("VTOL:Fixed Wing Activation is failed!!!");
      ROS_INFO("VTOL:Fixed Wing Activation is failed!!!");
      return -1;
    }
  }
}

So far, I have always worked with normal Quad-Rotor drones. @Jaeyoung-Lim friend, how do we set the altitude or destination of a “Fixed Wing” plane at VTOL drone which mavros commands are working for fixed wing? thank you very much.

Note:
I had written this VTOL transition in while loop which I can enter to Fixed Wing mode now; but I cannot go back to VTOL:Quad-Rotor mode, so I need to find a proper way to return back to VTOL:Quad-Rotor at will. I will do new testings within this week.

1 Like

Friends, I have a huge problem right now. I had successfully change the VTOL: Quad-Rotor to VTOL:Fixed Wing which I had shared my code above. However, I cannot go back to initial vtol transition: “VTOL: Quad-Rotor” now.

What I try to do is "When you reach to 50 meters altitude range, then change transition into “VTOL:Quad-Rotor”. However, nothing happens at the end and I couldn’t find any way to solve this problem.

if( current_position.pose.pose.position.z >= 49.4 && current_position.pose.pose.position.z <= 50.009999 ){
 arm_cmd_vtol.request.state == 3;
}

What do you think about what might the cause be? I will be very glad if you would share some opinions to solve this problem, thank you very much.