{"action":"created","issue":{"url":"https://api.github.com/repos/ros/std_msgs/issues/8","repository_url":"https://api.github.com/repos/ros/std_msgs","labels_url":"https://api.github.com/repos/ros/std_msgs/issues/8/labels{/name}","comments_url":"https://api.github.com/repos/ros/std_msgs/issues/8/comments","events_url":"https://api.github.com/repos/ros/std_msgs/issues/8/events","html_url":"https://github.com/ros/std_msgs/issues/8","id":136850864,"number":8,"title":"MultiArrayDimension.stride is bad","user":{"login":"eric-wieser","id":425260,"avatar_url":"https://avatars.githubusercontent.com/u/425260?v=3","gravatar_id":"","url":"https://api.github.com/users/eric-wieser","html_url":"https://github.com/eric-wieser","followers_url":"https://api.github.com/users/eric-wieser/followers","following_url":"https://api.github.com/users/eric-wieser/following{/other_user}","gists_url":"https://api.github.com/users/eric-wieser/gists{/gist_id}","starred_url":"https://api.github.com/users/eric-wieser/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/eric-wieser/subscriptions","organizations_url":"https://api.github.com/users/eric-wieser/orgs","repos_url":"https://api.github.com/users/eric-wieser/repos","events_url":"https://api.github.com/users/eric-wieser/events{/privacy}","received_events_url":"https://api.github.com/users/eric-wieser/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":1,"created_at":"2016-02-27T00:17:39Z","updated_at":"2016-03-02T01:37:21Z","closed_at":null,"body":"In `MultiArrayLayout.msg`, the definition given is:\r\n\r\n```python\r\nmultiarray(i,j,k) = data[data_offset + dim_stride[1]*i + dim_stride[2]*j + k]\r\n#\r\n# A standard, 3-channel 640x480 image with interleaved color channels\r\n# would be specified as:\r\n\r\ndim[0].label  = \"height\"\r\ndim[0].size   = 480\r\ndim[0].stride = 3*640*480 = 921600  (note dim[0] stride is just size of image)\r\ndim[1].label  = \"width\"\r\ndim[1].size   = 640\r\ndim[1].stride = 3*640 = 1920\r\ndim[2].label  = \"channel\"\r\ndim[2].size   = 3\r\ndim[2].stride = 3\r\n\r\n# multiarray(i,j,k) refers to the ith row, jth column, and kth channel.\r\n```\r\n\r\nThis is a fundamentally asymmetric definition:\r\n* `dim[0].stride` has no meaning\r\n* There is no way to specify the stride of the last index\r\n\r\n---\r\n\r\nI would like to contest that this defeats one of the main purposed of striding, which is to allow memory order to be exchanged. Instead, the indexing rule should be:\r\n\r\n```python\r\ndata[data_offset + dim_stride[0]*i + dim_stride[1]*j + dim_stride[2]*k]\r\n```\r\n\r\nAnd in our example, the dimensions would be\r\n\r\n```python\r\ndim[0].label  = \"height\"\r\ndim[0].size   = 480\r\ndim[0].stride = 3*640 = 1920 # how far do I need to step to get to the next row\r\ndim[1].label  = \"width\"\r\ndim[1].size   = 640\r\ndim[1].stride = 3 # how far do I need to step to get to the next pixel\r\ndim[2].label  = \"channel\"\r\ndim[2].size   = 3\r\ndim[2].stride = 1 # how far do I need to step to get to the next channel\r\n```\r\n\r\nNote this allows us to serialize our array in a different order as `[red data] [green data] [blue data]`, and then label the axes differently:\r\n\r\n```python\r\ndim[0].label  = \"height\"\r\ndim[0].size   = 480\r\ndim[0].stride = 640 # moving to the next row means stepping over the width\r\ndim[1].label  = \"width\"\r\ndim[1].size   = 640\r\ndim[1].stride = 1  # pixels in a row are adjacent\r\ndim[2].label  = \"channel\"\r\ndim[2].size   = 640*480  # moving to the next channel means stepping over a whole image\r\ndim[2].stride = 1\r\n```\r\n\r\nThis makes the definition of `stride` match up with the `numpy` definition of stride."},"comment":{"url":"https://api.github.com/repos/ros/std_msgs/issues/comments/191012289","html_url":"https://github.com/ros/std_msgs/issues/8#issuecomment-191012289","issue_url":"https://api.github.com/repos/ros/std_msgs/issues/8","id":191012289,"user":{"login":"tfoote","id":447804,"avatar_url":"https://avatars.githubusercontent.com/u/447804?v=3","gravatar_id":"","url":"https://api.github.com/users/tfoote","html_url":"https://github.com/tfoote","followers_url":"https://api.github.com/users/tfoote/followers","following_url":"https://api.github.com/users/tfoote/following{/other_user}","gists_url":"https://api.github.com/users/tfoote/gists{/gist_id}","starred_url":"https://api.github.com/users/tfoote/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tfoote/subscriptions","organizations_url":"https://api.github.com/users/tfoote/orgs","repos_url":"https://api.github.com/users/tfoote/repos","events_url":"https://api.github.com/users/tfoote/events{/privacy}","received_events_url":"https://api.github.com/users/tfoote/received_events","type":"User","site_admin":false},"created_at":"2016-03-02T01:37:21Z","updated_at":"2016-03-02T01:37:21Z","body":"This looks like a reasonable suggestion. Unfortunately I think that the design meeting notes for this message were on the old wiki and consequently are going to be hard to come by.\r\n\r\nAs a general note these messages were some of the first complex messages developed in ROS and were originally designed to be the underlying datatypes for Images and PointClouds. However they were determined that they could not capture all encodings for images. And for point clouds we mostly wanted to use external tools (ala pcl) for processing the point clouds instead of being restricted to the built in indexing. \r\n\r\nThese super generic datatypes also lost their semantic meaning because they are so generic making introspection and debugging much harder. (If you recieve a Int8MultiArrary on the wire do you pass it to an image viewer or a point cloud viewer?) As such they've basically been unused, but left for quick prototyping so as not to break anyone already using them. \r\n\r\nThis level of change of a core datatype is something that would break everything using it in it's current form. To not break any current user a new datatype could be added. But from our experience with the lack semantic meaning, I would highly recommend making the a very similar datatype but give it a non-generic name that means something, and consider adding any extra metadata fields which are appropriate for that semantic meaning. "}}