charge_manager 状态 1 自动录包功能部署说明
功能目标
新增一个独立的自动录包功能:
- 监听
/charge_manager_state - 每次状态从非
1变成1时,单独启动一次rosbag record - 每次状态从
1变成非1时,停止当前录包并生成.bag - 录包目录总大小超过
10G时,自动删除最老的.bag/.bag.active文件 - 录制 topic:
/livox/lidar/charge/left_rc/charge/right_rc
这相当于新增一个状态触发录包功能,替代原来 record_lidar 二进制内部不透明的触发逻辑。
一键部署脚本
在机器人105上执行:
cat > /tmp/install_auto_record_state1.sh <<'EOF'
#!/bin/bash
set -e
SCRIPT_DIR="/home/ysc/jy_cog/charge_manager_cpp/scripts"
LOG_DIR="/home/ysc/jy_cog/system/log/record_lidar_data"
AUTO_SCRIPT="$SCRIPT_DIR/auto_record_state1.sh"
START_SCRIPT="$SCRIPT_DIR/start_record_lidar.sh"
BACKUP_SCRIPT="$SCRIPT_DIR/start_record_lidar.sh.bak.$(date +%Y%m%d_%H%M%S)"
mkdir -p "$SCRIPT_DIR" "$LOG_DIR"
echo "[1/5] 写入自动录包脚本: $AUTO_SCRIPT"
cat > "$AUTO_SCRIPT" <<'EOS'
#!/bin/bash
RECORD_DIR="/home/ysc/jy_cog/system/log/record_lidar_data"
LIMIT_BYTES=$((10 * 1024 * 1024 * 1024))
KEEP_BYTES=$((8 * 1024 * 1024 * 1024))
mkdir -p "$RECORD_DIR"
record_pid=""
current_file=""
cleanup_old_bags() {
local total old_file current_base
total=$(du -sb "$RECORD_DIR" 2>/dev/null | awk '{print $1}')
current_base="$(basename "$current_file" 2>/dev/null || true)"
while [ -n "$total" ] && [ "$total" -gt "$LIMIT_BYTES" ]; do
old_file=$(find "$RECORD_DIR" -maxdepth 1 -type f \
\( -name "*.bag" -o -name "*.bag.active" \) \
! -name "${current_base}*" \
-printf "%T@ %p\n" 2>/dev/null | sort -n | head -n 1 | cut -d' ' -f2-)
[ -z "$old_file" ] && break
echo "$(date '+%F %T') delete old bag: $old_file"
rm -f "$old_file"
total=$(du -sb "$RECORD_DIR" 2>/dev/null | awk '{print $1}')
[ "$total" -le "$KEEP_BYTES" ] && break
done
}
start_record() {
if [ -n "$record_pid" ] && kill -0 "$record_pid" 2>/dev/null; then
echo "$(date '+%F %T') rosbag already running pid: $record_pid"
return
fi
cleanup_old_bags
local ts
ts=$(date '+%Y-%m-%d-%H-%M-%S')
current_file="$RECORD_DIR/record_lidar_data_${ts}"
echo "$(date '+%F %T') start record: $current_file"
cd "$RECORD_DIR" || exit 1
setsid rosbag record /livox/lidar /charge/left_rc /charge/right_rc \
-o "$current_file" --tcpnodelay &
record_pid=$!
echo "$(date '+%F %T') rosbag pid: $record_pid"
}
stop_record() {
if [ -n "$record_pid" ] && kill -0 "$record_pid" 2>/dev/null; then
echo "$(date '+%F %T') stop record pid: $record_pid"
kill -INT "-$record_pid" 2>/dev/null || kill -INT "$record_pid" 2>/dev/null || true
for _ in $(seq 1 10); do
kill -0 "$record_pid" 2>/dev/null || break
sleep 1
done
if kill -0 "$record_pid" 2>/dev/null; then
echo "$(date '+%F %T') rosbag still alive, send TERM: $record_pid"
kill -TERM "-$record_pid" 2>/dev/null || kill -TERM "$record_pid" 2>/dev/null || true
fi
wait "$record_pid" 2>/dev/null || true
fi
record_pid=""
current_file=""
cleanup_old_bags
}
trap 'stop_record; exit 0' INT TERM EXIT
last_state=""
echo "$(date '+%F %T') auto_record_state1 started"
rostopic echo -p /charge_manager_state | while IFS=, read -r stamp state; do
[ "$stamp" = "%time" ] && continue
[ -z "$state" ] && continue
if [ "$state" != "$last_state" ]; then
echo "$(date '+%F %T') state change: $last_state -> $state"
fi
if [ "$state" = "1" ] && [ "$last_state" != "1" ]; then
start_record
fi
if [ "$state" != "1" ] && [ "$last_state" = "1" ]; then
stop_record
fi
last_state="$state"
done
EOS
chmod +x "$AUTO_SCRIPT"
echo "[2/5] 备份原 start_record_lidar.sh"
if [ -f "$START_SCRIPT" ]; then
cp "$START_SCRIPT" "$BACKUP_SCRIPT"
echo "backup: $BACKUP_SCRIPT"
fi
echo "[3/5] 替换 start_record_lidar.sh"
cat > "$START_SCRIPT" <<EOS
#!/bin/bash
mkdir -p "$LOG_DIR"
bash "$AUTO_SCRIPT" >> "$LOG_DIR/record_lidar.log" 2>&1 &
EOS
chmod +x "$START_SCRIPT"
echo "[4/5] 清理旧录包进程"
pkill -INT -f "rosbag record" 2>/dev/null || true
pkill -f "auto_record_state1.sh" 2>/dev/null || true
pkill -f "/record_lidar" 2>/dev/null || true
pkill -f "./record_lidar" 2>/dev/null || true
echo "[5/5] 部署完成"
echo
echo "请重启 charge_manager 或重新执行 charge.sh,让新的 start_record_lidar.sh 生效。"
echo
echo "验证命令:"
echo " tail -f $LOG_DIR/record_lidar.log"
echo " watch -n 1 'date; ps -ef | grep -E \"[a]uto_record_state1|[r]osbag\"; ls -lh $LOG_DIR'"
EOF
bash /tmp/install_auto_record_state1.sh
重启方式
部署完成后,需要重启 charge_manager,或者重新执行原来的启动入口,让 auto_record_lidar=true 分支重新拉起新的脚本。
如果不知道服务名,可以先查看:
ps -ef | grep -E "charge_manager|charge.sh|roslaunch" | grep -v grep
验证方式
开一个窗口看日志:
tail -f /home/ysc/jy_cog/system/log/record_lidar_data/record_lidar.log
开另一个窗口看进程和文件:
watch -n 1 'date; ps -ef | grep -E "[a]uto_record_state1|[r]osbag"; ls -lh /home/ysc/jy_cog/system/log/record_lidar_data/'
功能正常时,状态进入 1 会看到:
state change: 0 -> 1
start record: /home/ysc/jy_cog/system/log/record_lidar_data/record_lidar_data_...
rosbag pid: xxxx
状态离开 1 会看到:
state change: 1 -> 2
stop record pid: xxxx
目录里应出现新的 .bag 文件。录制过程中可能短暂出现 .bag.active,正常停止后会变成 .bag。
验证 bag 内容
latest_bag=$(ls -t /home/ysc/jy_cog/system/log/record_lidar_data/*.bag | head -n 1)
rosbag info "$latest_bag"
应包含:
/livox/lidar
/charge/left_rc
/charge/right_rc
回滚方式
查看备份:
ls -lh /home/ysc/jy_cog/charge_manager_cpp/scripts/start_record_lidar.sh.bak.*
恢复最近备份:
latest_bak=$(ls -t /home/ysc/jy_cog/charge_manager_cpp/scripts/start_record_lidar.sh.bak.* | head -n 1)
cp "$latest_bak" /home/ysc/jy_cog/charge_manager_cpp/scripts/start_record_lidar.sh
chmod +x /home/ysc/jy_cog/charge_manager_cpp/scripts/start_record_lidar.sh
pkill -f auto_record_state1.sh
pkill -INT -f "rosbag record"
然后重启 charge_manager。