{"action":"created","comment":{"url":"https://api.github.com/repos/ros-industrial-consortium/descartes/pulls/comments/70019932","id":70019932,"diff_hunk":"@@ -0,0 +1,66 @@\n+#ifndef DESCARTES_LADDER_GRAPH_DIJKSTRAS_H\n+#define DESCARTES_LADDER_GRAPH_DIJKSTRAS_H\n+\n+#include \"descartes_planner/ladder_graph.h\"\n+\n+namespace descartes_planner\n+{\n+\n+struct VD // Vertex Descriptor","path":"descartes_planner/include/descartes_planner/ladder_graph_dijkstras.h","position":9,"original_position":9,"commit_id":"4e8b73720de4541991f256ce9b0ed3aa5c0f07c8","original_commit_id":"4e8b73720de4541991f256ce9b0ed3aa5c0f07c8","user":{"login":"shaun-edwards","id":2932571,"avatar_url":"https://avatars.githubusercontent.com/u/2932571?v=3","gravatar_id":"","url":"https://api.github.com/users/shaun-edwards","html_url":"https://github.com/shaun-edwards","followers_url":"https://api.github.com/users/shaun-edwards/followers","following_url":"https://api.github.com/users/shaun-edwards/following{/other_user}","gists_url":"https://api.github.com/users/shaun-edwards/gists{/gist_id}","starred_url":"https://api.github.com/users/shaun-edwards/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/shaun-edwards/subscriptions","organizations_url":"https://api.github.com/users/shaun-edwards/orgs","repos_url":"https://api.github.com/users/shaun-edwards/repos","events_url":"https://api.github.com/users/shaun-edwards/events{/privacy}","received_events_url":"https://api.github.com/users/shaun-edwards/received_events","type":"User","site_admin":false},"body":"Does this need to be a public type?","created_at":"2016-07-08T02:58:33Z","updated_at":"2016-07-08T02:58:33Z","html_url":"https://github.com/ros-industrial-consortium/descartes/pull/179#discussion_r70019932","pull_request_url":"https://api.github.com/repos/ros-industrial-consortium/descartes/pulls/179","_links":{"self":{"href":"https://api.github.com/repos/ros-industrial-consortium/descartes/pulls/comments/70019932"},"html":{"href":"https://github.com/ros-industrial-consortium/descartes/pull/179#discussion_r70019932"},"pull_request":{"href":"https://api.github.com/repos/ros-industrial-consortium/descartes/pulls/179"}}},"pull_request":{"url":"https://api.github.com/repos/ros-industrial-consortium/descartes/pulls/179","id":75890589,"html_url":"https://github.com/ros-industrial-consortium/descartes/pull/179","diff_url":"https://github.com/ros-industrial-consortium/descartes/pull/179.diff","patch_url":"https://github.com/ros-industrial-consortium/descartes/pull/179.patch","issue_url":"https://api.github.com/repos/ros-industrial-consortium/descartes/issues/179","number":179,"state":"open","locked":false,"title":"Planning Graph Completely Refactored","user":{"login":"Jmeyer1292","id":4960180,"avatar_url":"https://avatars.githubusercontent.com/u/4960180?v=3","gravatar_id":"","url":"https://api.github.com/users/Jmeyer1292","html_url":"https://github.com/Jmeyer1292","followers_url":"https://api.github.com/users/Jmeyer1292/followers","following_url":"https://api.github.com/users/Jmeyer1292/following{/other_user}","gists_url":"https://api.github.com/users/Jmeyer1292/gists{/gist_id}","starred_url":"https://api.github.com/users/Jmeyer1292/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Jmeyer1292/subscriptions","organizations_url":"https://api.github.com/users/Jmeyer1292/orgs","repos_url":"https://api.github.com/users/Jmeyer1292/repos","events_url":"https://api.github.com/users/Jmeyer1292/events{/privacy}","received_events_url":"https://api.github.com/users/Jmeyer1292/received_events","type":"User","site_admin":false},"body":"> This PR is a work in progress; I intend to expand a little more on what I did and why it should replace what's already here.\r\n\r\n# Forward\r\nThis pull request represents a complete re-write of the `planning_graph` data structure that underlies Descartes' existing planners. It strips away much of the abstraction that was previously there and focuses on storing the vast amount of graph data in a compact fashion that mirrors the actual problem that we solve.\r\n\r\nI tried a lot of small ways to fix various issues that really bugged me in Descartes' existing code. After a lot of proto-typing and internal debate, I decided that to achieve the speed, space efficiency, and correctness that I wanted would require me to drop the use of boost graph altogether.\r\n\r\nThe highlights are (for larger search problems with many edges):\r\n- ~2x faster\r\n- 1/10 of the memory usage\r\n- Less code (`planning_graph.cpp` 1060 -> 260 LOC; even extras are only a few hundred lines)\r\n- Easier to reason about graph mutation\r\n\r\nThese comparisons are made with respect to the current `indigo-devel` branch and DO NOT take into account the cost of collision checking. That dominates everything, and we'll need a different approach to make that more manageable. \r\n\r\n# Ladder Graph\r\nThe biggest change introduced by this PR is the replacement of the `boost::adjacency_list` graph with a custom graph type called a `LadderGraph`. \r\n\r\n## Data Structure\r\nPreviously, Descartes used several structures to represent data:\r\n - A boost graph which contained vertices (with IDs), and edges (with start ID, stop ID, and cost).\r\n - A map relating IDs to JointPoints (which contain joint values and auxiliary info)\r\n - A map relating the IDs of user input points to information such as what joint IDs are valid for that point, the next and former point, etc\r\n - A map relating IDs to boost vertex_descriptors\r\n\r\nAll of this indirection comes with a cost.  The last item has to be recomputed every time a modification is done to the graph because all of the vertex descriptors are invalidated when the graph changes.\r\n\r\nThe new algorithm has one data structure (psuedo-code):\r\n``` c++\r\nstruct Edge {\r\n  double cost;\r\n  unsigned next; // the index of the next rung to which this edge connects\r\n}\r\n\r\nusing EdgeList = vector<Edge>;\r\nstruct Rung\r\n{\r\n  vector<double> joint_data; // one contiguous storage for all vertices; vertex 0 is at position 0..DOF-1, vertex 1 is at DOF..2*DOF-1, etc...\r\n  vector<EdgeList> out_edges; // out_edges.size() == joint_data.size() / DOF\r\n  ID id;\r\n  Timing time;\r\n}\r\n\r\nstruct LadderGraph\r\n{\r\n  size_t DOF\r\n  vector<Rung> rungs;\r\n}\r\n```\r\n\r\nThis directly stores the information we care about with just about no redundancy or extra overhead. A vertex can be accessed through an indirect read without having to do any extra lookups. Mutating the graph is also cheap, as rungs can be swapped without copying the underlying data using C++11 move semantics.\r\n\r\n## Assumptions\r\nThe new graph makes some assumptions:\r\n - Every \"vertex\" will always have the same size (`DOF`)\r\n - Vertices in a given rung can only connect to vertices in the next rung\r\n\r\nFurthermore this structure emphasizes graph mutation that changes everything at a rung level. If we wanted to remove individual joint points, it would require some additional work and _might_ be less efficient for that.\r\n\r\n# Dijkstra's Search\r\nDijkstra's search algorithm is currently used to search the graph. This PR does not change that, but provides a custom implementation of it to work directly with our existing graph. I attempted to keep the existing boost graph algorithm by [adapting the new data structure](http://www.boost.org/doc/libs/1_61_0/libs/graph/doc/leda_conversion.html), but the adapter code, particularly the iterators, ended up being longer than the actual implementation of the search.\r\n\r\nThe search is based on the existing [algorithm](http://www.boost.org/doc/libs/1_61_0/libs/graph/doc/dijkstra_shortest_paths.html) and uses Boost's BinaryHeap to efficiently implement a priority queue.\r\n\r\n# Performance Numbers\r\n![relative_speed](https://cloud.githubusercontent.com/assets/4960180/16536180/4a47ccc0-3fb4-11e6-8508-130dace2a48b.jpg)\r\n\r\nThe above chart shows the relative speed and memory improvements of solving:\r\n - The roscon 2015 demo\r\n - 1200 points\r\n - time step = 0.1s between points\r\n\r\nThe graph was solved at different angular discretizations shown along the bottom. The y value represents the time/space consumption of this PR relative to indigo-devel.\r\n\r\n# Future Improvements\r\n## isValidMove()\r\nAfter the changes in this PR, the test to see if an arc between two vertices is possible (i.e. if does not exceed joint vel limits) is actually a huge expense. This function looks like:\r\n``` c++\r\nfor (std::size_t i = 0; i < from_joint_pose.size(); ++i)\r\n  {\r\n    double dtheta = std::abs(from_joint_pose[i] - to_joint_pose[i]);\r\n    double max_dtheta = dt * velocity_limits_[i];\r\n    if (dtheta > max_dtheta)\r\n      return false;\r\n}\r\n```\r\nThis does a lot of redundant work with the cost computation, also called in the hot loop:\r\n```c++\r\ndouble vector_diff = 0;\r\nfor (unsigned i = 0; i < start_vector.size(); i++)\r\n{\r\n  double joint_diff = std::abs(end_vector[i] - start_vector[i]);\r\n  vector_diff += joint_diff;\r\n}\r\n```\r\n\r\nAlso the `max_dtheta` is the same for all joints associated with a given user input point (because they all share a single timing constraint).\r\n\r\nLong story, short: If codify the idea we will test for joint velocity limits directly into the planner we can get another 1.3 to 2x speed improvement depending on the graph size. This change involves adding a `getJointVelocityLimits()` to the robot model. \r\n\r\n## OMP\r\nWith these changes, OMP can be used to completely parallelize the graph building using three extra lines of code (plus some config file changes). I saw 3-4x speed improvements from this.\r\n\r\n\r\n# Known Issues\r\n- There may be some regressions in warning messages generated by the graph\r\n- The remove vertex function (not exercised by sparse planner) has not really been tested\r\n- There is a bug with sparse planner and timing constraints (again/still). It is present in both indigo-devel and this PR. To fix other issues and do testing, this PR does include changes in #156. ","created_at":"2016-06-30T21:04:41Z","updated_at":"2016-07-08T02:58:33Z","closed_at":null,"merged_at":null,"merge_commit_sha":"6e3a89077a87d1227fcac2f5cf785a5765cda56c","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/ros-industrial-consortium/descartes/pulls/179/commits","review_comments_url":"https://api.github.com/repos/ros-industrial-consortium/descartes/pulls/179/comments","review_comment_url":"https://api.github.com/repos/ros-industrial-consortium/descartes/pulls/comments{/number}","comments_url":"https://api.github.com/repos/ros-industrial-consortium/descartes/issues/179/comments","statuses_url":"https://api.github.com/repos/ros-industrial-consortium/descartes/statuses/4e8b73720de4541991f256ce9b0ed3aa5c0f07c8","head":{"label":"Jmeyer1292:refactor2","ref":"refactor2","sha":"4e8b73720de4541991f256ce9b0ed3aa5c0f07c8","user":{"login":"Jmeyer1292","id":4960180,"avatar_url":"https://avatars.githubusercontent.com/u/4960180?v=3","gravatar_id":"","url":"https://api.github.com/users/Jmeyer1292","html_url":"https://github.com/Jmeyer1292","followers_url":"https://api.github.com/users/Jmeyer1292/followers","following_url":"https://api.github.com/users/Jmeyer1292/following{/other_user}","gists_url":"https://api.github.com/users/Jmeyer1292/gists{/gist_id}","starred_url":"https://api.github.com/users/Jmeyer1292/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Jmeyer1292/subscriptions","organizations_url":"https://api.github.com/users/Jmeyer1292/orgs","repos_url":"https://api.github.com/users/Jmeyer1292/repos","events_url":"https://api.github.com/users/Jmeyer1292/events{/privacy}","received_events_url":"https://api.github.com/users/Jmeyer1292/received_events","type":"User","site_admin":false},"repo":{"id":30791141,"name":"descartes","full_name":"Jmeyer1292/descartes","owner":{"login":"Jmeyer1292","id":4960180,"avatar_url":"https://avatars.githubusercontent.com/u/4960180?v=3","gravatar_id":"","url":"https://api.github.com/users/Jmeyer1292","html_url":"https://github.com/Jmeyer1292","followers_url":"https://api.github.com/users/Jmeyer1292/followers","following_url":"https://api.github.com/users/Jmeyer1292/following{/other_user}","gists_url":"https://api.github.com/users/Jmeyer1292/gists{/gist_id}","starred_url":"https://api.github.com/users/Jmeyer1292/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Jmeyer1292/subscriptions","organizations_url":"https://api.github.com/users/Jmeyer1292/orgs","repos_url":"https://api.github.com/users/Jmeyer1292/repos","events_url":"https://api.github.com/users/Jmeyer1292/events{/privacy}","received_events_url":"https://api.github.com/users/Jmeyer1292/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/Jmeyer1292/descartes","description":"ROS-Industrial Special Project: Cartesian Path Planner","fork":true,"url":"https://api.github.com/repos/Jmeyer1292/descartes","forks_url":"https://api.github.com/repos/Jmeyer1292/descartes/forks","keys_url":"https://api.github.com/repos/Jmeyer1292/descartes/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Jmeyer1292/descartes/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Jmeyer1292/descartes/teams","hooks_url":"https://api.github.com/repos/Jmeyer1292/descartes/hooks","issue_events_url":"https://api.github.com/repos/Jmeyer1292/descartes/issues/events{/number}","events_url":"https://api.github.com/repos/Jmeyer1292/descartes/events","assignees_url":"https://api.github.com/repos/Jmeyer1292/descartes/assignees{/user}","branches_url":"https://api.github.com/repos/Jmeyer1292/descartes/branches{/branch}","tags_url":"https://api.github.com/repos/Jmeyer1292/descartes/tags","blobs_url":"https://api.github.com/repos/Jmeyer1292/descartes/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Jmeyer1292/descartes/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Jmeyer1292/descartes/git/refs{/sha}","trees_url":"https://api.github.com/repos/Jmeyer1292/descartes/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Jmeyer1292/descartes/statuses/{sha}","languages_url":"https://api.github.com/repos/Jmeyer1292/descartes/languages","stargazers_url":"https://api.github.com/repos/Jmeyer1292/descartes/stargazers","contributors_url":"https://api.github.com/repos/Jmeyer1292/descartes/contributors","subscribers_url":"https://api.github.com/repos/Jmeyer1292/descartes/subscribers","subscription_url":"https://api.github.com/repos/Jmeyer1292/descartes/subscription","commits_url":"https://api.github.com/repos/Jmeyer1292/descartes/commits{/sha}","git_commits_url":"https://api.github.com/repos/Jmeyer1292/descartes/git/commits{/sha}","comments_url":"https://api.github.com/repos/Jmeyer1292/descartes/comments{/number}","issue_comment_url":"https://api.github.com/repos/Jmeyer1292/descartes/issues/comments{/number}","contents_url":"https://api.github.com/repos/Jmeyer1292/descartes/contents/{+path}","compare_url":"https://api.github.com/repos/Jmeyer1292/descartes/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Jmeyer1292/descartes/merges","archive_url":"https://api.github.com/repos/Jmeyer1292/descartes/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Jmeyer1292/descartes/downloads","issues_url":"https://api.github.com/repos/Jmeyer1292/descartes/issues{/number}","pulls_url":"https://api.github.com/repos/Jmeyer1292/descartes/pulls{/number}","milestones_url":"https://api.github.com/repos/Jmeyer1292/descartes/milestones{/number}","notifications_url":"https://api.github.com/repos/Jmeyer1292/descartes/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Jmeyer1292/descartes/labels{/name}","releases_url":"https://api.github.com/repos/Jmeyer1292/descartes/releases{/id}","deployments_url":"https://api.github.com/repos/Jmeyer1292/descartes/deployments","created_at":"2015-02-14T08:17:36Z","updated_at":"2015-04-28T16:22:19Z","pushed_at":"2016-07-02T02:15:25Z","git_url":"git://github.com/Jmeyer1292/descartes.git","ssh_url":"git@github.com:Jmeyer1292/descartes.git","clone_url":"https://github.com/Jmeyer1292/descartes.git","svn_url":"https://github.com/Jmeyer1292/descartes","homepage":"","size":659,"stargazers_count":0,"watchers_count":0,"language":"C++","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"hydro-devel"}},"base":{"label":"ros-industrial-consortium:indigo-devel","ref":"indigo-devel","sha":"44116b74045138a83009a0576457c7a7cc72e05b","user":{"login":"ros-industrial-consortium","id":6336074,"avatar_url":"https://avatars.githubusercontent.com/u/6336074?v=3","gravatar_id":"","url":"https://api.github.com/users/ros-industrial-consortium","html_url":"https://github.com/ros-industrial-consortium","followers_url":"https://api.github.com/users/ros-industrial-consortium/followers","following_url":"https://api.github.com/users/ros-industrial-consortium/following{/other_user}","gists_url":"https://api.github.com/users/ros-industrial-consortium/gists{/gist_id}","starred_url":"https://api.github.com/users/ros-industrial-consortium/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ros-industrial-consortium/subscriptions","organizations_url":"https://api.github.com/users/ros-industrial-consortium/orgs","repos_url":"https://api.github.com/users/ros-industrial-consortium/repos","events_url":"https://api.github.com/users/ros-industrial-consortium/events{/privacy}","received_events_url":"https://api.github.com/users/ros-industrial-consortium/received_events","type":"Organization","site_admin":false},"repo":{"id":19514912,"name":"descartes","full_name":"ros-industrial-consortium/descartes","owner":{"login":"ros-industrial-consortium","id":6336074,"avatar_url":"https://avatars.githubusercontent.com/u/6336074?v=3","gravatar_id":"","url":"https://api.github.com/users/ros-industrial-consortium","html_url":"https://github.com/ros-industrial-consortium","followers_url":"https://api.github.com/users/ros-industrial-consortium/followers","following_url":"https://api.github.com/users/ros-industrial-consortium/following{/other_user}","gists_url":"https://api.github.com/users/ros-industrial-consortium/gists{/gist_id}","starred_url":"https://api.github.com/users/ros-industrial-consortium/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ros-industrial-consortium/subscriptions","organizations_url":"https://api.github.com/users/ros-industrial-consortium/orgs","repos_url":"https://api.github.com/users/ros-industrial-consortium/repos","events_url":"https://api.github.com/users/ros-industrial-consortium/events{/privacy}","received_events_url":"https://api.github.com/users/ros-industrial-consortium/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/ros-industrial-consortium/descartes","description":"ROS-Industrial Special Project: Cartesian Path Planner","fork":false,"url":"https://api.github.com/repos/ros-industrial-consortium/descartes","forks_url":"https://api.github.com/repos/ros-industrial-consortium/descartes/forks","keys_url":"https://api.github.com/repos/ros-industrial-consortium/descartes/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ros-industrial-consortium/descartes/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ros-industrial-consortium/descartes/teams","hooks_url":"https://api.github.com/repos/ros-industrial-consortium/descartes/hooks","issue_events_url":"https://api.github.com/repos/ros-industrial-consortium/descartes/issues/events{/number}","events_url":"https://api.github.com/repos/ros-industrial-consortium/descartes/events","assignees_url":"https://api.github.com/repos/ros-industrial-consortium/descartes/assignees{/user}","branches_url":"https://api.github.com/repos/ros-industrial-consortium/descartes/branches{/branch}","tags_url":"https://api.github.com/repos/ros-industrial-consortium/descartes/tags","blobs_url":"https://api.github.com/repos/ros-industrial-consortium/descartes/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ros-industrial-consortium/descartes/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ros-industrial-consortium/descartes/git/refs{/sha}","trees_url":"https://api.github.com/repos/ros-industrial-consortium/descartes/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ros-industrial-consortium/descartes/statuses/{sha}","languages_url":"https://api.github.com/repos/ros-industrial-consortium/descartes/languages","stargazers_url":"https://api.github.com/repos/ros-industrial-consortium/descartes/stargazers","contributors_url":"https://api.github.com/repos/ros-industrial-consortium/descartes/contributors","subscribers_url":"https://api.github.com/repos/ros-industrial-consortium/descartes/subscribers","subscription_url":"https://api.github.com/repos/ros-industrial-consortium/descartes/subscription","commits_url":"https://api.github.com/repos/ros-industrial-consortium/descartes/commits{/sha}","git_commits_url":"https://api.github.com/repos/ros-industrial-consortium/descartes/git/commits{/sha}","comments_url":"https://api.github.com/repos/ros-industrial-consortium/descartes/comments{/number}","issue_comment_url":"https://api.github.com/repos/ros-industrial-consortium/descartes/issues/comments{/number}","contents_url":"https://api.github.com/repos/ros-industrial-consortium/descartes/contents/{+path}","compare_url":"https://api.github.com/repos/ros-industrial-consortium/descartes/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ros-industrial-consortium/descartes/merges","archive_url":"https://api.github.com/repos/ros-industrial-consortium/descartes/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ros-industrial-consortium/descartes/downloads","issues_url":"https://api.github.com/repos/ros-industrial-consortium/descartes/issues{/number}","pulls_url":"https://api.github.com/repos/ros-industrial-consortium/descartes/pulls{/number}","milestones_url":"https://api.github.com/repos/ros-industrial-consortium/descartes/milestones{/number}","notifications_url":"https://api.github.com/repos/ros-industrial-consortium/descartes/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ros-industrial-consortium/descartes/labels{/name}","releases_url":"https://api.github.com/repos/ros-industrial-consortium/descartes/releases{/id}","deployments_url":"https://api.github.com/repos/ros-industrial-consortium/descartes/deployments","created_at":"2014-05-06T23:55:32Z","updated_at":"2016-07-06T02:03:25Z","pushed_at":"2016-07-02T02:15:26Z","git_url":"git://github.com/ros-industrial-consortium/descartes.git","ssh_url":"git@github.com:ros-industrial-consortium/descartes.git","clone_url":"https://github.com/ros-industrial-consortium/descartes.git","svn_url":"https://github.com/ros-industrial-consortium/descartes","homepage":"","size":966,"stargazers_count":19,"watchers_count":19,"language":"C++","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":20,"mirror_url":null,"open_issues_count":45,"forks":20,"open_issues":45,"watchers":19,"default_branch":"indigo-devel"}},"_links":{"self":{"href":"https://api.github.com/repos/ros-industrial-consortium/descartes/pulls/179"},"html":{"href":"https://github.com/ros-industrial-consortium/descartes/pull/179"},"issue":{"href":"https://api.github.com/repos/ros-industrial-consortium/descartes/issues/179"},"comments":{"href":"https://api.github.com/repos/ros-industrial-consortium/descartes/issues/179/comments"},"review_comments":{"href":"https://api.github.com/repos/ros-industrial-consortium/descartes/pulls/179/comments"},"review_comment":{"href":"https://api.github.com/repos/ros-industrial-consortium/descartes/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/ros-industrial-consortium/descartes/pulls/179/commits"},"statuses":{"href":"https://api.github.com/repos/ros-industrial-consortium/descartes/statuses/4e8b73720de4541991f256ce9b0ed3aa5c0f07c8"}}}}
{"actor":{"display_login":"shaun-edwards"}}