diff --git a/clever/CMakeLists.txt b/clever/CMakeLists.txt index dfb0307d..1f1223cd 100644 --- a/clever/CMakeLists.txt +++ b/clever/CMakeLists.txt @@ -71,14 +71,9 @@ add_service_files( Navigate.srv NavigateGlobal.srv SetPosition.srv - SetPositionYawRate.srv SetPositionGlobal.srv - SetPositionGlobalYawRate.srv SetVelocity.srv - SetVelocityYawRate.srv SetAttitude.srv - SetAttitudeYawRate.srv - SetRatesYaw.srv SetRates.srv ) diff --git a/clever/src/simple_offboard.py b/clever/src/simple_offboard.py index 6a09fd26..f49532b5 100755 --- a/clever/src/simple_offboard.py +++ b/clever/src/simple_offboard.py @@ -75,6 +75,8 @@ rospy.Subscriber('/mavros/global_position/global', NavSatFix, global_position_up rospy.Subscriber('/mavros/battery', BatteryState, battery_update) +PT = PositionTarget +AT = AttitudeTarget AUTO_OFFBOARD = rospy.get_param('~auto_offboard', True) AUTO_ARM = AUTO_OFFBOARD and rospy.get_param('~auto_arm', True) OFFBOARD_TIMEOUT = rospy.Duration(rospy.get_param('~offboard_timeout', 3)) @@ -178,72 +180,32 @@ def get_publisher_and_message(req, stamp, continued=True, update_frame=True): setpoint = get_navigate_setpoint(stamp, current_nav_start, current_nav_finish.pose.position, current_nav_start_stamp, req.speed) - msg = PositionTarget(coordinate_frame=PositionTarget.FRAME_LOCAL_NED, - type_mask=PositionTarget.IGNORE_VX + PositionTarget.IGNORE_VY + PositionTarget.IGNORE_VZ + - PositionTarget.IGNORE_AFX + PositionTarget.IGNORE_AFY + PositionTarget.IGNORE_AFZ + - PositionTarget.IGNORE_YAW_RATE, + yaw_rate_flag = math.isnan(req.yaw) + msg = PositionTarget(coordinate_frame=PT.FRAME_LOCAL_NED, + type_mask=PT.IGNORE_VX + PT.IGNORE_VY + PT.IGNORE_VZ + + PT.IGNORE_AFX + PT.IGNORE_AFY + PT.IGNORE_AFZ + + (PT.IGNORE_YAW if yaw_rate_flag else PT.IGNORE_YAW_RATE), position=setpoint, - yaw=euler_from_orientation(current_nav_finish.pose.orientation)[2] - math.pi / 2) - return position_pub, msg - - elif isinstance(req, srv.SetPositionRequest): - ps.header.frame_id = req.frame_id or LOCAL_FRAME - ps.pose.position = Point(req.x, req.y, req.z) - ps.pose.orientation = orientation_from_euler(0, 0, req.yaw) - pose_local = tf_buffer.transform(ps, LOCAL_FRAME, TRANSFORM_TIMEOUT) - - msg = PositionTarget(coordinate_frame=PositionTarget.FRAME_LOCAL_NED, - type_mask=PositionTarget.IGNORE_VX + PositionTarget.IGNORE_VY + PositionTarget.IGNORE_VZ + - PositionTarget.IGNORE_AFX + PositionTarget.IGNORE_AFY + PositionTarget.IGNORE_AFZ + - PositionTarget.IGNORE_YAW_RATE, - position=pose_local.pose.position, - yaw=euler_from_orientation(pose_local.pose.orientation)[2] - math.pi / 2) - return position_pub, msg - - elif isinstance(req, srv.SetPositionYawRateRequest): - ps.header.frame_id = req.frame_id or LOCAL_FRAME - ps.pose.position = Point(req.x, req.y, req.z) - pose_local = tf_buffer.transform(ps, LOCAL_FRAME, TRANSFORM_TIMEOUT) - msg = PositionTarget(coordinate_frame=PositionTarget.FRAME_LOCAL_NED, - type_mask=PositionTarget.IGNORE_VX + PositionTarget.IGNORE_VY + PositionTarget.IGNORE_VZ + - PositionTarget.IGNORE_AFX + PositionTarget.IGNORE_AFY + PositionTarget.IGNORE_AFZ + - PositionTarget.IGNORE_YAW, - position=pose_local.pose.position, + yaw=euler_from_orientation(current_nav_finish.pose.orientation)[2] - math.pi / 2, yaw_rate=req.yaw_rate) return position_pub, msg - elif isinstance(req, srv.SetPositionGlobalRequest): - x, y = global_to_local(req.lat, req.lon) - + elif isinstance(req, (srv.SetPositionRequest, srv.SetPositionGlobalRequest)): ps.header.frame_id = req.frame_id or LOCAL_FRAME - ps.pose.position = Point(0, 0, req.z) + ps.pose.position = Point(getattr(req, 'x', 0), getattr(req, 'y', 0), req.z) ps.pose.orientation = orientation_from_euler(0, 0, req.yaw) pose_local = tf_buffer.transform(ps, LOCAL_FRAME, TRANSFORM_TIMEOUT) - pose_local.pose.position.x = x - pose_local.pose.position.y = y - msg = PositionTarget(coordinate_frame=PositionTarget.FRAME_LOCAL_NED, - type_mask=PositionTarget.IGNORE_VX + PositionTarget.IGNORE_VY + PositionTarget.IGNORE_VZ + - PositionTarget.IGNORE_AFX + PositionTarget.IGNORE_AFY + PositionTarget.IGNORE_AFZ + - PositionTarget.IGNORE_YAW_RATE, - position=pose_local.pose.position, - yaw=euler_from_orientation(pose_local.pose.orientation)[2] - math.pi / 2) - return position_pub, msg - - elif isinstance(req, srv.SetPositionGlobalYawRateRequest): - x, y = global_to_local(req.lat, req.lon) - - ps.header.frame_id = req.frame_id or LOCAL_FRAME - ps.pose.position = Point(0, 0, req.z) - pose_local = tf_buffer.transform(ps, LOCAL_FRAME, TRANSFORM_TIMEOUT) - pose_local.pose.position.x = x - pose_local.pose.position.y = y - - msg = PositionTarget(coordinate_frame=PositionTarget.FRAME_LOCAL_NED, - type_mask=PositionTarget.IGNORE_VX + PositionTarget.IGNORE_VY + PositionTarget.IGNORE_VZ + - PositionTarget.IGNORE_AFX + PositionTarget.IGNORE_AFY + PositionTarget.IGNORE_AFZ + - PositionTarget.IGNORE_YAW, + if isinstance(req, srv.SetPositionGlobalRequest): + pose_local.pose.position.x, pose_local.pose.position.y = global_to_local(req.lat, req.lon) + + yaw_rate_flag = math.isnan(req.yaw) + msg = PositionTarget(coordinate_frame=PT.FRAME_LOCAL_NED, + type_mask=PT.IGNORE_VX + PT.IGNORE_VY + PT.IGNORE_VZ + + PT.IGNORE_AFX + PT.IGNORE_AFY + PT.IGNORE_AFZ + + (PT.IGNORE_YAW if yaw_rate_flag else PT.IGNORE_YAW_RATE), position=pose_local.pose.position, + yaw=euler_from_orientation(pose_local.pose.orientation)[2] - math.pi / 2, yaw_rate=req.yaw_rate) return position_pub, msg @@ -254,23 +216,14 @@ def get_publisher_and_message(req, stamp, continued=True, update_frame=True): ps.pose.orientation = orientation_from_euler(0, 0, req.yaw) pose_local = tf_buffer.transform(ps, LOCAL_FRAME, TRANSFORM_TIMEOUT) vector_local = tf_buffer.transform(vs, LOCAL_FRAME, TRANSFORM_TIMEOUT) - msg = PositionTarget(coordinate_frame=PositionTarget.FRAME_LOCAL_NED, - type_mask=PositionTarget.IGNORE_PX + PositionTarget.IGNORE_PY + PositionTarget.IGNORE_PZ + - PositionTarget.IGNORE_AFX + PositionTarget.IGNORE_AFY + PositionTarget.IGNORE_AFZ + - PositionTarget.IGNORE_YAW_RATE, - velocity=vector_local.vector, - yaw=euler_from_orientation(pose_local.pose.orientation)[2] - math.pi / 2) - return position_pub, msg - elif isinstance(req, srv.SetVelocityYawRateRequest): - vs.vector = Vector3(req.vx, req.vy, req.vz) - vs.header.frame_id = req.frame_id or LOCAL_FRAME - vector_local = tf_buffer.transform(vs, LOCAL_FRAME, TRANSFORM_TIMEOUT) - msg = PositionTarget(coordinate_frame=PositionTarget.FRAME_LOCAL_NED, - type_mask=PositionTarget.IGNORE_PX + PositionTarget.IGNORE_PY + PositionTarget.IGNORE_PZ + - PositionTarget.IGNORE_AFX + PositionTarget.IGNORE_AFY + PositionTarget.IGNORE_AFZ + - PositionTarget.IGNORE_YAW, + yaw_rate_flag = math.isnan(req.yaw) + msg = PositionTarget(coordinate_frame=PT.FRAME_LOCAL_NED, + type_mask=PT.IGNORE_PX + PT.IGNORE_PY + PT.IGNORE_PZ + + PT.IGNORE_AFX + PT.IGNORE_AFY + PT.IGNORE_AFZ + + (PT.IGNORE_YAW if yaw_rate_flag else PT.IGNORE_YAW_RATE), velocity=vector_local.vector, + yaw=euler_from_orientation(pose_local.pose.orientation)[2] - math.pi / 2, yaw_rate=req.yaw_rate) return position_pub, msg @@ -280,25 +233,7 @@ def get_publisher_and_message(req, stamp, continued=True, update_frame=True): pose_local = tf_buffer.transform(ps, LOCAL_FRAME, TRANSFORM_TIMEOUT) msg = AttitudeTarget(orientation=pose_local.pose.orientation, thrust=req.thrust, - type_mask=AttitudeTarget.IGNORE_YAW_RATE + AttitudeTarget.IGNORE_PITCH_RATE + - AttitudeTarget.IGNORE_ROLL_RATE) - return attitude_pub, msg - - elif isinstance(req, srv.SetAttitudeYawRateRequest): - msg = AttitudeTarget(orientation=orientation_from_euler(req.roll, req.pitch, 0), - thrust=req.thrust, - type_mask=AttitudeTarget.IGNORE_PITCH_RATE + AttitudeTarget.IGNORE_ROLL_RATE) - msg.body_rate.z = req.yaw_rate - return attitude_pub, msg - - elif isinstance(req, srv.SetRatesYawRequest): - ps.header.frame_id = req.frame_id or LOCAL_FRAME - ps.pose.orientation = orientation_from_euler(0, 0, req.yaw) - pose_local = tf_buffer.transform(ps, LOCAL_FRAME, TRANSFORM_TIMEOUT) - msg = AttitudeTarget(orientation=pose_local.pose.orientation, - thrust=req.thrust, - type_mask=AttitudeTarget.IGNORE_YAW_RATE, - body_rate=Vector3(req.roll_rate, req.pitch_rate, 0)) + type_mask=AT.IGNORE_YAW_RATE + AT.IGNORE_PITCH_RATE + AT.IGNORE_ROLL_RATE) return attitude_pub, msg elif isinstance(req, srv.SetRatesRequest): @@ -328,6 +263,14 @@ def handle(req): rospy.logwarn('Navigate speed must be greater than zero, %s passed') return {'message': 'Navigate speed must be greater than zero, %s passed' % req.speed} + if getattr(req, 'yaw_rate', 0) != 0 and not math.isnan(getattr(req, 'yaw')): + rospy.logwarn('Yaw value should be NaN for setting yaw rate') + return {'message': 'Yaw value should be NaN for setting yaw rate'} + + if math.isnan(getattr(req, 'yaw', 0)) and math.isnan(getattr(req, 'yaw_rate', 0)): + rospy.logwarn('Both yaw and yaw_rate cannot be NaN') + return {'message': 'Both yaw and yaw_rate cannot be NaN'} + try: with handle_lock: stamp = rospy.get_rostime() @@ -378,15 +321,10 @@ def release(req): rospy.Service('navigate', srv.Navigate, handle) rospy.Service('navigate_global', srv.NavigateGlobal, handle) rospy.Service('set_position', srv.SetPosition, handle) -rospy.Service('set_position/yaw_rate', srv.SetPositionYawRate, handle) rospy.Service('set_position_global', srv.SetPositionGlobal, handle) -rospy.Service('set_position_global/yaw_rate', srv.SetPositionGlobalYawRate, handle) rospy.Service('set_velocity', srv.SetVelocity, handle) -rospy.Service('set_velocity/yaw_rate', srv.SetVelocityYawRate, handle) rospy.Service('set_attitude', srv.SetAttitude, handle) -rospy.Service('set_attitude/yaw_rate', srv.SetAttitudeYawRate, handle) rospy.Service('set_rates', srv.SetRates, handle) -rospy.Service('set_rates/yaw', srv.SetRatesYaw, handle) rospy.Service('land', Trigger, land) rospy.Service('release', Trigger, release) diff --git a/clever/srv/Navigate.srv b/clever/srv/Navigate.srv index e368f284..6605e900 100644 --- a/clever/srv/Navigate.srv +++ b/clever/srv/Navigate.srv @@ -2,6 +2,7 @@ float32 x float32 y float32 z float32 yaw +float32 yaw_rate float32 speed string frame_id bool update_frame diff --git a/clever/srv/NavigateGlobal.srv b/clever/srv/NavigateGlobal.srv index 68ca45ba..52305d29 100644 --- a/clever/srv/NavigateGlobal.srv +++ b/clever/srv/NavigateGlobal.srv @@ -2,6 +2,7 @@ float32 lat float32 lon float32 z float32 yaw +float32 yaw_rate float32 speed string frame_id bool update_frame diff --git a/clever/srv/SetAttitudeYawRate.srv b/clever/srv/SetAttitudeYawRate.srv deleted file mode 100644 index e914cf7e..00000000 --- a/clever/srv/SetAttitudeYawRate.srv +++ /dev/null @@ -1,8 +0,0 @@ -float32 roll -float32 pitch -float32 yaw_rate -float32 thrust -bool auto_arm ---- -bool success -string message diff --git a/clever/srv/SetPosition.srv b/clever/srv/SetPosition.srv index 421c4931..0a4288e3 100644 --- a/clever/srv/SetPosition.srv +++ b/clever/srv/SetPosition.srv @@ -2,6 +2,7 @@ float32 x float32 y float32 z float32 yaw +float32 yaw_rate string frame_id bool update_frame bool auto_arm diff --git a/clever/srv/SetPositionGlobal.srv b/clever/srv/SetPositionGlobal.srv index 742f4d95..29d84f8c 100644 --- a/clever/srv/SetPositionGlobal.srv +++ b/clever/srv/SetPositionGlobal.srv @@ -2,6 +2,7 @@ float32 lat float32 lon float32 z float32 yaw +float32 yaw_rate string frame_id bool update_frame bool auto_arm diff --git a/clever/srv/SetPositionGlobalYawRate.srv b/clever/srv/SetPositionGlobalYawRate.srv deleted file mode 100644 index 3fc42931..00000000 --- a/clever/srv/SetPositionGlobalYawRate.srv +++ /dev/null @@ -1,10 +0,0 @@ -float32 lat -float32 lon -float32 z -float32 yaw_rate -string frame_id -bool update_frame -bool auto_arm ---- -bool success -string message diff --git a/clever/srv/SetPositionYawRate.srv b/clever/srv/SetPositionYawRate.srv deleted file mode 100644 index 419621ca..00000000 --- a/clever/srv/SetPositionYawRate.srv +++ /dev/null @@ -1,10 +0,0 @@ -float32 x -float32 y -float32 z -float32 yaw_rate -string frame_id -bool update_frame -bool auto_arm ---- -bool success -string message diff --git a/clever/srv/SetRatesYaw.srv b/clever/srv/SetRatesYaw.srv deleted file mode 100644 index df8950ac..00000000 --- a/clever/srv/SetRatesYaw.srv +++ /dev/null @@ -1,10 +0,0 @@ -float32 pitch_rate -float32 roll_rate -float32 yaw -float32 thrust -string frame_id -bool update_frame -bool auto_arm ---- -bool success -string message diff --git a/clever/srv/SetVelocity.srv b/clever/srv/SetVelocity.srv index 01b818b2..4251d021 100644 --- a/clever/srv/SetVelocity.srv +++ b/clever/srv/SetVelocity.srv @@ -2,6 +2,7 @@ float32 vx float32 vy float32 vz float32 yaw +float32 yaw_rate string frame_id bool update_frame bool auto_arm diff --git a/clever/srv/SetVelocityYawRate.srv b/clever/srv/SetVelocityYawRate.srv deleted file mode 100644 index 3155644e..00000000 --- a/clever/srv/SetVelocityYawRate.srv +++ /dev/null @@ -1,10 +0,0 @@ -float32 vx -float32 vy -float32 vz -float32 yaw_rate -string frame_id -bool update_frame -bool auto_arm ---- -bool success -string message diff --git a/docs/simple_offboard.md b/docs/simple_offboard.md index ead7fea8..3033cf61 100644 --- a/docs/simple_offboard.md +++ b/docs/simple_offboard.md @@ -16,15 +16,15 @@ Simple offboard * `z` — высота в системе координат `frame_id`; * `lat`, `lon` – широта и долгота (в градусах); * `yaw` — рысканье в радианах в системе координат `frame_id` (0 – коптер смотрит по оси X); -* `yaw_rate` — угловая скорость по рысканью в радианах в секунду (против часовой); -* `thrust` — уровень газа (от 0 [нет газа] до 1 [полный газ]). +* `yaw_rate` — угловая скорость по рысканью в радианах в секунду (против часовой), `yaw` должен быть установлен в NaN; +* `thrust` — уровень газа от 0 (нет газа) до 1 (полный газ). > **Warning** API модуля `simple_offboard` на данный момент нестабилен и может измениться. Использование из языка Python --- -Объявление прокси ко всем сервисам: +Пример программы, объявляющей прокси ко всем сервисам: ```python import rospy @@ -35,26 +35,16 @@ rospy.init_node('foo') # Создаем прокси ко всем сервисам: -navigate = rospy.ServiceProxy('/navigate', srv.Navigate) - -set_position = rospy.ServiceProxy('/set_position', srv.SetPosition) -set_position_yaw_rate = -rospy.ServiceProxy('/set_position/yaw_rate', srv.SetPositionYawRate) - -set_position_global = rospy.ServiceProxy('/set_position_global', srv.SetPositionGlobal) -set_position_global_yaw_rate = rospy.ServiceProxy('/set_position_global/yaw_rate', srv.SetPositionGlobalYawRate) - -set_velocity = rospy.ServiceProxy('/set_velocity', srv.SetVelocity) -set_velocity_yaw_rate = rospy.ServiceProxy('/set_Velocity/yaw_rate', srv.SetVelocityYawRate) - -set_attitude = rospy.ServiceProxy('/set_attitude', srv.SetAttitude) -set_attitude_yaw_rate = rospy.ServiceProxy('/set_attitude/yaw_rate', srv.SetAttitudeYawRate) - -set_rates_yaw = rospy.ServiceProxy('/set_rates/yaw', srv.SetRatesYaw) -set_rates = rospy.ServiceProxy('/set_rates', srv.SetRates) - -get_telemetry = rospy.ServiceProxy('/get_telemetry', srv.GetTelemetry) -release = rospy.ServiceProxy('/release', Trigger) +get_telemetry = rospy.ServiceProxy('get_telemetry', srv.GetTelemetry) +navigate = rospy.ServiceProxy('navigate', srv.Navigate) +navigate_global = rospy.ServiceProxy('navigate_global', srv.NavigateGlobal) +set_position = rospy.ServiceProxy('set_position', srv.SetPosition) +set_position_global = rospy.ServiceProxy('set_position_global', srv.SetPositionGlobal) +set_velocity = rospy.ServiceProxy('set_velocity', srv.SetVelocity) +set_attitude = rospy.ServiceProxy('set_attitude', srv.SetAttitude) +set_rates = rospy.ServiceProxy('set_rates', srv.SetRates) +land = rospy.ServiceProxy('land', Trigger) +release = rospy.ServiceProxy('release', Trigger) ``` Неиспользуемые фукнции-прокси можно удалить из кода. @@ -72,8 +62,8 @@ release = rospy.ServiceProxy('/release', Trigger) * `connected` – есть ли подключение к FCU * `armed` – состояние `armed` винтов (винты включены, если true) * `mode` - текущий [полетный режим](/docs/modes.md) -* `x, y, z` – локальная позиция коптера -* `lat, lon` – широта, долгота (при наличии [gps](/docs/gps.md)) +* `x, y, z` – позиция коптера в системе координат `frame_id` +* `lat, lon` – текущая широта и долгота (при наличии [gps](/docs/gps.md)) * `vx, vy, vz` – скорость коптера * `pitch` – угол по тангажу (радианы) * `roll` – угол по крену (радианы) @@ -103,10 +93,11 @@ rosservice call /get_telemetry "{frame_id: ''}" Параметры: -* x, y, z – координаты в системе `frame_id` -* yaw – угол по рысканью -* speed – скорость полета (скорость движения setpoint) -* frame_id, update_frame, auto_arm. +* `x`, `y`, `z` – координаты в системе `frame_id` +* `yaw` – угол по рысканью +* `yaw_rate` – угловая скорость по рысканью (при установке yaw в NaN) +* `speed` – скорость полета (скорость движения setpoint) +* `frame_id`, `update_frame`, `auto_arm`. Примеры: @@ -134,6 +125,7 @@ navigate(x=3, y=2, z=2, speed=1, frame_id='aruco_map', update_frame=True) ``` Пример взлета на коптере на 2 метра из командной строки: + ```bash rosservice call /navigate "{x: 0.0, y: 0.0, z: 2, yaw: 0.0, speed: 0.5, frame_id: 'fcu_horiz', update_frame: false, auto_arm: true}" ``` @@ -146,11 +138,12 @@ rosservice call /navigate "{x: 0.0, y: 0.0, z: 2, yaw: 0.0, speed: 0.5, frame_id Параметры: -* lat, lon – широта и долгота -* z – высота в системе координат `frame_id` -* yaw – угол по рысканью -* speed – скорость полета (скорость движения setpoint) -* frame_id, update_frame, auto_arm. +* `lat`, `lon` – широта и долгота; +* `z` – высота в системе координат `frame_id`; +* `yaw` – угол по рысканью; +* `yaw_rate` – угловая скорость по рысканью (при установке yaw в NaN); +* `speed` – скорость полета (скорость движения setpoint); +* `frame_id`, `update_frame`, `auto_arm`. Объявление прокси к сервису: @@ -172,12 +165,18 @@ rosservice call /navigate_global "{lat: 55.707033, lon: 37.725010, z: 0.0, yaw: ### set_position -Установить цель по позиции и рысканью. +Установить цель по позиции и рысканью. + +Параметры: + +* `x`, `y`, `z` – координаты точки в системе координат `frame_id`; +* `yaw` – угол по рысканью; +* `yaw_rate` – угловая скорость по рысканью (при установке yaw в NaN); +* `speed` – скорость полета (скорость движения setpoint); +* `frame_id`, `update_frame`, `auto_arm`. > **Hint** Для полета на точку по прямой или взлета используйте более высокоуровневый сервис `navigate`. -Параметры: x, y, z, yaw, frame_id, update_frame - Задание позиции относительно текущей позиции коптера: ```python @@ -199,76 +198,61 @@ set_position(x=0, y=-1, z=0, frame_id='fcu_horiz') # пролететь впр set_position(x=2, y=2, z=3, frame_id='aruco_map', update_frame=True) # полет в координату 2:2, высота 3 метра ``` -### set_position_yaw_rate +Вращение на месте со скоростью 0.5 рад/c: -Установить цель по позиции и угловую скорость по рысканью. - -Параметры: x, y, z, yaw_rate, frame_id, update_frame - -### set_position_global - -> **Hint** Для полета в точку в глобальной системе координат по прямой используйте более высокоуровневый сервис `navigate_global`. - -Установить цель по позиции в глобальной системе координат (широта/долгота). - -Параметры: lat (широта), lon (долгота), z (высота в системе координат frame_id), yaw (рысканье в системе координат frame_id), update_frame. - -Полет в глобальную точку (оставаясь на текущей высоте): ```python -set_position_global(lat=55.707033, lon=37.725010, z=0, frame_id='fcu_horiz') +set_position(x=0, y=0, z=0, frame_id='fcu_horiz', yaw=float('nan'), yaw_rate=0.5) ``` -### set_position_global_yaw_rate - -Полет в позицию в глобальной системе координат вращаясь с заданной скоростью по рысканью. - -Параметры: lat (широта), lon (долгота), z (высота в системе координат frame_id), yaw_rate (угловая скорость по рысканью), update_frame. - ### set_velocity -Установить скорости и рысканье. Параметр `frame_id` влияет только на ориентацию результирующего вектора скорости, но не на его длину. +Установить скорости и рысканье. + +* `vx`, `vy`, `vz` – требуемая скорость полета; +* `yaw` – угол по рысканью; +* `yaw_rate` – угловая скорость по рысканью (при установке yaw в NaN); +* `frame_id`, `update_frame`, `auto_arm`. + +> **Note** Параметр `frame_id` влияет только на ориентацию результирующего вектора скорости, но не на его длину. Параметры: vx, vy, vz, yaw, frame_id, update_frame +Полет вперед (относительно коптера) со скоростью 1 м/с: + +```python +set_velocity(vx=1, vy=0.0, vz=0, frame_id: 'fcu_horiz') +``` + Полет по кругу: ```python -set_velocity_yaw_rate(vx=0.2, vy=0.0, vz=0, yaw_rate=0.5, frame_id: 'fcu_horiz', update_frame: true) +set_velocity(vx=0.2, vy=0.0, vz=0, yaw=float('nan'), yaw_rate=0.5, frame_id: 'fcu_horiz', update_frame: True) ``` -### set_velocity_yaw_rate - -Установить скорости и угловую скорость по рысканью. - -Параметры: vx, vy, vz, yaw_rate, frame_id, update_frame - ### set_attitude -Установить тангаж, крен, рысканье и уровень газа. Имеет смысл использовать этот сервис со значением frame_id равным `fcu_horiz`. +Установить тангаж, крен, рысканье и уровень газа. -Параметры: pitch, roll, yaw, thrust, frame_id, update_frame +> **Note** Параметр `frame_id` определяет систему координат, в которой задается `yaw`. -### set_attitude_yaw_rate +Параметры: -Установить тангаж, крен, угловую скорость по рысканью и уровень газа. Имеет смысл использовать этот сервис со значением frame_id равным `fcu_horiz`. **Возможно, не поддерживается в PX4**. - -Параметры: pitch, roll, yaw_rate, thrust - -### set_rates_yaw - -Установить угловые скорости по тангажу и крену, рысканье и уровень газа. - -Параметры: pitch_rate, roll_rate, yaw, thrust, frame_id, update_frame +* `pitch`, `roll`, `yaw` – необходимый угол по тангажу, крену и рысканью (рад.); +* `thrust` – уровень газа от 0 (нет газа) до 1 (полный газ); +* `frame_id`, `update_frame`. ### set_rates Установить угловые скорости по тагажу, крену и рысканью и уровень газа. -Параметры: pitch_rate, roll_rate, yaw_rate, thrust +Параметры: + +* pitch_rate, roll_rate, yaw_rate – угловая скорость по танажу, крену и рыканью (рад/с); +* thrust – уровень газа от 0 (нет газа) до 1 (полный газ). ### release -Перестать публиковать команды коптеру (отпустить управление). +Перестать публиковать sepoint'ы коптеру (отпустить управление). Возможно продолжение управления средствами [MAVROS](/docs/mavros.md), [Веб-пультом управления](/docs/web_rc.md). Посадка