mirror of
https://github.com/CopterExpress/clover.git
synced 2026-05-26 11:43:25 +00:00
Add simple_offboard/state topic publishing and some tests
This commit is contained in:
@@ -80,11 +80,10 @@ catkin_python_setup()
|
|||||||
## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...)
|
## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...)
|
||||||
|
|
||||||
## Generate messages in the 'msg' folder
|
## Generate messages in the 'msg' folder
|
||||||
# add_message_files(
|
add_message_files(
|
||||||
# FILES
|
FILES
|
||||||
# Message1.msg
|
State.msg
|
||||||
# Message2.msg
|
)
|
||||||
# )
|
|
||||||
|
|
||||||
## Generate services in the 'srv' folder
|
## Generate services in the 'srv' folder
|
||||||
add_service_files(
|
add_service_files(
|
||||||
|
|||||||
38
clover/msg/State.msg
Normal file
38
clover/msg/State.msg
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
uint8 MODE_NONE = 0
|
||||||
|
uint8 MODE_NAVIGATE = 1
|
||||||
|
uint8 MODE_NAVIGATE_GLOBAL = 2
|
||||||
|
uint8 MODE_POSITION = 3
|
||||||
|
uint8 MODE_VELOCITY = 4
|
||||||
|
uint8 MODE_ATTITUDE = 5
|
||||||
|
uint8 MODE_RATES = 6
|
||||||
|
|
||||||
|
uint8 YAW_MODE_YAW = 0
|
||||||
|
uint8 YAW_MODE_YAW_RATE = 1
|
||||||
|
uint8 YAW_MODE_YAW_TOWARDS = 2
|
||||||
|
|
||||||
|
# type of offboard control
|
||||||
|
uint8 mode
|
||||||
|
uint8 yaw_mode
|
||||||
|
|
||||||
|
# targets
|
||||||
|
float32 x
|
||||||
|
float32 y
|
||||||
|
float32 z
|
||||||
|
float32 speed
|
||||||
|
float32 lat
|
||||||
|
float32 lon
|
||||||
|
float32 vx
|
||||||
|
float32 vy
|
||||||
|
float32 vz
|
||||||
|
float32 roll
|
||||||
|
float32 pitch
|
||||||
|
float32 yaw
|
||||||
|
float32 roll_rate
|
||||||
|
float32 pitch_rate
|
||||||
|
float32 yaw_rate
|
||||||
|
float32 thrust
|
||||||
|
|
||||||
|
# frames of reference
|
||||||
|
string xy_frame_id
|
||||||
|
string z_frame_id
|
||||||
|
string yaw_frame_id
|
||||||
@@ -46,6 +46,7 @@
|
|||||||
#include <clover/SetVelocity.h>
|
#include <clover/SetVelocity.h>
|
||||||
#include <clover/SetAttitude.h>
|
#include <clover/SetAttitude.h>
|
||||||
#include <clover/SetRates.h>
|
#include <clover/SetRates.h>
|
||||||
|
#include <clover/State.h>
|
||||||
|
|
||||||
using std::string;
|
using std::string;
|
||||||
using std::isnan;
|
using std::isnan;
|
||||||
@@ -82,7 +83,7 @@ bool land_only_in_offboard, nav_from_sp, check_kill_switch;
|
|||||||
std::map<string, string> reference_frames;
|
std::map<string, string> reference_frames;
|
||||||
|
|
||||||
// Publishers
|
// Publishers
|
||||||
ros::Publisher attitude_pub, attitude_raw_pub, position_pub, position_raw_pub, rates_pub, thrust_pub;
|
ros::Publisher attitude_pub, attitude_raw_pub, position_pub, position_raw_pub, rates_pub, thrust_pub, state_pub;
|
||||||
|
|
||||||
// Service clients
|
// Service clients
|
||||||
ros::ServiceClient arming, set_mode;
|
ros::ServiceClient arming, set_mode;
|
||||||
@@ -106,6 +107,7 @@ Vector3Stamped setpoint_velocity, setpoint_velocity_transformed;
|
|||||||
QuaternionStamped setpoint_attitude, setpoint_attitude_transformed; // attitude or only the yaw
|
QuaternionStamped setpoint_attitude, setpoint_attitude_transformed; // attitude or only the yaw
|
||||||
Vector3 setpoint_rates;
|
Vector3 setpoint_rates;
|
||||||
float nav_speed;
|
float nav_speed;
|
||||||
|
float setpoint_lat, setpoint_lon;
|
||||||
bool busy = false;
|
bool busy = false;
|
||||||
bool wait_armed = false;
|
bool wait_armed = false;
|
||||||
bool nav_from_sp_flag = false;
|
bool nav_from_sp_flag = false;
|
||||||
@@ -553,6 +555,44 @@ inline void checkState()
|
|||||||
throw std::runtime_error("No connection to FCU, https://clover.coex.tech/connection");
|
throw std::runtime_error("No connection to FCU, https://clover.coex.tech/connection");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void publishState()
|
||||||
|
{
|
||||||
|
clover::State msg;
|
||||||
|
msg.mode = setpoint_type;
|
||||||
|
msg.yaw_mode = setpoint_yaw_type;
|
||||||
|
msg.x = setpoint_position.pose.position.x;
|
||||||
|
msg.y = setpoint_position.pose.position.y;
|
||||||
|
msg.z = setpoint_position.pose.position.z;
|
||||||
|
msg.speed = nav_speed;
|
||||||
|
msg.lat = setpoint_lat;
|
||||||
|
msg.lon = setpoint_lon;
|
||||||
|
msg.vx = setpoint_velocity.vector.x;
|
||||||
|
msg.vy = setpoint_velocity.vector.y;
|
||||||
|
msg.vz = setpoint_velocity.vector.z;
|
||||||
|
|
||||||
|
double roll, pitch, yaw;
|
||||||
|
tf2::getEulerYPR(setpoint_attitude.quaternion, yaw, pitch, roll);
|
||||||
|
msg.roll = roll;
|
||||||
|
msg.pitch = pitch;
|
||||||
|
msg.yaw = yaw;
|
||||||
|
|
||||||
|
msg.roll_rate = setpoint_rates.x;
|
||||||
|
msg.pitch_rate = setpoint_rates.y;
|
||||||
|
msg.yaw_rate = setpoint_rates.z;
|
||||||
|
msg.thrust = thrust_msg.thrust;
|
||||||
|
|
||||||
|
if (setpoint_type == VELOCITY) {
|
||||||
|
msg.xy_frame_id = setpoint_velocity.header.frame_id;
|
||||||
|
msg.z_frame_id = setpoint_velocity.header.frame_id;
|
||||||
|
} else {
|
||||||
|
msg.xy_frame_id = setpoint_position.header.frame_id;
|
||||||
|
msg.z_frame_id = setpoint_altitude.header.frame_id;
|
||||||
|
}
|
||||||
|
msg.yaw_frame_id = setpoint_attitude.header.frame_id;
|
||||||
|
|
||||||
|
state_pub.publish(msg);
|
||||||
|
}
|
||||||
|
|
||||||
#define ENSURE_FINITE(var) { if (!std::isfinite(var)) throw std::runtime_error(#var " argument cannot be NaN or Inf"); }
|
#define ENSURE_FINITE(var) { if (!std::isfinite(var)) throw std::runtime_error(#var " argument cannot be NaN or Inf"); }
|
||||||
|
|
||||||
bool serve(enum setpoint_type_t sp_type, float x, float y, float z, float vx, float vy, float vz,
|
bool serve(enum setpoint_type_t sp_type, float x, float y, float z, float vx, float vy, float vz,
|
||||||
@@ -691,6 +731,8 @@ bool serve(enum setpoint_type_t sp_type, float x, float y, float z, float vx, fl
|
|||||||
auto xy_in_req_frame = tf_buffer.transform(pose_local, frame_id);
|
auto xy_in_req_frame = tf_buffer.transform(pose_local, frame_id);
|
||||||
x = xy_in_req_frame.pose.position.x;
|
x = xy_in_req_frame.pose.position.x;
|
||||||
y = xy_in_req_frame.pose.position.y;
|
y = xy_in_req_frame.pose.position.y;
|
||||||
|
setpoint_lat = lat;
|
||||||
|
setpoint_lon = lon;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Everything fine - switch setpoint type
|
// Everything fine - switch setpoint type
|
||||||
@@ -798,6 +840,8 @@ publish_setpoint:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
publishState();
|
||||||
|
|
||||||
if (auto_arm) {
|
if (auto_arm) {
|
||||||
offboardAndArm();
|
offboardAndArm();
|
||||||
wait_armed = false;
|
wait_armed = false;
|
||||||
@@ -897,6 +941,8 @@ bool land(std_srvs::Trigger::Request& req, std_srvs::Trigger::Response& res)
|
|||||||
bool release(std_srvs::Trigger::Request& req, std_srvs::Trigger::Response& res)
|
bool release(std_srvs::Trigger::Request& req, std_srvs::Trigger::Response& res)
|
||||||
{
|
{
|
||||||
setpoint_timer.stop();
|
setpoint_timer.stop();
|
||||||
|
setpoint_type = NONE;
|
||||||
|
publishState();
|
||||||
res.success = true;
|
res.success = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -965,6 +1011,9 @@ int main(int argc, char **argv)
|
|||||||
rates_pub = nh.advertise<TwistStamped>(mavros + "/setpoint_attitude/cmd_vel", 1);
|
rates_pub = nh.advertise<TwistStamped>(mavros + "/setpoint_attitude/cmd_vel", 1);
|
||||||
thrust_pub = nh.advertise<Thrust>(mavros + "/setpoint_attitude/thrust", 1);
|
thrust_pub = nh.advertise<Thrust>(mavros + "/setpoint_attitude/thrust", 1);
|
||||||
|
|
||||||
|
// State publisher
|
||||||
|
state_pub = nh_priv.advertise<clover::State>("state", 1, true);
|
||||||
|
|
||||||
// Service servers
|
// Service servers
|
||||||
auto gt_serv = nh.advertiseService("get_telemetry", &getTelemetry);
|
auto gt_serv = nh.advertiseService("get_telemetry", &getTelemetry);
|
||||||
auto na_serv = nh.advertiseService("navigate", &navigate);
|
auto na_serv = nh.advertiseService("navigate", &navigate);
|
||||||
|
|||||||
@@ -5,12 +5,16 @@ import threading
|
|||||||
import mavros_msgs.msg
|
import mavros_msgs.msg
|
||||||
from geometry_msgs.msg import PoseStamped
|
from geometry_msgs.msg import PoseStamped
|
||||||
from clover import srv
|
from clover import srv
|
||||||
|
from clover.msg import State
|
||||||
from math import nan
|
from math import nan
|
||||||
|
|
||||||
@pytest.fixture()
|
@pytest.fixture()
|
||||||
def node():
|
def node():
|
||||||
return rospy.init_node('offboard_test', anonymous=True)
|
return rospy.init_node('offboard_test', anonymous=True)
|
||||||
|
|
||||||
|
def get_state():
|
||||||
|
return rospy.wait_for_message('/simple_offboard/state', State, timeout=1)
|
||||||
|
|
||||||
def test_offboard(node):
|
def test_offboard(node):
|
||||||
navigate = rospy.ServiceProxy('navigate', srv.Navigate)
|
navigate = rospy.ServiceProxy('navigate', srv.Navigate)
|
||||||
get_telemetry = rospy.ServiceProxy('get_telemetry', srv.GetTelemetry)
|
get_telemetry = rospy.ServiceProxy('get_telemetry', srv.GetTelemetry)
|
||||||
@@ -68,5 +72,13 @@ def test_offboard(node):
|
|||||||
threading.Thread(target=publish_local_position, daemon=True).start()
|
threading.Thread(target=publish_local_position, daemon=True).start()
|
||||||
rospy.sleep(0.5)
|
rospy.sleep(0.5)
|
||||||
|
|
||||||
res = navigate()
|
res = navigate(z=1, frame_id='map')
|
||||||
assert res.success == True
|
assert res.success == True
|
||||||
|
state = get_state()
|
||||||
|
assert state.mode == State.MODE_NAVIGATE
|
||||||
|
assert state.yaw_mode == State.YAW_MODE_YAW
|
||||||
|
assert state.z == 1
|
||||||
|
assert state.yaw == 0
|
||||||
|
assert state.xy_frame_id == 'map'
|
||||||
|
assert state.z_frame_id == 'map'
|
||||||
|
assert state.yaw_frame_id == 'map'
|
||||||
|
|||||||
Reference in New Issue
Block a user