unity2moveit2/unity-project/Assets/Scripts/Core/VisualizationEngine.Collision.cs
ayuan9957 fe15edcbd5 Initial commit: Unity-MoveIt2 integrated robotic arm simulation system
- Unity frontend with ROS-TCP-Connector for ROS2 communication
- Docker-based ROS2 Jazzy backend with MoveIt2 integration
- Support for 1-9 DOF manipulators
- UR5 robot configuration and URDF files
- Assembly task feasibility analysis tools
- Comprehensive documentation and deployment guides

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-13 12:08:34 +08:00

336 lines
11 KiB
C#

using System.Collections.Generic;
using UnityEngine;
namespace UnityMoveIt2.Core
{
/// <summary>
/// 可视化引擎 - 碰撞可视化部分 / Visualization Engine - Collision Visualization Part
/// </summary>
public partial class VisualizationEngine
{
#region Collision Fields
[Header("碰撞可视化设置 / Collision Visualization Settings")]
[SerializeField]
private Color collisionColor = Color.red;
[SerializeField]
private Color warningColor = Color.yellow;
[SerializeField]
[Tooltip("碰撞透明度 / Collision Transparency")]
private float collisionTransparency = 0.5f;
[SerializeField]
[Tooltip("警告距离(米) / Warning Distance (m)")]
private float warningDistance = 0.1f;
[SerializeField]
[Tooltip("显示碰撞边界 / Show Collision Bounds")]
private bool showCollisionBounds = true;
private Dictionary<string, GameObject> collisionHighlights;
private List<CollisionPair> activeCollisions;
private Material collisionMaterial;
private Material warningMaterial;
#endregion
#region Collision Initialization
private void InitializeCollisionVisualization()
{
collisionHighlights = new Dictionary<string, GameObject>();
activeCollisions = new List<CollisionPair>();
// 创建碰撞材质 / Create collision materials
collisionMaterial = CreateTransparentMaterial(collisionColor, collisionTransparency);
warningMaterial = CreateTransparentMaterial(warningColor, collisionTransparency);
Debug.Log("[VisualizationEngine] 碰撞可视化已初始化 / Collision visualization initialized");
}
private Material CreateTransparentMaterial(Color color, float transparency)
{
Material mat = new Material(Shader.Find("Standard"));
mat.SetFloat("_Mode", 3); // Transparent mode
mat.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
mat.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
mat.SetInt("_ZWrite", 0);
mat.DisableKeyword("_ALPHATEST_ON");
mat.EnableKeyword("_ALPHABLEND_ON");
mat.DisableKeyword("_ALPHAPREMULTIPLY_ON");
mat.renderQueue = 3000;
mat.color = new Color(color.r, color.g, color.b, transparency);
return mat;
}
#endregion
#region Collision Update
private void UpdateCollisionVisualization()
{
// 更新碰撞高亮 / Update collision highlights
UpdateActiveCollisionHighlights();
// 清理过期的碰撞高亮 / Clean up expired collision highlights
CleanupInactiveCollisions();
}
private void UpdateActiveCollisionHighlights()
{
foreach (var collision in activeCollisions)
{
if (!collisionHighlights.ContainsKey(collision.objectName))
{
CreateCollisionHighlight(collision);
}
UpdateCollisionHighlight(collision);
}
}
private void CreateCollisionHighlight(CollisionPair collision)
{
GameObject target = GameObject.Find(collision.objectName);
if (target == null)
return;
GameObject highlight = new GameObject($"CollisionHighlight_{collision.objectName}");
highlight.transform.SetParent(collisionContainer.transform);
// 复制目标的网格 / Copy target's mesh
MeshFilter meshFilter = target.GetComponent<MeshFilter>();
if (meshFilter != null)
{
MeshFilter highlightMesh = highlight.AddComponent<MeshFilter>();
highlightMesh.mesh = meshFilter.mesh;
MeshRenderer renderer = highlight.AddComponent<MeshRenderer>();
renderer.material = collision.isWarning ? warningMaterial : collisionMaterial;
}
// 同步位置和旋转 / Sync position and rotation
highlight.transform.position = target.transform.position;
highlight.transform.rotation = target.transform.rotation;
highlight.transform.localScale = target.transform.localScale;
collisionHighlights[collision.objectName] = highlight;
}
private void UpdateCollisionHighlight(CollisionPair collision)
{
if (!collisionHighlights.ContainsKey(collision.objectName))
return;
GameObject highlight = collisionHighlights[collision.objectName];
GameObject target = GameObject.Find(collision.objectName);
if (target != null && highlight != null)
{
// 更新位置和旋转 / Update position and rotation
highlight.transform.position = target.transform.position;
highlight.transform.rotation = target.transform.rotation;
highlight.transform.localScale = target.transform.localScale;
// 更新材质 / Update material
MeshRenderer renderer = highlight.GetComponent<MeshRenderer>();
if (renderer != null)
{
renderer.material = collision.isWarning ? warningMaterial : collisionMaterial;
}
}
}
private void CleanupInactiveCollisions()
{
List<string> toRemove = new List<string>();
foreach (var kvp in collisionHighlights)
{
bool isActive = false;
foreach (var collision in activeCollisions)
{
if (collision.objectName == kvp.Key)
{
isActive = true;
break;
}
}
if (!isActive)
{
toRemove.Add(kvp.Key);
}
}
foreach (var key in toRemove)
{
if (collisionHighlights[key] != null)
{
Destroy(collisionHighlights[key]);
}
collisionHighlights.Remove(key);
}
}
#endregion
#region Public Collision Methods
/// <summary>
/// 高亮显示碰撞对象 / Highlight Collision Objects
/// </summary>
public void HighlightCollisions(List<string> objectNames)
{
activeCollisions.Clear();
foreach (var name in objectNames)
{
activeCollisions.Add(new CollisionPair
{
objectName = name,
isWarning = false,
distance = 0f
});
}
UpdateCollisionVisualization();
}
/// <summary>
/// 显示碰撞警告 / Show Collision Warnings
/// </summary>
public void ShowCollisionWarnings(List<ProximityInfo> proximities)
{
foreach (var proximity in proximities)
{
if (proximity.distance < warningDistance)
{
bool found = false;
foreach (var collision in activeCollisions)
{
if (collision.objectName == proximity.objectName)
{
found = true;
break;
}
}
if (!found)
{
activeCollisions.Add(new CollisionPair
{
objectName = proximity.objectName,
isWarning = true,
distance = proximity.distance
});
}
}
}
UpdateCollisionVisualization();
}
/// <summary>
/// 清除碰撞可视化 / Clear Collision Visualization
/// </summary>
public void ClearCollisionVisualization()
{
activeCollisions.Clear();
foreach (var kvp in collisionHighlights)
{
if (kvp.Value != null)
{
Destroy(kvp.Value);
}
}
collisionHighlights.Clear();
Debug.Log("[VisualizationEngine] 已清除碰撞可视化 / Cleared collision visualization");
}
/// <summary>
/// 设置碰撞对象列表 / Set Collision Objects List
/// </summary>
public void SetCollisionObjects(List<CollisionPair> collisions)
{
activeCollisions = new List<CollisionPair>(collisions);
UpdateCollisionVisualization();
}
#endregion
#region Collision Gizmos
private void DrawCollisionGizmos()
{
if (!showCollisionBounds)
return;
Gizmos.color = collisionColor;
foreach (var collision in activeCollisions)
{
GameObject obj = GameObject.Find(collision.objectName);
if (obj != null)
{
Bounds bounds = GetObjectBounds(obj);
if (bounds.size != Vector3.zero)
{
Gizmos.DrawWireCube(bounds.center, bounds.size);
}
}
}
}
private Bounds GetObjectBounds(GameObject obj)
{
Renderer renderer = obj.GetComponent<Renderer>();
if (renderer != null)
{
return renderer.bounds;
}
Collider collider = obj.GetComponent<Collider>();
if (collider != null)
{
return collider.bounds;
}
return new Bounds(obj.transform.position, Vector3.zero);
}
#endregion
}
#region Collision Data Structures
/// <summary>
/// 碰撞对信息 / Collision Pair Information
/// </summary>
[System.Serializable]
public class CollisionPair
{
public string objectName;
public bool isWarning;
public float distance;
}
/// <summary>
/// 接近度信息 / Proximity Information
/// </summary>
[System.Serializable]
public class ProximityInfo
{
public string objectName;
public float distance;
public Vector3 closestPoint;
}
#endregion
}