---
# System prepended metadata

title: PX4仿真實作

---

# PX4仿真實作
### 實作找尋設備
[DDS bridge](https://docs.px4.io/main/en/middleware/uxrce_dds.html)
[port setting](https://docs.px4.io/main/en/modules/modules_system.html#uxrce-dds-client)
### 找尋電腦裝置
```
ls /dev/ttyUSB*
```
**MicroAgent**
```
sudo MicroXRCEAgent serial --dev /dev/ttyUSB0 -b 57600 -v 6

uxrce_dds_client start -t serial -d /dev/ttyS1 -b 57600

uxrce_dds_client status
uxrce_dds_client stop
```
**Offboard command**
```
source /opt/ros/humble/setup.bash
colcon build
source install/local_setup.bash
ros2 run px4_ros_com offboard_control
```
```
MicroXRCEAgent udp4 -p 8888
```

為了使模擬數據可以更完整呈現，我們可以去做資料分析，首先需安裝pyulog:
[Pyulog](https://github.com/PX4/pyulog)，此為安裝教學。
接著我們須確認模擬結果是否有紀錄。
```
make px4_sitl gazebo
```
進入gazebo模擬後，在Teminal輸入**logger status**確認飛行紀錄有沒有進行，若無
```
logger on
```
開始進行紀錄
## ulog2csv
當我們需要從仿真中獲取數據，並在matlab裡面進行分析，就需要進行一個轉檔的動作
```
~/.local/bin/ulog2csv your_log.ulg  
```
## Offboard code
### attitude
```javascript=
/****************************************************************************
 *
 * Copyright 2020 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 of the copyright holder 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 HOLDER 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.
 *
 ****************************************************************************/

/**
 * @brief Offboard control example
 * @file offboard_control.cpp
 * @addtogroup examples
 * @author Mickey Cowden <info@cowden.tech>
 * @author Nuno Marques <nuno.marques@dronesolutions.io>
 */

 #include <px4_msgs/msg/offboard_control_mode.hpp>
 #include <px4_msgs/msg/trajectory_setpoint.hpp>
 #include <px4_msgs/msg/vehicle_command.hpp>
 #include <px4_msgs/msg/vehicle_control_mode.hpp>
 #include <px4_msgs/msg/vehicle_attitude_setpoint.hpp>
 #include <rclcpp/rclcpp.hpp>
 #include <stdint.h>
 
 #include <chrono>
 #include <iostream>
 
 using namespace std::chrono;
 using namespace std::chrono_literals;
 using namespace px4_msgs::msg;
 
 class OffboardControl : public rclcpp::Node
 {
 public:
	 OffboardControl() : Node("offboard_control")
	 {
 
		 offboard_control_mode_publisher_ = this->create_publisher<OffboardControlMode>("/fmu/in/offboard_control_mode", 10);
		 trajectory_setpoint_publisher_ = this->create_publisher<TrajectorySetpoint>("/fmu/in/trajectory_setpoint", 10);
		 vehicle_command_publisher_ = this->create_publisher<VehicleCommand>("/fmu/in/vehicle_command", 10);
		 vehicle_attitude_setpoint_publisher_ = this->create_publisher<VehicleAttitudeSetpoint>("/fmu/in/vehicle_attitude_setpoint", 10);
 
		 offboard_setpoint_counter_ = 0;
 
		 auto timer_callback = [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();
			 
			 }
 
			 // offboard_control_mode needs to be paired with trajectory_setpoint
			 publish_offboard_control_mode();
			 publish_trajectory_setpoint();
			 publish_vehicle_attitude_setpoint();
		 
 
			 // stop the counter after reaching 11
			 if (offboard_setpoint_counter_ < 11) {
				 offboard_setpoint_counter_++;
			 }
		 };
		 timer_ = this->create_wall_timer(100ms, timer_callback);
	 }
 
	 void arm();
	 void disarm();
 
 private:
	 rclcpp::TimerBase::SharedPtr timer_;
 
	 rclcpp::Publisher<OffboardControlMode>::SharedPtr offboard_control_mode_publisher_;
	 rclcpp::Publisher<TrajectorySetpoint>::SharedPtr trajectory_setpoint_publisher_;
	 rclcpp::Publisher<VehicleCommand>::SharedPtr vehicle_command_publisher_;
	 rclcpp::Publisher<VehicleAttitudeSetpoint>::SharedPtr vehicle_attitude_setpoint_publisher_;
	 std::atomic<uint64_t> timestamp_;   //!< common synced timestamped
	 std::array<float, 4> quat_from_euler(double roll, double pitch, double yaw);
	 uint64_t offboard_setpoint_counter_;   //!< counter for the number of setpoints sent
	 float time_counter_ = 0.0;
	 void publish_offboard_control_mode();
	 void publish_trajectory_setpoint();
	 void publish_vehicle_command(uint16_t command, float param1 = 0.0, float param2 = 0.0);
	 void publish_vehicle_attitude_setpoint();
 };
 
 /**
  * @brief Send a command to Arm the vehicle
  */
 void OffboardControl::arm()
 {
	 publish_vehicle_command(VehicleCommand::VEHICLE_CMD_COMPONENT_ARM_DISARM, 1.0);
 
	 RCLCPP_INFO(this->get_logger(), "Arm command send");
 }
 
 /**
  * @brief Send a command to Disarm the vehicle
  */
 void OffboardControl::disarm()
 {
	 publish_vehicle_command(VehicleCommand::VEHICLE_CMD_COMPONENT_ARM_DISARM, 0.0);
 
	 RCLCPP_INFO(this->get_logger(), "Disarm command send");
 }
 
 /**
  * @brief Publish the offboard control mode.
  *        For this example, only position and altitude controls are active.
  */
 void OffboardControl::publish_offboard_control_mode()
 {
	 OffboardControlMode msg{};
	 msg.position = false;
	 msg.velocity = false;
	 msg.acceleration = false;
	 msg.attitude = true;
	 msg.body_rate = false;
	 msg.timestamp = this->get_clock()->now().nanoseconds() / 1000;
	 offboard_control_mode_publisher_->publish(msg);
 }
 
 /**
  * @brief Publish a trajectory setpoint
  *        For this example, it sends a trajectory setpoint to make the
  *        vehicle hover at 5 meters with a yaw angle of 180 degrees.
  */
 void OffboardControl::publish_trajectory_setpoint()
 {
	 TrajectorySetpoint msg{};
	 msg.position = {0.0, 0.0, -5.0};
	 msg.yaw = -3.14; // [-PI:PI]
	 msg.timestamp = this->get_clock()->now().nanoseconds() / 1000;
	 trajectory_setpoint_publisher_->publish(msg);
 }

 void OffboardControl::publish_vehicle_attitude_setpoint()
 {
	 VehicleAttitudeSetpoint msg{};
	 uint64_t now_ns = this->get_clock()->now().nanoseconds();
	 msg.timestamp = this->get_clock()->now().nanoseconds() / 1000;
	 time_counter_ += 0.1f; 
	 double roll = 0, pitch = 0, yaw = 0 ;
	 roll =(M_PI/7.2)*sin(M_PI*time_counter_/ 15);
	 pitch =(M_PI/7.2)*cos(M_PI*time_counter_/ 15);
	 yaw =(M_PI)*cos(M_PI*time_counter_/ 30);
	 //roll =(M_PI/9);
	 //pitch =(M_PI/9);
	 //yaw = (M_PI/4);
 
	 // Convert roll, pitch, yaw to quaternion
	 std::array<float, 4> q_d = quat_from_euler(roll, pitch, yaw);  // Function to convert Euler angles to quaternion
 
	 // Set the desired attitude quaternion
	 msg.q_d = q_d;
	 msg.thrust_body = {0.0, 0.0, -0.4}; // Thrust to keep the drone in the air
RCLCPP_INFO(this->get_logger(), "q_d: [%.3f, %.3f, %.3f, %.3f]", q_d[0], q_d[1], q_d[2], q_d[3]);
RCLCPP_INFO(this->get_logger(), "thrust_body: [%.3f, %.3f, %.3f]", msg.thrust_body[0], msg.thrust_body[1], msg.thrust_body[2]);
	 vehicle_attitude_setpoint_publisher_->publish(msg);

	 RCLCPP_INFO(this->get_logger(),"Time: %.3f sec",now_ns/1e9);
 }

 std::array<float, 4> OffboardControl::quat_from_euler(double roll, double pitch, double yaw)
 {
	 std::array<float, 4> q{};
 
	 double cy = cos(yaw * 0.5);
	 double sy = sin(yaw * 0.5);
	 double cp = cos(pitch * 0.5);
	 double sp = sin(pitch * 0.5);
	 double cr = cos(roll * 0.5);
	 double sr = sin(roll * 0.5);
 
	 // Calculate the quaternion components
	 q[0] = cr * cp * cy + sr * sp * sy;  // w
	 q[1] = sr * cp * cy - cr * sp * sy;  // x
	 q[2] = cr * sp * cy + sr * cp * sy;  // y
	 q[3] = cr * cp * sy - sr * sp * cy;  // z
 
	 return q;
 }
 /**
  * @brief Publish vehicle commands
  * @param command   Command code (matches VehicleCommand and MAVLink MAV_CMD codes)
  * @param param1    Command parameter 1
  * @param param2    Command parameter 2
  */
 void OffboardControl::publish_vehicle_command(uint16_t command, float param1, float param2)
 {
	 VehicleCommand msg{};
	 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;
	 msg.timestamp = this->get_clock()->now().nanoseconds() / 1000;
	 vehicle_command_publisher_->publish(msg);
 }
 
 int main(int argc, char *argv[])
 {
	 std::cout << "Starting offboard control node..." << std::endl;
	 setvbuf(stdout, NULL, _IONBF, BUFSIZ);
	 rclcpp::init(argc, argv);
	 rclcpp::spin(std::make_shared<OffboardControl>());
 
	 rclcpp::shutdown();
	 return 0;
 }
 
```
### circle
```javascript=
/**
 * @brief Offboard control example
 * @file offboard_control.cpp
 * @addtogroup examples
 * @author Mickey Cowden <info@cowden.tech>
 * @author Nuno Marques <nuno.marques@dronesolutions.io>
 */

 #include <px4_msgs/msg/offboard_control_mode.hpp>
 #include <px4_msgs/msg/trajectory_setpoint.hpp>
 #include <px4_msgs/msg/vehicle_command.hpp>
 #include <px4_msgs/msg/vehicle_control_mode.hpp>
 #include <rclcpp/rclcpp.hpp>
 #include <stdint.h>
 
 #include <chrono>
 #include <iostream>
 
 using namespace std::chrono;
 using namespace std::chrono_literals;
 using namespace px4_msgs::msg;
 
 class OffboardControl : public rclcpp::Node
 {
 public:
	 OffboardControl() : Node("offboard_control")
	 {
 
		 offboard_control_mode_publisher_ = this->create_publisher<OffboardControlMode>("/fmu/in/offboard_control_mode", 10);
		 trajectory_setpoint_publisher_ = this->create_publisher<TrajectorySetpoint>("/fmu/in/trajectory_setpoint", 10);
		 vehicle_command_publisher_ = this->create_publisher<VehicleCommand>("/fmu/in/vehicle_command", 10);
	 
 
		 offboard_setpoint_counter_ = 0;
 
		 auto timer_callback = [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();
			 }
 
			 // 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_++;
			 }
		 };
		 timer_ = this->create_wall_timer(10ms, timer_callback);
	 }
 
	 void arm();
	 void disarm();
 
 private:
	 rclcpp::TimerBase::SharedPtr timer_;
 
	 rclcpp::Publisher<OffboardControlMode>::SharedPtr offboard_control_mode_publisher_;
	 rclcpp::Publisher<TrajectorySetpoint>::SharedPtr trajectory_setpoint_publisher_;
	 rclcpp::Publisher<VehicleCommand>::SharedPtr vehicle_command_publisher_;
 
	 std::atomic<uint64_t> timestamp_;   //!< common synced timestamped
 
	 uint64_t offboard_setpoint_counter_;   //!< counter for the number of setpoints sent
 
	 double time_counter_ = 0.0;
	 void publish_offboard_control_mode();
	 void publish_trajectory_setpoint();
	 void publish_vehicle_command(uint16_t command, float param1 = 0.0, float param2 = 0.0);
 
 };
 
 /**
  * @brief Send a command to Arm the vehicle
  */
 void OffboardControl::arm()
 {
	 publish_vehicle_command(VehicleCommand::VEHICLE_CMD_COMPONENT_ARM_DISARM, 1.0);
 
	 RCLCPP_INFO(this->get_logger(), "Arm command send");
 }
 
 /**
  * @brief Send a command to Disarm the vehicle
  */
 void OffboardControl::disarm()
 {
	 publish_vehicle_command(VehicleCommand::VEHICLE_CMD_COMPONENT_ARM_DISARM, 0.0);
 
	 RCLCPP_INFO(this->get_logger(), "Disarm command send");
 }
 
 /**
  * @brief Publish the offboard control mode.
  *        For this example, only position and altitude controls are active.
  */
 void OffboardControl::publish_offboard_control_mode()
 {
	 OffboardControlMode msg{};
	 msg.position = true;
	 msg.velocity = false;
	 msg.acceleration = false;
	 msg.attitude = false;
	 msg.body_rate = false;
	 msg.timestamp = this->get_clock()->now().nanoseconds() / 1000;
	 offboard_control_mode_publisher_->publish(msg);
 }
 
 /**
  * @brief Publish a trajectory setpoint
  *        For this example, it sends a trajectory setpoint to make the
  *        vehicle hover at 5 meters with a yaw angle of 180 degrees.
  */
 void OffboardControl::publish_trajectory_setpoint()
 {
	 // **圓形軌跡參數**
	 const float R = 30.0f;   // 半徑
	 const float omega = 0.19f; // 控制運動速度
 
	 // **時間遞增**
	 time_counter_ += 0.01f;  // 適當調整，確保 PX4 能跟上
 
	 // **計算圓形軌跡**
	 float x = R * std::cos(omega * time_counter_);
	 float y = R * std::sin(omega * time_counter_);
	 double z = -7.0f + 1.0f * std::sin(omega *time_counter_);; // 固定高度
	 double yaw = 0.0;//std::atan2(-y, -x); // 讓機頭始終面向軌跡方向
 
	 TrajectorySetpoint msg{};
	 msg.position = {static_cast<float>(x), static_cast<float>(y), static_cast<float>(z)};
	 msg.yaw = yaw;
	 msg.timestamp = this->get_clock()->now().nanoseconds() / 1000;
 
	 trajectory_setpoint_publisher_->publish(msg);
 }
 
 /**
  * @brief Publish vehicle commands
  * @param command   Command code (matches VehicleCommand and MAVLink MAV_CMD codes)
  * @param param1    Command parameter 1
  * @param param2    Command parameter 2
  */
 void OffboardControl::publish_vehicle_command(uint16_t command, float param1, float param2)
 {
	 VehicleCommand msg{};
	 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;
	 msg.timestamp = this->get_clock()->now().nanoseconds() / 1000;
	 vehicle_command_publisher_->publish(msg);
 }
 
 int main(int argc, char *argv[])
 {
	 std::cout << "Starting offboard control node..." << std::endl;
	 setvbuf(stdout, NULL, _IONBF, BUFSIZ);
	 rclcpp::init(argc, argv);
	 rclcpp::spin(std::make_shared<OffboardControl>());
 
	 rclcpp::shutdown();
	 return 0;
 }
 
```
### eight
```javascript=
/**
 * @brief Offboard control example
 * @file offboard_control.cpp
 * @addtogroup examples
 * @author Mickey Cowden <info@cowden.tech>
 * @author Nuno Marques <nuno.marques@dronesolutions.io>
 */

 #include <px4_msgs/msg/offboard_control_mode.hpp>
 #include <px4_msgs/msg/trajectory_setpoint.hpp>
 #include <px4_msgs/msg/vehicle_command.hpp>
 #include <px4_msgs/msg/vehicle_control_mode.hpp>
 #include <rclcpp/rclcpp.hpp>
 #include <stdint.h>
 
 #include <chrono>
 #include <iostream>
 
 using namespace std::chrono;
 using namespace std::chrono_literals;
 using namespace px4_msgs::msg;
 
 class OffboardControl : public rclcpp::Node
 {
 public:
	 OffboardControl() : Node("offboard_control")
	 {
 
		 offboard_control_mode_publisher_ = this->create_publisher<OffboardControlMode>("/fmu/in/offboard_control_mode", 10);
		 trajectory_setpoint_publisher_ = this->create_publisher<TrajectorySetpoint>("/fmu/in/trajectory_setpoint", 10);
		 vehicle_command_publisher_ = this->create_publisher<VehicleCommand>("/fmu/in/vehicle_command", 10);
	 
 
		 offboard_setpoint_counter_ = 0;
 
		 auto timer_callback = [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();
			 }
 
			 // 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_++;
			 }
		 };
		 timer_ = this->create_wall_timer(10ms, timer_callback);
	 }
 
	 void arm();
	 void disarm();
 
 private:
	 rclcpp::TimerBase::SharedPtr timer_;
 
	 rclcpp::Publisher<OffboardControlMode>::SharedPtr offboard_control_mode_publisher_;
	 rclcpp::Publisher<TrajectorySetpoint>::SharedPtr trajectory_setpoint_publisher_;
	 rclcpp::Publisher<VehicleCommand>::SharedPtr vehicle_command_publisher_;
 
	 std::atomic<uint64_t> timestamp_;   //!< common synced timestamped
 
	 uint64_t offboard_setpoint_counter_;   //!< counter for the number of setpoints sent
 
	 double time_counter_ = 0.0;
	 void publish_offboard_control_mode();
	 void publish_trajectory_setpoint();
	 void publish_vehicle_command(uint16_t command, float param1 = 0.0, float param2 = 0.0);
 
 };
 
 /**
  * @brief Send a command to Arm the vehicle
  */
 void OffboardControl::arm()
 {
	 publish_vehicle_command(VehicleCommand::VEHICLE_CMD_COMPONENT_ARM_DISARM, 1.0);
 
	 RCLCPP_INFO(this->get_logger(), "Arm command send");
 }
 
 /**
  * @brief Send a command to Disarm the vehicle
  */
 void OffboardControl::disarm()
 {
	 publish_vehicle_command(VehicleCommand::VEHICLE_CMD_COMPONENT_ARM_DISARM, 0.0);
 
	 RCLCPP_INFO(this->get_logger(), "Disarm command send");
 }
 
 /**
  * @brief Publish the offboard control mode.
  *        For this example, only position and altitude controls are active.
  */
 void OffboardControl::publish_offboard_control_mode()
 {
	 OffboardControlMode msg{};
	 msg.position = true;
	 msg.velocity = false;
	 msg.acceleration = false;
	 msg.attitude = false;
	 msg.body_rate = false;
	 msg.timestamp = this->get_clock()->now().nanoseconds() / 1000;
	 offboard_control_mode_publisher_->publish(msg);
 }
 
 /**
  * @brief Publish a trajectory setpoint
  *        For this example, it sends a trajectory setpoint to make the
  *        vehicle hover at 5 meters with a yaw angle of 180 degrees.
  */
 void OffboardControl::publish_trajectory_setpoint()
 {
	 // **八字形參數**
	 const float A = 25.0f;   // X 軸擺幅
	 const float B = 25.0f;   // Y 軸擺幅
	 const float omega = 0.16f; // 控制運動速度
 
	 // **時間遞增**
	 time_counter_ += 0.01f;  // 減少變化幅度，讓 PX4 能跟上
 
	 // **計算八字形軌跡**
	 float x = A * std::sin(omega*time_counter_);
	 float y = B * std::sin(omega*time_counter_) * std::cos(omega*time_counter_);
	 double z = -20.0f + 0.5f * std::sin(omega*time_counter_); // 固定高度
	 double yaw = 0.0; // 保持機頭朝前
 
	 TrajectorySetpoint msg{};
	 msg.position = {static_cast<float>(x), static_cast<float>(y), static_cast<float>(z)};
	 
	 msg.yaw = yaw;
	 msg.timestamp = this->get_clock()->now().nanoseconds() / 1000;
	 
	 trajectory_setpoint_publisher_->publish(msg);
 }
 
 /**
  * @brief Publish vehicle commands
  * @param command   Command code (matches VehicleCommand and MAVLink MAV_CMD codes)
  * @param param1    Command parameter 1
  * @param param2    Command parameter 2
  */
 void OffboardControl::publish_vehicle_command(uint16_t command, float param1, float param2)
 {
	 VehicleCommand msg{};
	 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;
	 msg.timestamp = this->get_clock()->now().nanoseconds() / 1000;
	 vehicle_command_publisher_->publish(msg);
 }
 
 int main(int argc, char *argv[])
 {
	 std::cout << "Starting offboard control node..." << std::endl;
	 setvbuf(stdout, NULL, _IONBF, BUFSIZ);
	 rclcpp::init(argc, argv);
	 rclcpp::spin(std::make_shared<OffboardControl>());
 
	 rclcpp::shutdown();
	 return 0;
 }
 
```
```javascript=
#find USB
 ls /dev/ttyUSB*

#offboard

micrortps_agent -b 57600 -d /dev/ttyUSB0          #terminal1
micrortps_client start -b 57600 -d /dev/ttyS1     #QGCterminal

source ~/px4_ros_com_ros2/install/setup.bash		 #terminal3
ros2 run px4_ros_com offboard_control		    #terminal3
 
 
source ~/px4_ros_com_ros2/install/setup.bash
 
 
 
 #clean ros2 
 cd ~/px4_ros_com_ros2/src/px4_ros_com/scripts
 source clean_all.bash
 
#build ros2 workspace
 cd ~/px4_ros_com_ros2/src/px4_ros_com/scripts
 source build_ros2_workspace.bash
 source build_ros2_workspace.bash --verbose||true  #顯示編譯過程
 
 #ulog2csv
 vehicle attitude
 actuator control
 
 
 
-------------------------------------------------------------------------------------------------------
 simulation : 
 	cd ~/PX4-Autopilot/ -------> make px4_sitl_rtps gazebo
 QGroundcontrol :
 	cd ~/Downloads/ -----------> ./QGroundControl.AppImage

 -------------------------------------------------------------------------------------------------------
 
 
 *************************************** About Git ***************************************
 Q: What is git?
 A: 方便控制代碼版本的軟體（未來想走韌體or軟體必學，學會了比較好找工作）or Google What is Git
 本電腦的 GOOGLE & Github 帳號密碼在白板上，為游老師的帳號密碼
 Github Name : Modern Control - Lab
 以往是git clone PX4的代碼至本機，但是為了方便開發，希望先 fork 至 本實驗室的 github上
 再 git clone 至本機，進行版本控制
  *************************************** git 指令 ***************************************
 git status  //查看狀態
 git branch  //查看支線
 git branch "輸入新支線名稱"  //創立新的支線
 git chekcout "輸入支線名稱"    //切換至該支線
 git pull //將本地端儲存庫的程式碼更新與遠端儲存庫（github）一樣，不太理解可以上網查git clone vs git pull
 //另外  git pull = git fetch + git merge
 git add "輸入修過檔案的名稱"  //此步驟會先將修改過得檔案放入 staged
 git commit -m "修改內容或是做了神魔更動"  //記住 git add 完畢後一定要git commit -m
 git push //將git暫存的東西push到遠端儲存庫（github），完成此次修改
 
 
 
 
 
 
 
 
```