Genesis Error 수정하기
import argparse
import numpy as np
import genesis as gs
import time
import threading
from pynput import keyboard
# 아래는 추가함 / 마우스휠을 통해서 조작하기 위해서
from pynput import mouse
class DroneController:
def __init__(self):
self.thrust = 14468.429183500699 # Base hover RPM - constant hover
self.rotation_delta = 200 # Differential RPM for rotation
self.thrust_delta = 10 # Amount to change thrust by when accelerating/decelerating
self.running = True
self.rpms = [self.thrust] * 4
self.pressed_keys = set()
# mouse listener for scrolling
self.mouse_listener = mouse.Listener(on_scroll=self.on_scroll)
self.mouse_listener.start()
# 여기는 마우스 휠 조작을 통해서 카메라 줌인, 줌아웃을 위한 코드
def on_press(self, key):
try:
if key == keyboard.Key.esc:
self.running = False
return False
self.pressed_keys.add(key)
print(f"Key pressed: {key}")
except AttributeError:
pass
def on_release(self, key):
try:
self.pressed_keys.discard(key)
except KeyError:
pass
def update_thrust(self):
# Store previous RPMs for debugging
prev_rpms = self.rpms.copy()
# Reset RPMs to hover thrust
self.rpms = [self.thrust] * 4
# Acceleration (Spacebar) - All rotors spin faster
if keyboard.Key.space in self.pressed_keys:
self.thrust += self.thrust_delta
self.rpms = [self.thrust] * 4
print("Accelerating")
# Deceleration (Left Shift) - All rotors spin slower
if keyboard.Key.shift in self.pressed_keys:
self.thrust -= self.thrust_delta
self.rpms = [self.thrust] * 4
print("Decelerating")
# Forward (North) - Front rotors spin faster
if keyboard.Key.up in self.pressed_keys:
self.rpms[0] += self.rotation_delta # Front left
self.rpms[1] += self.rotation_delta # Front right
self.rpms[2] -= self.rotation_delta # Back left
self.rpms[3] -= self.rotation_delta # Back right
print("Moving Forward")
# Backward (South) - Back rotors spin faster
if keyboard.Key.down in self.pressed_keys:
self.rpms[0] -= self.rotation_delta # Front left
self.rpms[1] -= self.rotation_delta # Front right
self.rpms[2] += self.rotation_delta # Back left
self.rpms[3] += self.rotation_delta # Back right
print("Moving Backward")
# Left (West) - Left rotors spin faster
if keyboard.Key.left in self.pressed_keys:
self.rpms[0] -= self.rotation_delta # Front left
self.rpms[2] -= self.rotation_delta # Back left
self.rpms[1] += self.rotation_delta # Front right
self.rpms[3] += self.rotation_delta # Back right
print("Moving Left")
# Right (East) - Right rotors spin faster
if keyboard.Key.right in self.pressed_keys:
self.rpms[0] += self.rotation_delta # Front left
self.rpms[2] += self.rotation_delta # Back left
self.rpms[1] -= self.rotation_delta # Front right
self.rpms[3] -= self.rotation_delta # Back right
print("Moving Right")
self.rpms = np.clip(self.rpms, 0, 25000)
# Debug print if any RPMs changed
if not np.array_equal(prev_rpms, self.rpms):
print(f"RPMs changed from {prev_rpms} to {self.rpms}")
return self.rpms
# 여기는 마우스 휠 조작을 통해 카메라 줌인, 줌아웃을 위한 코드
def on_scroll(self, x, y, dx, dy):
"""Handle mouse wheel scroll to zoom in/out."""
current_fov = self.scene.viewer.camera_fov
if dy > 0: # Scroll up (zoom in)
new_fov = max(5, current_fov - 1)
elif dy < 0: # Scroll down (zoom out)
new_fov = min(90, current_fov + 1)
else:
return
self.scene.viewer.set_camera_fov(new_fov)
print(f"Updated FOV: {new_fov}")
def update_camera(scene, drone):
"""Updates the camera position to follow the drone"""
if not scene.viewer:
return
drone_pos = drone.get_pos()
# Camera position relative to drone
offset_x = 0.0 # centered horizontally
offset_y = -4.0 # 4 units behind (in Y axis)
offset_z = 2.0 # 2 units above
camera_pos = (float(drone_pos[0] + offset_x), float(drone_pos[1] + offset_y), float(drone_pos[2] + offset_z))
# Update camera position and look target
scene.viewer.set_camera_pose(pos=camera_pos, lookat=tuple(float(x) for x in drone_pos))
def run_sim(scene, drone, controller):
while controller.running:
try:
# Update drone with current RPMs
rpms = controller.update_thrust()
drone.set_propellels_rpm(rpms)
# Update physics
scene.step()
# Update camera position to follow drone
update_camera(scene, drone)
time.sleep(1 / 60) # Limit simulation rate
except Exception as e:
print(f"Error in simulation loop: {e}")
if scene.viewer:
scene.viewer.stop()
def main():
parser = argparse.ArgumentParser()
parser.add_argument("-v", "--vis", action="store_true", default=True, help="Enable visualization (default: True)")
parser.add_argument("-m", "--mac", action="store_true", default=False, help="Running on MacOS (default: False)")
args = parser.parse_args()
# Initialize Genesis
gs.init(backend=gs.gpu)
# Create scene with initial camera view
viewer_options = gs.options.ViewerOptions(
camera_pos=(0.0, -4.0, 2.0), # Now behind the drone (negative Y)
camera_lookat=(0.0, 0.0, 0.5),
camera_fov=30,
max_FPS=60,
)
scene = gs.Scene(
sim_options=gs.options.SimOptions(
dt=0.01,
gravity=(0, 0, -9.81),
),
viewer_options=viewer_options,
show_viewer=args.vis,
)
# Add entities
plane = scene.add_entity(gs.morphs.Plane())
drone = scene.add_entity(
morph=gs.morphs.Drone(
file="urdf/drones/cf2x.urdf",
pos=(0.0, 0, 0.5), # Start a bit higher
),
)
# Build scene
scene.build()
# Initialize controller
controller = DroneController()
# Print control instructions
print("\nDrone Controls:")
print("↑ - Move Forward (North)")
print("↓ - Move Backward (South)")
print("← - Move Left (West)")
print("→ - Move Right (East)")
print("ESC - Quit\n")
print("Initial hover RPM:", controller.thrust)
# Start keyboard listener
listener = keyboard.Listener(on_press=controller.on_press, on_release=controller.on_release)
listener.start()
if args.mac:
# Run simulation in another thread
sim_thread = threading.Thread(target=run_sim, args=(scene, drone, controller))
sim_thread.start()
if args.vis:
scene.viewer.start()
# Wait for threads to finish
sim_thread.join()
else:
# Run simulation in main thread
run_sim(scene, drone, controller)
listener.stop()
if __name__ == "__main__":
main()
위 코드를 동작시키려고 하자 에러가 발생했습니다.
에러의 내용인 즉 pynput이 존재하지 않는다는것!
그래서 이를 수정하고자 당연하게도 pip install pynput을 진행했지만, 에러가 발생했습니다.



위 사진과 같이 굉장한 에러가 발생했습니다.
이 에러는 evdev 패키지를 빌드하는 과정에서 Python C 헤더 파일이 없어서 발생합니다. 이 문제를 해결하려면 Python의 개발 헤더 파일과 관련 도구를 설치해야 합니다.
먼저 가상환경이 실행되고 있고, sudo apt update를 했습니다.

이후 pip install --upgrade pip를 통해서 pip를 업그레이드 했습니다.
(물론 이미 업그레이드가 된 상태였습니다.)

다음으로 python --version을 통해 파이썬 버전을 확인하고, 파이썬3.12에 맞도록
sudo apt install python3-dev python3.12-dev build-essential을 진행했습니다.
(Linux 시스템에서는 Python C 확장을 컴파일하려면 python3-dev 또는 python3.x-dev 패키지가 필요합니다.)

그 다음으로 sudo apt install build-essential을 통해 build-essential 패키지를 설치합니다. 이를 통해서 컴파일러 및 관련 도구도 함께 설치됩니다.
그 다음 pip install evdev를 다시 설치합니다.

그 다음 다시 pip install pynput을 시도하면

짠~! 제대로 설치되는 것을 확인할 수 있습니다!