Compare commits

...

11 Commits

Author SHA1 Message Date
Jaeyoung Lim ea6f95781f Add fw pos control states
F
2023-03-30 14:25:43 +02:00
Jaeyoung Lim ec3c3c0030 Add velocity control as a fw state
F
F
2023-03-30 14:10:07 +02:00
Jaeyoung Lim 3a104a425c Cleanup fixed wing path navigation state machine 2023-03-29 14:29:06 +02:00
Ramon Roche 319f3db5e1 tools: ip converter remove verbose output 2023-03-27 10:28:43 -07:00
Beniamino Pozzan 51dd6b783c microdds_client: Mark parameter as used only if truly used
Signed-off-by: Beniamino Pozzan <beniamino.pozzan@phd.unipd.it>
2023-03-27 10:28:43 -07:00
Beniamino Pozzan c7f67a3328 microdds_client: remove multi-instances supports, add agent IP as PX4 parameter
- multi-instances support is removed from the parameter definitions.

- XRCE_DDS_AG_IP allows to define the agent IP when udp transport is used.
The parameter is used by default if the module is started without the -h argument.

- XRCE_DDS_PRT allows to define the agent listning udp port when the
udp transport is uded. The parameter is used by default if the module is started
without the -p argument.

- Tools/convert_ip.py assists in converting ips in decimal dot notation into int32
notation.

Signed-off-by: Beniamino Pozzan <beniamino.pozzan@phd.unipd.it>
2023-03-27 10:28:43 -07:00
Daniel Mesham 6fddbea3e4 microdds_client: fix check for length of participant XML (#21374) 2023-03-27 10:03:09 -07:00
Silvan Fuhrer ba17a137e1 Navigator: MissionFeasibiltyCheck first WP: check only to current vehicle position
Signed-off-by: Silvan Fuhrer <silvan@auterion.com>
2023-03-27 17:43:33 +02:00
Silvan Fuhrer 465ddddbfd Navigator: take min of vehicle position or Home distance for first WP check
To prevent mission rejections when vehicle is currently far away from Mission start,
but planned home is close to it.

Signed-off-by: Silvan Fuhrer <silvan@auterion.com>
2023-03-27 17:43:33 +02:00
Silvan Fuhrer d8ed35c422 Navigator: take vehicle position for first-WP-distance-check
And only use Home position if current vehicle position is unknown.

Signed-off-by: Silvan Fuhrer <silvan@auterion.com>
2023-03-27 17:43:33 +02:00
Silvan Fuhrer 4d2a31afe3 Navigator: remove max distance between WP mission feasibility check (MIS_DIST_WPS)
Signed-off-by: Silvan Fuhrer <silvan@auterion.com>
2023-03-27 17:43:33 +02:00
19 changed files with 305 additions and 281 deletions
@@ -25,7 +25,6 @@ param set-default FW_W_EN 1
param set-default MIS_TAKEOFF_ALT 20
param set-default MIS_DIST_1WP 2500
param set-default MIS_DIST_WPS 10000
param set-default NAV_ACC_RAD 15
param set-default NAV_DLL_ACT 2
@@ -25,7 +25,6 @@ param set-default FW_W_EN 1
param set-default MIS_TAKEOFF_ALT 20
param set-default MIS_DIST_1WP 2500
param set-default MIS_DIST_WPS 10000
param set-default NAV_ACC_RAD 15
param set-default NAV_DLL_ACT 2
@@ -25,7 +25,6 @@ param set-default FW_W_EN 1
param set-default MIS_TAKEOFF_ALT 20
param set-default MIS_DIST_1WP 2500
param set-default MIS_DIST_WPS 10000
param set-default NAV_ACC_RAD 15
param set-default NAV_DLL_ACT 2
@@ -27,7 +27,6 @@ param set-default FW_W_EN 1
param set-default MIS_LTRMIN_ALT 30
param set-default MIS_TAKEOFF_ALT 20
param set-default MIS_DIST_1WP 2500
param set-default MIS_DIST_WPS 10000
param set-default NAV_ACC_RAD 15
param set-default NAV_DLL_ACT 2
+1 -1
View File
@@ -277,7 +277,7 @@ then
# Override namespace if environment variable is defined
microdds_ns="-n $PX4_MICRODDS_NS"
fi
microdds_client start -t udp -p 8888 $microdds_ns
microdds_client start -t udp -h 127.0.0.1 -p 8888 $microdds_ns
if param greater -s MNT_MODE_IN -1
then
@@ -79,7 +79,6 @@ param set-default MC_YAWRATE_MAX 20
param set-default MC_AIRMODE 1
param set-default MIS_DIST_1WP 100
param set-default MIS_DIST_WPS 100000
param set-default MIS_TAKEOFF_ALT 15
param set-default MPC_XY_P 0.8
@@ -46,7 +46,6 @@ param set-default RTL_LAND_DELAY -1
#
param set-default NAV_ACC_RAD 10
param set-default MIS_DIST_WPS 5000
param set-default MIS_TAKEOFF_ALT 25
param set-default MIS_TKO_LAND_REQ 2
@@ -23,7 +23,6 @@ param set-default EKF2_FUSE_BETA 1
param set-default HTE_VXY_THR 2.0
param set-default MIS_DIST_WPS 5000
param set-default MIS_TKO_LAND_REQ 2
param set-default MPC_ACC_HOR_MAX 2
+51
View File
@@ -0,0 +1,51 @@
#!/usr/bin/env python3
"""
Converts IP address given in decimal dot notation to int32 to be used in XRCE_DDS_0_CFG parameter
and vice-versa
@author: Beniamino Pozzan (beniamino.pozzan@phd.unipd.it)
"""
import argparse
parser = argparse.ArgumentParser(
prog = 'convert_ip',
description = 'converts IP to int32 and viceversa'
)
parser.add_argument('input',
type=str,
help='IP address to convert')
parser.add_argument('-r','--reverse',
action='store_true',
help='converts from int32 to dot decimal')
args = parser.parse_args()
if( args.reverse == False ):
try:
ip_parts = [int(x) for x in args.input.split('.')]
except:
raise ValueError("Not a valid IP")
if( len(ip_parts)!=4 ):
raise ValueError("Not a valid IP")
if( not all(x>=0 and x<255 for x in ip_parts) ):
raise ValueError("Not a valid IP")
ip = (ip_parts[0]<<24) + (ip_parts[1]<<16) + (ip_parts[2]<<8) + ip_parts[3]
if(ip & 0x80000000):
ip = -0x100000000 + ip
print(ip)
else:
try:
ip = int(args.input)
except:
raise ValueError("Not a valid IP")
if(ip < 0):
ip = ip + 0x100000000
print('{}.{}.{}.{}'.format(ip>>24, (ip>>16)&0xff, (ip>>8)&0xff, ip&0xff))
@@ -696,39 +696,42 @@ FixedwingPositionControl::updateManualTakeoffStatus()
}
}
void
FixedwingPositionControl::set_control_mode_current(const hrt_abstime &now)
FW_POSCTRL_MODE
FixedwingPositionControl::set_control_mode_current(const hrt_abstime &now, const FW_POSCTRL_MODE &current_mode)
{
/* only run position controller in fixed-wing mode and during transitions for VTOL */
if (_vehicle_status.vehicle_type == vehicle_status_s::VEHICLE_TYPE_ROTARY_WING && !_vehicle_status.in_transition_mode) {
_control_mode_current = FW_POSCTRL_MODE_OTHER;
return; // do not publish the setpoint
return FW_POSCTRL_MODE_OTHER; // do not publish the setpoint
}
FW_POSCTRL_MODE commanded_position_control_mode = _control_mode_current;
_skipping_takeoff_detection = false;
if (_control_mode.flag_control_offboard_enabled && !_control_mode.flag_control_position_enabled
&& _control_mode.flag_control_velocity_enabled) {
return FW_POSCTRL_MODE_AUTO_VELOCITY;
}
if (((_control_mode.flag_control_auto_enabled && _control_mode.flag_control_position_enabled) ||
_control_mode.flag_control_offboard_enabled) && _position_setpoint_current_valid) {
if (_pos_sp_triplet.current.type == position_setpoint_s::SETPOINT_TYPE_TAKEOFF) {
if (_vehicle_status.is_vtol && _vehicle_status.in_transition_mode) {
_control_mode_current = FW_POSCTRL_MODE_AUTO;
// in this case we want the waypoint handled as a position setpoint -- a submode in control_auto()
_pos_sp_triplet.current.type = position_setpoint_s::SETPOINT_TYPE_POSITION;
} else {
_control_mode_current = FW_POSCTRL_MODE_AUTO_TAKEOFF;
return FW_POSCTRL_MODE_AUTO;
if (commanded_position_control_mode != FW_POSCTRL_MODE_AUTO_TAKEOFF && !_landed) {
} else {
if (current_mode != FW_POSCTRL_MODE_AUTO_TAKEOFF && !_landed) {
// skip takeoff detection when switching from any other mode, auto or manual,
// while already in air.
// TODO: find a better place for / way of doing this
_skipping_takeoff_detection = true;
}
return FW_POSCTRL_MODE_AUTO_TAKEOFF;
}
} else if (_pos_sp_triplet.current.type == position_setpoint_s::SETPOINT_TYPE_LAND) {
@@ -739,10 +742,10 @@ FixedwingPositionControl::set_control_mode_current(const hrt_abstime &now)
// Straight landings are currently only possible in Missions, and there the previous WP
// is valid, and circular ones are used outside of Missions, as the land mode sets prev_valid=false.
if (_position_setpoint_previous_valid) {
_control_mode_current = FW_POSCTRL_MODE_AUTO_LANDING_STRAIGHT;
return FW_POSCTRL_MODE_AUTO_LANDING_STRAIGHT;
} else {
_control_mode_current = FW_POSCTRL_MODE_AUTO_LANDING_CIRCULAR;
return FW_POSCTRL_MODE_AUTO_LANDING_CIRCULAR;
}
} else {
@@ -751,7 +754,7 @@ FixedwingPositionControl::set_control_mode_current(const hrt_abstime &now)
}
} else {
_control_mode_current = FW_POSCTRL_MODE_AUTO;
return FW_POSCTRL_MODE_AUTO;
}
} else if (_control_mode.flag_control_auto_enabled
@@ -761,33 +764,33 @@ FixedwingPositionControl::set_control_mode_current(const hrt_abstime &now)
// failsafe modes engaged if position estimate is invalidated
if (commanded_position_control_mode != FW_POSCTRL_MODE_AUTO_ALTITUDE
&& commanded_position_control_mode != FW_POSCTRL_MODE_AUTO_CLIMBRATE) {
if (current_mode != FW_POSCTRL_MODE_AUTO_ALTITUDE
&& current_mode != FW_POSCTRL_MODE_AUTO_CLIMBRATE) {
// reset timer the first time we switch into this mode
_time_in_fixed_bank_loiter = now;
}
if (hrt_elapsed_time(&_time_in_fixed_bank_loiter) < (_param_nav_gpsf_lt.get() * 1_s)
&& !_vehicle_status.in_transition_mode) {
if (commanded_position_control_mode != FW_POSCTRL_MODE_AUTO_ALTITUDE) {
if (current_mode != FW_POSCTRL_MODE_AUTO_ALTITUDE) {
// Need to init because last loop iteration was in a different mode
events::send(events::ID("fixedwing_position_control_fb_loiter"), events::Log::Critical,
"Start loiter with fixed bank angle");
}
_control_mode_current = FW_POSCTRL_MODE_AUTO_ALTITUDE;
return FW_POSCTRL_MODE_AUTO_ALTITUDE;
} else {
if (commanded_position_control_mode != FW_POSCTRL_MODE_AUTO_CLIMBRATE && !_vehicle_status.in_transition_mode) {
if (current_mode != FW_POSCTRL_MODE_AUTO_CLIMBRATE && !_vehicle_status.in_transition_mode) {
events::send(events::ID("fixedwing_position_control_descend"), events::Log::Critical, "Start descending");
}
_control_mode_current = FW_POSCTRL_MODE_AUTO_CLIMBRATE;
return FW_POSCTRL_MODE_AUTO_CLIMBRATE;
}
} else if (_control_mode.flag_control_manual_enabled && _control_mode.flag_control_position_enabled) {
if (commanded_position_control_mode != FW_POSCTRL_MODE_MANUAL_POSITION) {
if (current_mode != FW_POSCTRL_MODE_MANUAL_POSITION) {
/* Need to init because last loop iteration was in a different mode */
_hdg_hold_yaw = _yaw; // yaw is not controlled, so set setpoint to current yaw
_hdg_hold_enabled = false; // this makes sure the waypoints are reset below
@@ -799,15 +802,15 @@ FixedwingPositionControl::set_control_mode_current(const hrt_abstime &now)
_att_sp.yaw_body = _yaw; // yaw is not controlled, so set setpoint to current yaw
}
_control_mode_current = FW_POSCTRL_MODE_MANUAL_POSITION;
return FW_POSCTRL_MODE_MANUAL_POSITION;
} else if (_control_mode.flag_control_manual_enabled && _control_mode.flag_control_altitude_enabled) {
_control_mode_current = FW_POSCTRL_MODE_MANUAL_ALTITUDE;
return FW_POSCTRL_MODE_MANUAL_ALTITUDE;
} else {
_control_mode_current = FW_POSCTRL_MODE_OTHER;
}
return FW_POSCTRL_MODE_OTHER;
}
void
@@ -864,61 +867,6 @@ FixedwingPositionControl::move_position_setpoint_for_vtol_transition(position_se
}
}
void
FixedwingPositionControl::control_auto(const float control_interval, const Vector2d &curr_pos,
const Vector2f &ground_speed, const position_setpoint_s &pos_sp_prev, const position_setpoint_s &pos_sp_curr,
const position_setpoint_s &pos_sp_next)
{
position_setpoint_s current_sp = pos_sp_curr;
move_position_setpoint_for_vtol_transition(current_sp);
const uint8_t position_sp_type = handle_setpoint_type(current_sp);
_position_sp_type = position_sp_type;
if (position_sp_type == position_setpoint_s::SETPOINT_TYPE_LOITER
|| current_sp.type == position_setpoint_s::SETPOINT_TYPE_LOITER) {
publishOrbitStatus(current_sp);
}
switch (position_sp_type) {
case position_setpoint_s::SETPOINT_TYPE_IDLE:
_att_sp.thrust_body[0] = 0.0f;
_att_sp.roll_body = 0.0f;
_att_sp.pitch_body = radians(_param_fw_psp_off.get());
break;
case position_setpoint_s::SETPOINT_TYPE_POSITION:
control_auto_position(control_interval, curr_pos, ground_speed, pos_sp_prev, current_sp);
break;
case position_setpoint_s::SETPOINT_TYPE_VELOCITY:
control_auto_velocity(control_interval, curr_pos, ground_speed, current_sp);
break;
case position_setpoint_s::SETPOINT_TYPE_LOITER:
control_auto_loiter(control_interval, curr_pos, ground_speed, pos_sp_prev, current_sp, pos_sp_next);
break;
}
/* Copy thrust output for publication, handle special cases */
if (position_sp_type == position_setpoint_s::SETPOINT_TYPE_IDLE) {
_att_sp.thrust_body[0] = 0.0f;
} else {
// when we are landed state we want the motor to spin at idle speed
_att_sp.thrust_body[0] = (_landed) ? min(_param_fw_thr_idle.get(), 1.f) : get_tecs_thrust();
}
/* Copy thrust and pitch values from tecs */
_att_sp.pitch_body = get_tecs_pitch();
if (!_vehicle_status.in_transition_to_fw) {
publishLocalPositionSetpoint(current_sp);
}
}
void
FixedwingPositionControl::control_auto_fixed_bank_alt_hold(const float control_interval)
{
@@ -979,10 +927,6 @@ FixedwingPositionControl::handle_setpoint_type(const position_setpoint_s &pos_sp
{
uint8_t position_sp_type = pos_sp_curr.type;
if (!_control_mode.flag_control_position_enabled && _control_mode.flag_control_velocity_enabled) {
return position_setpoint_s::SETPOINT_TYPE_VELOCITY;
}
Vector2d curr_wp{0, 0};
/* current waypoint (the one currently heading for) */
@@ -1022,6 +966,8 @@ void
FixedwingPositionControl::control_auto_position(const float control_interval, const Vector2d &curr_pos,
const Vector2f &ground_speed, const position_setpoint_s &pos_sp_prev, const position_setpoint_s &pos_sp_curr)
{
move_position_setpoint_for_vtol_transition(pos_sp_curr);
const float acc_rad = _npfg.switchDistance(500.0f);
Vector2d curr_wp{0, 0};
Vector2d prev_wp{0, 0};
@@ -1123,6 +1069,19 @@ FixedwingPositionControl::control_auto_position(const float control_interval, co
tecs_fw_thr_max,
_param_sinkrate_target.get(),
_param_climbrate_target.get());
if (_landed) {
_att_sp.thrust_body[0] = _param_fw_thr_min.get();
} else {
_att_sp.thrust_body[0] = min(get_tecs_thrust(), _param_fw_thr_max.get());
}
_att_sp.pitch_body = get_tecs_pitch();
if (!_vehicle_status.in_transition_to_fw) {
publishLocalPositionSetpoint(pos_sp_curr);
}
}
void
@@ -1181,6 +1140,8 @@ FixedwingPositionControl::control_auto_loiter(const float control_interval, cons
const Vector2f &ground_speed, const position_setpoint_s &pos_sp_prev, const position_setpoint_s &pos_sp_curr,
const position_setpoint_s &pos_sp_next)
{
move_position_setpoint_for_vtol_transition(pos_sp_curr);
Vector2d curr_wp{0, 0};
Vector2d prev_wp{0, 0};
@@ -1280,6 +1241,20 @@ FixedwingPositionControl::control_auto_loiter(const float control_interval, cons
tecs_fw_thr_max,
_param_sinkrate_target.get(),
_param_climbrate_target.get());
if (_landed) {
_att_sp.thrust_body[0] = _param_fw_thr_min.get();
} else {
_att_sp.thrust_body[0] = min(get_tecs_thrust(), _param_fw_thr_max.get());
}
_att_sp.pitch_body = get_tecs_pitch();
if (!_vehicle_status.in_transition_to_fw) {
publishLocalPositionSetpoint(pos_sp_curr);
}
}
void
@@ -2279,7 +2254,7 @@ FixedwingPositionControl::Run()
Vector2d curr_pos(_current_latitude, _current_longitude);
Vector2f ground_speed(_local_pos.vx, _local_pos.vy);
set_control_mode_current(_local_pos.timestamp);
_control_mode_current = set_control_mode_current(_local_pos.timestamp, _control_mode_current);
update_in_air_states(_local_pos.timestamp);
@@ -2318,12 +2293,6 @@ FixedwingPositionControl::Run()
_new_landing_gear_position = landing_gear_s::GEAR_KEEP; // is overwritten in Takeoff and Land
switch (_control_mode_current) {
case FW_POSCTRL_MODE_AUTO: {
control_auto(control_interval, curr_pos, ground_speed, _pos_sp_triplet.previous, _pos_sp_triplet.current,
_pos_sp_triplet.next);
break;
}
case FW_POSCTRL_MODE_AUTO_ALTITUDE: {
control_auto_fixed_bank_alt_hold(control_interval);
break;
@@ -2345,11 +2314,27 @@ FixedwingPositionControl::Run()
break;
}
case FW_POSCTRL_MODE_AUTO_LOITER: {
control_auto_loiter(control_interval, curr_pos, ground_speed, _pos_sp_triplet.previous, _pos_sp_triplet.current,
_pos_sp_triplet.next);
break;
}
case FW_POSCTRL_MODE_AUTO_POSITION: {
control_auto_position(control_interval, curr_pos, ground_speed, _pos_sp_triplet.previous, _pos_sp_triplet.current);
break;
}
case FW_POSCTRL_MODE_AUTO_TAKEOFF: {
control_auto_takeoff(_local_pos.timestamp, control_interval, curr_pos, ground_speed, _pos_sp_triplet.current);
break;
}
case FW_POSCTRL_MODE_AUTO_VELOCITY: {
control_auto_velocity(control_interval, curr_pos, ground_speed, _pos_sp_triplet.current);
break;
}
case FW_POSCTRL_MODE_MANUAL_POSITION: {
control_manual_position(control_interval, curr_pos, ground_speed);
break;
@@ -167,6 +167,20 @@ static constexpr float MANUAL_TOUCHDOWN_NUDGE_INPUT_DEADZONE = 0.15f;
// [s] time interval after touchdown for ramping in runway clamping constraints (touchdown is assumed at FW_LND_TD_TIME after start of flare)
static constexpr float POST_TOUCHDOWN_CLAMP_TIME = 0.5f;
enum FW_POSCTRL_MODE {
FW_POSCTRL_MODE_AUTO_ALTITUDE,
FW_POSCTRL_MODE_AUTO_CLIMBRATE,
FW_POSCTRL_MODE_AUTO_TAKEOFF,
FW_POSCTRL_MODE_AUTO_LANDING_STRAIGHT,
FW_POSCTRL_MODE_AUTO_LANDING_CIRCULAR,
FW_POSCTRL_MODE_AUTO_LOITER,
FW_POSCTRL_MODE_AUTO_POSITION,
FW_POSCTRL_MODE_AUTO_VELOCITY,
FW_POSCTRL_MODE_MANUAL_POSITION,
FW_POSCTRL_MODE_MANUAL_ALTITUDE,
FW_POSCTRL_MODE_OTHER
};
class FixedwingPositionControl final : public ModuleBase<FixedwingPositionControl>, public ModuleParams,
public px4::WorkItem
{
@@ -236,17 +250,7 @@ private:
uint8_t _position_sp_type{0};
enum FW_POSCTRL_MODE {
FW_POSCTRL_MODE_AUTO,
FW_POSCTRL_MODE_AUTO_ALTITUDE,
FW_POSCTRL_MODE_AUTO_CLIMBRATE,
FW_POSCTRL_MODE_AUTO_TAKEOFF,
FW_POSCTRL_MODE_AUTO_LANDING_STRAIGHT,
FW_POSCTRL_MODE_AUTO_LANDING_CIRCULAR,
FW_POSCTRL_MODE_MANUAL_POSITION,
FW_POSCTRL_MODE_MANUAL_ALTITUDE,
FW_POSCTRL_MODE_OTHER
} _control_mode_current{FW_POSCTRL_MODE_OTHER}; // used to check if the mode has changed
FW_POSCTRL_MODE _control_mode_current{FW_POSCTRL_MODE_OTHER}; // used to check if the mode has changed
enum StickConfig {
STICK_CONFIG_SWAP_STICKS_BIT = (1 << 0),
@@ -529,19 +533,6 @@ private:
/* automatic control methods */
/**
* @brief Automatic position control for waypoints, orbits, and velocity control
*
* @param control_interval Time since last position control call [s]
* @param curr_pos Current 2D local position vector of vehicle [m]
* @param ground_speed Local 2D ground speed of vehicle [m/s]
* @param pos_sp_prev previous position setpoint
* @param pos_sp_curr current position setpoint
* @param pos_sp_next next position setpoint
*/
void control_auto(const float control_interval, const Vector2d &curr_pos, const Vector2f &ground_speed,
const position_setpoint_s &pos_sp_prev, const position_setpoint_s &pos_sp_curr, const position_setpoint_s &pos_sp_next);
/**
* @brief Controls altitude and airspeed for a fixed-bank loiter.
*
@@ -685,8 +676,10 @@ private:
* May also change the position setpoint type depending on the desired behavior.
*
* @param now Current system time [us]
* @param current_mode Current flight mode
* @return FW_POSCTRL_MODE Next flight mode to transition to
*/
void set_control_mode_current(const hrt_abstime &now);
FW_POSCTRL_MODE set_control_mode_current(const hrt_abstime &now, const FW_POSCTRL_MODE &current_mode);
/**
* @brief Compensate trim throttle for air density and vehicle weight.
+61 -13
View File
@@ -79,7 +79,7 @@ void on_time(uxrSession *session, int64_t current_time, int64_t received_timesta
}
}
MicroddsClient::MicroddsClient(Transport transport, const char *device, int baudrate, const char *host,
MicroddsClient::MicroddsClient(Transport transport, const char *device, int baudrate, const char *agent_ip,
const char *port, bool localhost_only, bool custom_participant, const char *client_namespace) :
ModuleParams(nullptr),
_localhost_only(localhost_only), _custom_participant(custom_participant),
@@ -122,9 +122,11 @@ MicroddsClient::MicroddsClient(Transport transport, const char *device, int baud
#if defined(MICRODDS_CLIENT_UDP)
_transport_udp = new uxrUDPTransport();
strncpy(_port, port, PORT_MAX_LENGTH - 1);
strncpy(_agent_ip, agent_ip, AGENT_IP_MAX_LENGTH - 1);
if (_transport_udp) {
if (uxr_init_udp_transport(_transport_udp, UXR_IPv4, host, port)) {
if (uxr_init_udp_transport(_transport_udp, UXR_IPv4, _agent_ip, _port)) {
_comm = &_transport_udp->comm;
_fd = _transport_udp->platform.poll_fd.fd;
@@ -265,7 +267,7 @@ void MicroddsClient::run()
"</dds>"
);
if (ret < 0 || ret >= TOPIC_NAME_SIZE) {
if (ret < 0 || ret >= PARTICIPANT_XML_SIZE) {
PX4_ERR("create entities failed: namespace too long");
return;
}
@@ -546,8 +548,26 @@ int MicroddsClient::task_spawn(int argc, char *argv[])
int MicroddsClient::print_status()
{
PX4_INFO("Running, %s", _connected ? "connected" : "disconnected");
PX4_INFO("Payload tx: %i B/s", _last_payload_tx_rate);
PX4_INFO("Payload rx: %i B/s", _last_payload_rx_rate);
#if defined(MICRODDS_CLIENT_UDP)
if (_transport_udp != nullptr) {
PX4_INFO("Using transport: udp");
PX4_INFO("Agent IP: %s", _agent_ip);
PX4_INFO("Agent port: %s", _port);
}
#endif
if (_transport_serial != nullptr) {
PX4_INFO("Using transport: serial");
}
if (_connected) {
PX4_INFO("Payload tx: %i B/s", _last_payload_tx_rate);
PX4_INFO("Payload rx: %i B/s", _last_payload_rx_rate);
}
return 0;
}
@@ -558,19 +578,19 @@ MicroddsClient *MicroddsClient::instantiate(int argc, char *argv[])
int ch;
const char *myoptarg = nullptr;
char port[PORT_MAX_LENGTH] = {0};
char agent_ip[AGENT_IP_MAX_LENGTH] = {0};
#if defined(MICRODDS_CLIENT_UDP)
Transport transport = Transport::Udp;
#else
Transport transport = Transport::Serial;
#endif
const char *device = nullptr;
int baudrate = 921600;
const char *port = "8888";
bool localhost_only = false;
bool custom_participant = false;
const char *ip = "127.0.0.1";
const char *client_namespace = nullptr;//"px4";
@@ -605,11 +625,11 @@ MicroddsClient *MicroddsClient::instantiate(int argc, char *argv[])
#if defined(MICRODDS_CLIENT_UDP)
case 'h':
ip = myoptarg;
snprintf(agent_ip, AGENT_IP_MAX_LENGTH, "%s", myoptarg);
break;
case 'p':
port = myoptarg;
snprintf(port, PORT_MAX_LENGTH, "%s", myoptarg);
break;
case 'l':
@@ -636,6 +656,33 @@ MicroddsClient *MicroddsClient::instantiate(int argc, char *argv[])
}
}
#if defined(MICRODDS_CLIENT_UDP)
if (port[0] == '\0') {
// no port specified, use XRCE_DDS_PRT
int32_t port_i = 0;
param_get(param_find("XRCE_DDS_PRT"), &port_i);
if (port_i < 0 || port_i > 65535) {
PX4_ERR("port must be between 0 and 65535");
return nullptr;
}
snprintf(port, PORT_MAX_LENGTH, "%u", (uint16_t)port_i);
}
if (agent_ip[0] == '\0') {
// no agent ip specified, use XRCE_DDS_AG_IP
int32_t ip_i = 0;
param_get(param_find("XRCE_DDS_AG_IP"), &ip_i);
snprintf(agent_ip, AGENT_IP_MAX_LENGTH, "%u.%u.%u.%u", static_cast<uint8_t>(((ip_i) >> 24) & 0xff),
static_cast<uint8_t>(((ip_i) >> 16) & 0xff),
static_cast<uint8_t>(((ip_i) >> 8) & 0xff),
static_cast<uint8_t>(ip_i & 0xff));
}
#endif // MICRODDS_CLIENT_UDP
if (error_flag) {
return nullptr;
}
@@ -647,7 +694,8 @@ MicroddsClient *MicroddsClient::instantiate(int argc, char *argv[])
}
}
return new MicroddsClient(transport, device, baudrate, ip, port, localhost_only, custom_participant, client_namespace);
return new MicroddsClient(transport, device, baudrate, agent_ip, port, localhost_only, custom_participant,
client_namespace);
}
int MicroddsClient::print_usage(const char *reason)
@@ -671,8 +719,8 @@ $ microdds_client start -t udp -h 127.0.0.1 -p 15555
PRINT_MODULE_USAGE_PARAM_STRING('t', "udp", "serial|udp", "Transport protocol", true);
PRINT_MODULE_USAGE_PARAM_STRING('d', nullptr, "<file:dev>", "serial device", true);
PRINT_MODULE_USAGE_PARAM_INT('b', 0, 0, 3000000, "Baudrate (can also be p:<param_name>)", true);
PRINT_MODULE_USAGE_PARAM_STRING('h', "127.0.0.1", "<IP>", "Host IP", true);
PRINT_MODULE_USAGE_PARAM_INT('p', 8888, 0, 65535, "Remote Port", true);
PRINT_MODULE_USAGE_PARAM_STRING('h', nullptr, "<IP>", "Agent IP. If not provided, defaults to XRCE_DDS_AG_IP", true);
PRINT_MODULE_USAGE_PARAM_INT('p', -1, 0, 65535, "Agent listening port. If not provided, defaults to XRCE_DDS_PRT", true);
PRINT_MODULE_USAGE_PARAM_FLAG('l', "Restrict to localhost (use in combination with ROS_LOCALHOST_ONLY=1)", true);
PRINT_MODULE_USAGE_PARAM_FLAG('c', "Use custom participant config (profile_name=\"px4_participant\")", true);
PRINT_MODULE_USAGE_PARAM_STRING('n', nullptr, nullptr, "Client DDS namespace", true);
@@ -78,6 +78,17 @@ private:
const bool _custom_participant;
const char *_client_namespace;
// max port characters (5+'\0')
static const uint8_t PORT_MAX_LENGTH = 6;
// max agent ip characters (15+'\0')
static const uint8_t AGENT_IP_MAX_LENGTH = 16;
#if defined(CONFIG_NET) || defined(__PX4_POSIX)
char _port[PORT_MAX_LENGTH];
char _agent_ip[AGENT_IP_MAX_LENGTH];
#endif
SendTopicsSubs *_subs{nullptr};
RcvTopicsPubs *_pubs{nullptr};
+19 -21
View File
@@ -1,16 +1,3 @@
# parameters to auto start
# mode (normal, minimal)
# UDP port
# max rate
# DDS DOMAIN ID
#
# multiple instances?
module_name: Micro XRCE-DDS
serial_config:
- command: |
@@ -22,13 +9,8 @@ serial_config:
microdds_client start ${XRCE_DDS_ARGS}
port_config_param:
name: XRCE_DDS_${i}_CFG
name: XRCE_DDS_CFG
group: Micro XRCE-DDS
# MAVLink instances:
# 0: Telem1 Port (Telemetry Link)
# 1: Telem2 Port (Companion Link). Disabled by default to reduce RAM usage
# 2: Board-specific / no fixed function or port
#default: [TEL1, "", ""]
supports_networking: true
parameters:
@@ -46,7 +28,7 @@ parameters:
XRCE_DDS_KEY:
description:
short: XRCE DDS key
short: XRCE DDS Session key
long: |
XRCE DDS key, must be different from zero.
In a single agent - multi client configuration, each client
@@ -56,13 +38,29 @@ parameters:
reboot_required: true
default: 1
XRCE_DDS_UDP_PRT:
XRCE_DDS_PRT:
description:
short: Micro DDS UDP Port
long: |
If ethernet enabled and selected as configuration for micro DDS,
selected udp port will be set and used.
type: int32
min: 0
max: 65535
reboot_required: true
default: 8888
requires_ethernet: true
XRCE_DDS_AG_IP:
description:
short: Micro DDS Agent IP address
long: |
If ethernet enabled and selected as configuration for micro DDS,
selected Agent IP address will be set and used.
Decimal dot notation is not supported. IP address must be provided
in int32 format. For example, 192.168.1.2 is mapped to -1062731518;
127.0.0.1 is mapped to 2130706433.
type: int32
reboot_required: true
default: 2130706433
requires_ethernet: true
@@ -1,6 +1,6 @@
/****************************************************************************
*
* Copyright (c) 2022 PX4 Development Team. All rights reserved.
* Copyright (c) 2022-2023 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -50,6 +50,7 @@ void FeasibilityChecker::reset()
_is_landed = false;
_home_alt_msl = NAN;
_home_lat_lon = matrix::Vector2d((double)NAN, (double)NAN);
_current_position_lat_lon = matrix::Vector2d((double)NAN, (double)NAN);
_vehicle_type = VehicleType::RotaryWing;
_mission_validity_failed = false;
@@ -119,6 +120,12 @@ void FeasibilityChecker::updateData()
_is_landed = land_detected.landed;
}
if (_vehicle_global_position_sub.updated()) {
vehicle_global_position_s vehicle_global_position = {};
_vehicle_global_position_sub.copy(&vehicle_global_position);
_current_position_lat_lon = matrix::Vector2d(vehicle_global_position.lat, vehicle_global_position.lon);
}
param_t handle = param_find("FW_LND_ANG");
if (handle != PARAM_INVALID) {
@@ -131,12 +138,6 @@ void FeasibilityChecker::updateData()
param_get(handle, &_param_mis_dist_1wp);
}
handle = param_find("MIS_DIST_WPS");
if (handle != PARAM_INVALID) {
param_get(handle, &_param_mis_dist_wps);
}
handle = param_find("NAV_ACC_RAD");
if (handle != PARAM_INVALID) {
@@ -195,7 +196,7 @@ void FeasibilityChecker::doCommonChecks(mission_item_s &mission_item, const int
}
if (!_distance_first_waypoint_failed) {
_distance_first_waypoint_failed = !checkDistanceToFirstWaypoint(mission_item);
_distance_first_waypoint_failed = !checkHorizontalDistanceToFirstWaypoint(mission_item);
}
if (!_below_home_alt_failed) {
@@ -601,50 +602,44 @@ bool FeasibilityChecker::checkTakeoffLandAvailable()
}
bool FeasibilityChecker::checkDistanceToFirstWaypoint(mission_item_s &mission_item)
bool FeasibilityChecker::checkHorizontalDistanceToFirstWaypoint(mission_item_s &mission_item)
{
if (_param_mis_dist_1wp <= 0.0f || !_home_lat_lon.isAllFinite()) {
/* param not set, check is ok */
return true;
}
if (_param_mis_dist_1wp > FLT_EPSILON &&
(_current_position_lat_lon.isAllFinite()) && !_first_waypoint_found &&
MissionBlock::item_contains_position(mission_item)) {
if (!_first_waypoint_found && MissionBlock::item_contains_position(mission_item)) {
_first_waypoint_found = true;
float dist_to_1wp_from_current_pos = 1e6f;
/* check distance from current position to item */
float dist_to_1wp = get_distance_to_next_waypoint(
mission_item.lat, mission_item.lon,
_home_lat_lon(0), _home_lat_lon(1));
if (_current_position_lat_lon.isAllFinite()) {
dist_to_1wp_from_current_pos = get_distance_to_next_waypoint(
mission_item.lat, mission_item.lon,
_current_position_lat_lon(0), _current_position_lat_lon(1));
}
if (dist_to_1wp < _param_mis_dist_1wp) {
if (dist_to_1wp_from_current_pos < _param_mis_dist_1wp) {
return true;
} else {
/* item is too far from home */
/* item is too far from current position */
mavlink_log_critical(_mavlink_log_pub,
"First waypoint too far away: %dm, %d max\t",
(int)dist_to_1wp, (int)_param_mis_dist_1wp);
(int)dist_to_1wp_from_current_pos, (int)_param_mis_dist_1wp);
events::send<uint32_t, uint32_t>(events::ID("navigator_mis_first_wp_too_far"), {events::Log::Error, events::LogInternal::Info},
"First waypoint too far away: {1m} (maximum: {2m})", (uint32_t)dist_to_1wp, (uint32_t)_param_mis_dist_1wp);
"First waypoint too far away: {1m} (maximum: {2m})", (uint32_t)dist_to_1wp_from_current_pos,
(uint32_t)_param_mis_dist_1wp);
return false;
}
}
/* no waypoints found in mission, then we will not fly far away */
return true;
}
bool FeasibilityChecker::checkDistancesBetweenWaypoints(const mission_item_s &mission_item)
{
if (_param_mis_dist_wps <= 0.0f) {
/* param not set, check is ok */
return true;
}
/* check only items with valid lat/lon */
if (!MissionBlock::item_contains_position(mission_item)) {
return true;
@@ -658,24 +653,8 @@ bool FeasibilityChecker::checkDistancesBetweenWaypoints(const mission_item_s &mi
_last_lat, _last_lon);
if (dist_between_waypoints > _param_mis_dist_wps) {
/* distance between waypoints is too high */
mavlink_log_critical(_mavlink_log_pub,
"Distance between waypoints too far: %d meters, %d max.\t",
(int)dist_between_waypoints, (int)_param_mis_dist_wps);
events::send<uint32_t, uint32_t>(events::ID("navigator_mis_wp_dist_too_far"), {events::Log::Error, events::LogInternal::Info},
"Distance between waypoints too far: {1m}, (maximum: {2m})", (uint32_t)dist_between_waypoints,
(uint32_t)_param_mis_dist_wps);
return false;
/* do not allow waypoints that are literally on top of each other */
/* and do not allow condition gates that are at the same position as a navigation waypoint */
} else if (dist_between_waypoints < 0.05f &&
(mission_item.nav_cmd == NAV_CMD_CONDITION_GATE || _last_cmd == NAV_CMD_CONDITION_GATE)) {
if (dist_between_waypoints < 0.05f &&
(mission_item.nav_cmd == NAV_CMD_CONDITION_GATE || _last_cmd == NAV_CMD_CONDITION_GATE)) {
/* Waypoints and gate are at the exact same position, which indicates an
* invalid mission and makes calculating the direction from one waypoint
@@ -1,6 +1,6 @@
/****************************************************************************
*
* Copyright (c) 2022 PX4 Development Team. All rights reserved.
* Copyright (c) 2022-2023 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -37,6 +37,7 @@
#include <mathlib/mathlib.h>
#include <uORB/topics/home_position.h>
#include <uORB/topics/vehicle_status.h>
#include <uORB/topics/vehicle_global_position.h>
#include <uORB/topics/vehicle_land_detected.h>
#include <uORB/Subscription.hpp>
#include <px4_platform_common/module_params.h>
@@ -96,17 +97,18 @@ private:
uORB::Subscription _home_pos_sub{ORB_ID(home_position)};
uORB::Subscription _status_sub{ORB_ID(vehicle_status)};
uORB::Subscription _land_detector_sub{ORB_ID(vehicle_land_detected)};
uORB::Subscription _vehicle_global_position_sub{ORB_ID(vehicle_global_position)};
// parameters
float _param_fw_lnd_ang{0.f};
float _param_mis_dist_1wp{0.f};
float _param_mis_dist_wps{0.f};
float _param_nav_acc_rad{0.f};
int32_t _param_mis_takeoff_land_req{0};
bool _is_landed{false};
float _home_alt_msl{NAN};
matrix::Vector2d _home_lat_lon = matrix::Vector2d((double)NAN, (double)NAN);
matrix::Vector2d _current_position_lat_lon = matrix::Vector2d((double)NAN, (double)NAN);
VehicleType _vehicle_type{VehicleType::RotaryWing};
// internal flags to keep track of which checks failed
@@ -130,7 +132,7 @@ private:
int _landing_approach_index{-1};
mission_item_s _mission_item_previous = {};
// internal checkDistanceToFirstWaypoint variables
// internal checkHorizontalDistanceToFirstWaypoint variables
bool _first_waypoint_found{false};
// internal checkDistancesBetweenWaypoints variables
@@ -172,12 +174,12 @@ private:
bool checkLandPatternValidity(mission_item_s &mission_item, const int current_index, const int last_index);
/**
* @brief Check distance to first waypoint.
* @brief Check distance to first waypoint from current vehicle position (if available).
*
* @param mission_item The current mission item
* @return False if the check failed.
*/
bool checkDistanceToFirstWaypoint(mission_item_s &mission_item);
bool checkHorizontalDistanceToFirstWaypoint(mission_item_s &mission_item);
/**
* @brief Check distances between waypoints
@@ -1,6 +1,6 @@
/****************************************************************************
*
* Copyright (C) 2022 PX4 Development Team. All rights reserved.
* Copyright (C) 2022-2023 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -33,8 +33,6 @@
#include <gtest/gtest.h>
#include "FeasibilityChecker.hpp"
#include <uORB/topics/home_position.h>
#include <uORB/topics/vehicle_land_detected.h>
#include <lib/geo/geo.h>
@@ -67,6 +65,15 @@ public:
orb_publish(ORB_ID(home_position), home_pub, &home);
}
void publishCurrentPosition(double lat, double lon)
{
vehicle_global_position_s gpos = {};
gpos.lat = lat;
gpos.lon = lon;
orb_advert_t gpos_pub = orb_advertise(ORB_ID(vehicle_global_position), &gpos);
orb_publish(ORB_ID(vehicle_global_position), gpos_pub, &gpos);
}
void publishLanded(bool landed)
{
vehicle_land_detected_s land_detected = {};
@@ -123,73 +130,47 @@ TEST_F(FeasibilityCheckerTest, mission_item_validity)
ASSERT_EQ(ret, false);
}
TEST_F(FeasibilityCheckerTest, max_dist_between_waypoints)
{
TestFeasibilityChecker checker;
checker.publishLanded(true);
param_t param = param_handle(px4::params::MIS_DIST_WPS);
float max_dist = 1000.0f;
param_set(param, &max_dist);
checker.paramsChanged();
mission_item_s mission_item = {};
mission_item.nav_cmd = NAV_CMD_WAYPOINT;
checker.processNextItem(mission_item, 0, 3);
// waypoints are within limits, check should pass
double lat_new, lon_new;
waypoint_from_heading_and_distance(mission_item.lat, mission_item.lon, 0, 999, &lat_new, &lon_new);
mission_item.lat = lat_new;
mission_item.lon = lon_new;
checker.processNextItem(mission_item, 1, 3);
ASSERT_EQ(checker.someCheckFailed(), false);
// waypoints are above limits, check should fail
waypoint_from_heading_and_distance(mission_item.lat, mission_item.lon, 0, 1001, &lat_new, &lon_new);
mission_item.lat = lat_new;
mission_item.lon = lon_new;
checker.processNextItem(mission_item, 2, 3);
ASSERT_EQ(checker.someCheckFailed(), true);
}
TEST_F(FeasibilityCheckerTest, check_dist_first_waypoint)
{
// GIVEN: MIS_DIST_1WP set to 500m
TestFeasibilityChecker checker;
checker.publishLanded(true);
checker.publishHomePosition(0, 0, 0);
param_t param = param_handle(px4::params::MIS_DIST_1WP);
float max_dist = 500.0f;
param_set(param, &max_dist);
checker.paramsChanged();
mission_item_s mission_item = {};
mission_item.nav_cmd = NAV_CMD_WAYPOINT;
double lat_new, lon_new;
waypoint_from_heading_and_distance(mission_item.lat, mission_item.lon, 0, 501, &lat_new, &lon_new);
mission_item.lat = lat_new;
mission_item.lon = lon_new;
// GIVEN: no valid Current position
// THEN: always pass
checker.processNextItem(mission_item, 0, 1);
ASSERT_EQ(checker.someCheckFailed(), false);
ASSERT_EQ(checker.someCheckFailed(), true);
// BUT WHEN: valid current position, first WP 501m away from current pos
checker.reset();
checker.publishLanded(true);
checker.publishHomePosition(0, 0, 0);
checker.publishCurrentPosition(0, 0);
waypoint_from_heading_and_distance(0, 0, 0, 501, &lat_new, &lon_new);
mission_item.lat = lat_new;
mission_item.lon = lon_new;
// THEN: fail
checker.processNextItem(mission_item, 0, 1);
ASSERT_EQ(checker.someCheckFailed(), true);
// BUT WHEN: valid current position fist WP 499m away from current
checker.reset();
checker.publishLanded(true);
checker.publishCurrentPosition(0, 0);
waypoint_from_heading_and_distance(0, 0, 0, 499, &lat_new, &lon_new);
mission_item.lat = lat_new;
mission_item.lon = lon_new;
checker.processNextItem(mission_item, 0, 1);
// THEN: pass
checker.processNextItem(mission_item, 0, 1);
ASSERT_EQ(checker.someCheckFailed(), false);
}
-1
View File
@@ -242,7 +242,6 @@ private:
DEFINE_PARAMETERS(
(ParamFloat<px4::params::MIS_DIST_1WP>) _param_mis_dist_1wp,
(ParamFloat<px4::params::MIS_DIST_WPS>) _param_mis_dist_wps,
(ParamInt<px4::params::MIS_MNT_YAW_CTL>) _param_mis_mnt_yaw_ctl
)
+3 -19
View File
@@ -73,14 +73,14 @@ PARAM_DEFINE_FLOAT(MIS_TAKEOFF_ALT, 2.5f);
PARAM_DEFINE_INT32(MIS_TKO_LAND_REQ, 0);
/**
* Maximal horizontal distance from home to first waypoint
* Maximal horizontal distance from current position to first waypoint
*
* Failsafe check to prevent running mission stored from previous flight at a new takeoff location.
* Set a value of zero or less to disable. The mission will not be started if the current
* waypoint is more distant than MIS_DIST_1WP from the home position.
* waypoint is more distant than MIS_DIST_1WP from the current position.
*
* @unit m
* @min 0
* @min -1
* @max 10000
* @decimal 1
* @increment 100
@@ -88,22 +88,6 @@ PARAM_DEFINE_INT32(MIS_TKO_LAND_REQ, 0);
*/
PARAM_DEFINE_FLOAT(MIS_DIST_1WP, 900);
/**
* Maximal horizontal distance between waypoint
*
* Failsafe check to prevent running missions which are way too big.
* Set a value of zero or less to disable. The mission will not be started if any distance between
* two subsequent waypoints is greater than MIS_DIST_WPS.
*
* @unit m
* @min 0
* @max 10000
* @decimal 1
* @increment 100
* @group Mission
*/
PARAM_DEFINE_FLOAT(MIS_DIST_WPS, 900);
/**
* Enable yaw control of the mount. (Only affects multicopters and ROI mission items)
*