|
1 | 1 | #!/usr/bin/env python |
2 | | -# -*- coding: utf-8 -*- |
3 | 2 |
|
4 | 3 | """ |
5 | 4 |
|
@@ -85,40 +84,57 @@ def arm_and_takeoff_nogps(aTargetAltitude): |
85 | 84 | set_attitude(thrust = thrust) |
86 | 85 | time.sleep(0.2) |
87 | 86 |
|
88 | | - |
89 | | -def set_attitude(roll_angle = 0.0, pitch_angle = 0.0, yaw_rate = 0.0, thrust = 0.5, duration = 0): |
90 | | - """ |
91 | | - Note that from AC3.3 the message should be re-sent every second (after about 3 seconds |
92 | | - with no message the velocity will drop back to zero). In AC3.2.1 and earlier the specified |
93 | | - velocity persists until it is canceled. The code below should work on either version |
94 | | - (sending the message multiple times does not cause problems). |
95 | | - """ |
96 | | - |
| 87 | +def send_attitude_target(roll_angle = 0.0, pitch_angle = 0.0, |
| 88 | + yaw_angle = None, yaw_rate = 0.0, use_yaw_rate = False, |
| 89 | + thrust = 0.5): |
97 | 90 | """ |
98 | | - The roll and pitch rate cannot be controllbed with rate in radian in AC3.4.4 or earlier, |
99 | | - so you must use quaternion to control the pitch and roll for those vehicles. |
| 91 | + use_yaw_rate: the yaw can be controlled using yaw_angle OR yaw_rate. |
| 92 | + When one is used, the other is ignored by Ardupilot. |
| 93 | + thrust: 0 <= thrust <= 1, as a fraction of maximum vertical thrust. |
| 94 | + Note that as of Copter 3.5, thrust = 0.5 triggers a special case in |
| 95 | + the code for maintaining current altitude. |
100 | 96 | """ |
101 | | - |
| 97 | + if not use_yaw_rate and yaw_angle is None: |
| 98 | + yaw_angle = vehicle.attitude.yaw |
102 | 99 | # Thrust > 0.5: Ascend |
103 | 100 | # Thrust == 0.5: Hold the altitude |
104 | 101 | # Thrust < 0.5: Descend |
105 | 102 | msg = vehicle.message_factory.set_attitude_target_encode( |
106 | 103 | 0, # time_boot_ms |
107 | 104 | 1, # Target system |
108 | 105 | 1, # Target component |
109 | | - 0b00000000, # Type mask: bit 1 is LSB |
110 | | - to_quaternion(roll_angle, pitch_angle), # Quaternion |
| 106 | + 0b00000000 if use_yaw_rate else 0b00000100, |
| 107 | + to_quaternion(roll_angle, pitch_angle, yaw_angle), # Quaternion |
111 | 108 | 0, # Body roll rate in radian |
112 | 109 | 0, # Body pitch rate in radian |
113 | | - math.radians(yaw_rate), # Body yaw rate in radian |
| 110 | + math.radians(yaw_rate), # Body yaw rate in radian/second |
114 | 111 | thrust # Thrust |
115 | 112 | ) |
116 | 113 | vehicle.send_mavlink(msg) |
117 | 114 |
|
| 115 | +def set_attitude(roll_angle = 0.0, pitch_angle = 0.0, |
| 116 | + yaw_angle = None, yaw_rate = 0.0, use_yaw_rate = False, |
| 117 | + thrust = 0.5, duration = 0): |
| 118 | + """ |
| 119 | + Note that from AC3.3 the message should be re-sent more often than every |
| 120 | + second, as an ATTITUDE_TARGET order has a timeout of 1s. |
| 121 | + In AC3.2.1 and earlier the specified attitude persists until it is canceled. |
| 122 | + The code below should work on either version. |
| 123 | + Sending the message multiple times is the recommended way. |
| 124 | + """ |
| 125 | + send_attitude_target(roll_angle, pitch_angle, |
| 126 | + yaw_angle, yaw_rate, False, |
| 127 | + thrust) |
118 | 128 | start = time.time() |
119 | 129 | while time.time() - start < duration: |
120 | | - vehicle.send_mavlink(msg) |
| 130 | + send_attitude_target(roll_angle, pitch_angle, |
| 131 | + yaw_angle, yaw_rate, False, |
| 132 | + thrust) |
121 | 133 | time.sleep(0.1) |
| 134 | + # Reset attitude, or it will persist for 1s more due to the timeout |
| 135 | + send_attitude_target(0, 0, |
| 136 | + 0, 0, True, |
| 137 | + thrust) |
122 | 138 |
|
123 | 139 | def to_quaternion(roll = 0.0, pitch = 0.0, yaw = 0.0): |
124 | 140 | """ |
|
0 commit comments