mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-10-24 00:53:34 +08:00
Implement Pacakge delivery via Gripper during mission
This feature allows user to use a Gripper type pacakge delivery mechanism on a drone to trigger the delivery during a mission via the mission item `DO_GRIPPER`. This is a minimal change that is intended to have simplest pacakge delivery feature on PX4, however the future scope would extend this feature out of Navigator, and rather move towards a federated PX4 (flight-mode flexibility) architecture. But until then, this will serve the purpose. Update Tools/sitl_gazebo submodule to remove sdf file overwrite error - There was an error happening due to .sdf file being overwritten, it was caused by a wrongfully added. sdf file. - This update pulls in the PR commit: https://github.com/Auterion/sitl_gazebo/pull/147 Initial cut on supporing PAYLOAD_PLACE mission item Tidy and comment on navigation.h to clarify mission item definition - Convert vehicle command ack subscription data type to SubscriptionData, to not care about having a dedicated struct for copying the latest data - Tidy and comment on navigation.h to clarify the definition of mission_item_s, which is confusing as it is an intergration of MAVLink Standard into PX4's internal Mission Item structure Rename mission_block's mission item reached function & cleanup navigator - Isolated Handle Vehicle Commands function inside the Navigator - Rename mission_block's mission item reached function to 'reached or completed', as the navigation command can also be an action (e.g. DO_SET_SERVO, which doesn't make sense to refer to as 'reached' when we have successfully done executed the command) Include MAVLink PR commit to include payload_drop message More changes to add payload_drop MAVLink message support - Comitting for testing purposes Add mission item payload_drop to vehicle command payload drop link - Now with a mission item with the nav_cmd set to 'payload drop', the appropriate 'payload drop' vehicle command will be issued Make Payload drop executable via Mission Plan Implement payload_drop module to simulate payload delivery - Simple module that acknowledges the payload drop vehicle command after certain time, to simulate a successful delivery Additional changes - payload drop module not working yet - Need to do more thread stuff to make it work :( Fix Payload Drop enum mismatch in vehicle_command enums - First functional Payload Drop Implementation MVP - Simple Ack & resuming mission from Navigator tested successfully Hold the position while executing payload drop mission item - Still the position hold is not solid, maybe I am missing something in the position setpoint part and all the internal implications of Navigator :( Add DO_WINCH command support Some fixes after rebase on develop branch - Some missed brackets - Some comment edits, etc Add DO_WINCH command support - Still has a problem of flying away from the waypoint while the DO_WINCH is being executed, probably position setpoint related stuff :( Apply braking of the vehicle for DO_WINCH command - Copies the behavior of NAV_CMD_DELAY, which executes a smooth, braking behavior when executing the delay because of the braking condition in `set_mission_items` function - This will not apply to Fixed wings - The payload deploy getting triggered may be too early, as right now as soon as the vehicle approaches the waypoint within the acceptance threshold, the payload gets deployed Add DO_GRIPPER support Implement Gripper actual Hardware triggering support - Currently not working, possibly in the mixer there's a bug - Implemented the publishing of actuator_controls_1 uORB topic - Implemented the test command for the payload_drop module, to test the grpiper functionality - Edited px4board file to include the payload_drop module - Added Holybro X500 V2 airframe file, to enable testing on X500 V2 - Created new Quad X Payload Delivery mixer, which maps the actuator controls 1 topic's data into the MAIN pin 5 output Make Payload Drop Gripper Work - Initialization of the Gripper position to CLOSED on Constructor of the payload_drop module - Setting the OPEN and CLOSED value to the appropriate actuator controls input Set vehicle_command_ack message's timestamp correctly - By not setting the timestamp, the ack commands were not correctly graphed in PlotJuggler! Rename payload drop module to payload deliverer - I think it's a more complex name (harder to type), but more generic Add Gripper class (WIP) Add Gripper class functionalities - Add gripper uORB message - Add gripper state machine Use Gripper class as main interface in payload_deliverer - Utilizes Gripper class functions for doing Gripper functionality Remove mixer based package delivery trigger logic - Remove custom mixer files that mapped actuator controls to outputs statically Additional improvements of the payload_deliverer Fix payload_deliverer module not starting - _task_id wasn't geting set appropriately in task_spawn function, which led to runtime failure Add Gripper Function to mixer_module - Still not showing up as function mapping in QGC, needs fix Add parameters to control gripper behavior - Now user can enable / disable gripper - Also select which type of gripper to use Applying review from nuno Remove timeout fetching from mission item and use gripper's timeout - Previously, it was planned to use a custom DO_GRIPPER and DO_WINCH MAVLink message definitions with information on timeout, but since now we are using original message definition, only relevant timeout information is defined in the payload_deliverer class - This change brings in the timeout parameter to the Navigator, which then sets the timeout in the mission_block class level, which then processes the timeout logic Make payload deployment work for Allmend test :P Support gripper open/close test commands in payload_deliverer Move enum definition for GRIPPER_ACTION to vehicle_command.msg Remove double call for ` ${R}etc/init.d/rc.vehicle_setup` - Was introduced during the rebase - Was causing module already running & uORB topic can't be advertised errors Fix format via `make format` command Modify S500 airframe file to use for control allocation usage - Added Control allocation related parameters as default to not have it reset every time the airframe is selected Implement mission specific payload deploy timeout and more changes Switch payload_deliverer to run on work queue Remove unnecessary files - Airframe changes from enabling control allocation are removed Address review comments - Remove debug messages - Remove unnecessary or verbose comments & code - Properly call parameter_update() function Switch payload_deliverer to scheduled interval work item & refactor - Switch to Schedeuled on Interval Work Item, as previous vehicle command subscription callback based behavior led to vehicle comamnd ack not being sent accordingly (since the Run() wouldn't be called unless there's a new vehicle command), leading to ack command not being sent out - Also, old vehicle commands were getting fetched due to the subscription callback as well, which was removed with this patch - Fix the wrong population of floating point param2 field of vehicle command by int8_t type gripper action by creating dedicated function - Refactor and add comments to increase readability Add gripper::grabbing() method and handle this in parameter update - Previously, the intermediate state 'grabbing' was not considered, and when the parameter update was called after the first initialization of the gripper, the grab() function was being called again, which would produce unnecessary duplicate vehicle command. - Also replaced direct .grab() access to sending vehicle comamnd, which unifies the gripper actuation mechanism through vehicle commands. Navigator: Change SubscriptionData to Subscription to reduce memory usage - Also removed unused vehicle command ack sub PayloadDeliverer: Remove unnecessary changes & Bring back vehicle_command sub cb
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
############################################################################
|
||||
#
|
||||
# Copyright (c) 2022 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.
|
||||
#
|
||||
############################################################################
|
||||
px4_add_module(
|
||||
MODULE modules__payload_deliverer
|
||||
MAIN payload_deliverer
|
||||
SRCS
|
||||
payload_deliverer.cpp
|
||||
gripper.cpp
|
||||
MODULE_CONFIG
|
||||
module.yaml
|
||||
COMPILE_FLAGS
|
||||
#-DDEBUG_BUILD
|
||||
DEPENDS
|
||||
px4_work_queue
|
||||
)
|
||||
@@ -0,0 +1,5 @@
|
||||
menuconfig MODULES_PAYLOAD_DELIVERER
|
||||
bool "payload_deliverer"
|
||||
default n
|
||||
---help---
|
||||
Enable payload_deliverer module
|
||||
@@ -0,0 +1,129 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2022 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 "gripper.h"
|
||||
|
||||
void Gripper::init(const GripperConfig &config)
|
||||
{
|
||||
switch (config.type) {
|
||||
case GripperConfig::GripperType::SERVO:
|
||||
break;
|
||||
|
||||
case GripperConfig::GripperType::UNDEFINED:
|
||||
|
||||
// FALL THROUGH
|
||||
default:
|
||||
_valid = false;
|
||||
return;
|
||||
}
|
||||
|
||||
switch (config.sensor) {
|
||||
case GripperConfig::GripperSensorType::ENCODER:
|
||||
// Handle encoder sensor setup
|
||||
_has_feedback_sensor = true;
|
||||
break;
|
||||
|
||||
case GripperConfig::GripperSensorType::NONE:
|
||||
default:
|
||||
// No feedback sensor
|
||||
_has_feedback_sensor = false;
|
||||
break;
|
||||
}
|
||||
|
||||
_timeout_us = config.timeout_us;
|
||||
|
||||
// We have valid gripper type & sensor configuration
|
||||
_valid = true;
|
||||
}
|
||||
|
||||
void Gripper::grab()
|
||||
{
|
||||
publish_gripper_command(gripper_s::COMMAND_GRAB);
|
||||
_state = GripperState::GRABBING;
|
||||
_last_command_time = hrt_absolute_time();
|
||||
}
|
||||
|
||||
void Gripper::release()
|
||||
{
|
||||
publish_gripper_command(gripper_s::COMMAND_RELEASE);
|
||||
_state = GripperState::RELEASING;
|
||||
_last_command_time = hrt_absolute_time();
|
||||
}
|
||||
|
||||
void Gripper::update()
|
||||
{
|
||||
const bool command_timed_out = (hrt_elapsed_time(&_last_command_time) >= _timeout_us);
|
||||
|
||||
// Handle transition from intermediate state to definite state
|
||||
switch (_state) {
|
||||
case GripperState::GRABBING:
|
||||
if (_has_feedback_sensor) {
|
||||
// Handle feedback sensor input, return true for now (not supported)
|
||||
_state = GripperState::GRABBED;
|
||||
break;
|
||||
}
|
||||
|
||||
if (command_timed_out) {
|
||||
_state = GripperState::GRABBED;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case GripperState::RELEASING:
|
||||
if (_has_feedback_sensor) {
|
||||
// Handle feedback sensor input, return true for now (not supported)
|
||||
_released_state_cache = true;
|
||||
_state = GripperState::RELEASED;
|
||||
break;
|
||||
}
|
||||
|
||||
if (command_timed_out) {
|
||||
_released_state_cache = true;
|
||||
_state = GripperState::RELEASED;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
// DO NOTHING
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Gripper::publish_gripper_command(const int8_t gripper_command)
|
||||
{
|
||||
gripper_s gripper{};
|
||||
gripper.timestamp = hrt_absolute_time();
|
||||
gripper.command = gripper_command;
|
||||
_gripper_pub.publish(gripper);
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2022 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 <drivers/drv_hrt.h>
|
||||
|
||||
#include <uORB/Publication.hpp>
|
||||
#include <uORB/topics/gripper.h>
|
||||
|
||||
using namespace time_literals;
|
||||
|
||||
/**
|
||||
* Griper class to handle functionality of using a Gripper
|
||||
*/
|
||||
|
||||
typedef struct GripperConfig {
|
||||
enum class GripperType {
|
||||
UNDEFINED = -1,
|
||||
SERVO = 0,
|
||||
};
|
||||
|
||||
GripperType type{GripperType::UNDEFINED};
|
||||
|
||||
// Gripper state feedback sensor type
|
||||
enum class GripperSensorType {
|
||||
NONE = -1,
|
||||
ENCODER,
|
||||
};
|
||||
|
||||
GripperSensorType sensor{GripperSensorType::NONE};
|
||||
|
||||
hrt_abstime timeout_us{0};
|
||||
|
||||
} GripperConfig;
|
||||
|
||||
enum class GripperState {
|
||||
IDLE = 0,
|
||||
GRABBING,
|
||||
GRABBED,
|
||||
RELEASING,
|
||||
RELEASED
|
||||
};
|
||||
|
||||
class Gripper
|
||||
{
|
||||
public:
|
||||
Gripper() = default;
|
||||
|
||||
// Initialize the gripper
|
||||
void init(const GripperConfig &config);
|
||||
|
||||
// Actuate the gripper to the grab position
|
||||
void grab();
|
||||
|
||||
// Actuate the gripper to release position
|
||||
void release();
|
||||
|
||||
// Update gripper state
|
||||
void update();
|
||||
|
||||
// Returns true if in grabbed position either sensed or timeout based
|
||||
bool grabbed() { return _state == GripperState::GRABBED; }
|
||||
bool grabbing() { return _state == GripperState::GRABBING; }
|
||||
|
||||
// Returns true if in released position either sensed or timeout based
|
||||
bool released() { return _state == GripperState::RELEASED; }
|
||||
|
||||
// Returns true only once after the state transitioned into released
|
||||
// Used for sending vehicle command ack only when the gripper actually releases
|
||||
// in payload deliverer
|
||||
bool released_read_once()
|
||||
{
|
||||
if (_released_state_cache) {
|
||||
_released_state_cache = false;
|
||||
return true;
|
||||
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Returns true if Gripper output function is assigned properly
|
||||
bool is_valid() const { return _valid; }
|
||||
|
||||
private:
|
||||
// Internal function to send gripper command via uORB
|
||||
void publish_gripper_command(const int8_t gripper_command);
|
||||
|
||||
// Internal settings
|
||||
bool _valid{false};
|
||||
bool _has_feedback_sensor{false};
|
||||
hrt_abstime _timeout_us{0};
|
||||
|
||||
// Internal state
|
||||
GripperState _state{GripperState::IDLE};
|
||||
hrt_abstime _last_command_time{0};
|
||||
bool _released_state_cache{false}; // Cached flag that is set once gripper release was successful, gets reset once read
|
||||
|
||||
uORB::Publication<gripper_s> _gripper_pub{ORB_ID(gripper)};
|
||||
};
|
||||
@@ -0,0 +1,36 @@
|
||||
module_name: payload_deliverer
|
||||
|
||||
parameters:
|
||||
- group: Payload Deliverer
|
||||
definitions:
|
||||
|
||||
# Gripper configuration
|
||||
PD_GRIPPER_EN:
|
||||
description:
|
||||
short: Enable Gripper actuation in Payload Deliverer
|
||||
type: boolean
|
||||
default: 0
|
||||
|
||||
PD_GRIPPER_TYPE:
|
||||
description:
|
||||
short: Type of Gripper (Servo, etc.)
|
||||
type: enum
|
||||
values:
|
||||
-1: Undefined
|
||||
0: Servo
|
||||
min: -1
|
||||
max: 0
|
||||
default: 0
|
||||
|
||||
PD_GRIPPER_TO:
|
||||
description:
|
||||
short: Timeout for successful gripper actuation acknowledgement
|
||||
long: |
|
||||
Maximum time Gripper will wait while the successful griper actuation isn't recognised.
|
||||
If the gripper has no feedback sensor, it will simply wait for
|
||||
this time before considering gripper actuation successful and publish a
|
||||
'vehicle_command_ack' signaling successful gripper action
|
||||
type: float
|
||||
unit: s
|
||||
min: 0
|
||||
default: 3
|
||||
@@ -0,0 +1,279 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2022 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 "payload_deliverer.h"
|
||||
|
||||
PayloadDeliverer::PayloadDeliverer()
|
||||
: ModuleParams(nullptr),
|
||||
ScheduledWorkItem(MODULE_NAME, px4::wq_configurations::lp_default)
|
||||
{
|
||||
}
|
||||
|
||||
bool PayloadDeliverer::init()
|
||||
{
|
||||
ScheduleOnInterval(1_s);
|
||||
|
||||
// Additionallly to 1Hz scheduling, add cb for vehicle_command message
|
||||
if (!_vehicle_command_sub.registerCallback()) {
|
||||
PX4_ERR("callback registration failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
initialize_gripper();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PayloadDeliverer::initialize_gripper()
|
||||
{
|
||||
// If gripper instance is invalid, try initializing it
|
||||
if (!_gripper.is_valid() && _param_gripper_enable.get()) {
|
||||
GripperConfig config{};
|
||||
config.type = (GripperConfig::GripperType)_param_gripper_type.get();
|
||||
config.sensor = GripperConfig::GripperSensorType::NONE; // Feedback sensor isn't supported for now
|
||||
config.timeout_us = hrt_abstime(_param_gripper_timeout_s.get() * 1000000ULL);
|
||||
_gripper.init(config);
|
||||
}
|
||||
|
||||
// NOTE: Support for changing gripper sensor type / gripper type configuration when
|
||||
// the parameter change is detected isn't added as we don't have actual use case for that
|
||||
// yet!
|
||||
|
||||
if (!_gripper.is_valid()) {
|
||||
PX4_DEBUG("Gripper object initialization invalid!");
|
||||
return false;
|
||||
|
||||
} else {
|
||||
_gripper.update();
|
||||
|
||||
// If gripper wasn't commanded to go to grab position, command.
|
||||
if (!_gripper.grabbed() && !_gripper.grabbing()) {
|
||||
PX4_DEBUG("Gripper intialize: putting to grab position!");
|
||||
send_gripper_vehicle_command(vehicle_command_s::GRIPPER_ACTION_GRAB);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void PayloadDeliverer::parameter_update()
|
||||
{
|
||||
updateParams();
|
||||
initialize_gripper();
|
||||
}
|
||||
|
||||
void PayloadDeliverer::Run()
|
||||
{
|
||||
const hrt_abstime now = hrt_absolute_time();
|
||||
vehicle_command_s vcmd{};
|
||||
|
||||
if (should_exit()) {
|
||||
ScheduleClear();
|
||||
_vehicle_command_sub.unregisterCallback();
|
||||
exit_and_cleanup();
|
||||
return;
|
||||
}
|
||||
|
||||
if (_parameter_update_sub.updated()) {
|
||||
parameter_update_s param_update_dummy;
|
||||
_parameter_update_sub.copy(¶m_update_dummy);
|
||||
parameter_update();
|
||||
}
|
||||
|
||||
if (_vehicle_command_sub.update(&vcmd)) {
|
||||
handle_vehicle_command(now, &vcmd);
|
||||
|
||||
} else {
|
||||
handle_vehicle_command(now);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void PayloadDeliverer::handle_vehicle_command(const hrt_abstime &now, const vehicle_command_s *vehicle_command)
|
||||
{
|
||||
if (!_gripper.is_valid()) {
|
||||
PX4_WARN("Gripper instance not valid but vehicle command was received. Gripper won't work!");
|
||||
return;
|
||||
}
|
||||
|
||||
_gripper.update();
|
||||
|
||||
// Process successful gripper release acknowledgement
|
||||
if (_gripper.released_read_once()) {
|
||||
vehicle_command_ack_s vcmd_ack{};
|
||||
vcmd_ack.timestamp = now;
|
||||
vcmd_ack.command = vehicle_command_s::VEHICLE_CMD_DO_GRIPPER;
|
||||
vcmd_ack.result = vehicle_command_ack_s::VEHICLE_CMD_RESULT_ACCEPTED;
|
||||
_vehicle_command_ack_pub.publish(vcmd_ack);
|
||||
PX4_DEBUG("Payload Drop Successful Ack Sent!");
|
||||
}
|
||||
|
||||
// If there's no vehicle command to process, just return
|
||||
if (vehicle_command == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Process DO_GRIPPER vehicle command
|
||||
if (vehicle_command->command == vehicle_command_s::VEHICLE_CMD_DO_GRIPPER) {
|
||||
const int32_t gripper_action = *(int32_t *)&vehicle_command->param2; // Convert the action to integer
|
||||
|
||||
switch (gripper_action) {
|
||||
case vehicle_command_s::GRIPPER_ACTION_GRAB:
|
||||
_gripper.grab();
|
||||
break;
|
||||
|
||||
case vehicle_command_s::GRIPPER_ACTION_RELEASE:
|
||||
_gripper.release();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool PayloadDeliverer::send_gripper_vehicle_command(const int32_t gripper_action)
|
||||
{
|
||||
vehicle_command_s vcmd;
|
||||
vcmd.timestamp = hrt_absolute_time();
|
||||
vcmd.command = vehicle_command_s::VEHICLE_CMD_DO_GRIPPER;
|
||||
*(int32_t *)&vcmd.param2 = gripper_action;
|
||||
return _vehicle_command_pub.publish(vcmd);
|
||||
}
|
||||
|
||||
void PayloadDeliverer::gripper_test()
|
||||
{
|
||||
if (!_gripper.is_valid()) {
|
||||
PX4_DEBUG("Gripper is not initialized correctly!");
|
||||
return;
|
||||
}
|
||||
|
||||
PX4_INFO("Test: Opening the Gripper!");
|
||||
send_gripper_vehicle_command(vehicle_command_s::GRIPPER_ACTION_RELEASE);
|
||||
|
||||
px4_usleep(5_s);
|
||||
|
||||
PX4_INFO("Test: Closing the Gripper!");
|
||||
send_gripper_vehicle_command(vehicle_command_s::GRIPPER_ACTION_GRAB);
|
||||
}
|
||||
|
||||
void PayloadDeliverer::gripper_open()
|
||||
{
|
||||
if (!_gripper.is_valid()) {
|
||||
PX4_DEBUG("Gripper is not initialized correctly!");
|
||||
return;
|
||||
}
|
||||
|
||||
send_gripper_vehicle_command(vehicle_command_s::GRIPPER_ACTION_RELEASE);
|
||||
}
|
||||
|
||||
void PayloadDeliverer::gripper_close()
|
||||
{
|
||||
if (!_gripper.is_valid()) {
|
||||
PX4_DEBUG("Gripper is not initialized correctly!");
|
||||
return;
|
||||
}
|
||||
|
||||
send_gripper_vehicle_command(vehicle_command_s::GRIPPER_ACTION_GRAB);
|
||||
}
|
||||
|
||||
int PayloadDeliverer::custom_command(int argc, char *argv[])
|
||||
{
|
||||
if (argc >= 1) {
|
||||
// Tests the basic payload open / close ability
|
||||
if (strcmp(argv[0], "gripper_test") == 0) {
|
||||
get_instance()->gripper_test();
|
||||
return 0;
|
||||
|
||||
} else if (strcmp(argv[0], "gripper_open") == 0) {
|
||||
get_instance()->gripper_open();
|
||||
return 0;
|
||||
|
||||
} else if (strcmp(argv[0], "gripper_close") == 0) {
|
||||
get_instance()->gripper_close();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return print_usage("Unrecognized command");
|
||||
}
|
||||
|
||||
int PayloadDeliverer::print_usage(const char *reason)
|
||||
{
|
||||
if (reason) {
|
||||
PX4_WARN("%s\n", reason);
|
||||
}
|
||||
|
||||
PRINT_MODULE_DESCRIPTION(
|
||||
R"DESCR_STR(
|
||||
### Description
|
||||
Handles payload delivery with either Gripper or a Winch with an appropriate timeout / feedback sensor setting,
|
||||
and communicates back the delivery result as an acknowledgement internally
|
||||
|
||||
)DESCR_STR");
|
||||
|
||||
PRINT_MODULE_USAGE_NAME("payload_deliverer", "command");
|
||||
PRINT_MODULE_USAGE_COMMAND("start");
|
||||
PRINT_MODULE_USAGE_COMMAND_DESCR("gripper_test", "Tests the Gripper's release & grabbing sequence");
|
||||
PRINT_MODULE_USAGE_COMMAND_DESCR("gripper_open", "Opens the gripper");
|
||||
PRINT_MODULE_USAGE_COMMAND_DESCR("gripper_close", "Closes the gripper");
|
||||
PRINT_MODULE_USAGE_DEFAULT_COMMANDS();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int PayloadDeliverer::task_spawn(int argc, char *argv[])
|
||||
{
|
||||
PayloadDeliverer *instance = new PayloadDeliverer();
|
||||
|
||||
if (instance) {
|
||||
_object.store(instance);
|
||||
_task_id = task_id_is_work_queue;
|
||||
|
||||
if (instance->init()) {
|
||||
return PX4_OK;
|
||||
}
|
||||
|
||||
} else {
|
||||
PX4_ERR("Alloc failed");
|
||||
}
|
||||
|
||||
// Cleanup instance in memory and mark this module as invalid to run
|
||||
delete instance;
|
||||
_object.store(nullptr);
|
||||
_task_id = -1;
|
||||
|
||||
return PX4_ERROR;
|
||||
}
|
||||
|
||||
int payload_deliverer_main(int argc, char *argv[])
|
||||
{
|
||||
return PayloadDeliverer::main(argc, argv);
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2022 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file payload_deliverer.h
|
||||
* @author Junwoo Hwang (junwoo091400@gmail.com)
|
||||
*/
|
||||
#include "gripper.h"
|
||||
|
||||
#include <drivers/drv_hrt.h>
|
||||
#include <px4_platform_common/module.h>
|
||||
#include <px4_platform_common/module_params.h>
|
||||
#include <px4_platform_common/px4_work_queue/ScheduledWorkItem.hpp>
|
||||
|
||||
#include <uORB/Publication.hpp>
|
||||
#include <uORB/Subscription.hpp>
|
||||
#include <uORB/SubscriptionCallback.hpp>
|
||||
|
||||
#include <uORB/topics/vehicle_command.h>
|
||||
#include <uORB/topics/vehicle_command_ack.h>
|
||||
#include <uORB/topics/actuator_controls.h>
|
||||
#include <uORB/topics/parameter_update.h>
|
||||
|
||||
using namespace time_literals;
|
||||
|
||||
extern "C" __EXPORT int payload_deliverer_main(int argc, char *argv[]);
|
||||
|
||||
/**
|
||||
* @brief Payload Deliverer Module
|
||||
*
|
||||
* Activates a winch / gripper when the DO_WINCH or DO_GRIPPER vehicle command is received,
|
||||
* after which the vehicle_command_ack command gets sent upon successful confirmation
|
||||
* of the payload deployment.
|
||||
*
|
||||
* The module runs based on having a subscription callback mechanism to the 'vehicle_command' topic
|
||||
* as it only needs to run when we receive the relevant vehicle command.
|
||||
*
|
||||
* This module communicates with the Navigator which handles publishing such vehicle commands.
|
||||
*/
|
||||
class PayloadDeliverer : public ModuleBase<PayloadDeliverer>, public ModuleParams, public px4::ScheduledWorkItem
|
||||
{
|
||||
public:
|
||||
PayloadDeliverer();
|
||||
|
||||
/** @see ModuleBase **/
|
||||
static int task_spawn(int argc, char *argv[]);
|
||||
static int custom_command(int argc, char *argv[]);
|
||||
static int print_usage(const char *reason = nullptr);
|
||||
|
||||
// Initializes the module
|
||||
bool init();
|
||||
|
||||
// Gripper test commands provoked by custom_command() via CLI interface
|
||||
void gripper_test();
|
||||
void gripper_open();
|
||||
void gripper_close();
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Main Run function that runs when subscription callback is triggered
|
||||
*/
|
||||
void Run() override;
|
||||
|
||||
/**
|
||||
* @brief Called to update the parameters and initialize gripper instance if necessary
|
||||
*/
|
||||
void parameter_update();
|
||||
|
||||
/**
|
||||
* @brief Initialize gripper with current parameter settings
|
||||
*/
|
||||
bool initialize_gripper();
|
||||
|
||||
/**
|
||||
* @brief Commands the payload delivery mechanism based on the received vehicle command
|
||||
*
|
||||
* Also handle vehicle command acknowledgement once the delivery is confirmed from the mechanism
|
||||
*/
|
||||
void handle_vehicle_command(const hrt_abstime &now, const vehicle_command_s *vehicle_command = nullptr);
|
||||
|
||||
/**
|
||||
* @brief Send DO_GRIPPER vehicle command with specified gripper action correctly formatted
|
||||
*
|
||||
* This is useful since vehicle command uses float types for param2, where the gripper action is
|
||||
* specified, but we want to use int32_t data type for it instead, hence filling out the floating
|
||||
* point data structure like integer type is necessary.
|
||||
*
|
||||
* @param gripper_command GRIPPER_ACTION_GRAB or GRIPPER_ACTION_RELEASE
|
||||
*/
|
||||
bool send_gripper_vehicle_command(const int32_t gripper_action);
|
||||
|
||||
Gripper _gripper; // Gripper object to handle gripper action
|
||||
|
||||
// Subscription
|
||||
uORB::SubscriptionCallbackWorkItem _vehicle_command_sub{this, ORB_ID(vehicle_command)};
|
||||
uORB::SubscriptionInterval _parameter_update_sub{ORB_ID(parameter_update), 1_s}; // subscription limited to 1 Hz updates
|
||||
|
||||
// Publications
|
||||
uORB::Publication<vehicle_command_ack_s> _vehicle_command_ack_pub{ORB_ID(vehicle_command_ack)};
|
||||
uORB::Publication<vehicle_command_s> _vehicle_command_pub{ORB_ID(vehicle_command)};
|
||||
|
||||
DEFINE_PARAMETERS(
|
||||
(ParamFloat<px4::params::PD_GRIPPER_TO>) _param_gripper_timeout_s,
|
||||
(ParamInt<px4::params::PD_GRIPPER_TYPE>) _param_gripper_type,
|
||||
(ParamBool<px4::params::PD_GRIPPER_EN>) _param_gripper_enable
|
||||
)
|
||||
};
|
||||
Reference in New Issue
Block a user