Skip to content

Commit fad5d52

Browse files
authored
Merge pull request #177 from KKalem/humble
DJICaptain
2 parents 921ba35 + d39c9ef commit fad5d52

File tree

3 files changed

+56
-64
lines changed

3 files changed

+56
-64
lines changed

behaviours/go_to_geopoint/go_to_geopoint/geopoint_server.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,7 @@ def feedback_loop(self, pose_stamped: PoseStamped, goal_handle: ServerGoalHandle
360360
pose_stamped: target location
361361
goal_handle: passed in to enable feedback publishing
362362
"""
363-
rate = self._node.create_rate(2)
363+
rate = self._node.create_rate(10)
364364
d = self.compute_distance(pose_stamped)
365365
feedback = self.action_type.Feedback
366366
tol_check = self._tol_check(d)

scripts/smarc_bringups/scripts/dji_bringup.sh

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
ROBOT_NAME=Quadrotor
33
SESSION=${ROBOT_NAME}_bringup
44

5-
if [ whoami | grep -q "alars"]; then
5+
if [[ "$(whoami)" == *"alars"* ]]; then
66
USE_SIM_TIME=False
77
MAP_FRAME=$ROBOT_NAME/map
88
else
@@ -48,7 +48,8 @@ if [ "$USE_SIM_TIME" = "False" ]; then
4848
tmux select-pane -t $SESSION:0.2
4949
tmux send-keys "ros2 topic echo /$ROBOT_NAME/captain_status std_msgs/msg/String --field data" C-m
5050

51-
# tmux select-pane -t $SESSION:0.3
51+
tmux select-pane -t $SESSION:0.3
52+
tmux send-keys "cd ~ && ./record_bag_ex_camComp.sh" C-m
5253
else
5354
tmux select-window -t $SESSION:0
5455
tmux send-keys "ros2 topic pub /$ROBOT_NAME/smarc/vehicle_health std_msgs/msg/Int8 \"data: 0\" -r 5" C-m

vehicles/hardware/dji/dji_captain/dji_captain/dji_captain.py

Lines changed: 52 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/usr/bin/python3
22

3-
import rclpy, sys, math
3+
import rclpy, sys, math, time
44
import numpy as np
55
from enum import Enum
66

@@ -64,12 +64,14 @@ def __init__(self, node: Node):
6464
self._move_to_setpoint : PoseStamped | None = None
6565
self._joy_timer : None | Timer = None
6666
self._joy_pub = node.create_publisher(Joy, PSDKTopics.FLU_JOY.value, qos_profile=10)
67+
self._joy_ramp_time : float = 5.0
68+
self._setpoint_received_at : float|None = None
6769

6870
self.MOVE_TO_SETPOINT_TOPIC = "move_to_setpoint"
6971
self.MOVE_TO_SETPOINT_MAX_AGE : float = 0.5 # seconds, how long we keep the move to setpoint before we consider it stale
70-
self.JOY_MAX = 0.4
72+
self.JOY_MAX = 0.8
7173
self.JOY_PERIOD = .1
72-
self.READY_BATTERY_PERCENTAGE = 40
74+
self.READY_BATTERY_PERCENTAGE = 25
7375
self.READY_HEIGHT_ABOVE_GROUND = 2
7476
self.ERROR_BATTERY_PERCENTAGE = 15
7577
self.ERROR_HEIGHT_ABOVE_GROUND = 1
@@ -114,22 +116,14 @@ def __init__(self, node: Node):
114116
self._carrying_payload : bool = False
115117
self._battery_percent : float | None = None
116118

117-
self.prev_joy_left : float | None = None
118-
self.prev_joy_forw : float | None = None
119-
self.prev_joy_vert : float | None = None
120-
self.kP_horiz: float | None = None
121-
self.deriv_limit_horiz: float | None = None
122-
self.kP_vert: float | None = None
123-
self.deriv_limit_vert: float | None = None
124-
125119

126120
topics = [PSDKTopics.__dict__[t].value for t in PSDKTopics.__members__.keys()]
127121
topics = ["/Quadrotor/ " + PSDKTopics.__dict__[t].value for t in PSDKTopics.__members__.keys()]
128122
self.log(f"Subscribed to PSDK topics: --topics {' '.join(topics)}")
129123

130124

131125
self._tf_pub = node.create_publisher(TFMessage,"/tf",qos_profile=10)
132-
self._tf_timer = node.create_timer(0.02, self._publish_tf)
126+
self._tf_timer = node.create_timer(0.01, self._publish_tf)
133127

134128
self._vehicle_health_pub = node.create_publisher(Int8, SmarcTopics.VEHICLE_HEALTH_TOPIC, qos_profile=10)
135129
self._vehicle_health_timer = node.create_timer(1, self._publish_vehicle_health)
@@ -353,6 +347,7 @@ def status_str(self) -> str:
353347
s += f" Vehicle Health: WAITING\n"
354348

355349

350+
356351
return s
357352

358353
def log(self, msg: str):
@@ -371,6 +366,17 @@ def _move_to_setpoint_callback(self, msg: PoseStamped):
371366
self.log(f"Move to setpoint message is older than {self.MOVE_TO_SETPOINT_MAX_AGE}s, ignoring it.")
372367
self._move_to_setpoint = None
373368
return
369+
370+
# Check if the new setpoint is the same as the current one
371+
if self._move_to_setpoint is not None:
372+
curr = self._move_to_setpoint.pose.position
373+
new = msg.pose.position
374+
if abs(curr.x - new.x) > 1e-6 and \
375+
abs(curr.y - new.y) > 1e-6 and \
376+
abs(curr.z - new.z) > 1e-6:
377+
self.log(f"New move to setpoint received: {format_pose_stamped(msg)}")
378+
self._setpoint_received_at = time.time()
379+
374380

375381
if msg.header.frame_id != self.ODOM_FRAME:
376382
try:
@@ -406,24 +412,20 @@ def _move_to_setpoint_callback(self, msg: PoseStamped):
406412
velocity_as_pose_stamped.pose.position.y = self._velocity_ground.vector.y
407413
velocity_as_pose_stamped.pose.position.z = self._velocity_ground.vector.z
408414
velocity_as_pose_stamped_base_flat = do_transform_pose_stamped(velocity_as_pose_stamped, tf)
409-
self.prev_joy_forw = velocity_as_pose_stamped_base_flat.pose.position.x
410-
self.prev_joy_left = velocity_as_pose_stamped_base_flat.pose.position.y
411-
self.prev_joy_vert = velocity_as_pose_stamped_base_flat.pose.position.z
415+
self.prev_joy_vec = np.array([velocity_as_pose_stamped_base_flat.pose.position.x, \
416+
velocity_as_pose_stamped_base_flat.pose.position.y, \
417+
velocity_as_pose_stamped_base_flat.pose.position.z])
412418
else:
413-
self.prev_joy_forw = 0
414-
self.prev_joy_left = 0
415-
self.prev_joy_vert = 0
419+
self.prev_joy_vec = np.array([0.0, 0.0, 0.0])
416420

417421
except Exception as e:
418422
self.log(f"Failed to transform velocity from {self.BASE_ENU_FRAME} to {self.BASE_FLAT_FRAME}: {e}")
419423
self._move_to_setpoint = None
420424
return
421425

422-
self.kP_horiz = self._node.get_parameter("p_gain_horiz").value
423-
self.deriv_limit_horiz = self._node.get_parameter("horiz_deriv_limit").value
424-
self.kP_vert = self._node.get_parameter("p_gain_vert").value
425-
self.deriv_limit_vert = self._node.get_parameter("vert_deriv_limit").value
426+
426427
self._joy_timer = self._node.create_timer(self.JOY_PERIOD, self._move_with_joy)
428+
self._setpoint_received_at = time.time()
427429
self.log("Joy timer started to move with joy.")
428430

429431

@@ -434,16 +436,10 @@ def cancel_joy_timer():
434436
if self._joy_timer is not None:
435437
self._joy_timer.cancel()
436438
self._joy_timer = None
437-
self.prev_joy_forw = None
438-
self.prev_joy_left = None
439-
self.prev_joy_vert = None
440-
self.kP_horiz = None
441-
self.deriv_limit_horiz = None
442-
self.kP_vert = None
443-
self.deriv_limit_vert = None
439+
self._setpoint_received_at = None
444440
self.log("Joy timer cancelled.")
445441

446-
if self._move_to_setpoint is None:
442+
if self._move_to_setpoint is None or self._setpoint_received_at is None:
447443
self.log("No move to setpoint set, cannot move with joy.")
448444
return
449445

@@ -458,16 +454,7 @@ def cancel_joy_timer():
458454
self.log("Not got control, cannot move with joy.")
459455
cancel_joy_timer()
460456
return
461-
462-
if self.kP_vert is None or self.kP_horiz is None or self.deriv_limit_horiz is None or self.deriv_limit_vert is None:
463-
self.log("PID gains or limits not set, cannot move with joy.")
464-
cancel_joy_timer()
465-
return
466-
467-
if self.prev_joy_forw is None or self.prev_joy_left is None or self.prev_joy_vert is None:
468-
self.log("previous conditions not set, cannot move with joy.")
469-
cancel_joy_timer()
470-
return
457+
471458

472459
tf_diff = self._tf_buffer.lookup_transform(
473460
target_frame = self.BASE_FLAT_FRAME,
@@ -480,37 +467,39 @@ def cancel_joy_timer():
480467
e_left = target_in_base.pose.position.y
481468
e_updn = target_in_base.pose.position.z # we like mirrors around a point
482469

483-
j_forw = max(min(self.kP_horiz * e_forw, self.JOY_MAX), -self.JOY_MAX)
484-
j_forw_deriv = (j_forw - self.prev_joy_forw) / self.JOY_PERIOD
485-
if(np.abs(j_forw_deriv) > self.deriv_limit_horiz):
486-
j_forw = max(min(self.prev_joy_forw + np.sign(j_forw_deriv) * self.deriv_limit_horiz * self.JOY_PERIOD, self.JOY_MAX), -self.JOY_MAX)
487-
488-
j_left = max(min(self.kP_horiz * e_left, self.JOY_MAX), -self.JOY_MAX)
489-
j_left_deriv = (j_left - self.prev_joy_left) / self.JOY_PERIOD
490-
if(np.abs(j_left_deriv) > self.deriv_limit_horiz):
491-
j_left = max(min(self.prev_joy_left + np.sign(j_left_deriv) * self.deriv_limit_horiz * self.JOY_PERIOD, self.JOY_MAX), -self.JOY_MAX)
470+
err = np.array([e_forw, e_left, e_updn])
471+
now = time.time()
472+
time_diff = now - self._setpoint_received_at
473+
if time_diff < self._joy_ramp_time:
474+
time_diff_mult = (time_diff / self._joy_ramp_time)
475+
else:
476+
time_diff_mult = 1.0
477+
err_mag = np.linalg.norm(err) * time_diff_mult
492478

493-
j_vert = max(min(self.kP_vert * e_updn, self.JOY_MAX), -self.JOY_MAX)
494-
j_vert_deriv = (j_vert - self.prev_joy_vert) / self.JOY_PERIOD
495-
if(np.abs(j_vert_deriv) > self.deriv_limit_vert):
496-
j_vert = max(min(self.prev_joy_vert + np.sign(j_vert_deriv) * self.deriv_limit_vert * self.JOY_PERIOD, self.JOY_MAX), -self.JOY_MAX)
479+
if np.linalg.norm(err) > err_mag and np.linalg.norm(err) > 0:
480+
err = err / np.linalg.norm(err) * err_mag
497481

498-
self.prev_joy_vert = j_vert
499-
self.prev_joy_forw = j_forw
500-
self.prev_joy_left = j_left
482+
# Limit the magnitude to JOY_MAX
483+
err = err * 0.7 #TODO make this actually competent
484+
485+
err_norm = np.linalg.norm(err)
486+
if err_norm > self.JOY_MAX and err_norm > 0:
487+
err = err / err_norm * self.JOY_MAX
488+
489+
j_forw, j_left, j_updn = err.tolist()
490+
491+
501492

502493
joy_msg = Joy()
503494
joy_msg.header.stamp = self.now_stamp
504-
joy_msg.axes = [j_forw, j_left, j_vert, 0.0] # Assuming axes: [forward, left, up/down, yaw]
495+
joy_msg.axes = [j_forw, j_left, j_updn, 0.0] # Assuming axes: [forward, left, up/down, yaw]
505496
joy_msg.buttons = []
506497

507498
self._joy_pub.publish(joy_msg)
508499

509500
def declare_node_parameters(self):
510-
self._node.declare_parameter("p_gain_horiz", 2.5)
511-
self._node.declare_parameter("p_gain_vert", 2.5)
512-
self._node.declare_parameter("horiz_deriv_limit", .4)
513-
self._node.declare_parameter("vert_deriv_limit", .4)
501+
self._node.declare_parameter("p_gain", 2.5)
502+
self._node.declare_parameter("deriv_limit", .4)
514503

515504
def _rc_cb(self, msg: Joy):
516505
# if RC is touched by user, we give up control
@@ -521,6 +510,8 @@ def _rc_cb(self, msg: Joy):
521510
self._release_control_srv.call_async(Trigger.Request()).add_done_callback(
522511
lambda future: self.log(f"Release control service called, success: {future.result().success}, message: {future.result().message}")
523512
)
513+
514+
# self.log(f"RC buttons: {msg.buttons}")
524515

525516

526517
def _velocity_ground_callback(self, msg: Vector3Stamped):

0 commit comments

Comments
 (0)