(Jetson Project2#4)hector mapping complete

mseokq23·2024년 12월 2일
0

command

*terminal 1

roslaunch rplidar_ros rplidar_a1.launch

*terminal 2

roslaunch hector_slam_launch tutorial.launch

if you want save current map, command this

rosrun map_server map_saver -f ~/my_map

+) initialize server with public domain

ngrok http --subdomain=arto 5000

++) and launch this script

sudo python3 server_2.py
from flask import Flask, request, jsonify, send_file
import os
import subprocess
from PIL import Image
import atexit
import time
import io
from functools import wraps

app = Flask(__name__)

# API Key Authentication (For Enhanced Security)
API_KEY = '2mLYH5v9QCl96lvRDkMWNjLJEsx_523BzdqXvkj8QKAZCBBFJ'  # Replace with a secure key in production

def require_api_key(f):
    @wraps(f)
    def decorated(*args, **kwargs):
        if 'x-api-key' not in request.headers:
            return jsonify({"error": "API 키가 필요합니다."}), 401
        if request.headers['x-api-key'] != API_KEY:
            return jsonify({"error": "유효하지 않은 API 키입니다."}), 403
        return f(*args, **kwargs)
    return decorated

# Function to Execute ROS Command
def execute_ros_command():
    """
    Executes the ROS map_saver command in the background and waits for the .pgm file to be created.
    """
    try:
        # Execute the ROS command in a bash shell
        command = "rosrun map_server map_saver -f ~/my_map"
        process = subprocess.Popen(command, shell=True, executable='/bin/bash')

        # Path to the generated .pgm file
        pgm_path = '/home/jetson/my_map.pgm'  # Update this path as needed

        # Wait for the .pgm file to be created with a timeout
        timeout = 60  # seconds
        elapsed_time = 0
        while not os.path.exists(pgm_path) and elapsed_time < timeout:
            time.sleep(1)
            elapsed_time += 1

        if os.path.exists(pgm_path):
            # Optionally, wait for the process to finish
            process.wait(timeout=10)
            return True
        else:
            print("맵 파일 생성 시간이 초과되었습니다.")
            return False
    except Exception as e:
        print(f"명령 실행 중 오류 발생: {e}")
        return False

# Route to Save Map and Convert to PNG
@app.route('/save_map', methods=['POST'])
@require_api_key
def save_map():
    """
    Executes the ROS map_saver command and converts the resulting .pgm file to .png.
    """
    data = request.get_json()
    if data and data.get('command') == 'save_map':
        if execute_ros_command():
            pgm_path = '/home/jetson/my_map.pgm'  # Update this path as needed
            png_path = '/home/jetson/my_map.png'  # Desired PNG path

            try:
                # Open the .pgm file and convert it to .png
                with Image.open(pgm_path) as img:
                    img = img.convert('RGB')  # Convert to RGB if necessary
                    img.save(png_path, 'PNG')
                return jsonify({"status": "success", "message": "Map saved and converted to PNG"}), 200
            except Exception as e:
                print(f"PNG 변환 중 오류 발생: {e}")
                return jsonify({"status": "error", "message": "맵을 PNG로 변환하는 데 실패했습니다."}), 500
        else:
            return jsonify({"status": "error", "message": "맵 저장 명령을 실행하지 못했습니다."}), 500
    return jsonify({"status": "error", "message": "유효하지 않은 명령입니다."}), 400


# 홈 디렉토리에 있는 .pgm 파일을 PNG로 변환하여 전송하는 라우트

@app.route('/image')

def send_image():

    # 홈 디렉토리에서 파일 경로 지정

    file_path = '/home/jetson/my_map.pgm'



    if not os.path.exists(file_path):

        return jsonify({'error': 'Map file not found'}), 404



    # .pgm 이미지를 열어서 PNG로 변환

    try:

        with Image.open(file_path) as img:

            img = img.convert('RGB')  # 필요에 따라 색상 모드 변환

            img_io = io.BytesIO()

            img.save(img_io, 'PNG')

            img_io.seek(0)



            return send_file(img_io, mimetype='image/png')

    except Exception as e:

        print(f"Error converting map image: {e}")

        return jsonify({'error': 'Failed to process map image'}), 500



# 외부에서 업로드된 .png 파일을 바로 처리하는 라우트

@app.route('/picture', methods=['POST'])

def handle_uploaded_picture():

    if 'image' not in request.files:

        return jsonify({'error': '파일이 없습니다.'}), 400



    file = request.files['image']

    if file.filename == '':

        return jsonify({'error': '파일명이 없습니다.'}), 400



    if file and file.filename.lower().endswith('.png'):

        # 파일을 업로드 폴더에 저장

        filepath = os.path.join(app.config['UPLOAD_FOLDER'], file.filename)

        file.save(filepath)

        return jsonify({'message': '파일 업로드 성공', 'filename': file.filename}), 200



    return jsonify({'error': '유효하지 않은 파일 형식입니다. .png 파일을 업로드하세요.'}), 400



# 업로드된 이미지를 가져오는 라우트 (Flutter 앱에서 호출)

@app.route('/uploads/<filename>')

def get_uploaded_picture(filename):

    filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename)

    if os.path.exists(filepath):

        return send_file(filepath, mimetype='image/png')

    else:

        return jsonify({'error': '파일을 찾을 수 없습니다.'}), 404








# Run the Flask App
if __name__ == '__main__':
    # Register a shutdown handler
    atexit.register(lambda: print("Flask 서버가 종료됩니다."))
    # Run the app on all interfaces, port 5000
    app.run(host='0.0.0.0', port=5000)

+++)

ngrok http --url=arto.ngrok.io 5000

0개의 댓글