Skip to content

Commit

Permalink
Rover Ackermann module (PX4#23024)
Browse files Browse the repository at this point in the history
New module handling Ackermann rover guidance and control.
Only enabled in SITL and in the rover builds for now.
  • Loading branch information
chfriedrich98 authored and vertiq-jordan committed Aug 21, 2024
1 parent 53014c0 commit 7ac6c3c
Show file tree
Hide file tree
Showing 24 changed files with 1,128 additions and 0 deletions.
7 changes: 7 additions & 0 deletions ROMFS/px4fmu_common/init.d/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,13 @@ if(CONFIG_MODULES_DIFFERENTIAL_DRIVE)
)
endif()

if(CONFIG_MODULES_ROVER_ACKERMANN)
px4_add_romfs_files(
rc.rover_ackermann_apps
rc.rover_ackermann_defaults
)
endif()

if(CONFIG_MODULES_UUV_ATT_CONTROL)
px4_add_romfs_files(
rc.uuv_apps
Expand Down
12 changes: 12 additions & 0 deletions ROMFS/px4fmu_common/init.d/airframes/50010_ackermann_rover_generic
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/bin/sh
#
# @name Generic ackermann rover
#
# @type Rover
# @class Rover
#
# @board px4_fmu-v2 exclude
# @board bitcraze_crazyflie exclude
#

. ${R}etc/init.d/rc.rover_ackermann_defaults
6 changes: 6 additions & 0 deletions ROMFS/px4fmu_common/init.d/airframes/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,12 @@ if(CONFIG_MODULES_DIFFERENTIAL_DRIVE)
)
endif()

if(CONFIG_MODULES_ROVER_ACKERMANN)
px4_add_romfs_files(
50010_ackermann_rover_generic
)
endif()

if(CONFIG_MODULES_UUV_ATT_CONTROL)
px4_add_romfs_files(
# [60000, 61000] (Unmanned) Underwater Robots
Expand Down
11 changes: 11 additions & 0 deletions ROMFS/px4fmu_common/init.d/rc.rover_ackermann_apps
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/bin/sh
# Standard apps for a ackermann drive rover.

# Start the attitude and position estimator.
ekf2 start &

# Start rover ackermann drive controller.
rover_ackermann start

# Start Land Detector.
land_detector start rover
13 changes: 13 additions & 0 deletions ROMFS/px4fmu_common/init.d/rc.rover_ackermann_defaults
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/bin/sh
# Ackermann rover parameters.

set VEHICLE_TYPE rover_ackermann
param set-default MAV_TYPE 10 # MAV_TYPE_GROUND_ROVER
param set-default CA_AIRFRAME 5 # Rover (Ackermann)
param set-default CA_R_REV 1 # Motor is assumed to be reversible
param set-default EKF2_MAG_TYPE 1 # make sure magnetometer is fused even when not flying
param set-default EKF2_GBIAS_INIT 0.01
param set-default EKF2_ANGERR_INIT 0.01
param set-default NAV_ACC_RAD 0.5 # Waypoint acceptance radius
param set-default NAV_RCL_ACT 6 # Disarm on manual control loss
param set-default COM_FAIL_ACT_T 1 # Delay before failsafe after rc loss
9 changes: 9 additions & 0 deletions ROMFS/px4fmu_common/init.d/rc.vehicle_setup
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,15 @@ then
. ${R}etc/init.d/rc.rover_differential_apps
fi

#
# Ackermann Rover setup.
#
if [ $VEHICLE_TYPE = rover_ackermann ]
then
# Start ackermann drive rover apps.
. ${R}etc/init.d/rc.rover_ackermann_apps
fi

#
# VTOL setup.
#
Expand Down
1 change: 1 addition & 0 deletions boards/px4/fmu-v5/rover.px4board
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,4 @@ CONFIG_MODULES_VTOL_ATT_CONTROL=n
CONFIG_EKF2_AUX_GLOBAL_POSITION=y
# CONFIG_EKF2_WIND is not set
CONFIG_MODULES_DIFFERENTIAL_DRIVE=y
CONFIG_MODULES_ROVER_ACKERMANN=y
2 changes: 2 additions & 0 deletions boards/px4/fmu-v5x/rover.px4board
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,5 @@ CONFIG_MODULES_MC_RATE_CONTROL=n
CONFIG_MODULES_VTOL_ATT_CONTROL=n
CONFIG_EKF2_AUX_GLOBAL_POSITION=y
# CONFIG_EKF2_WIND is not set
CONFIG_MODULES_DIFFERENTIAL_DRIVE=y
CONFIG_MODULES_ROVER_ACKERMANN=y
1 change: 1 addition & 0 deletions boards/px4/fmu-v6c/rover.px4board
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ CONFIG_MODULES_VTOL_ATT_CONTROL=n
CONFIG_EKF2_AUX_GLOBAL_POSITION=y
# CONFIG_EKF2_WIND is not set
CONFIG_MODULES_DIFFERENTIAL_DRIVE=y
CONFIG_MODULES_ROVER_ACKERMANN=y
1 change: 1 addition & 0 deletions boards/px4/fmu-v6u/rover.px4board
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ CONFIG_MODULES_VTOL_ATT_CONTROL=n
CONFIG_EKF2_AUX_GLOBAL_POSITION=y
# CONFIG_EKF2_WIND is not set
CONFIG_MODULES_DIFFERENTIAL_DRIVE=y
CONFIG_MODULES_ROVER_ACKERMANN=y
1 change: 1 addition & 0 deletions boards/px4/fmu-v6x/rover.px4board
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ CONFIG_MODULES_VTOL_ATT_CONTROL=n
CONFIG_EKF2_AUX_GLOBAL_POSITION=y
# CONFIG_EKF2_WIND is not set
CONFIG_MODULES_DIFFERENTIAL_DRIVE=y
CONFIG_MODULES_ROVER_ACKERMANN=y
1 change: 1 addition & 0 deletions boards/px4/fmu-v6xrt/rover.px4board
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ CONFIG_MODULES_VTOL_ATT_CONTROL=n
CONFIG_EKF2_AUX_GLOBAL_POSITION=y
# CONFIG_EKF2_WIND is not set
CONFIG_MODULES_DIFFERENTIAL_DRIVE=y
CONFIG_MODULES_ROVER_ACKERMANN=y
1 change: 1 addition & 0 deletions boards/px4/sitl/default.px4board
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ CONFIG_MODE_NAVIGATOR_VTOL_TAKEOFF=y
CONFIG_MODULES_PAYLOAD_DELIVERER=y
CONFIG_MODULES_RC_UPDATE=y
CONFIG_MODULES_REPLAY=y
CONFIG_MODULES_ROVER_ACKERMANN=y
CONFIG_MODULES_ROVER_POS_CONTROL=y
CONFIG_MODULES_SENSORS=y
CONFIG_COMMON_SIMULATION=y
Expand Down
1 change: 1 addition & 0 deletions msg/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ set(msg_files
RcParameterMap.msg
RegisterExtComponentReply.msg
RegisterExtComponentRequest.msg
RoverAckermannGuidanceStatus.msg
Rpm.msg
RtlStatus.msg
RtlTimeEstimate.msg
Expand Down
10 changes: 10 additions & 0 deletions msg/RoverAckermannGuidanceStatus.msg
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
uint64 timestamp # time since system start (microseconds)

float32 actual_speed # [m/s] Rover ground speed
float32 desired_speed # [m/s] Rover desired ground speed
float32 lookahead_distance # [m] Lookahead distance of pure the pursuit controller
float32 heading_error # [deg] Heading error of the pure pursuit controller
float32 pid_throttle_integral # [-1, 1] Integral of the PID for the normalized throttle to control the rover speed during missions
float32 crosstrack_error # [m] Shortest distance from the vehicle to the path

# TOPICS rover_ackermann_guidance_status
1 change: 1 addition & 0 deletions src/modules/logger/logged_topics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ void LoggedTopics::add_default_topics()
add_topic("position_setpoint_triplet", 200);
add_optional_topic("px4io_status");
add_topic("radio_status");
add_topic("rover_ackermann_guidance_status", 100);
add_topic("rtl_time_estimate", 1000);
add_topic("rtl_status", 2000);
add_optional_topic("sensor_airflow", 100);
Expand Down
47 changes: 47 additions & 0 deletions src/modules/rover_ackermann/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
############################################################################
#
# Copyright (c) 2024 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
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# 3. Neither the name PX4 nor the names of its contributors may be
# used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
############################################################################

add_subdirectory(RoverAckermannGuidance)

px4_add_module(
MODULE modules__rover_ackermann
MAIN rover_ackermann
SRCS
RoverAckermann.cpp
RoverAckermann.hpp
DEPENDS
RoverAckermannGuidance
px4_work_queue
MODULE_CONFIG
module.yaml
)
6 changes: 6 additions & 0 deletions src/modules/rover_ackermann/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
menuconfig MODULES_ROVER_ACKERMANN
bool "rover_ackermann"
default n
depends on MODULES_CONTROL_ALLOCATOR
---help---
Enable support for control of ackermann drive rovers
162 changes: 162 additions & 0 deletions src/modules/rover_ackermann/RoverAckermann.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
/****************************************************************************
*
* Copyright (c) 2024 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
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/

#include "RoverAckermann.hpp"

using namespace time_literals;
using namespace matrix;

RoverAckermann::RoverAckermann() :
ModuleParams(nullptr),
ScheduledWorkItem(MODULE_NAME, px4::wq_configurations::rate_ctrl)
{
updateParams();
}

bool RoverAckermann::init()
{
ScheduleOnInterval(10_ms); // 100 Hz
return true;
}

void RoverAckermann::updateParams()
{
ModuleParams::updateParams();
}

void RoverAckermann::Run()
{
if (should_exit()) {
ScheduleClear();
exit_and_cleanup();
}

// uORB subscriber updates
if (_parameter_update_sub.updated()) {
updateParams();
}

if (_vehicle_status_sub.updated()) {
vehicle_status_s vehicle_status;
_vehicle_status_sub.copy(&vehicle_status);
_nav_state = vehicle_status.nav_state;
}

// Navigation modes
switch (_nav_state) {
case vehicle_status_s::NAVIGATION_STATE_MANUAL: {
manual_control_setpoint_s manual_control_setpoint{};

if (_manual_control_setpoint_sub.update(&manual_control_setpoint)) {
_motor_setpoint.steering = manual_control_setpoint.roll;
_motor_setpoint.throttle = manual_control_setpoint.throttle;
}

} break;

case vehicle_status_s::NAVIGATION_STATE_AUTO_MISSION:
_motor_setpoint = _ackermann_guidance.purePursuit();
break;

default: // Unimplemented nav states will stop the rover
_motor_setpoint.steering = 0.f;
_motor_setpoint.throttle = 0.f;
break;
}

hrt_abstime now = hrt_absolute_time();

// Publish to wheel motors
actuator_motors_s actuator_motors{};
actuator_motors.reversible_flags = _param_r_rev.get();
actuator_motors.control[0] = _motor_setpoint.throttle;
actuator_motors.timestamp = now;
_actuator_motors_pub.publish(actuator_motors);

// Publish to servo
actuator_servos_s actuator_servos{};
actuator_servos.control[0] = _motor_setpoint.steering;
actuator_servos.timestamp = now;
_actuator_servos_pub.publish(actuator_servos);
}

int RoverAckermann::task_spawn(int argc, char *argv[])
{
RoverAckermann *instance = new RoverAckermann();

if (instance) {
_object.store(instance);
_task_id = task_id_is_work_queue;

if (instance->init()) {
return PX4_OK;
}

} else {
PX4_ERR("alloc failed");
}

delete instance;
_object.store(nullptr);
_task_id = -1;

return PX4_ERROR;
}

int RoverAckermann::custom_command(int argc, char *argv[])
{
return print_usage("unknown command");
}

int RoverAckermann::print_usage(const char *reason)
{
if (reason) {
PX4_ERR("%s\n", reason);
}

PRINT_MODULE_DESCRIPTION(
R"DESCR_STR(
### Description
Rover state machine.
)DESCR_STR");

PRINT_MODULE_USAGE_NAME("rover_ackermann", "controller");
PRINT_MODULE_USAGE_COMMAND("start");
PRINT_MODULE_USAGE_DEFAULT_COMMANDS();
return 0;
}

extern "C" __EXPORT int rover_ackermann_main(int argc, char *argv[])
{
return RoverAckermann::main(argc, argv);
}
Loading

0 comments on commit 7ac6c3c

Please sign in to comment.