Skip to content

Commit 2cc3390

Browse files
committed
Add Saving PWM values for button RC override
1 parent 4a4a65e commit 2cc3390

File tree

9 files changed

+383
-53
lines changed

9 files changed

+383
-53
lines changed

qgroundcontrol.qrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@
185185
<file alias="QGroundControl/Controls/TerrainStatus.qml">src/PlanView/TerrainStatus.qml</file>
186186
<file alias="QGroundControl/Controls/TakeoffItemMapVisual.qml">src/PlanView/TakeoffItemMapVisual.qml</file>
187187
<file alias="QGroundControl/Controls/ToolStrip.qml">src/QmlControls/ToolStrip.qml</file>
188-
<file alias="QGroundControl/Controls/ToolStripHoverButton.qml">src/QmlControls/ToolStripHoverButton.qml</file>
188+
<file alias="QGroundControl/Controls/ToolStripHoverButton.qml">src/QmlControls/ToolStripHoverButton.qml</file>
189189
<file alias="QGroundControl/Controls/TransectStyleComplexItemEditor.qml">src/PlanView/TransectStyleComplexItemEditor.qml</file>
190190
<file alias="QGroundControl/Controls/TransectStyleComplexItemStats.qml">src/PlanView/TransectStyleComplexItemStats.qml</file>
191191
<file alias="QGroundControl/Controls/TransectStyleComplexItemTabBar.qml">src/PlanView/TransectStyleComplexItemTabBar.qml</file>

src/Joystick/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ add_library(Joystick
1212
JoystickManager.cc
1313
JoystickSDL.cc
1414
JoystickMavCommand.cc
15+
JoystickRcOverride.cc
1516
${EXTRA_SRC}
1617
)
1718

src/Joystick/Joystick.cc

Lines changed: 107 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ const char* Joystick::_settingsGroup = "Joysticks";
2626
const char* Joystick::_calibratedSettingsKey = "Calibrated4"; // Increment number to force recalibration
2727
const char* Joystick::_buttonActionNameKey = "ButtonActionName%1";
2828
const char* Joystick::_buttonActionRepeatKey = "ButtonActionRepeat%1";
29+
const char* Joystick::_buttonActionLowPwmValueKey = "ButtonActionLowPwm%1";
30+
const char* Joystick::_buttonActionHighPwmValueKey = "ButtonActionHighPwm%1";
2931
const char* Joystick::_throttleModeSettingsKey = "ThrottleMode";
3032
const char* Joystick::_negativeThrustSettingsKey = "NegativeThrust";
3133
const char* Joystick::_exponentialSettingsKey = "Exponential";
@@ -126,6 +128,8 @@ Joystick::Joystick(const QString& name, int axisCount, int buttonCount, int hatC
126128
connect(_multiVehicleManager, &MultiVehicleManager::activeVehicleChanged, this, &Joystick::_activeVehicleChanged);
127129

128130
_customMavCommands = JoystickMavCommand::load("JoystickMavCommands.json");
131+
JoystickRcOverride rco(8, 1200, 1800, true);
132+
_rcOverrides.append(rco);
129133
}
130134

131135
void Joystick::stop()
@@ -860,6 +864,59 @@ QString Joystick::getButtonAction(int button)
860864
return QString(_buttonActionNone);
861865
}
862866

867+
bool Joystick::assignableActionIsPWM(int button) {
868+
qDebug(JoystickLog) << "assignableActionIsPWM: " << button;
869+
if (_validButton(button)) {
870+
auto action = getButtonAction(button);
871+
qDebug(JoystickLog) << "action " << action;
872+
return action.contains("PWM");
873+
}
874+
return false;
875+
}
876+
877+
void Joystick::setButtonPWM(int button, bool lowPwm, int value) {
878+
qDebug(JoystickLog) << "setButtonPWM: " << button << (lowPwm ? "LOW " : "HIGH ") << value;
879+
if (_validButton(button)) {
880+
if (assignableActionIsPWM(button)) {
881+
auto action = getButtonAction(button);
882+
int rc = getRcChannelFromAction(action);
883+
if (rc < 0) {
884+
return;
885+
}
886+
QSettings settings;
887+
settings.beginGroup(_settingsGroup);
888+
settings.beginGroup(_name);
889+
if (lowPwm) {
890+
settings.setValue(QString(_buttonActionLowPwmValueKey).arg(button), value);
891+
} else {
892+
settings.setValue(QString(_buttonActionHighPwmValueKey).arg(button), value);
893+
}
894+
}
895+
}
896+
}
897+
898+
int Joystick::getButtonPWM(int button, bool lowPwm) {
899+
qDebug(JoystickLog) << "getButtonPWM: " << button << (lowPwm ? "LOW " : "HIGH ");
900+
if (_validButton(button)) {
901+
if (assignableActionIsPWM(button)) {
902+
auto action = getButtonAction(button);
903+
int rc = getRcChannelFromAction(action);
904+
if (rc < 0) {
905+
return -1;
906+
}
907+
QSettings settings;
908+
settings.beginGroup(_settingsGroup);
909+
settings.beginGroup(_name);
910+
if (lowPwm) {
911+
return settings.value(QString(_buttonActionLowPwmValueKey).arg(button), -1).toInt();
912+
} else {
913+
return settings.value(QString(_buttonActionHighPwmValueKey).arg(button), -1).toInt();
914+
}
915+
}
916+
}
917+
return -1;
918+
}
919+
863920
QStringList Joystick::buttonActions()
864921
{
865922
QStringList list;
@@ -1045,13 +1102,22 @@ void Joystick::_executeButtonAction(const QString& action, bool buttonDown)
10451102
emit gripperAction(GRIPPER_ACTION_RELEASE);
10461103
}
10471104
} else {
1048-
if (buttonDown && _activeVehicle) {
1049-
for (auto& item : _customMavCommands) {
1050-
if (action == item.name()) {
1051-
item.send(_activeVehicle);
1052-
return;
1105+
qCDebug(JoystickLog) << "Action " << action << " button " << (buttonDown ? "down" : "up");
1106+
if (_activeVehicle) {
1107+
bool actionServed = false;
1108+
if (action.startsWith("Channel")) {
1109+
actionServed = _executeRcOverrideButtonAction(action, buttonDown);
1110+
}
1111+
if (buttonDown && !actionServed) {
1112+
for (auto& item : _customMavCommands) {
1113+
if (action == item.name()) {
1114+
item.send(_activeVehicle);
1115+
return;
1116+
}
10531117
}
10541118
}
1119+
} else {
1120+
qCDebug(JoystickLog) << "_buttonAction unknown action:" << action;
10551121
}
10561122
}
10571123
}
@@ -1143,6 +1209,11 @@ void Joystick::_buildActionList(Vehicle* activeVehicle)
11431209
_assignableButtonActions.append(new AssignableButtonAction(this, _buttonActionGripperGrab));
11441210
_assignableButtonActions.append(new AssignableButtonAction(this, _buttonActionGripperRelease));
11451211

1212+
for (int ch = 8; ch <= 16;ch++) {
1213+
_assignableButtonActions.append(new AssignableButtonAction(this, QString("Channel %1 direct PWM").arg(ch)));
1214+
}
1215+
1216+
_assignableButtonActions.append(new AssignableButtonAction(this, _buttonActionEmergencyStop));
11461217
for (auto& item : _customMavCommands) {
11471218
_assignableButtonActions.append(new AssignableButtonAction(this, item.name()));
11481219
}
@@ -1153,3 +1224,34 @@ void Joystick::_buildActionList(Vehicle* activeVehicle)
11531224
}
11541225
emit assignableActionsChanged();
11551226
}
1227+
1228+
bool Joystick::_executeRcOverrideButtonAction(const QString &action, bool buttonDown)
1229+
{
1230+
QRegularExpression re("^Channel (\\d{1,2}) direct PWM");
1231+
QRegularExpressionMatch match = re.match(action);
1232+
if (match.hasMatch()) {
1233+
QString channelNoStr = match.captured(1);
1234+
qCDebug(JoystickLog) << "RC override matched for channel " << channelNoStr;
1235+
uint8_t channelNo = channelNoStr.toInt();
1236+
1237+
for (auto& item : _rcOverrides) {
1238+
if (channelNo == item.channel()) {
1239+
item.send(_activeVehicle, buttonDown);
1240+
return true;
1241+
}
1242+
}
1243+
}
1244+
return false;
1245+
}
1246+
1247+
int Joystick::getRcChannelFromAction(QString actionName) {
1248+
QRegularExpression re("^Channel (\\d{1,2}) direct PWM");
1249+
QRegularExpressionMatch match = re.match(actionName);
1250+
if (match.hasMatch()) {
1251+
QString channelNoStr = match.captured(1);
1252+
qCDebug(JoystickLog) << "RC override matched for channel " << channelNoStr;
1253+
uint8_t channelNo = channelNoStr.toInt();
1254+
return channelNo;
1255+
}
1256+
return -1;
1257+
}

src/Joystick/Joystick.h

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,11 @@
1616
#include <QThread>
1717
#include <atomic>
1818

19+
#include "JoystickMavCommand.h"
20+
#include "JoystickRcOverride.h"
21+
#include "MultiVehicleManager.h"
1922
#include "QGCLoggingCategory.h"
2023
#include "Vehicle.h"
21-
#include "MultiVehicleManager.h"
22-
#include "JoystickMavCommand.h"
2324

2425
Q_DECLARE_LOGGING_CATEGORY(JoystickLog)
2526
Q_DECLARE_LOGGING_CATEGORY(JoystickValuesLog)
@@ -118,6 +119,10 @@ class Joystick : public QThread
118119
Q_INVOKABLE bool getButtonRepeat (int button);
119120
Q_INVOKABLE void setButtonAction (int button, const QString& action);
120121
Q_INVOKABLE QString getButtonAction (int button);
122+
Q_INVOKABLE bool assignableActionIsPWM (int button);
123+
Q_INVOKABLE void setButtonPWM (int button, bool lowPwm, int value);
124+
Q_INVOKABLE int getButtonPWM (int button, bool lowPwm);
125+
121126

122127
// Property accessors
123128

@@ -307,6 +312,7 @@ class Joystick : public QThread
307312
MultiVehicleManager* _multiVehicleManager = nullptr;
308313

309314
QList<JoystickMavCommand> _customMavCommands;
315+
QList<JoystickRcOverride> _rcOverrides;
310316

311317
static const float _minAxisFrequencyHz;
312318
static const float _maxAxisFrequencyHz;
@@ -320,6 +326,8 @@ class Joystick : public QThread
320326
static const char* _calibratedSettingsKey;
321327
static const char* _buttonActionNameKey;
322328
static const char* _buttonActionRepeatKey;
329+
static const char* _buttonActionLowPwmValueKey;
330+
static const char* _buttonActionHighPwmValueKey;
323331
static const char* _throttleModeSettingsKey;
324332
static const char* _negativeThrustSettingsKey;
325333
static const char* _exponentialSettingsKey;
@@ -365,4 +373,6 @@ class Joystick : public QThread
365373

366374
private slots:
367375
void _activeVehicleChanged(Vehicle* activeVehicle);
376+
bool _executeRcOverrideButtonAction(const QString &action, bool buttonDown);
377+
int getRcChannelFromAction(QString actionName);
368378
};

src/Joystick/JoystickRcOverride.cc

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
//
2+
// Created by zdanek on 08.07.2022.
3+
//
4+
5+
#include "JoystickRcOverride.h"
6+
7+
#include "Vehicle.h"
8+
9+
JoystickRcOverride::JoystickRcOverride(const uint8_t rcChannel,
10+
const uint16_t loPwmValue,
11+
const uint16_t hiPwmValue,
12+
bool latch)
13+
: rcChannel(rcChannel)
14+
, loPwmValue(loPwmValue)
15+
, hiPwmValue(hiPwmValue)
16+
, latchMode(latch)
17+
{}
18+
19+
void JoystickRcOverride::send(Vehicle *vehicle, bool buttonDown)
20+
{
21+
uint16_t pwmValue = buttonDown ? hiPwmValue : loPwmValue;
22+
23+
if (latchMode) {
24+
if (buttonDown) {
25+
latchButtonDown = !latchButtonDown;
26+
pwmValue = latchButtonDown ? hiPwmValue : loPwmValue;
27+
} else {
28+
return;
29+
}
30+
}
31+
vehicle->rcChannelOverride(rcChannel, pwmValue);
32+
}
33+
34+
uint8_t JoystickRcOverride::channel() const
35+
{
36+
return rcChannel;
37+
};

src/Joystick/JoystickRcOverride.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//
2+
// Created by zdanek on 08.07.2022.
3+
//
4+
5+
#pragma once
6+
7+
#include "Vehicle.h"
8+
9+
class JoystickRcOverride
10+
{
11+
public:
12+
JoystickRcOverride(const uint8_t rcChannel,
13+
const uint16_t loPwmValue,
14+
const uint16_t hiPwmValue,
15+
bool latch);
16+
void send(Vehicle* vehicle, bool buttonDown);
17+
uint8_t channel() const;
18+
19+
private:
20+
uint8_t rcChannel;
21+
uint16_t loPwmValue;
22+
uint16_t hiPwmValue;
23+
bool latchMode;
24+
bool latchButtonDown = false;
25+
};
26+

src/Vehicle/Vehicle.cc

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4310,3 +4310,62 @@ void Vehicle::sendGripperAction(GRIPPER_OPTIONS gripperOption)
43104310
break;
43114311
}
43124312
}
4313+
4314+
void Vehicle::rcChannelOverride(uint8_t rcChannel, uint16_t pwmValue)
4315+
{
4316+
const int maxRcChannels = 16;
4317+
if (rcChannel > maxRcChannels) {
4318+
qCWarning(VehicleLog) << "Unsupported rc channel " << rcChannel << " to override";
4319+
return;
4320+
}
4321+
if (pwmValue > 2000 || pwmValue < 1000) {
4322+
qCWarning(VehicleLog) << "Bad PWM override value " << pwmValue << " for channel " << rcChannel;
4323+
return;
4324+
}
4325+
SharedLinkInterfacePtr sharedLink = vehicleLinkManager()->primaryLink().lock();
4326+
if (!sharedLink) {
4327+
qCDebug(VehicleLog)<< "rcChannelOverride: primary link gone!";
4328+
return;
4329+
}
4330+
4331+
if (sharedLink->linkConfiguration()->isHighLatency()) {
4332+
return;
4333+
}
4334+
4335+
qCDebug(VehicleLog) << "Sending RC channel " << rcChannel << " PWM override to " << pwmValue;
4336+
4337+
uint16_t override_data[18] = {};
4338+
for (int i = 0; i < 18; i++) {
4339+
override_data[i] = UINT16_MAX;
4340+
}
4341+
override_data[rcChannel - 1] = pwmValue;
4342+
4343+
mavlink_message_t message;
4344+
4345+
mavlink_msg_rc_channels_override_pack_chan(
4346+
static_cast<uint8_t>(_mavlink->getSystemId()),
4347+
static_cast<uint8_t>(_mavlink->getComponentId()),
4348+
sharedLink->mavlinkChannel(),
4349+
&message,
4350+
static_cast<uint8_t>(_id),
4351+
0,
4352+
override_data[0],
4353+
override_data[1],
4354+
override_data[2],
4355+
override_data[3],
4356+
override_data[4],
4357+
override_data[5],
4358+
override_data[6],
4359+
override_data[7],
4360+
override_data[8],
4361+
override_data[9],
4362+
override_data[10],
4363+
override_data[11],
4364+
override_data[12],
4365+
override_data[13],
4366+
override_data[14],
4367+
override_data[15],
4368+
override_data[16],
4369+
override_data[17]);
4370+
sendMessageOnLinkThreadSafe(sharedLink.get(), message);
4371+
}

src/Vehicle/Vehicle.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -485,6 +485,14 @@ class Vehicle : public FactGroup
485485
void setJoystickEnabled (bool enabled);
486486
void sendJoystickDataThreadSafe (float roll, float pitch, float yaw, float thrust, quint16 buttons);
487487

488+
/// Sends Channel override value
489+
/// @param rcChannel channel number 1-16
490+
/// @param pwmValue direct value 1000 - 2000
491+
void rcChannelOverride(uint8_t rcChannel, uint16_t pwmValue);
492+
/// Sends disabling of channel override
493+
/// @param rcChannel channel number 1-16
494+
void disableChannelOverride(uint8_t rcChannel);
495+
488496
// Property accesors
489497
int id() const{ return _id; }
490498
int compId() const{ return _compID; }

0 commit comments

Comments
 (0)