-
Notifications
You must be signed in to change notification settings - Fork 36
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Update master #60
Update master #60
Changes from all commits
4b8916f
4a19920
e026436
c93fb7c
4786b17
3d72cf2
0e1bcdb
fba0e6e
a07929e
90c2618
3173cba
b394aa8
ed8366b
7340276
f3de91b
c831458
1a7234f
aa8416f
e09f0ae
d1cb0a4
339b873
bd9b3f9
170369a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The TF Sensor Sample is not added. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. TF is ROS onlyhttps://github.com/Field-Robotics-Japan/UnitySensors/pull/72 Since TF is one of the features that ROS has, I think the sample scene should only be implemented in UnitySensorsROS. TFはROSの機能なので、UnitySensors側ではなくUnitySensorsROS側にのみサンプルシーンを置くべきだと考えています。 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. TFの機能を分離したPRをマージしました。 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,75 @@ | ||
using System.Collections; | ||
using System.Collections.Generic; | ||
using UnityEngine; | ||
using UnitySensors; | ||
|
||
public class TFSensor : Sensor { | ||
public class TFSensor : Sensor | ||
{ | ||
public struct TFData | ||
{ | ||
public string frame_id_parent; | ||
public string frame_id_child; | ||
public Vector3 position; | ||
public Quaternion rotation; | ||
}; | ||
|
||
[ReadOnly] | ||
private Vector3 _position; | ||
[SerializeField] | ||
public string frame_id; | ||
[SerializeField] | ||
public TFSensor[] _children; | ||
|
||
[ReadOnly] | ||
private Quaternion _rotation; | ||
private Transform _transform; | ||
|
||
public Vector3 position { get => _position; } | ||
public Quaternion rotation { get => _rotation; } | ||
public TFData[] tf { get => GetTFData(); } | ||
|
||
protected override void Init() | ||
{ | ||
_transform = transform; | ||
base.Init(); | ||
} | ||
|
||
protected override void UpdateSensor() | ||
{ | ||
base.UpdateSensor(); | ||
} | ||
|
||
public TFData[] GetTFData() | ||
{ | ||
List<TFData> tf = new List<TFData>(); | ||
|
||
Matrix4x4 worldToLocalMatrix = _transform.worldToLocalMatrix; | ||
Quaternion worldToLocalQuaternion = Quaternion.Inverse(_transform.rotation); | ||
foreach (TFSensor child in _children) | ||
{ | ||
tf.AddRange(child.GetTFData(frame_id, worldToLocalMatrix, worldToLocalQuaternion)); | ||
} | ||
return tf.ToArray(); | ||
} | ||
|
||
public TFData[] GetTFData(string frame_id_parent, Matrix4x4 worldToLocalMatrix, Quaternion worldToLocalQuaternion) | ||
{ | ||
List<TFData> tf = new List<TFData>(); | ||
|
||
TFData tfData; | ||
tfData.frame_id_parent = frame_id_parent; | ||
tfData.frame_id_child = frame_id; | ||
tfData.position = worldToLocalMatrix * _transform.position; | ||
tfData.rotation = worldToLocalQuaternion * _transform.rotation; | ||
tf.Add(tfData); | ||
|
||
worldToLocalMatrix = _transform.worldToLocalMatrix; | ||
worldToLocalQuaternion = Quaternion.Inverse(_transform.rotation); | ||
foreach (TFSensor child in _children) | ||
{ | ||
tf.AddRange(child.GetTFData(frame_id, worldToLocalMatrix, worldToLocalQuaternion)); | ||
} | ||
return tf.ToArray(); | ||
} | ||
|
||
public void AddChild(TFSensor child) | ||
{ | ||
List<TFSensor> children = _children!=null ? new List<TFSensor>(_children) : new List<TFSensor>(); | ||
children.Add(child); | ||
_children = children.ToArray(); | ||
} | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The sample scene and sample URDF is needed, I think. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
using System.Xml; | ||
using System.Collections; | ||
using System.Collections.Generic; | ||
using UnityEngine; | ||
using UnityEditor; | ||
|
||
using UnitySensors; | ||
using UnitySensors.ROS; | ||
|
||
#if UNITY_EDITOR | ||
class URDF2TFConverter : EditorWindow | ||
{ | ||
private enum Mode | ||
{ | ||
FromTextAsset, | ||
FromFilePath | ||
} | ||
|
||
private Mode _mode; | ||
private string _filePath; | ||
private TextAsset _urdfFile; | ||
|
||
[MenuItem("UnitySensorsROS/Generate TF Objects...")] | ||
public static void ShowWindow() | ||
{ | ||
EditorWindow.GetWindow(typeof(URDF2TFConverter)); | ||
} | ||
|
||
private void OnGUI() | ||
{ | ||
GUILayout.Label("Setting", EditorStyles.boldLabel); | ||
|
||
EditorGUILayout.Space(); | ||
|
||
_mode = (Mode)EditorGUILayout.EnumPopup("Source", _mode); | ||
|
||
if (_mode == Mode.FromTextAsset) | ||
{ | ||
_urdfFile = EditorGUILayout.ObjectField("URDF File", _urdfFile, typeof(TextAsset), true) as TextAsset; | ||
} | ||
else | ||
{ | ||
_filePath = EditorGUILayout.TextField("URDF File Path", _filePath); | ||
} | ||
|
||
EditorGUILayout.Space(); | ||
|
||
if (GUILayout.Button("Generate TF Objects")) | ||
{ | ||
if (_mode == Mode.FromTextAsset && !_urdfFile) return; | ||
Generate(); | ||
} | ||
} | ||
|
||
private void Generate() | ||
{ | ||
XmlDocument doc = new XmlDocument(); | ||
|
||
if(_mode == Mode.FromTextAsset) | ||
{ | ||
doc.LoadXml(_urdfFile.text); | ||
} | ||
else | ||
{ | ||
doc.Load(_filePath); | ||
} | ||
|
||
XmlNode robot_node = doc.SelectSingleNode("robot"); | ||
GameObject robot_obj = new GameObject(); | ||
Transform robot_trans = robot_obj.transform; | ||
string robot_name = robot_node.Attributes.GetNamedItem("name").Value; | ||
robot_obj.name = robot_name; | ||
|
||
Dictionary<string, Transform> links = new Dictionary<string, Transform>(); | ||
Dictionary<string, TFSensor> tfs = new Dictionary<string, TFSensor>(); | ||
links.Add(robot_name, robot_trans); | ||
|
||
XmlNodeList link_nodes = robot_node.SelectNodes("link"); | ||
for (int i = 0; i < link_nodes.Count; i++) | ||
{ | ||
GameObject link_obj = new GameObject(); | ||
string link_name = link_nodes[i].Attributes.GetNamedItem("name").Value; | ||
link_obj.name = link_name; | ||
links.Add(link_name, link_obj.transform); | ||
TFSensor tf = link_obj.AddComponent<TFSensor>(); | ||
tf.frame_id = link_name; | ||
tfs.Add(link_name, tf); | ||
if (i == 0) link_obj.AddComponent<TFPublisher>(); | ||
} | ||
|
||
XmlNodeList joint_nodes = robot_node.SelectNodes("joint"); | ||
for (int i = 0; i < joint_nodes.Count; i++) | ||
{ | ||
string parent_name = joint_nodes[i].SelectSingleNode("parent").Attributes.GetNamedItem("link").Value; | ||
string child_name = joint_nodes[i].SelectSingleNode("child").Attributes.GetNamedItem("link").Value; | ||
links[child_name].parent = links[parent_name]; | ||
tfs[parent_name].AddChild(tfs[child_name]); | ||
|
||
XmlNode origin_node = joint_nodes[i].SelectSingleNode("origin"); | ||
if (origin_node != null) | ||
{ | ||
XmlNode xyz_node = origin_node.Attributes.GetNamedItem("xyz"); | ||
if (xyz_node != null) | ||
{ | ||
string[] pos_str = xyz_node.Value.Split(' '); | ||
Vector3 pos = new Vector3(-float.Parse(pos_str[1]), float.Parse(pos_str[2]), float.Parse(pos_str[0])); | ||
links[child_name].localPosition = pos; | ||
} | ||
else | ||
{ | ||
links[child_name].localPosition = Vector3.zero; | ||
} | ||
|
||
XmlNode rpy_node = origin_node.Attributes.GetNamedItem("rpy"); | ||
if (rpy_node != null) | ||
{ | ||
string[] rot_str = rpy_node.Value.Split(' '); | ||
Vector3 rot = new Vector3(-float.Parse(rot_str[1]), float.Parse(rot_str[2]), float.Parse(rot_str[0])); | ||
links[child_name].localEulerAngles = rot * Mathf.Rad2Deg; | ||
} | ||
else | ||
{ | ||
links[child_name].localEulerAngles = Vector3.zero; | ||
} | ||
} | ||
} | ||
|
||
foreach (Transform link in links.Values) | ||
{ | ||
if (link.parent) continue; | ||
link.parent = robot_trans; | ||
} | ||
} | ||
} | ||
|
||
#endif |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
{ | ||
"name": "UnitySensorsROSEditor", | ||
"rootNamespace": "", | ||
"references": [ | ||
"GUID:e9a473e6ad03eae4a89800bf81bd1594", | ||
"GUID:fa38f881a10f6314fa784b8975c16eff" | ||
], | ||
"includePlatforms": [], | ||
"excludePlatforms": [], | ||
"allowUnsafeCode": false, | ||
"overrideReferences": false, | ||
"precompiledReferences": [], | ||
"autoReferenced": true, | ||
"defineConstraints": [], | ||
"versionDefines": [], | ||
"noEngineReferences": false | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
using System.Collections; | ||
using System.Collections.Generic; | ||
using UnityEngine; | ||
|
||
using RosMessageTypes.Sensor; | ||
|
||
namespace UnitySensors.ROS | ||
{ | ||
[RequireComponent(typeof(GPSSensor))] | ||
public class NavSatFixPublisher : Publisher<GPSSensor, Serializer> | ||
{ | ||
[SerializeField] | ||
private string _topicName = "gnss/raw_data"; | ||
[SerializeField] | ||
private string _frame_id = "gnss_link"; | ||
|
||
[SerializeField] | ||
private NavSatFixSerializer _serializer_navsat; | ||
|
||
protected override void Init() | ||
{ | ||
_ros.RegisterPublisher<NavSatFixMsg>(_topicName); | ||
_serializer_navsat.Init(_frame_id); | ||
} | ||
|
||
protected override void Publish(float time) | ||
{ | ||
_serializer_navsat.Serialize(time, _sensor.coordinate); | ||
_ros.Publish(_topicName, _serializer_navsat.msg); | ||
} | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This Update does not contain noise model.
I will merge this in this case.
But we need to add them ASAP, at least gaussian noise.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For Livox and Velodyne, GaussianNoise is already implemented.
Currently, the GaussianNoise class is not implemented because the noise generation process is implemented within parallel and GPU processing.
LivoxとVelodyneについてはガウシアンノイズは実装済みです。
これらのノイズ生成処理は並列処理などの内部に実装されているため、GaussianNoiseクラス自体はまだありません。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did not word this point well enough. Sorry about that. I thought the noise was necessary for GPS and IMU. We also confirmed that Livox and Velodyne are implemented without any problems.
Regarding the noise of GPS and IMU, I would like to merge them for the following reasons and set them as future issues. 1.
Since the commit contents of this PR are larger than the above concerns, we would like to prioritize to merge them first. I will raise an Issue regarding the concerns.
ノイズモデルについて言葉足らずでした。申し訳ありません。上記のReview時点では、GPSとIMUにノイズが必要だとと考えていました。また、LivoxとVelodyneについても問題なく実装されていることを確認しました。
GPSとIMUのノイズの実装については、以下の理由から本PRでは一旦無視し、今後の課題としたいと思います。1.
GussianNoiseだけでなく、分散や外れ値の設定もGPSのFIXの状況に応じて変更する必要があると考えています。そのため、今後の課題として設定し、どこまでノイズモデルを設定するか決定してから実装したいと考えます。
ドリフトノイズを実装すべきかどうか議論する必要があると考えます。こちらについてもどこまでノイズモデルを設定するか決定してから実装したいと考えます。
本PRのコミット内容は上記の懸念事項よりも大きいため、優先順位をつけて先にマージしたいと思います。懸念事項についてはIssueを立てておきます。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Linked to #73 #74 for GPS and IMU noise models.