From 929ece2db1acdf9100993566266e1fdaaf5f969c Mon Sep 17 00:00:00 2001 From: Eli Yip Date: Wed, 28 May 2025 10:55:19 +0800 Subject: [PATCH] chore: stash temp files --- cmd/hand_controller/main.go | 183 ++++++++++++++++++++++++++++++++++++ pkg/config/config.go | 105 +++++++++++++++++++++ 2 files changed, 288 insertions(+) create mode 100644 cmd/hand_controller/main.go create mode 100644 pkg/config/config.go diff --git a/cmd/hand_controller/main.go b/cmd/hand_controller/main.go new file mode 100644 index 0000000..2bb2d6f --- /dev/null +++ b/cmd/hand_controller/main.go @@ -0,0 +1,183 @@ +package main + +import ( + "flag" + "fmt" + "log" + "os" + "os/signal" + "syscall" + "time" + + "hands/pkg/config" + "hands/pkg/control" + "hands/pkg/control/modes" + "hands/pkg/device" + _ "hands/pkg/device/models" // 导入以注册设备类型 +) + +func main() { + // 解析命令行参数 + configPath := flag.String("config", "config.json", "配置文件路径") + flag.Parse() + + // 加载配置 + cfg, err := loadOrCreateConfig(*configPath) + if err != nil { + log.Fatalf("加载配置失败: %v", err) + } + + // 创建设备管理器 + deviceManager := device.NewDeviceManager() + + // 创建并注册设备 + for _, deviceCfg := range cfg.Devices { + dev, err := createDevice(deviceCfg, cfg.CanServiceURL) + if err != nil { + log.Printf("创建设备 %s 失败: %v", deviceCfg.ID, err) + continue + } + + if err := deviceManager.RegisterDevice(dev); err != nil { + log.Printf("注册设备 %s 失败: %v", deviceCfg.ID, err) + continue + } + + log.Printf("成功注册设备: %s (%s)", deviceCfg.ID, deviceCfg.Model) + } + + // 创建操作模式管理器 + modeManager := control.NewModeManager() + + // 注册操作模式 + modeManager.RegisterMode(modes.NewDirectPoseMode()) + + animFactory := modes.NewAnimationFactory() + for _, animType := range animFactory.GetSupportedAnimations() { + anim, _ := animFactory.CreateAnimation(animType) + modeManager.RegisterMode(anim) + } + + // 设置默认设备 + if len(cfg.Devices) > 0 { + defaultDev, err := deviceManager.GetDevice(cfg.DefaultDevice.ID) + if err != nil { + log.Printf("获取默认设备失败: %v", err) + } else { + modeManager.SetDevice(defaultDev) + + // 连接设备 + if err := defaultDev.Connect(); err != nil { + log.Printf("连接设备失败: %v", err) + } else { + log.Printf("成功连接设备: %s", cfg.DefaultDevice.ID) + } + } + } + + // 启动默认模式 + if err := modeManager.SwitchMode("DirectPose", nil); err != nil { + log.Printf("启动默认模式失败: %v", err) + } else { + log.Println("成功启动直接姿态控制模式") + } + + // 演示功能 + demonstrateFeatures(modeManager, deviceManager) + + // 等待中断信号 + waitForShutdown() + + log.Println("应用程序正在关闭...") +} + +func loadOrCreateConfig(configPath string) (*config.Config, error) { + if _, err := os.Stat(configPath); os.IsNotExist(err) { + // 配置文件不存在,创建默认配置 + cfg := config.GetDefaultConfig() + if err := config.SaveConfig(cfg, configPath); err != nil { + return nil, fmt.Errorf("保存默认配置失败:%w", err) + } + log.Printf("创建默认配置文件: %s", configPath) + return cfg, nil + } + + return config.LoadConfig(configPath) +} + +func createDevice(deviceCfg config.DeviceConfig, canServiceURL string) (device.Device, error) { + deviceConfig := map[string]interface{}{ + "id": deviceCfg.ID, + "can_service_url": canServiceURL, + "can_interface": deviceCfg.CanInterface, + } + + // 合并设备特定参数 + for k, v := range deviceCfg.Parameters { + deviceConfig[k] = v + } + + return device.CreateDevice(deviceCfg.Model, deviceConfig) +} + +func demonstrateFeatures(modeManager *control.ModeManager, deviceManager *device.DeviceManager) { + log.Println("开始功能演示...") + + // 演示直接姿态控制 + log.Println("演示直接姿态控制...") + if activeMode := modeManager.GetActiveMode(); activeMode != nil { + if poseMode, ok := activeMode.(*modes.DirectPoseMode); ok { + // 获取设备 + devices := deviceManager.GetAllDevices() + if len(devices) > 0 { + dev := devices[0] + + // 发送手指姿态 + fingerPoses := map[string][]byte{ + "thumb": {45}, + "index": {30}, + "middle": {60}, + "ring": {45}, + "pinky": {30}, + } + + inputs := map[string]interface{}{ + "finger_poses": fingerPoses, + } + + if err := poseMode.Update(dev, inputs); err != nil { + log.Printf("发送手指姿态失败: %v", err) + } else { + log.Println("成功发送手指姿态") + } + + time.Sleep(2 * time.Second) + } + } + } + + // 演示动画模式 + log.Println("演示波浪动画...") + params := map[string]interface{}{ + "duration": 3 * time.Second, + "frames": 30, + } + + if err := modeManager.SwitchMode("Animation_wave", params); err != nil { + log.Printf("切换到波浪动画失败: %v", err) + } else { + log.Println("成功启动波浪动画") + time.Sleep(4 * time.Second) + } + + // 切换回直接控制模式 + if err := modeManager.SwitchMode("DirectPose", nil); err != nil { + log.Printf("切换回直接控制模式失败: %v", err) + } +} + +func waitForShutdown() { + sigChan := make(chan os.Signal, 1) + signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM) + <-sigChan +} diff --git a/pkg/config/config.go b/pkg/config/config.go new file mode 100644 index 0000000..e4029d3 --- /dev/null +++ b/pkg/config/config.go @@ -0,0 +1,105 @@ +package config + +import ( + "encoding/json" + "fmt" + "os" +) + +// Config 应用配置 +type Config struct { + CanServiceURL string `json:"can_service_url"` + DefaultDevice DeviceConfig `json:"default_device"` + Devices []DeviceConfig `json:"devices"` + Server ServerConfig `json:"server"` +} + +// DeviceConfig 设备配置 +type DeviceConfig struct { + ID string `json:"id"` + Model string `json:"model"` + CanInterface string `json:"can_interface"` + Parameters map[string]interface{} `json:"parameters"` +} + +// ServerConfig 服务器配置 +type ServerConfig struct { + Port int `json:"port"` + Host string `json:"host"` + LogLevel string `json:"log_level"` + EnableCORS bool `json:"enable_cors"` +} + +// LoadConfig 从文件加载配置 +func LoadConfig(configPath string) (*Config, error) { + file, err := os.Open(configPath) + if err != nil { + return nil, fmt.Errorf("打开配置文件失败:%w", err) + } + defer file.Close() + + var config Config + decoder := json.NewDecoder(file) + if err := decoder.Decode(&config); err != nil { + return nil, fmt.Errorf("解析配置文件失败:%w", err) + } + + // 设置默认值 + if config.Server.Port == 0 { + config.Server.Port = 8080 + } + if config.Server.Host == "" { + config.Server.Host = "localhost" + } + if config.Server.LogLevel == "" { + config.Server.LogLevel = "info" + } + + return &config, nil +} + +// SaveConfig 保存配置到文件 +func SaveConfig(config *Config, configPath string) error { + file, err := os.Create(configPath) + if err != nil { + return fmt.Errorf("创建配置文件失败:%w", err) + } + defer file.Close() + + encoder := json.NewEncoder(file) + encoder.SetIndent("", " ") + if err := encoder.Encode(config); err != nil { + return fmt.Errorf("保存配置文件失败:%w", err) + } + + return nil +} + +// GetDefaultConfig 获取默认配置 +func GetDefaultConfig() *Config { + return &Config{ + CanServiceURL: "http://localhost:8081", + DefaultDevice: DeviceConfig{ + ID: "left_hand", + Model: "L10", + CanInterface: "can0", + Parameters: make(map[string]interface{}), + }, + Devices: []DeviceConfig{ + { + ID: "left_hand", + Model: "L10", + CanInterface: "can0", + Parameters: map[string]interface{}{ + "hand_type": "left", + }, + }, + }, + Server: ServerConfig{ + Port: 8080, + Host: "localhost", + LogLevel: "info", + EnableCORS: true, + }, + } +}