2

Hello guys I have a offboard code which give about 50 setpoints to drone. It draws spiral with that setpoints. My problem is I couldnt get smooth travel. In every setpoint drone gives a high roll or pitch instant and then floats to the next setpoint. Is there a way to have stable velocity while passing the setpoints. Here is the code:

        #include <px4_msgs/msg/offboard_control_mode.hpp>
    #include <px4_msgs/msg/trajectory_setpoint.hpp>
    #include <px4_msgs/msg/timesync.hpp>
    #include <px4_msgs/msg/vehicle_command.hpp>
    #include <px4_msgs/msg/vehicle_control_mode.hpp>
    #include <px4_msgs/msg/vehicle_local_position.hpp>
    #include <rclcpp/rclcpp.hpp>

    #include <stdint.h>
    #include <chrono>
    #include <iostream>
    #include "std_msgs/msg/string.hpp"
    #include <math.h>

    float X;
    float Y;    

    using namespace std::chrono;
    using namespace std::chrono_literals;
    using namespace px4_msgs::msg;
    class setpoint : public rclcpp::Node {
    public:
        setpoint() : Node("setpoint") {
        
            offboard_control_mode_publisher_ =
                this->create_publisher<OffboardControlMode>("fmu/offboard_control_mode/in", 10);
            trajectory_setpoint_publisher_ =
                this->create_publisher<TrajectorySetpoint>("fmu/trajectory_setpoint/in", 10);
            vehicle_command_publisher_ =
                this->create_publisher<VehicleCommand>("fmu/vehicle_command/in", 10);

            // get common timestamp
            timesync_sub_ =
                this->create_subscription<px4_msgs::msg::Timesync>("fmu/timesync/out", 10,
                    [this](const px4_msgs::msg::Timesync::UniquePtr msg) {
                        timestamp_.store(msg->timestamp);
                    });

            offboard_setpoint_counter_ = 0;

        

            auto sendCommands = [this]() -> void {
                if (offboard_setpoint_counter_ == 10) {
                    // Change to Offboard mode after 10 setpoints
                    this->publish_vehicle_command(VehicleCommand::VEHICLE_CMD_DO_SET_MODE, 1, 6);

                    // Arm the vehicle
                    this->arm();

                }
    //-------------
                subscription_ = this->create_subscription<px4_msgs::msg::VehicleLocalPosition>(
                "/fmu/vehicle_local_position/out",
    #ifdef ROS_DEFAULT_API
                10,
    #endif
                [this](const px4_msgs::msg::VehicleLocalPosition::UniquePtr msg) {
                X = msg->x;
                Y = msg->y;
                std::cout << "\n\n\n\n\n\n\n\n\n\n";
                std::cout << "RECEIVED VEHICLE GPS POSITION DATA"   << std::endl;
                std::cout << "=================================="   << std::endl;
                std::cout << "ts: "      << msg->timestamp    << std::endl;
                //std::cout << "lat: " << msg->x  << std::endl;
                //std::cout << "lon: " << msg->y << std::endl;
                std::cout << "lat: " << X  << std::endl;
                std::cout << "lon: " << Y << std::endl;
                std::cout << "waypoint: " << waypoints[waypointIndex][0] << std::endl;
                std::cout << "waypoint: " << waypoints[waypointIndex][1] << std::endl;
                if((waypoints[waypointIndex][0] + 0.3 > X && waypoints[waypointIndex][0] - 0.3 < X)&&(waypoints[waypointIndex][1] + 0.3 > Y && waypoints[waypointIndex][1] - 0.3 < Y)){
                waypointIndex++;
                if (waypointIndex >= waypoints.size())
                    exit(0);
                    //waypointIndex = 0;

                RCLCPP_INFO(this->get_logger(), "Next waypoint: %.2f %.2f %.2f", waypoints[waypointIndex][0], waypoints[waypointIndex][1], waypoints[waypointIndex][2]);
            }
            });
    //--------------

                        // offboard_control_mode needs to be paired with trajectory_setpoint
                publish_offboard_control_mode();
                publish_trajectory_setpoint();

                    // stop the counter after reaching 11
                if (offboard_setpoint_counter_ < 11) {
                    offboard_setpoint_counter_++;
                }
            };

        /*
            auto nextWaypoint = [this]() -> void {
                
                waypointIndex++; 

                if (waypointIndex >= waypoints.size()) 
                    waypointIndex = 0;

                RCLCPP_INFO(this->get_logger(), "Next waypoint: %.2f %.2f %.2f", waypoints[waypointIndex][0], waypoints[waypointIndex][1], waypoints[waypointIndex][2]);
            };
            */
            commandTimer = this->create_wall_timer(100ms, sendCommands);
            //waypointTimer = this->create_wall_timer(2s, nextWaypoint); //EA   
        }

        void arm() const;
        void disarm() const;
        void topic_callback() const;
    private:
        

    std::vector<std::vector<float>> waypoints = {{0,0,-5,},
    {2,0,-5,},
    {2.35216,0.476806,-5,},
    {2.57897,1.09037,-5,},
    {2.64107,1.80686,-5,},
    {2.50814,2.58248,-5,},
    {2.16121,3.36588,-5,},
    {1.59437,4.10097,-5,},
    {0.815842,4.73016,-5,},
    {-0.151838,5.19778,-5,},
    {-1.27233,5.45355,-5,},
    {-2.49688,5.45578,-5,},
    {-3.76641,5.17438,-5,},
    {-5.01428,4.59315,-5,},
    {-6.1696,3.71161,-5,},
    {-7.16089,2.54591,-5,},
    {-7.91994,1.12896,-5,},
    {-8.38568,-0.490343,-5,},
    {-8.50782,-2.24876,-5,},
    {-8.25018,-4.07119,-5,},
    {-7.59329,-5.87384,-5,},
    {-6.53644,-7.56803,-5,},
    {-5.09871,-9.06439,-5,},
    {-3.31919,-10.2773,-5,},
    {-1.25611,-11.1293,-5,},
    {1.01499,-11.5555,-5,},
    {3.40395,-11.5071,-5,},
    {5.8096,-10.9548,-5,},
    {8.12407,-9.89139,-5,},
    {10.2375,-8.33272,-5,},
    {12.0431,-6.31859,-5,},
    {13.4424,-3.91182,-5,},
    {14.3502,-1.19649,-5,},
    {14.6991,1.72493,-5,},
    {14.4435,4.73543,-5,},
    {13.5626,7.70817,-5,},
    {12.0624,10.5118,-5,},
    {9.97696,13.0162,-5,},
    {7.36759,15.0983,-5,},
    {4.32167,16.6482,-5,},
    {0.949612,17.5744,-5,},
    {-2.619,17.8084,-5,},
    {-6.24045,17.3094,-5,},
    {-9.76262,16.0665,-5,},
    {-13.0314,14.1004,-5,},
    {-15.8974,11.4644,-5,},
    {-18.2226,8.24237,-5,},
    {-19.8868,4.54696,-5,},
    {-20.7936,0.515337,-5,},
    {-20.8754,-3.69574,-5,},
    {-20.0972,-7.91595,-5,},
    {-20.8754,-3.69574,-5,},
    {-20.7936,0.515337,-5,},
    {-19.8868,4.54696,-5,},
    {-18.2226,8.24237,-5,},
    {-15.8974,11.4644,-5,},
    {-13.0314,14.1004,-5,},
    {-9.76262,16.0665,-5,},
    {-6.24045,17.3094,-5,},
    {-2.619,17.8084,-5,},
    {0.949612,17.5744,-5,},
    {4.32167,16.6482,-5,},
    {7.36759,15.0983,-5,},
    {9.97696,13.0162,-5,},
    {12.0624,10.5118,-5,},
    {13.5626,7.70817,-5,},
    {14.4435,4.73543,-5,},
    {14.6991,1.72493,-5,},
    {14.3502,-1.19649,-5,},
    {13.4424,-3.91182,-5,},
    {12.0431,-6.31859,-5,},
    {10.2375,-8.33272,-5,},
    {8.12407,-9.89139,-5,},
    {5.8096,-10.9548,-5,},
    {3.40395,-11.5071,-5,},
    {1.01499,-11.5555,-5,},
    {-1.25611,-11.1293,-5,},
    {-3.31919,-10.2773,-5,},
    {-5.09871,-9.06439,-5,},
    {-6.53644,-7.56803,-5,},
    {-7.59329,-5.87384,-5,},
    {-8.25018,-4.07119,-5,},
    {-8.50782,-2.24876,-5,},
    {-8.38568,-0.490343,-5,},
    {-7.91994,1.12896,-5,},
    {-7.16089,2.54591,-5,},
    {-6.1696,3.71161,-5,},
    {-5.01428,4.59315,-5,},
    {-3.76641,5.17438,-5,},
    {-2.49688,5.45578,-5,},
    {-1.27233,5.45355,-5,},
    {-0.151838,5.19778,-5,},
    {0.815842,4.73016,-5,},
    {1.59437,4.10097,-5,},
    {2.16121,3.36588,-5,},
    {2.50814,2.58248,-5,},
    {2.64107,1.80686,-5,},
    {2.57897,1.09037,-5,},
    {2.35216,0.476806,-5,},
    {2,0,-5,},
    {0,0,-5,},
    {0,0,0,}
    };      // Land
        

        int waypointIndex = 0;

        rclcpp::TimerBase::SharedPtr commandTimer;
        rclcpp::TimerBase::SharedPtr waypointTimer;

        rclcpp::Publisher<OffboardControlMode>::SharedPtr offboard_control_mode_publisher_;
        rclcpp::Publisher<TrajectorySetpoint>::SharedPtr trajectory_setpoint_publisher_;
        rclcpp::Publisher<VehicleCommand>::SharedPtr vehicle_command_publisher_;
        rclcpp::Subscription<px4_msgs::msg::Timesync>::SharedPtr timesync_sub_;
        //
        rclcpp::Subscription<px4_msgs::msg::VehicleLocalPosition>::SharedPtr subscription_;
        //
        std::atomic<uint64_t> timestamp_;   //!< common synced timestamped

        uint64_t offboard_setpoint_counter_;   //!< counter for the number of setpoints sent

        void publish_offboard_control_mode() const;
        void publish_trajectory_setpoint() const;
        void publish_vehicle_command(uint16_t command, float param1 = 0.0,
                        float param2 = 0.0) const;
    };

    void setpoint::arm() const {
        publish_vehicle_command(VehicleCommand::VEHICLE_CMD_COMPONENT_ARM_DISARM, 1.0);

        RCLCPP_INFO(this->get_logger(), "Arm command send");
    }

    void setpoint::disarm() const {
        publish_vehicle_command(VehicleCommand::VEHICLE_CMD_COMPONENT_ARM_DISARM, 0.0);

        RCLCPP_INFO(this->get_logger(), "Disarm command send");
    }

    void setpoint::publish_offboard_control_mode() const {
        OffboardControlMode msg{};
        msg.timestamp = timestamp_.load();
        msg.position = true;
        msg.velocity = false;
        msg.acceleration = false;
        msg.attitude = false;
        msg.body_rate = false;

        offboard_control_mode_publisher_->publish(msg);
    }   

    void setpoint::publish_trajectory_setpoint() const {
        TrajectorySetpoint msg{};
        msg.timestamp = timestamp_.load();
        msg.position = {waypoints[waypointIndex][0],waypoints[waypointIndex][1],waypoints[waypointIndex][2]};
        msg.yaw = std::nanf("0");       //-3.14; // [-PI:PI]
        trajectory_setpoint_publisher_->publish(msg);
    }

    void setpoint::publish_vehicle_command(uint16_t command, float param1,
                            float param2) const {
        VehicleCommand msg{};
        msg.timestamp = timestamp_.load();
        msg.param1 = param1;
        msg.param2 = param2;
        msg.command = command;
        msg.target_system = 1;
        msg.target_component = 1;
        msg.source_system = 1;
        msg.source_component = 1;
        msg.from_external = true;

        vehicle_command_publisher_->publish(msg);
    }

    int main(int argc, char* argv[]) {
        std::cout << "Starting setpoint node..." << std::endl;
        
        setvbuf(stdout, NULL, _IONBF, BUFSIZ);
        rclcpp::init(argc, argv);
        rclcpp::spin(std::make_shared<setpoint>());

        rclcpp::shutdown();
        return 0;
    }
Ege Alşan
  • 21
  • 3

1 Answers1

0

We send the setpoints to the controller by giving reference points. The aircraft will then try to maneuver to the given points via its control strategy (usually PID). Therefore, to have a smooth maneuver, it is usually suggested to give a series of discrete points between two waypoints, i.e., trajectory which parameterized by time. It should then solve the abrupt motion of your UAV. I'm no expert, but I hope this helps.

Patrick Lo
  • 26
  • 2
  • Thank you for your fast answer I will try this. And I want to ask another question: how can I make heading of the vehicle forvard. I want the vehicle head towards the direction which vehicle moving. – Ege Alşan Jul 27 '22 at 12:26
  • well, you can calculate the vector of your heading (tangent of your trajectory), and then tranlate that into quaternions (or as in ROS2, could just simply provide the yaw), and then publish it to your UAV. – Patrick Lo Jul 27 '22 at 13:18
  • okay I was wondering if the offboard system has a function or not and I guess not. I will stick to your method I think. Thank you for your all kind responses:D – Ege Alşan Jul 27 '22 at 14:21