mirror of
https://github.com/ArduPilot/ardupilot
synced 2025-01-03 06:28:27 -04:00
AP_DDS: add REP-147 Global Position Control
Signed-off-by: Ryan Friedman <ryanfriedman5410+github@gmail.com>
This commit is contained in:
parent
cd72dcb73f
commit
da976300d1
@ -44,6 +44,7 @@ static constexpr uint16_t DELAY_PING_MS = 500;
|
|||||||
sensor_msgs_msg_Joy AP_DDS_Client::rx_joy_topic {};
|
sensor_msgs_msg_Joy AP_DDS_Client::rx_joy_topic {};
|
||||||
tf2_msgs_msg_TFMessage AP_DDS_Client::rx_dynamic_transforms_topic {};
|
tf2_msgs_msg_TFMessage AP_DDS_Client::rx_dynamic_transforms_topic {};
|
||||||
geometry_msgs_msg_TwistStamped AP_DDS_Client::rx_velocity_control_topic {};
|
geometry_msgs_msg_TwistStamped AP_DDS_Client::rx_velocity_control_topic {};
|
||||||
|
ardupilot_msgs_msg_GlobalPosition AP_DDS_Client::rx_global_position_control_topic {};
|
||||||
|
|
||||||
|
|
||||||
const AP_Param::GroupInfo AP_DDS_Client::var_info[] {
|
const AP_Param::GroupInfo AP_DDS_Client::var_info[] {
|
||||||
@ -391,6 +392,8 @@ void AP_DDS_Client::update_topic(geographic_msgs_msg_GeoPoseStamped& msg)
|
|||||||
if (ahrs.get_location(loc)) {
|
if (ahrs.get_location(loc)) {
|
||||||
msg.pose.position.latitude = loc.lat * 1E-7;
|
msg.pose.position.latitude = loc.lat * 1E-7;
|
||||||
msg.pose.position.longitude = loc.lng * 1E-7;
|
msg.pose.position.longitude = loc.lng * 1E-7;
|
||||||
|
// TODO this is assumed to be absolute frame in WGS-84 as per the GeoPose message definition in ROS.
|
||||||
|
// Use loc.get_alt_frame() to convert if necessary.
|
||||||
msg.pose.position.altitude = loc.alt * 0.01; // Transform from cm to m
|
msg.pose.position.altitude = loc.alt * 0.01; // Transform from cm to m
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -502,6 +505,19 @@ void AP_DDS_Client::on_topic(uxrSession* uxr_session, uxrObjectId object_id, uin
|
|||||||
if (!AP_DDS_External_Control::handle_velocity_control(rx_velocity_control_topic)) {
|
if (!AP_DDS_External_Control::handle_velocity_control(rx_velocity_control_topic)) {
|
||||||
// TODO #23430 handle velocity control failure through rosout, throttled.
|
// TODO #23430 handle velocity control failure through rosout, throttled.
|
||||||
}
|
}
|
||||||
|
#endif // AP_EXTERNAL_CONTROL_ENABLED
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case topics[to_underlying(TopicIndex::GLOBAL_POSITION_SUB)].dr_id.id: {
|
||||||
|
const bool success = ardupilot_msgs_msg_GlobalPosition_deserialize_topic(ub, &rx_global_position_control_topic);
|
||||||
|
if (success == false) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if AP_EXTERNAL_CONTROL_ENABLED
|
||||||
|
if (!AP_DDS_External_Control::handle_global_position_control(rx_global_position_control_topic)) {
|
||||||
|
// TODO #23430 handle global position control failure through rosout, throttled.
|
||||||
|
}
|
||||||
#endif // AP_EXTERNAL_CONTROL_ENABLED
|
#endif // AP_EXTERNAL_CONTROL_ENABLED
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
#include "uxr/client/client.h"
|
#include "uxr/client/client.h"
|
||||||
#include "ucdr/microcdr.h"
|
#include "ucdr/microcdr.h"
|
||||||
|
|
||||||
|
#include "ardupilot_msgs/msg/GlobalPosition.h"
|
||||||
#include "builtin_interfaces/msg/Time.h"
|
#include "builtin_interfaces/msg/Time.h"
|
||||||
|
|
||||||
#include "sensor_msgs/msg/NavSatFix.h"
|
#include "sensor_msgs/msg/NavSatFix.h"
|
||||||
@ -65,6 +67,8 @@ private:
|
|||||||
static sensor_msgs_msg_Joy rx_joy_topic;
|
static sensor_msgs_msg_Joy rx_joy_topic;
|
||||||
// incoming REP147 velocity control
|
// incoming REP147 velocity control
|
||||||
static geometry_msgs_msg_TwistStamped rx_velocity_control_topic;
|
static geometry_msgs_msg_TwistStamped rx_velocity_control_topic;
|
||||||
|
// incoming REP147 goal interface global position
|
||||||
|
static ardupilot_msgs_msg_GlobalPosition rx_global_position_control_topic;
|
||||||
// outgoing transforms
|
// outgoing transforms
|
||||||
tf2_msgs_msg_TFMessage tx_static_transforms_topic;
|
tf2_msgs_msg_TFMessage tx_static_transforms_topic;
|
||||||
tf2_msgs_msg_TFMessage tx_dynamic_transforms_topic;
|
tf2_msgs_msg_TFMessage tx_dynamic_transforms_topic;
|
||||||
|
@ -6,6 +6,49 @@
|
|||||||
|
|
||||||
#include <AP_ExternalControl/AP_ExternalControl.h>
|
#include <AP_ExternalControl/AP_ExternalControl.h>
|
||||||
|
|
||||||
|
// These are the Goal Interface constants. Because microxrceddsgen does not expose
|
||||||
|
// them in the generated code, they are manually maintained
|
||||||
|
// Position ignore flags
|
||||||
|
static constexpr uint16_t TYPE_MASK_IGNORE_LATITUDE = 1;
|
||||||
|
static constexpr uint16_t TYPE_MASK_IGNORE_LONGITUDE = 2;
|
||||||
|
static constexpr uint16_t TYPE_MASK_IGNORE_ALTITUDE = 4;
|
||||||
|
|
||||||
|
bool AP_DDS_External_Control::handle_global_position_control(ardupilot_msgs_msg_GlobalPosition& cmd_pos)
|
||||||
|
{
|
||||||
|
auto *external_control = AP::externalcontrol();
|
||||||
|
if (external_control == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(cmd_pos.header.frame_id, MAP_FRAME) == 0) {
|
||||||
|
// Narrow the altitude
|
||||||
|
const int32_t alt_cm = static_cast<int32_t>(cmd_pos.altitude * 100);
|
||||||
|
|
||||||
|
Location::AltFrame alt_frame;
|
||||||
|
if (!convert_alt_frame(cmd_pos.coordinate_frame, alt_frame)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr uint32_t MASK_POS_IGNORE =
|
||||||
|
TYPE_MASK_IGNORE_LATITUDE |
|
||||||
|
TYPE_MASK_IGNORE_LONGITUDE |
|
||||||
|
TYPE_MASK_IGNORE_ALTITUDE;
|
||||||
|
|
||||||
|
if (!(cmd_pos.type_mask & MASK_POS_IGNORE)) {
|
||||||
|
Location loc(cmd_pos.latitude * 1E7, cmd_pos.longitude * 1E7, alt_cm, alt_frame);
|
||||||
|
if (!external_control->set_global_position(loc)) {
|
||||||
|
return false; // Don't try sending other commands if this fails
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO add velocity and accel handling
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool AP_DDS_External_Control::handle_velocity_control(geometry_msgs_msg_TwistStamped& cmd_vel)
|
bool AP_DDS_External_Control::handle_velocity_control(geometry_msgs_msg_TwistStamped& cmd_vel)
|
||||||
{
|
{
|
||||||
auto *external_control = AP::externalcontrol();
|
auto *external_control = AP::externalcontrol();
|
||||||
@ -40,5 +83,25 @@ bool AP_DDS_External_Control::handle_velocity_control(geometry_msgs_msg_TwistSta
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AP_DDS_External_Control::convert_alt_frame(const uint8_t frame_in, Location::AltFrame& frame_out)
|
||||||
|
{
|
||||||
|
|
||||||
|
// Specified in ROS REP-147; only some are supported.
|
||||||
|
switch (frame_in) {
|
||||||
|
case 5: // FRAME_GLOBAL_INT
|
||||||
|
frame_out = Location::AltFrame::ABSOLUTE;
|
||||||
|
break;
|
||||||
|
case 6: // FRAME_GLOBAL_REL_ALT
|
||||||
|
frame_out = Location::AltFrame::ABOVE_HOME;
|
||||||
|
break;
|
||||||
|
case 11: // FRAME_GLOBAL_TERRAIN_ALT
|
||||||
|
frame_out = Location::AltFrame::ABOVE_TERRAIN;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif // AP_DDS_ENABLED
|
#endif // AP_DDS_ENABLED
|
@ -1,11 +1,19 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#if AP_DDS_ENABLED
|
#if AP_DDS_ENABLED
|
||||||
|
#include "ardupilot_msgs/msg/GlobalPosition.h"
|
||||||
#include "geometry_msgs/msg/TwistStamped.h"
|
#include "geometry_msgs/msg/TwistStamped.h"
|
||||||
|
|
||||||
|
#include <AP_Common/Location.h>
|
||||||
|
|
||||||
class AP_DDS_External_Control
|
class AP_DDS_External_Control
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
// REP-147 Goal Interface Global Position Control
|
||||||
|
// https://ros.org/reps/rep-0147.html#goal-interface
|
||||||
|
static bool handle_global_position_control(ardupilot_msgs_msg_GlobalPosition& cmd_pos);
|
||||||
static bool handle_velocity_control(geometry_msgs_msg_TwistStamped& cmd_vel);
|
static bool handle_velocity_control(geometry_msgs_msg_TwistStamped& cmd_vel);
|
||||||
|
private:
|
||||||
|
static bool convert_alt_frame(const uint8_t frame_in, Location::AltFrame& frame_out);
|
||||||
};
|
};
|
||||||
#endif // AP_DDS_ENABLED
|
#endif // AP_DDS_ENABLED
|
||||||
|
@ -22,6 +22,7 @@ enum class TopicIndex: uint8_t {
|
|||||||
JOY_SUB,
|
JOY_SUB,
|
||||||
DYNAMIC_TRANSFORMS_SUB,
|
DYNAMIC_TRANSFORMS_SUB,
|
||||||
VELOCITY_CONTROL_SUB,
|
VELOCITY_CONTROL_SUB,
|
||||||
|
GLOBAL_POSITION_SUB,
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline constexpr uint8_t to_underlying(const TopicIndex index)
|
static inline constexpr uint8_t to_underlying(const TopicIndex index)
|
||||||
@ -142,4 +143,14 @@ constexpr struct AP_DDS_Client::Topic_table AP_DDS_Client::topics[] = {
|
|||||||
.dw_profile_label = "",
|
.dw_profile_label = "",
|
||||||
.dr_profile_label = "velocitycontrol__dr",
|
.dr_profile_label = "velocitycontrol__dr",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.topic_id = to_underlying(TopicIndex::GLOBAL_POSITION_SUB),
|
||||||
|
.pub_id = to_underlying(TopicIndex::GLOBAL_POSITION_SUB),
|
||||||
|
.sub_id = to_underlying(TopicIndex::GLOBAL_POSITION_SUB),
|
||||||
|
.dw_id = uxrObjectId{.id=to_underlying(TopicIndex::GLOBAL_POSITION_SUB), .type=UXR_DATAWRITER_ID},
|
||||||
|
.dr_id = uxrObjectId{.id=to_underlying(TopicIndex::GLOBAL_POSITION_SUB), .type=UXR_DATAREADER_ID},
|
||||||
|
.topic_profile_label = "globalposcontrol__t",
|
||||||
|
.dw_profile_label = "",
|
||||||
|
.dr_profile_label = "globalposcontrol__dr",
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
60
libraries/AP_DDS/Idl/ardupilot_msgs/msg/GlobalPosition.idl
Normal file
60
libraries/AP_DDS/Idl/ardupilot_msgs/msg/GlobalPosition.idl
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
// generated from rosidl_adapter/resource/msg.idl.em
|
||||||
|
// with input from ardupilot_msgs/msg/GlobalPosition.msg
|
||||||
|
// generated code does not contain a copyright notice
|
||||||
|
|
||||||
|
#include "geometry_msgs/msg/Twist.idl"
|
||||||
|
#include "std_msgs/msg/Header.idl"
|
||||||
|
|
||||||
|
module ardupilot_msgs {
|
||||||
|
module msg {
|
||||||
|
module GlobalPosition_Constants {
|
||||||
|
const uint8 FRAME_GLOBAL_INT = 5;
|
||||||
|
const uint8 FRAME_GLOBAL_REL_ALT = 6;
|
||||||
|
const uint8 FRAME_GLOBAL_TERRAIN_ALT = 11;
|
||||||
|
@verbatim (language="comment", text=
|
||||||
|
"Position ignore flags")
|
||||||
|
const uint16 IGNORE_LATITUDE = 1;
|
||||||
|
const uint16 IGNORE_LONGITUDE = 2;
|
||||||
|
const uint16 IGNORE_ALTITUDE = 4;
|
||||||
|
@verbatim (language="comment", text=
|
||||||
|
"Velocity vector ignore flags")
|
||||||
|
const uint16 IGNORE_VX = 8;
|
||||||
|
const uint16 IGNORE_VY = 16;
|
||||||
|
const uint16 IGNORE_VZ = 32;
|
||||||
|
@verbatim (language="comment", text=
|
||||||
|
"Acceleration/Force vector ignore flags")
|
||||||
|
const uint16 IGNORE_AFX = 64;
|
||||||
|
const uint16 IGNORE_AFY = 128;
|
||||||
|
const uint16 IGNORE_AFZ = 256;
|
||||||
|
@verbatim (language="comment", text=
|
||||||
|
"Force in af vector flag")
|
||||||
|
const uint16 FORCE = 512;
|
||||||
|
const uint16 IGNORE_YAW = 1024;
|
||||||
|
const uint16 IGNORE_YAW_RATE = 2048;
|
||||||
|
};
|
||||||
|
@verbatim (language="comment", text=
|
||||||
|
"Experimental REP-147 Goal Interface" "\n"
|
||||||
|
"https://ros.org/reps/rep-0147.html#goal-interface")
|
||||||
|
struct GlobalPosition {
|
||||||
|
std_msgs::msg::Header header;
|
||||||
|
|
||||||
|
uint8 coordinate_frame;
|
||||||
|
|
||||||
|
uint16 type_mask;
|
||||||
|
|
||||||
|
double latitude;
|
||||||
|
|
||||||
|
double longitude;
|
||||||
|
|
||||||
|
@verbatim (language="comment", text=
|
||||||
|
"in meters, AMSL or above terrain")
|
||||||
|
float altitude;
|
||||||
|
|
||||||
|
geometry_msgs::msg::Twist velocity;
|
||||||
|
|
||||||
|
geometry_msgs::msg::Twist acceleration_or_force;
|
||||||
|
|
||||||
|
float yaw;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
@ -216,6 +216,7 @@ Published topics:
|
|||||||
* /rosout [rcl_interfaces/msg/Log] 1 publisher
|
* /rosout [rcl_interfaces/msg/Log] 1 publisher
|
||||||
|
|
||||||
Subscribed topics:
|
Subscribed topics:
|
||||||
|
* /ap/cmd_gps_pose [ardupilot_msgs/msg/GlobalPosition] 1 subscriber
|
||||||
* /ap/cmd_vel [geometry_msgs/msg/TwistStamped] 1 subscriber
|
* /ap/cmd_vel [geometry_msgs/msg/TwistStamped] 1 subscriber
|
||||||
* /ap/joy [sensor_msgs/msg/Joy] 1 subscriber
|
* /ap/joy [sensor_msgs/msg/Joy] 1 subscriber
|
||||||
* /ap/tf [tf2_msgs/msg/TFMessage] 1 subscriber
|
* /ap/tf [tf2_msgs/msg/TFMessage] 1 subscriber
|
||||||
@ -311,6 +312,10 @@ cp /opt/ros/humble/share/builtin_interfaces/msg/Time.idl libraries/AP_DDS/Idl/bu
|
|||||||
# Build the code again with the `--enable-dds` flag as described above
|
# Build the code again with the `--enable-dds` flag as described above
|
||||||
```
|
```
|
||||||
|
|
||||||
|
If the message is custom for ardupilot, first create the ROS message in `Tools/ros2/ardupilot_msgs/msg/GlobalPosition.msg`.
|
||||||
|
Then, build ardupilot_msgs with colcon.
|
||||||
|
Finally, copy the IDL folder from the install directory into the source tree.
|
||||||
|
|
||||||
### Rules for adding topics and services to `dds_xrce_profile.xml`
|
### Rules for adding topics and services to `dds_xrce_profile.xml`
|
||||||
|
|
||||||
Topics and services available from `AP_DDS` are automatically mapped into ROS 2
|
Topics and services available from `AP_DDS` are automatically mapped into ROS 2
|
||||||
|
@ -276,4 +276,19 @@
|
|||||||
<request_topic_name>rq/ap/mode_switchRequest</request_topic_name>
|
<request_topic_name>rq/ap/mode_switchRequest</request_topic_name>
|
||||||
<reply_topic_name>rr/ap/mode_switchReply</reply_topic_name>
|
<reply_topic_name>rr/ap/mode_switchReply</reply_topic_name>
|
||||||
</replier>
|
</replier>
|
||||||
|
<topic profile_name="globalposcontrol__t">
|
||||||
|
<name>rt/ap/cmd_gps_pose</name>
|
||||||
|
<dataType>ardupilot_msgs::msg::dds_::GlobalPosition_</dataType>
|
||||||
|
<historyQos>
|
||||||
|
<kind>KEEP_LAST</kind>
|
||||||
|
<depth>5</depth>
|
||||||
|
</historyQos>
|
||||||
|
</topic>
|
||||||
|
<data_reader profile_name="globalposcontrol__dr">
|
||||||
|
<topic>
|
||||||
|
<kind>NO_KEY</kind>
|
||||||
|
<name>rt/ap/cmd_gps_pose</name>
|
||||||
|
<dataType>ardupilot_msgs::msg::dds_::GlobalPosition_</dataType>
|
||||||
|
</topic>
|
||||||
|
</data_reader>
|
||||||
</profiles>
|
</profiles>
|
||||||
|
Loading…
Reference in New Issue
Block a user